找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 928|回复: 0
收起左侧

制作出给stm32wb55烧外部nor flash(w25q32jv)的stldr档

[复制链接]
ID:1160110 发表于 2025-9-9 22:02 | 显示全部楼层 |阅读模式
使用 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 ,就可以识别后做烧录
qspi_borad.jpg qspi_programmer_write.jpg qspi_programmer_read.jpg stldr.png

  1. #include "main.h"
  2. #include "stm32wbxx_hal.h"
  3. #include "stm32wbxx_hal_qspi.h"
  4. /* USER CODE BEGIN 0 */
  5. static uint8_t QSPI_WriteEnable(void);
  6. static uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout);
  7. static uint8_t QSPI_Configuration(void);
  8. static uint8_t QSPI_ResetChip(void);
  9. static HAL_StatusTypeDef QSPI_EnableQuadIfNeeded(void);
  10. #define HAL_QPSI_TIMEOUT_DEFAULT_VALUE HAL_QSPI_TIMEOUT_DEFAULT_VALUE
  11. #define HAL_QSPI_TIMEOUT_DEFAULT_VALUE 5000U
  12. #if defined(__ICCARM__)
  13. /* New definition from EWARM V9, compatible with EWARM8 */
  14. int iar_fputc(int ch);
  15. #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
  16. #elif defined (__CC_ARM) || defined(__ARMCC_VERSION)
  17. /* ARM Compiler 5/6 */
  18. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  19. #elif defined(__GNUC__)
  20. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  21. #endif /* __ICCARM__ */
  22. /* USER CODE END 0 */
  23. QSPI_HandleTypeDef hqspi;
  24. UART_HandleTypeDef huart1;

  25. /* USER CODE BEGIN 1 */
  26. void MX_QUADSPI_Init(void)
  27. {

  28.   /* USER CODE BEGIN QUADSPI_Init 0 */

  29.   /* USER CODE END QUADSPI_Init 0 */

  30.   /* USER CODE BEGIN QUADSPI_Init 1 */

  31.   /* USER CODE END QUADSPI_Init 1 */
  32.   /* QUADSPI parameter configuration*/
  33.   hqspi.Instance = QUADSPI;
  34.   hqspi.Init.ClockPrescaler = 2;
  35.   //hqspi.Init.ClockPrescaler = 2;
  36.   //hqspi.Init.FifoThreshold = 4;
  37.   hqspi.Init.FifoThreshold = 4;
  38.   hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
  39.   hqspi.Init.FlashSize = 21;
  40.   //hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
  41.   hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
  42.   hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  43.   if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  44.   {
  45.     Error_Handler();
  46.   }
  47.   /* USER CODE BEGIN QUADSPI_Init 2 */

  48.   /* USER CODE END QUADSPI_Init 2 */

  49. }
  50. static void W25Qx_QSPI_Delay(uint32_t ms)
  51. {
  52.         HAL_Delay(ms);
  53. }
  54. /* QUADSPI init function */
  55. uint8_t CSP_QUADSPI_Init(void) {
  56.         //prepare QSPI peripheral for ST-Link Utility operations
  57.         if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) {
  58.                 return HAL_ERROR;
  59.         }

  60.         MX_QUADSPI_Init();

  61.         if (QSPI_ResetChip() != HAL_OK) {
  62.                 return HAL_ERROR;
  63.         }

  64.         HAL_Delay(1);

  65.         if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
  66.                 return HAL_ERROR;
  67.         }

  68.         if (QSPI_WriteEnable() != HAL_OK) {

  69.                 return HAL_ERROR;
  70.         }
  71. #if 0
  72.         QSPI_CommandTypeDef s_command;
  73.         uint8_t value = W25Q256JV_FSR_QE;

  74.         s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  75.         s_command.Instruction = WRITE_STATUS_REG2_CMD;
  76.         s_command.AddressMode = QSPI_ADDRESS_NONE;
  77.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  78.         s_command.DataMode = QSPI_DATA_1_LINE;
  79.         s_command.DummyCycles = 0;
  80.         s_command.NbData = 1;
  81.         s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
  82.         //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  83.         s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;


  84.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  85.         {
  86.                 return HAL_ERROR;
  87.         }
  88.                         /* 传输数据 */
  89.         if (HAL_QSPI_Transmit(&hqspi, &value, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  90.         {
  91.                 return HAL_ERROR;
  92.         }
  93. #endif

  94. #if 0
  95.           s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;                // 指令QSPI单线传输
  96.           s_command.Instruction       = ENTER_QPI_MODE_CMD;                                        // 指令,0x38使能QPI模式
  97.           s_command.AddressMode       = QSPI_ADDRESS_NONE;                                // 地址跳过
  98.           s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;                // 交替字节模式跳过
  99.           s_command.DummyCycles       = 0;                                                                // 空指令周期数
  100.           s_command.DataMode          = QSPI_DATA_NONE;                                        // 数据模式跳过
  101.           s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;                        // 禁止DDR模式
  102.           //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;                // 禁止DDR模式数据延时
  103.           s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;                  // 在每个事务中发送指令

  104.           /* Send the command */
  105.           if (HAL_QSPI_Command(&hqspi, &s_command, 1000) != HAL_OK)
  106.                 {
  107.                         return HAL_ERROR;
  108.                 }

  109. #endif
  110. #if 0
  111.         if (QSPI_AutoPollingMemReady(W25Q128JV_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK)
  112.         {
  113.                                 return HAL_ERROR;
  114.         }
  115. #endif
  116.         printf("CSP_QUADSPI_Init Done1\n");
  117. #if 1
  118.         if (QSPI_Configuration() != HAL_OK) {
  119.                 return HAL_ERROR;
  120.         }
  121. #endif
  122.         QSPI_EnableQuadIfNeeded();
  123.         HAL_Delay(100);
  124.         printf("CSP_QUADSPI_Init Done2\n");
  125.         return HAL_OK;
  126. }


  127. uint8_t CSP_QSPI_Erase_Chip(void) {
  128.         QSPI_CommandTypeDef sCommand;

  129.         if (QSPI_WriteEnable() != HAL_OK) {
  130.                 return HAL_ERROR;
  131.         }

  132.         /* Erasing Sequence --------------------------------- */
  133.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  134.         sCommand.Instruction = CHIP_ERASE_CMD;
  135.         sCommand.AddressMode = QSPI_ADDRESS_NONE;
  136.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  137.         sCommand.DataMode = QSPI_DATA_NONE;
  138.         sCommand.DummyCycles = 0;
  139.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  140.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  141.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;

  142.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_MAX_DELAY) != HAL_OK) {
  143.                 return HAL_ERROR;
  144.         }

  145.         if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) {
  146.                 return HAL_ERROR;
  147.         }

  148.         return HAL_OK;
  149. }

  150. uint8_t QSPI_AutoPollingMemReady(uint32_t Timeout) {

  151.         QSPI_CommandTypeDef     s_command;
  152.         QSPI_AutoPollingTypeDef s_config;
  153.         /* 配置自动轮询模式等待存储器准备就绪 */
  154.         s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  155.         s_command.Instruction       = READ_STATUS_REG1_CMD;
  156.         s_command.AddressMode       = QSPI_ADDRESS_NONE;
  157.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  158.         s_command.DataMode          = QSPI_DATA_1_LINE;
  159.         s_command.DummyCycles       = 0;
  160.         s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
  161.         //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  162.         s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

  163.         s_config.Match           = 0x00;
  164.         s_config.Mask            = W25Q256JV_FSR_BUSY;
  165.         s_config.MatchMode       = QSPI_MATCH_MODE_AND;
  166.         s_config.StatusBytesSize = 1;
  167.         s_config.Interval        = 0x10;
  168.         s_config.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;

  169.         if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, HAL_MAX_DELAY) != HAL_OK)
  170.         {
  171.                 return HAL_ERROR;
  172.         }

  173.         return HAL_OK;
  174. }

  175. static uint8_t QSPI_WriteEnable(void) {
  176.         QSPI_CommandTypeDef     s_command;
  177.         QSPI_AutoPollingTypeDef s_config;
  178.         /* 启用写操作 */
  179.         s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  180.         s_command.Instruction       = WRITE_ENABLE_CMD;
  181.         s_command.AddressMode       = QSPI_ADDRESS_NONE;
  182.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  183.         s_command.DataMode          = QSPI_DATA_NONE;
  184.         s_command.DummyCycles       = 0;
  185.         s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
  186.         //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  187.         s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
  188.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  189.         {
  190.                 return HAL_ERROR;
  191.         }

  192.         /* 配置自动轮询模式等待写启用 */
  193.         s_config.Match           = W25Q256JV_FSR_WREN;
  194.         s_config.Mask            = W25Q256JV_FSR_WREN;
  195.         s_config.MatchMode       = QSPI_MATCH_MODE_AND;
  196.         s_config.StatusBytesSize = 1;
  197.         s_config.Interval        = 0x10;
  198.         s_config.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;

  199.         s_command.Instruction    = READ_STATUS_REG1_CMD;
  200.         s_command.DataMode       = QSPI_DATA_1_LINE;
  201.         s_command.NbData         = 1;

  202.         if (HAL_QSPI_AutoPolling(&hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  203.         {
  204.                 return HAL_ERROR;
  205.         }

  206.         return HAL_OK;
  207. }
  208. /*Enable quad mode and set dummy cycles count*/
  209. static HAL_StatusTypeDef QSPI_EnableQuadIfNeeded(void)
  210. {
  211.     HAL_StatusTypeDef ret;
  212.     QSPI_CommandTypeDef sCommand = {0};
  213.     uint8_t sr1 = 0, sr2 = 0;

  214.     /* 1) 讀 SR1 */
  215.     sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  216.     sCommand.Instruction     = READ_STATUS_REG_CMD;
  217.     sCommand.AddressMode     = QSPI_ADDRESS_NONE;
  218.     sCommand.DataMode        = QSPI_DATA_1_LINE;
  219.     sCommand.NbData          = 1;
  220.     sCommand.SIOOMode        = QSPI_SIOO_INST_EVERY_CMD;
  221.     if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
  222.     if (HAL_QSPI_Receive(&hqspi, &sr1, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;

  223.     /* 2) 讀 SR2 */
  224.     sCommand.Instruction = READ_STATUS_REG2_CMD;
  225.     if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
  226.     if (HAL_QSPI_Receive(&hqspi, &sr2, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;

  227.     /* 若 QE 已經為 1,直接回傳 OK */
  228.     if (sr2 & QE_BIT) return HAL_OK;

  229.     /* 3) WREN */
  230.     ret = QSPI_WriteEnable();
  231.     if (ret != HAL_OK) return ret;

  232.     /* 4) 寫 SR1 + SR2 (把 QE bit 設為 1) */
  233.     uint8_t sr_buf[2];
  234.     sr_buf[0] = sr1;
  235.     sr_buf[1] = sr2 | QE_BIT;

  236.     sCommand.Instruction = WRITE_STATUS_REG1_CMD; /* 0x01: write SR1 + SR2 */
  237.     sCommand.DataMode    = QSPI_DATA_1_LINE;
  238.     sCommand.NbData      = 2;
  239.     sCommand.AddressMode = QSPI_ADDRESS_NONE;
  240.     if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
  241.     if (HAL_QSPI_Transmit(&hqspi, sr_buf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;

  242.     /* 5) poll WIP until finished */
  243.     if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) return HAL_ERROR;

  244.     /* 6) read back SR2 to ensure QE is set */
  245.     sCommand.Instruction = READ_STATUS_REG2_CMD;
  246.     sCommand.DataMode    = QSPI_DATA_1_LINE;
  247.     sCommand.NbData      = 1;
  248.     if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;
  249.     if (HAL_QSPI_Receive(&hqspi, &sr2, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) return HAL_ERROR;

  250.     if (sr2 & QE_BIT) return HAL_OK;
  251.     return HAL_ERROR;
  252. }

  253. uint8_t QSPI_Configuration(void) {
  254.         QSPI_CommandTypeDef sCommand = { 0 };
  255.         uint8_t reg;
  256.         HAL_StatusTypeDef ret;

  257.         /* Read Volatile Configuration register 2 --------------------------- */
  258.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  259.         sCommand.Instruction = READ_STATUS_REG2_CMD;
  260.         sCommand.AddressMode = QSPI_ADDRESS_NONE;
  261.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  262.         sCommand.DataMode = QSPI_DATA_1_LINE;
  263.         sCommand.DummyCycles = 0;
  264.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  265.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  266.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  267.         sCommand.NbData = 1;

  268.         if ((ret = HAL_QSPI_Command(&hqspi, &sCommand,
  269.                         HAL_QPSI_TIMEOUT_DEFAULT_VALUE)) != HAL_OK) {
  270.                 return ret;
  271.         }

  272.         if ((ret = HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE))
  273.                         != HAL_OK) {
  274.                 return ret;
  275.         }

  276.         /* Enable Volatile Write operations ---------------------------------------- */
  277.         sCommand.DataMode = QSPI_DATA_NONE;
  278.         sCommand.Instruction = VOLATILE_SR_WRITE_ENABLE;

  279.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  280.                         != HAL_OK) {
  281.                 return ret;
  282.         }

  283.         /* Write Volatile Configuration register 2 (QE = 1) -- */
  284.         sCommand.DataMode = QSPI_DATA_1_LINE;
  285.         sCommand.Instruction = WRITE_STATUS_REG2_CMD;
  286.         reg |= 2; // QE bit

  287.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  288.                         != HAL_OK) {
  289.                 return ret;
  290.         }

  291.         if (HAL_QSPI_Transmit(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  292.                         != HAL_OK) {
  293.                 return ret;
  294.         }

  295.         /* Read Volatile Configuration register 3 --------------------------- */
  296.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  297.         sCommand.Instruction = READ_STATUS_REG3_CMD;
  298.         sCommand.AddressMode = QSPI_ADDRESS_NONE;
  299.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  300.         sCommand.DataMode = QSPI_DATA_1_LINE;
  301.         sCommand.DummyCycles = 0;
  302.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  303.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  304.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  305.         sCommand.NbData = 1;

  306.         if ((ret = HAL_QSPI_Command(&hqspi, &sCommand,
  307.                         HAL_QPSI_TIMEOUT_DEFAULT_VALUE)) != HAL_OK) {
  308.                 return ret;
  309.         }

  310.         if ((ret = HAL_QSPI_Receive(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE))
  311.                         != HAL_OK) {
  312.                 return ret;
  313.         }

  314.         /* Write Volatile Configuration register 2 (DRV1:2 = 00) -- */
  315.         sCommand.Instruction = WRITE_STATUS_REG3_CMD;
  316.         reg &= 0x9f; // DRV1:2 bit

  317.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  318.                         != HAL_OK) {
  319.                 return ret;
  320.         }

  321.         if (HAL_QSPI_Transmit(&hqspi, ®, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  322.                         != HAL_OK) {
  323.                 return ret;
  324.         }

  325.         return HAL_OK;
  326. #if 0
  327.         QSPI_CommandTypeDef sCommand;
  328.           uint8_t reg;


  329.         /*enter 4 byte address*/
  330.                 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  331.                 sCommand.Instruction = ENTER_4_BYTE_ADD_CMD;
  332.                 sCommand.AddressMode = QSPI_ADDRESS_NONE;
  333.                 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  334.                 sCommand.DataMode = QSPI_DATA_NONE;
  335.                 sCommand.DummyCycles = 0;
  336.                 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  337.                 //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  338.                 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  339.                 sCommand.NbData = 0;

  340.                 if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  341.                                 != HAL_OK) {
  342.                         return HAL_ERROR;
  343.                 }




  344.         /*read configuration register*/
  345.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  346.         sCommand.Instruction = READ_CONFIGURATION_REG_CMD;
  347.         sCommand.AddressMode = QSPI_ADDRESS_NONE;
  348.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  349.         sCommand.DataMode = QSPI_DATA_1_LINE;
  350.         sCommand.DummyCycles = 0;
  351.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  352.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  353.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  354.         sCommand.NbData = 1;

  355.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  356.                         != HAL_OK) {
  357.                 return HAL_ERROR;
  358.         }


  359.         if (HAL_QSPI_Receive(&hqspi, ®,
  360.         HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
  361.                 return HAL_ERROR;
  362.         }



  363.         if (QSPI_WriteEnable() != HAL_OK) {

  364.                         return HAL_ERROR;
  365.                 }


  366.         /*set dummy cycles*/
  367.         MODIFY_REG(reg, 0xF0, (DUMMY_CLOCK_CYCLES_READ_QUAD << POSITION_VAL(0xF0)));

  368.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  369.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  370.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  371.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  372.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  373.         sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
  374.         sCommand.AddressMode = QSPI_ADDRESS_NONE;
  375.         sCommand.DataMode = QSPI_DATA_1_LINE;
  376.         sCommand.DummyCycles = 0;
  377.         sCommand.NbData = 1;

  378.         if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  379.                         != HAL_OK) {
  380.                 return HAL_ERROR;
  381.         }

  382.         if (HAL_QSPI_Transmit(&hqspi, ®,
  383.         HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
  384.                 Error_Handler();
  385.                 return HAL_ERROR;
  386.         }
  387.         return HAL_OK;
  388. #endif
  389. }


  390. uint8_t CSP_QSPI_EraseSector(uint32_t EraseStartAddress, uint32_t EraseEndAddress) {

  391.         QSPI_CommandTypeDef sCommand;

  392.         EraseStartAddress = EraseStartAddress
  393.                         - EraseStartAddress % MEMORY_SECTOR_SIZE;

  394.         /* Erasing Sequence -------------------------------------------------- */
  395.         sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  396.         sCommand.Instruction       = 0xD8;
  397.         sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
  398.         sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
  399.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  400.         sCommand.DataMode          = QSPI_DATA_NONE;
  401.         sCommand.DummyCycles       = 0;
  402.         sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
  403.     //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  404.         sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

  405.         while (EraseEndAddress >= EraseStartAddress) {
  406.                 sCommand.Address = (EraseStartAddress & 0x0FFFFFFF);

  407.                 if (QSPI_WriteEnable() != HAL_OK) {
  408.                         return HAL_ERROR;
  409.                 }

  410.                 if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  411.                                 != HAL_OK) {
  412.                         return HAL_ERROR;
  413.                 }
  414.                 EraseStartAddress += MEMORY_SECTOR_SIZE;

  415.                 if (QSPI_AutoPollingMemReady(W25Q128JV_SECTOR_ERASE_MAX_TIME) != HAL_OK) {
  416.                         return HAL_ERROR;
  417.                 }
  418.         }

  419.         return HAL_OK;
  420. }

  421. uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t address,uint32_t buffer_size) {

  422.         QSPI_CommandTypeDef sCommand;
  423.         uint32_t end_addr, current_size, current_addr;

  424.         /* Calculation of the size between the write address and the end of the page */
  425.         current_addr = 0;

  426.         //
  427.         while (current_addr <= address) {
  428.                 current_addr += MEMORY_PAGE_SIZE;
  429.         }
  430.         current_size = current_addr - address;

  431.         /* Check if the size of the data is less than the remaining place in the page */
  432.         if (current_size > buffer_size) {
  433.                 current_size = buffer_size;
  434.         }

  435.         /* Initialize the adress variables */
  436.         current_addr = address;
  437.         end_addr = address + buffer_size;

  438. #if 1
  439. #if 1
  440.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  441.         sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
  442.         sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
  443.         sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
  444.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  445.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  446.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  447.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  448.         sCommand.DataMode = QSPI_DATA_4_LINES;
  449.         sCommand.NbData = buffer_size;
  450.         sCommand.Address = address;
  451.         sCommand.DummyCycles = 0;
  452. #else
  453.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  454.         sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
  455.         sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
  456.         sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
  457.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  458.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  459.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  460.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  461.         sCommand.DataMode = QSPI_DATA_4_LINES;
  462.         sCommand.NbData = buffer_size;
  463.         sCommand.Address = address;
  464.         sCommand.DummyCycles = 0;
  465. #endif
  466. #else
  467.         /* 初始化程序命令 */
  468.         sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  469.         sCommand.Instruction       = PAGE_PROG;
  470.         sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;
  471.         sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
  472.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  473.         sCommand.DataMode          = QSPI_DATA_1_LINE;
  474.         sCommand.DummyCycles       = 0;
  475.         sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;
  476.         //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  477.         sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
  478. #endif
  479.         /* Perform the write page by page */
  480.         do {
  481.                 sCommand.Address = current_addr;
  482.                 sCommand.NbData = current_size;

  483.                 if (current_size == 0) {
  484.                         return HAL_OK;
  485.                 }

  486.                 /* Enable write operations */
  487.                 if (QSPI_WriteEnable() != HAL_OK) {
  488.                         return HAL_ERROR;
  489.                 }

  490.                 /* Configure the command */
  491.                 if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  492.                                 != HAL_OK) {

  493.                         return HAL_ERROR;
  494.                 }

  495.                 /* Transmission of the data */
  496.                 if (HAL_QSPI_Transmit(&hqspi, buffer, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  497.                                 != HAL_OK) {

  498.                         return HAL_ERROR;
  499.                 }

  500.                 /* Configure automatic polling mode to wait for end of program */
  501.                 if (QSPI_AutoPollingMemReady(HAL_MAX_DELAY) != HAL_OK) {
  502.                         return HAL_ERROR;
  503.                 }

  504.                 /* Update the address and size variables for next page programming */
  505.                 current_addr += current_size;
  506.                 buffer += current_size;
  507.                 current_size =
  508.                                 ((current_addr + MEMORY_PAGE_SIZE) > end_addr) ?
  509.                                                 (end_addr - current_addr) : MEMORY_PAGE_SIZE;
  510.         } while (current_addr <= end_addr);

  511.         return HAL_OK;

  512. }


  513. uint8_t CSP_QSPI_EnableMemoryMappedMode(void) {

  514.         QSPI_CommandTypeDef sCommand;
  515.         QSPI_MemoryMappedTypeDef sMemMappedCfg;

  516.         /* Enable Memory-Mapped mode-------------------------------------------------- */
  517.         sCommand.InstructionMode    = QSPI_INSTRUCTION_1_LINE;
  518.         sCommand.Instruction        = 0x0B;                      // Fast Read
  519.         sCommand.AddressMode        = QSPI_ADDRESS_1_LINE;
  520.         sCommand.AddressSize        = QSPI_ADDRESS_24_BITS;
  521.         sCommand.AlternateByteMode  = QSPI_ALTERNATE_BYTES_NONE; // 單線不需要 Mode/Alt byte
  522.         sCommand.DataMode           = QSPI_DATA_1_LINE;
  523.         sCommand.DummyCycles        = 8;                         // 0x0B 規格書要求 8 dummy
  524.         sCommand.DdrMode            = QSPI_DDR_MODE_DISABLE;
  525.         sCommand.SIOOMode           = QSPI_SIOO_INST_EVERY_CMD;
  526.         sCommand.Address            = 0;
  527.         sCommand.NbData             = 0;                         // memory-mapped 忽略

  528.         sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
  529.         sMemMappedCfg.TimeOutPeriod     = 0;
  530. #if 0
  531. #if 1
  532.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  533.         sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
  534.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
  535.         //sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  536.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  537.         sCommand.AlternateBytes = 0xFF;
  538.         sCommand.AlternateBytesSize = 1;
  539.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  540.         sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  541.         sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
  542.         sCommand.DataMode = QSPI_DATA_4_LINES;
  543.         sCommand.NbData = 0;
  544.         sCommand.Address = 0;
  545.         sCommand.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
  546.         sCommand.DummyCycles = 4;
  547.         sMemMappedCfg.TimeOutPeriod  = 0;
  548.         sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
  549. #else
  550.         sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  551.         sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
  552.         sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_4_LINES;
  553.         sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
  554.         sCommand.AlternateBytes = 0xFF;
  555.         sCommand.AlternateBytesSize = 1;
  556.         //sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  557.         sCommand.SIOOMode = QSPI_SIOO_INST_ONLY_FIRST_CMD;
  558.         sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
  559.         sCommand.DataMode = QSPI_DATA_4_LINES;
  560.         sCommand.NbData = 0;
  561.         sCommand.Address = 0;
  562.         sCommand.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
  563.         sCommand.DummyCycles = 4;
  564.         sMemMappedCfg.TimeOutPeriod  = 0;
  565.         sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
  566. #endif
  567. #endif
  568.         if (HAL_QSPI_MemoryMapped(&hqspi, &sCommand, &sMemMappedCfg) != HAL_OK) {
  569.                 return HAL_ERROR;
  570.         }
  571.         HAL_Delay(100);
  572.         return HAL_OK;
  573. }

  574. uint8_t QSPI_ResetChip() {
  575.         QSPI_CommandTypeDef s_command;
  576.         uint32_t temp = 0;
  577.         /* 初始化复位使能命令 */
  578.         s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  579.         s_command.Instruction       = RESET_ENABLE_CMD;
  580.         s_command.AddressMode       = QSPI_ADDRESS_NONE;
  581.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  582.         s_command.DataMode          = QSPI_DATA_NONE;
  583.         s_command.DummyCycles       = 0;
  584.         s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
  585.         //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  586.         s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

  587.         /* 发送命令 */
  588.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  589.         {
  590.                 return HAL_ERROR;
  591.         }

  592.         /* 发送复位存储器命令 */
  593.         s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  594.         s_command.Instruction = RESET_MEMORY_CMD;
  595.         s_command.AddressMode = QSPI_ADDRESS_NONE;
  596.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  597.         s_command.DataMode = QSPI_DATA_NONE;
  598.         s_command.DummyCycles = 0;
  599.         s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
  600.         //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  601.         s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
  602.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  603.         {
  604.                 return HAL_ERROR;
  605.         }

  606.         for (temp = 0; temp < 500000; temp++) {
  607.                 __NOP();
  608.         }
  609. #if 0
  610.         s_command.InstructionMode = QSPI_INSTRUCTION_4_LINES;
  611.         s_command.Instruction = RESET_ENABLE_CMD;

  612.         /* 发送命令 */
  613.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  614.         {
  615.                 return HAL_ERROR;
  616.         }
  617.         W25Qx_QSPI_Delay(1);
  618.         /* 配置自动轮询模式等待存储器就绪 */
  619.         if (QSPI_AutoPollingMemReady(HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
  620.         {
  621.                 return HAL_ERROR;
  622.         }
  623. #endif
  624.         return HAL_OK;
  625. }
  626. uint8_t CSP_QSPI_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size) {
  627.         QSPI_CommandTypeDef s_command;
  628.           if(Size == 0)
  629.           {
  630.             printf("BSP_QSPI_Read Size = 0");
  631.             return HAL_ERROR;
  632.           }
  633. #if 1
  634.                 /* 初始化读命令 */
  635.                 s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  636.                 s_command.Instruction       = 0x03;
  637.                 s_command.AddressMode       = QSPI_ADDRESS_1_LINE;
  638.                 s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
  639.                 s_command.Address           = ReadAddr;
  640.                 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  641.                 s_command.DataMode          = QSPI_DATA_1_LINE;
  642.                 s_command.DummyCycles       = 0;
  643.                 s_command.NbData            = Size;
  644.                 s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
  645.                 //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  646.                 s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

  647.                 /* 配置命令 */
  648.                 if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  649.                 {
  650.                         return HAL_ERROR;
  651.                 }

  652.                 /* 接收数据 */
  653.                 if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  654.                 {
  655.                         return HAL_ERROR;
  656.                 }
  657. #else
  658.         /* Initialize the read command */
  659.         s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
  660.         s_command.Instruction = QUAD_IN_OUT_FAST_READ_CMD;
  661.         s_command.AddressMode = QSPI_ADDRESS_4_LINES;
  662.         s_command.AddressSize = QSPI_ADDRESS_24_BITS;
  663.         s_command.Address = ReadAddr;
  664.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  665.         s_command.DataMode = QSPI_DATA_4_LINES;
  666.         s_command.DummyCycles = 6U;
  667.         s_command.NbData = Size;
  668.         s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
  669.         //s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
  670.         s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;

  671.         /* Configure the command */
  672.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  673.                         != HAL_OK) {
  674.                 return HAL_ERROR;
  675.         }

  676.         /* Set S# timing for Read command */
  677.         MODIFY_REG(hqspi.Instance->DCR, QUADSPI_DCR_CSHT,
  678.                         QSPI_CS_HIGH_TIME_5_CYCLE);

  679.         /* Reception of the data */
  680.         if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
  681.                         != HAL_OK) {
  682.                 return HAL_ERROR;
  683.         }

  684.         /* Restore S# timing for nonRead commands */
  685.         MODIFY_REG(hqspi.Instance->DCR, QUADSPI_DCR_CSHT,
  686.                         QSPI_CS_HIGH_TIME_6_CYCLE);
  687. #endif
  688.         return HAL_OK;
  689. }
  690. uint32_t QSPI_FLASH_ReadDeviceID(void)
  691. {
  692.         QSPI_CommandTypeDef s_command;
  693.         uint32_t Temp = 0;
  694.         uint8_t pData[3];
  695.         /*##-2-读取设备ID测试    ###########################################*/
  696.         /* 读取制造/设备 ID */
  697.         s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
  698.         s_command.Instruction       = 0x90;
  699.         s_command.AddressMode       = QSPI_ADDRESS_1_LINE;
  700.         s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
  701.         s_command.Address           = 0x000000;
  702.         s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
  703.         s_command.DataMode          = QSPI_DATA_1_LINE;
  704.         s_command.DummyCycles       = 0;
  705.         s_command.NbData            = 2;
  706.         s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
  707.         //s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
  708.         s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

  709.         if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  710.         {
  711.                 printf("something wrong ....\r\n");
  712.     return 0;
  713.         }
  714.         if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  715.         {
  716.                 printf("something wrong ....\r\n");
  717.     return 0;
  718.         }

  719.         Temp = pData[1] |( pData[0]<<8 ) ;
  720.         return Temp;
  721. }
  722. PUTCHAR_PROTOTYPE
  723. {
  724.   /* Place your implementation of fputc here */
  725.   /* e.g. write a character to the USART1 and Loop until the end of transmission */
  726.   HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  727.   return ch;
  728. }
  729. /* USER CODE END 1 */
复制代码
参考 github/WellinZHANG/External_Loader

QSPI_MemoryMapped.7z

983.25 KB, 下载次数: 0, 下载积分: 黑币 -5

source code

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表