|
|
使用 P-NUCLEO-WB55
主要 的qspi驅動代碼如下,因是使用ok焊接,所以在讀和mapping的時候4線不成功,改成用1線式
pin腳使用如下:
/**QUADSPI GPIO Configuration
PB8 ------> QUADSPI_BK1_IO1
PB9 ------> QUADSPI_BK1_IO0
PA6 ------> QUADSPI_BK1_IO3
PA7 ------> QUADSPI_BK1_IO2
PB10 ------> QUADSPI_CLK
PB11 ------> QUADSPI_BK1_NCS
整包source code跑ide
附件是使用QSPI_MemoryMapped 的sample code改寫 builde出 elf檔后,改附檔名為stldr,放入stm32Cube programmer的ExternalLoader ,就可以識別后做燒錄
- #include "main.h"
- #include "stm32wbxx_hal.h"
- #include "stm32wbxx_hal_qspi.h"
- /* USER CODE BEGIN 0 */
- static uint8_t QSPI_WriteEnable(void);
- static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout);
- static uint8_t QSPI_Configuration(void);
- static uint8_t QSPI_ResetChip(void);
- static HAL_StatusTypeDef QSPI_EnableQuadIfNeeded(void);
- #define HAL_QPSI_TIMEOUT_DEFAULT_VALUE HAL_QSPI_TIMEOUT_DEFAULT_VALUE
- #define HAL_QSPI_TIMEOUT_DEFAULT_VALUE 5000U
- #if defined(__ICCARM__)
- /* New definition from EWARM V9, compatible with EWARM8 */
- int iar_fputc(int ch);
- #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
- #elif defined (__CC_ARM) || defined(__ARMCC_VERSION)
- /* ARM Compiler 5/6 */
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #elif defined(__GNUC__)
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #endif /* __ICCARM__ */
- /* USER CODE END 0 */
- QSPI_HandleTypeDef hqspi;
- UART_HandleTypeDef huart1;
- /* USER CODE BEGIN 1 */
- void MX_QUADSPI_Init(void)
- {
- /* USER CODE BEGIN QUADSPI_Init 0 */
- /* USER CODE END QUADSPI_Init 0 */
- /* USER CODE BEGIN QUADSPI_Init 1 */
- /* USER CODE END QUADSPI_Init 1 */
- /* QUADSPI parameter configuration*/
- hqspi.Instance = QUADSPI;
- hqspi.Init.ClockPrescaler = 2;
- //hqspi.Init.ClockPrescaler = 2;
- //hqspi.Init.FifoThreshold = 4;
- hqspi.Init.FifoThreshold = 4;
- hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
- hqspi.Init.FlashSize = 21;
- //hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
- hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
- hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
- if (HAL_QSPI_Init(&hqspi) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN QUADSPI_Init 2 */
- /* USER CODE END QUADSPI_Init 2 */
- }
- static void W25Qx_QSPI_Delay(uint32_t ms)
- {
- HAL_Delay(ms);
- }
- /* QUADSPI init function */
- uint8_t CSP_QUADSPI_Init(void) {
- //prepare QSPI peripheral for ST-Link Utility operations
- if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) {
- return HAL_ERROR;
- }
- MX_QUADSPI_Init();
- if (QSPI_ResetChip() != HAL_OK) {
- return HAL_ERROR;
- }
- HAL_Delay(1);
- if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- return HAL_ERROR;
- }
- if (QSPI_WriteEnable() != HAL_OK) {
- return HAL_ERROR;
- }
- #if 0
- QSPI_CommandTypeDef s_command;
- uint8_t value = W25Q256JV_FSR_QE;
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = WRITE_STATUS_REG2_CMD;
- s_command.AddressMode = QSPI_ADDRESS_NONE;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_1_LINE;
- s_command.DummyCycles = 0;
- s_command.NbData = 1;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- /* 傳輸數據 */
- if (HAL_QSPI_Transmit(&hqspi, &value, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- #endif
- #if 0
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; // 指令QSPI單線傳輸
- s_command.Instruction = ENTER_QPI_MODE_CMD; // 指令,0x38使能QPI模式
- s_command.AddressMode = QSPI_ADDRESS_NONE; // 地址跳過
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; // 交替字節模式跳過
- s_command.DummyCycles = 0; // 空指令周期數
- s_command.DataMode = QSPI_DATA_NONE; // 數據模式跳過
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE; // 禁止DDR模式
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; // 禁止DDR模式數據延時
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; // 在每個事務中發送指令
- /* Send the command */
- if (HAL_QSPI_Command(&hqspi, &s_command, 1000) != HAL_OK)
- {
- return HAL_ERROR;
- }
- #endif
- #if 0
- if (QSPI_AutoPollingMemReady(W25Q128JV_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK)
- {
- return HAL_ERROR;
- }
- #endif
- printf("CSP_QUADSPI_Init Done1\n");
- #if 1
- if (QSPI_Configuration() != HAL_OK) {
- return HAL_ERROR;
- }
- #endif
- QSPI_EnableQuadIfNeeded();
- HAL_Delay(100);
- printf("CSP_QUADSPI_Init Done2\n");
- return HAL_OK;
- }
- uint8_t CSP_QSPI_Erase_Chip(void) {
- QSPI_CommandTypeDef sCommand;
- if (QSPI_WriteEnable() != HAL_OK) {
- return HAL_ERROR;
- }
- /* Erasing Sequence --------------------------------- */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = CHIP_ERASE_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_NONE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_MAX_DELAY) != HAL_OK) {
- return HAL_ERROR;
- }
- if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) {
- return HAL_ERROR;
- }
- return HAL_OK;
- }
- uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout) {
- QSPI_CommandTypeDef s_command;
- QSPI_AutoPollingTypeDef s_config;
- /* 配置自動輪詢模式等待存儲器準備就緒 */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = READ_STATUS_REG1_CMD;
- s_command.AddressMode = QSPI_ADDRESS_NONE;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_1_LINE;
- s_command.DummyCycles = 0;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- s_config.Match = 0x00;
- s_config.Mask = W25Q256JV_FSR_BUSY;
- s_config.MatchMode = QSPI_MATCH_MODE_AND;
- s_config.StatusBytesSize = 1;
- s_config.Interval = 0x10;
- s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
- if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, HAL_MAX_DELAY) != HAL_OK)
- {
- return HAL_ERROR;
- }
- return HAL_OK;
- }
- static uint8_t QSPI_WriteEnable(void) {
- QSPI_CommandTypeDef s_command;
- QSPI_AutoPollingTypeDef s_config;
- /* 啟用寫操作 */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = WRITE_ENABLE_CMD;
- s_command.AddressMode = QSPI_ADDRESS_NONE;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_NONE;
- s_command.DummyCycles = 0;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- /* 配置自動輪詢模式等待寫啟用 */
- s_config.Match = W25Q256JV_FSR_WREN;
- s_config.Mask = W25Q256JV_FSR_WREN;
- s_config.MatchMode = QSPI_MATCH_MODE_AND;
- s_config.StatusBytesSize = 1;
- s_config.Interval = 0x10;
- s_config.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
- s_command.Instruction = READ_STATUS_REG1_CMD;
- s_command.DataMode = QSPI_DATA_1_LINE;
- s_command.NbData = 1;
- if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- return HAL_OK;
- }
- /*Enable quad mode and set dummy cycles count*/
- static HAL_StatusTypeDef QSPI_EnableQuadIfNeeded(void)
- {
- HAL_StatusTypeDef ret;
- QSPI_CommandTypeDef sCommand = {0};
- uint8_t sr1 = 0, sr2 = 0;
- /* 1) 讀 SR1 */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = READ_STATUS_REG_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.NbData = 1;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- if (HAL_QSPI_Receive(&hqspi, &sr1, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- /* 2) 讀 SR2 */
- sCommand.Instruction = READ_STATUS_REG2_CMD;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- if (HAL_QSPI_Receive(&hqspi, &sr2, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- /* 若 QE 已經為 1,直接回傳 OK */
- if (sr2 & QE_BIT) return HAL_OK;
- /* 3) WREN */
- ret = QSPI_WriteEnable();
- if (ret != HAL_OK) return ret;
- /* 4) 寫 SR1 + SR2 (把 QE bit 設為 1) */
- uint8_t sr_buf[2];
- sr_buf[0] = sr1;
- sr_buf[1] = sr2 | QE_BIT;
- sCommand.Instruction = WRITE_STATUS_REG1_CMD; /* 0x01: write SR1 + SR2 */
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.NbData = 2;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- if (HAL_QSPI_Transmit(&hqspi, sr_buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- /* 5) poll WIP until finished */
- if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) return HAL_ERROR;
- /* 6) read back SR2 to ensure QE is set */
- sCommand.Instruction = READ_STATUS_REG2_CMD;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.NbData = 1;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- if (HAL_QSPI_Receive(&hqspi, &sr2, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
- if (sr2 & QE_BIT) return HAL_OK;
- return HAL_ERROR;
- }
- uint8_t QSPI_Configuration(void) {
- QSPI_CommandTypeDef sCommand = { 0 };
- uint8_t reg;
- HAL_StatusTypeDef ret;
- /* Read Volatile Configuration register 2 --------------------------- */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = READ_STATUS_REG2_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.NbData = 1;
- if ((ret = HAL_QSPI_Command(&hqspi, &sCommand,
- HAL_QPSI_TIMEOUT_DEFAULT_VALUE)) != HAL_OK) {
- return ret;
- }
- if ((ret = HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE))
- != HAL_OK) {
- return ret;
- }
- /* Enable Volatile Write operations ---------------------------------------- */
- sCommand.DataMode = QSPI_DATA_NONE;
- sCommand.Instruction = VOLATILE_SR_WRITE_ENABLE;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return ret;
- }
- /* Write Volatile Configuration register 2 (QE = 1) -- */
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.Instruction = WRITE_STATUS_REG2_CMD;
- reg |= 2; // QE bit
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return ret;
- }
- if (HAL_QSPI_Transmit(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return ret;
- }
- /* Read Volatile Configuration register 3 --------------------------- */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = READ_STATUS_REG3_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.NbData = 1;
- if ((ret = HAL_QSPI_Command(&hqspi, &sCommand,
- HAL_QPSI_TIMEOUT_DEFAULT_VALUE)) != HAL_OK) {
- return ret;
- }
- if ((ret = HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE))
- != HAL_OK) {
- return ret;
- }
- /* Write Volatile Configuration register 2 (DRV1:2 = 00) -- */
- sCommand.Instruction = WRITE_STATUS_REG3_CMD;
- reg &= 0x9f; // DRV1:2 bit
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return ret;
- }
- if (HAL_QSPI_Transmit(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return ret;
- }
- return HAL_OK;
- #if 0
- QSPI_CommandTypeDef sCommand;
- uint8_t reg;
- /*enter 4 byte address*/
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = ENTER_4_BYTE_ADD_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_NONE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.NbData = 0;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- /*read configuration register*/
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = READ_CONFIGURATION_REG_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.NbData = 1;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- if (HAL_QSPI_Receive(&hqspi, ®,
- HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- return HAL_ERROR;
- }
- if (QSPI_WriteEnable() != HAL_OK) {
- return HAL_ERROR;
- }
- /*set dummy cycles*/
- MODIFY_REG(reg, 0xF0, (DUMMY_CLOCK_CYCLES_READ_QUAD << POSITION_VAL(0xF0)));
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 0;
- sCommand.NbData = 1;
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- if (HAL_QSPI_Transmit(&hqspi, ®,
- HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
- Error_Handler();
- return HAL_ERROR;
- }
- return HAL_OK;
- #endif
- }
- uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, uint32_t EraseEndAddress) {
- QSPI_CommandTypeDef sCommand;
- EraseStartAddress = EraseStartAddress
- - EraseStartAddress % MEMORY_SECTOR_SIZE;
- /* Erasing Sequence -------------------------------------------------- */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = 0xD8;
- sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_NONE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- while (EraseEndAddress >= EraseStartAddress) {
- sCommand.Address = (EraseStartAddress & 0x0FFFFFFF);
- if (QSPI_WriteEnable() != HAL_OK) {
- return HAL_ERROR;
- }
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- EraseStartAddress += MEMORY_SECTOR_SIZE;
- if (QSPI_AutoPollingMemReady(W25Q128JV_SECTOR_ERASE_MAX_TIME) != HAL_OK) {
- return HAL_ERROR;
- }
- }
- return HAL_OK;
- }
- uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t address,uint32_t buffer_size) {
- QSPI_CommandTypeDef sCommand;
- uint32_t end_addr, current_size, current_addr;
- /* Calculation of the size between the write address and the end of the page */
- current_addr = 0;
- //
- while (current_addr <= address) {
- current_addr += MEMORY_PAGE_SIZE;
- }
- current_size = current_addr - address;
- /* Check if the size of the data is less than the remaining place in the page */
- if (current_size > buffer_size) {
- current_size = buffer_size;
- }
- /* Initialize the adress variables */
- current_addr = address;
- end_addr = address + buffer_size;
- #if 1
- #if 1
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.DataMode = QSPI_DATA_4_LINES;
- sCommand.NbData = buffer_size;
- sCommand.Address = address;
- sCommand.DummyCycles = 0;
- #else
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.DataMode = QSPI_DATA_4_LINES;
- sCommand.NbData = buffer_size;
- sCommand.Address = address;
- sCommand.DummyCycles = 0;
- #endif
- #else
- /* 初始化程序命令 */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = PAGE_PROG;
- sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 0;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- #endif
- /* Perform the write page by page */
- do {
- sCommand.Address = current_addr;
- sCommand.NbData = current_size;
- if (current_size == 0) {
- return HAL_OK;
- }
- /* Enable write operations */
- if (QSPI_WriteEnable() != HAL_OK) {
- return HAL_ERROR;
- }
- /* Configure the command */
- if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- /* Transmission of the data */
- if (HAL_QSPI_Transmit(&hqspi, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- /* Configure automatic polling mode to wait for end of program */
- if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) {
- return HAL_ERROR;
- }
- /* Update the address and size variables for next page programming */
- current_addr += current_size;
- buffer += current_size;
- current_size =
- ((current_addr + MEMORY_PAGE_SIZE) > end_addr) ?
- (end_addr - current_addr) : MEMORY_PAGE_SIZE;
- } while (current_addr <= end_addr);
- return HAL_OK;
- }
- uint8_t CSP_QSPI_EnableMemoryMappedMode(void) {
- QSPI_CommandTypeDef sCommand;
- QSPI_MemoryMappedTypeDef sMemMappedCfg;
- /* Enable Memory-Mapped mode-------------------------------------------------- */
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.Instruction = 0x0B; // Fast Read
- sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; // 單線不需要 Mode/Alt byte
- sCommand.DataMode = QSPI_DATA_1_LINE;
- sCommand.DummyCycles = 8; // 0x0B 規格書要求 8 dummy
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.Address = 0;
- sCommand.NbData = 0; // memory-mapped 忽略
- sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
- sMemMappedCfg.TimeOutPeriod = 0;
- #if 0
- #if 1
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
- //sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- sCommand.AlternateBytes = 0xFF;
- sCommand.AlternateBytesSize = 1;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
- sCommand.DataMode = QSPI_DATA_4_LINES;
- sCommand.NbData = 0;
- sCommand.Address = 0;
- sCommand.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
- sCommand.DummyCycles = 4;
- sMemMappedCfg.TimeOutPeriod = 0;
- sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
- #else
- sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
- sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
- sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
- sCommand.AlternateBytes = 0xFF;
- sCommand.AlternateBytesSize = 1;
- //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- sCommand.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD;
- sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
- sCommand.DataMode = QSPI_DATA_4_LINES;
- sCommand.NbData = 0;
- sCommand.Address = 0;
- sCommand.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
- sCommand.DummyCycles = 4;
- sMemMappedCfg.TimeOutPeriod = 0;
- sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
- #endif
- #endif
- if (HAL_QSPI_MemoryMapped(&hqspi, &sCommand, &sMemMappedCfg) != HAL_OK) {
- return HAL_ERROR;
- }
- HAL_Delay(100);
- return HAL_OK;
- }
- uint8_t QSPI_ResetChip() {
- QSPI_CommandTypeDef s_command;
- uint32_t temp = 0;
- /* 初始化復位使能命令 */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = RESET_ENABLE_CMD;
- s_command.AddressMode = QSPI_ADDRESS_NONE;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_NONE;
- s_command.DummyCycles = 0;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- /* 發送命令 */
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- /* 發送復位存儲器命令 */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = RESET_MEMORY_CMD;
- s_command.AddressMode = QSPI_ADDRESS_NONE;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_NONE;
- s_command.DummyCycles = 0;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- for (temp = 0; temp < 500000; temp++) {
- __NOP();
- }
- #if 0
- s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES;
- s_command.Instruction = RESET_ENABLE_CMD;
- /* 發送命令 */
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- W25Qx_QSPI_Delay(1);
- /* 配置自動輪詢模式等待存儲器就緒 */
- if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
- {
- return HAL_ERROR;
- }
- #endif
- return HAL_OK;
- }
- uint8_t CSP_QSPI_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) {
- QSPI_CommandTypeDef s_command;
- if(Size == 0)
- {
- printf("BSP_QSPI_Read Size = 0");
- return HAL_ERROR;
- }
- #if 1
- /* 初始化讀命令 */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = 0x03;
- s_command.AddressMode = QSPI_ADDRESS_1_LINE;
- s_command.AddressSize = QSPI_ADDRESS_24_BITS;
- s_command.Address = ReadAddr;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_1_LINE;
- s_command.DummyCycles = 0;
- s_command.NbData = Size;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- /* 配置命令 */
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- /* 接收數據 */
- if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- return HAL_ERROR;
- }
- #else
- /* Initialize the read command */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
- s_command.AddressMode = QSPI_ADDRESS_4_LINES;
- s_command.AddressSize = QSPI_ADDRESS_24_BITS;
- s_command.Address = ReadAddr;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_4_LINES;
- s_command.DummyCycles = 6U;
- s_command.NbData = Size;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- /* Configure the command */
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- /* Set S# timing for Read command */
- MODIFY_REG(hqspi.Instance->DCR, QUADSPI_DCR_CSHT,
- QSPI_CS_HIGH_TIME_5_CYCLE);
- /* Reception of the data */
- if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
- != HAL_OK) {
- return HAL_ERROR;
- }
- /* Restore S# timing for nonRead commands */
- MODIFY_REG(hqspi.Instance->DCR, QUADSPI_DCR_CSHT,
- QSPI_CS_HIGH_TIME_6_CYCLE);
- #endif
- return HAL_OK;
- }
- uint32_t QSPI_FLASH_ReadDeviceID(void)
- {
- QSPI_CommandTypeDef s_command;
- uint32_t Temp = 0;
- uint8_t pData[3];
- /*##-2-讀取設備ID測試 ###########################################*/
- /* 讀取制造/設備 ID */
- s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
- s_command.Instruction = 0x90;
- s_command.AddressMode = QSPI_ADDRESS_1_LINE;
- s_command.AddressSize = QSPI_ADDRESS_24_BITS;
- s_command.Address = 0x000000;
- s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
- s_command.DataMode = QSPI_DATA_1_LINE;
- s_command.DummyCycles = 0;
- s_command.NbData = 2;
- s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
- //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
- s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
- if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- printf("something wrong ....\r\n");
- return 0;
- }
- if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
- {
- printf("something wrong ....\r\n");
- return 0;
- }
- Temp = pData[1] |( pData[0]<<8 ) ;
- return Temp;
- }
- PUTCHAR_PROTOTYPE
- {
- /* Place your implementation of fputc here */
- /* e.g. write a character to the USART1 and Loop until the end of transmission */
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
- /* USER CODE END 1 */
復制代碼 參考 github/WellinZHANG/External_Loader
|
-
-
QSPI_MemoryMapped.7z
2025-9-10 02:14 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
983.25 KB, 下載次數: 0, 下載積分: 黑幣 -5
source code
評分
-
查看全部評分
|