diff --git a/include/littlefs_sd_shim.h b/include/littlefs_sd_shim.h index 7706d03..8f0be3d 100644 --- a/include/littlefs_sd_shim.h +++ b/include/littlefs_sd_shim.h @@ -1,5 +1,5 @@ -#ifndef ROCKETLIB_LITTLEFS_SHIM_H -#define ROCKETLIB_LITTLEFS_SHIM_H +#ifndef ROCKETLIB_LITTLEFS_SD_SHIM_H +#define ROCKETLIB_LITTLEFS_SD_SHIM_H #include "lfs.h" #include "stm32h7xx_hal_sd.h" @@ -16,4 +16,4 @@ int lfsshim_sd_mount_mbr(lfs_t *lfs, SD_HandleTypeDef *hsd); } #endif -#endif // ROCKETLIB_LITTLEFS_SHIM_H +#endif // ROCKETLIB_LITTLEFS_SD_SHIM_H diff --git a/include/mx25l25645g.h b/include/mx25l25645g.h new file mode 100644 index 0000000..cb5592d --- /dev/null +++ b/include/mx25l25645g.h @@ -0,0 +1,12 @@ +#ifndef ROCKETLIB_MX25L225645G_H +#define ROCKETLIB_MX25L225645G_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // ROCKETLIB_MX25L225645G_H \ No newline at end of file diff --git a/include/qspi_flash.h b/include/qspi_flash.h new file mode 100644 index 0000000..641d46d --- /dev/null +++ b/include/qspi_flash.h @@ -0,0 +1,17 @@ +#ifndef ROCKETLIB_QSPI_FLASH.H +#define ROCKETLIB_QSPI_FLASH .H + +#include +#include + +#include "common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ROCKETLIB_QSPI_FLASH.H */ \ No newline at end of file diff --git a/stm32h7/mx25l25645g.c b/stm32h7/mx25l25645g.c new file mode 100644 index 0000000..ad3e8b4 --- /dev/null +++ b/stm32h7/mx25l25645g.c @@ -0,0 +1,128 @@ +#include "mx25l25645g_defs.h" +#include "stm32h7xx_hal.h" + +QSPI_HandleTypeDef hqspi; +static uint32_t Timeout = 100; + +static const QSPI_InitTypeDef qspi_init_cfg = { + .ClockPrescaler = 4, + .FifoThreshold = 4, + .SampleShifting = QSPI_SAMPLE_SHIFTING_NONE, + .FlashSize = 24, // MX25L25645G = 32MB + .ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE, + .ClockMode = QSPI_CLOCK_MODE_0, + .FlashID = QSPI_FLASH_ID_1, + .DualFlash = QSPI_DUALFLASH_DISABLE, +}; + +void MX_QUADSPI_Init(void) { + hqspi.Instance = QUADSPI; + hqspi.Init = qspi_init_cfg; + if (HAL_QSPI_Init(&hqspi) != HAL_OK) { + Error_Handler(); + } +} + +// Normal SPI command for flash +const QSPI_CommandTypeDef CMD_BASE = {.Instruction = 0x0; +// .Address = 0x014; +// .AlternateBytes = 0x0; +// .AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; +.DummyCycles = 0; +.InstructionMode = QSPI_INSTRUCTION_1_LINE; +.AddressMode = QSPI_ADDRESS_NONE; +.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; +.DataMode = QSPI_DATA_NONE; +// .NbData = 0x0; +.DdrMode = QSPI_DDR_MODE_DISABLE; +// .DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; +.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +} +; + +// Quad SPI command for flash +QSPI_CommandTypeDef CMD_BASE_QSPI = {.Instruction = 0x0; +// .Address = 0x014; +// .AlternateBytes = 0x0; +// .AddressSize = QSPI_ADDRESS_8_BITS; +.AlternateBytesSize = + QSPI_ALTERNATE_BYTES_8_BITS; // may need to change to QSPI_ADDRESS_24_BITS or 32 +.DummyCycles = 0; // was 8 +.InstructionMode = QSPI_INSTRUCTION_4_LINES; +.AddressMode = QSPI_ADDRESS_NONE; +.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; +.DataMode = QSPI_DATA_NONE; +.NbData = 0; +.DdrMode = QSPI_DDR_MODE_DISABLE; +.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; +.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; +} +; + +static HAL_StatusTypeDef mx25l_exit_qpi(void) { + QSPI_CommandTypeDef cmd = CMD_BASE_QSPI; + cmd.Instruction = MX_CMD_RSTQIO; // 0xF5 + cmd.DataMode = QSPI_DATA_NONE; + cmd.NbData = 0; + return HAL_QSPI_Command(&hqspi, &cmd, Timeout); +} + +// Enable QSPI mode on the flash +HAL_StatusTypeDef mx25l_enter_qpi(void) { + QSPI_CommandTypeDef cmd = CMD_BASE; + cmd.Instruction = MX_CMD_EQIO; + cmd.DataMode = QSPI_DATA_NONE; + cmd.NbData = 0; + return HAL_QSPI_Command(&hqspi, &cmd, Timeout); +} + +// static HAL_StatusTypeDef qspi_write_enable(void) { +// QSPI_CommandTypeDef cmd = CMD_BASE_QSPI; +// cmd.Instruction = MX_CMD_WREN; +// cmd.DataMode = QSPI_DATA_NONE; +// cmd.NbData = 0; + +// return HAL_QSPI_Command(&hqspi, &cmd, Timeout); +// } + +// static HAL_StatusTypeDef qspi_mx25l_wait_wip0(void) { +// // Command: Read Status Register (RDSR) +// QSPI_CommandTypeDef cmd = {0}; +// cmd.InstructionMode = QSPI_INSTRUCTION_1_LINE; +// cmd.Instruction = MX_CMD_RDSR; +// cmd.AddressMode = QSPI_ADDRESS_NONE; +// cmd.DataMode = QSPI_DATA_1_LINE; +// cmd.NbData = 1; +// cmd.DummyCycles = 0; +// cmd.DdrMode = QSPI_DDR_MODE_DISABLE; +// cmd.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; + +// // Polling config: wait until WIP=0 +// QSPI_AutoPollingTypeDef cfg = {0}; +// cfg.Match = 0x00; // WIP must become 0 +// cfg.Mask = 0x01; // Check only bit0 +// cfg.MatchMode = QSPI_MATCH_MODE_AND; +// cfg.StatusBytesSize = 1; +// cfg.Interval = 0x10; +// cfg.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; + +// return HAL_QSPI_AutoPolling(&hqspi, &cmd, &cfg, Timeout); +// } + +int main(void) { + HAL_Init(); + SystemClock_Config(); + + // Initialize the QSPI MSP + MX_GPIO_Init(); + + // Initialize the QSPI mode with 1 instruction line, CMD_BASE + MX_QUADSPI_Init(); + + // Enable QPI mode on flash + mx25l_enter_qpi(); + + // From now on instruction becomes 4 lines since qspi is enabled, QSPI_CMD_BASE + + while (1) {} +} \ No newline at end of file diff --git a/stm32h7/mx25l25645g_defs.h b/stm32h7/mx25l25645g_defs.h new file mode 100644 index 0000000..8e096b2 --- /dev/null +++ b/stm32h7/mx25l25645g_defs.h @@ -0,0 +1,118 @@ +#ifndef ROCKETLIB_MX25l25645G_DEFS_H +#define ROCKETLIB_MX25l25645G_DEFS_H + +#include +#include + +#include "common.h" + +typedef enum { + + // ============================================================ + // Read/Write Array Commands (3-Byte Address) + // ============================================================ + + MX_CMD_READ = 0x03, // Normal Read + MX_CMD_FAST_READ = 0x0B, // Fast Read (requires dummy cycles) + + MX_CMD_DREAD = 0x3B, // Dual Output Fast Read + MX_CMD_2READ = 0xBB, // Dual I/O Fast Read + + MX_CMD_QREAD = 0x6B, // Quad Output Fast Read + MX_CMD_4READ = 0xEB, // Quad I/O Fast Read + + MX_CMD_4DTRD = 0xED, // Quad I/O DDR Read (DTR) + + MX_CMD_PP = 0x02, // Page Program + MX_CMD_4PP = 0x38, // Quad Page Program + + MX_CMD_SE = 0x20, // Sector Erase (4KB) + MX_CMD_BE32K = 0x52, // Block Erase (32KB) + MX_CMD_BE = 0xD8, // Block Erase (64KB) + + MX_CMD_CE = 0xC7, // Chip Erase (also possible: 0x60) + + // ============================================================ + // Read/Write Array Commands (4-Byte Address Command Set) + // ============================================================ + + MX_CMD_READ4B = 0x13, // Normal Read (4-byte address) + MX_CMD_FAST_READ4B = 0x0C, // Fast Read (4-byte address) + + MX_CMD_DREAD4B = 0x3C, // Dual Output Fast Read (4B) + MX_CMD_2READ4B = 0xBC, // Dual I/O Fast Read (4B) + + MX_CMD_QREAD4B = 0x6C, // Quad Output Fast Read (4B) + MX_CMD_4READ4B = 0xEC, // Quad I/O Fast Read (4B) + + MX_CMD_4DTRD4B = 0xEE, // Quad I/O DDR Read (4B) + + MX_CMD_PP4B = 0x12, // Page Program (4B) + MX_CMD_4PP4B = 0x3E, // Quad Page Program (4B) + + MX_CMD_SE4B = 0x21, // Sector Erase (4KB, 4B) + MX_CMD_BE32K4B = 0x5C, // Block Erase (32KB, 4B) + MX_CMD_BE4B = 0xDC, // Block Erase (64KB, 4B) + + // ============================================================ + // Register / Setting Commands + // ============================================================ + + MX_CMD_WREN = 0x06, // Write Enable + MX_CMD_WRDI = 0x04, // Write Disable + + MX_CMD_RDSR = 0x05, // Read Status Register + MX_CMD_WRSR = 0x01, // Write Status + Configuration Register + + MX_CMD_RDCR = 0x15, // Read Configuration Register + + MX_CMD_RDEAR = 0xC8, // Read Extended Address Register + MX_CMD_WREAR = 0xC5, // Write Extended Address Register + + MX_CMD_WPSEL = 0x68, // Write Protection Selection + + MX_CMD_EQIO = 0x35, // Enable QPI Mode + MX_CMD_RSTQIO = 0xF5, // Reset / Exit QPI Mode + + MX_CMD_EN4B = 0xB7, // Enter 4-byte Address Mode + MX_CMD_EX4B = 0xE9, // Exit 4-byte Address Mode + + MX_CMD_PGM_ERS_SUSPEND = 0xB0, // Program/Erase Suspend + MX_CMD_PGM_ERS_RESUME = 0x30, // Program/Erase Resume + + MX_CMD_DP = 0xB9, // Deep Power Down + MX_CMD_RDP = 0xAB, // Release from Deep Power Down + + MX_CMD_SBL = 0xC0, // Set Burst Length + + // ============================================================ + // ID / Security Commands + // ============================================================ + + MX_CMD_RDID = 0x9F, // Read JEDEC ID + + MX_CMD_RES = 0xAB, // Read Electronic ID (Legacy) + + MX_CMD_REMS = 0x90, // Read Manufacturer / Device ID + + MX_CMD_ENSO = 0xB1, // Enter Secured OTP Mode + MX_CMD_EXSO = 0xC1, // Exit Secured OTP Mode + + MX_CMD_RDSCUR = 0x2B, // Read Security Register + MX_CMD_WRSCUR = 0x2F, // Write Security Register + + MX_CMD_RDDPB = 0xE0, // Read DPB (Dynamic Protection Bits) + MX_CMD_WRDPB = 0xE1, // Write DPB + + MX_CMD_RDECC = 0x18, // Read ECC Status + + // ============================================================ + // Reset Commands + // ============================================================ + + MX_CMD_RSTEN = 0x66, // Reset Enable + MX_CMD_RST = 0x99, // Reset Memory Device + +} command_t; + +#endif /* ROCKETLIB_MX25l25645G_DEFS_H */ \ No newline at end of file