STM32H7B0 HAL OSPI配置的一次失败原因分享

博主在使用OSPI1驱动W25Q128时遇到调试问题,通过发现并修正CUBEMX 6.4 HAL库中关于DCR1配置的错误,成功解决了硬件初始化问题。关键在于识别MemoryType、DeviceSize等配置的变更。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 OSPI1 驱动W25Q128,但是始终无法调试成果,最后发现是HAL 库的问题

我使用的HAL库是CUBEMX自动生成的,CUBEMX版本是6.4

HAL库在这个函数中存在错误:
HAL_StatusTypeDef HAL_OSPI_Init (OSPI_HandleTypeDef *hospi)

      MODIFY_REG(hospi->Instance->DCR1,
                 (OCTOSPI_DCR1_MTYP | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_CKCSHT |
                  OCTOSPI_DCR1_FRCK | OCTOSPI_DCR1_CKMODE),
                 (hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) |
                  ((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) |
                  (hospi->Init.ClkChipSelectHighTime << OCTOSPI_DCR1_CKCSHT_Pos) | hospi->Init.ClockMode));

替换成

      /* Configure memory type, device size, chip select high time, clocked chip select high time, delay block bypass, free running clock, clock mode */
      MODIFY_REG(hospi->Instance->DCR1,
                 (OCTOSPI_DCR1_MTYP   | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_CKCSHT |
                  OCTOSPI_DCR1_DLYBYP | OCTOSPI_DCR1_FRCK    | OCTOSPI_DCR1_CKMODE),
                 (hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) |
                  ((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) |
                  (hospi->Init.ClkChipSelectHighTime << OCTOSPI_DCR1_CKCSHT_Pos) |
                  hospi->Init.DelayBlockBypass | hospi->Init.ClockMode));

问题就解决了。

### STM32 OCTOSPI 接口下载操作指南 对于STM32系列微控制器而言,利用OCTOSPI接口进行程序下载是一种高效的方法。此方法允许开发者将固件直接烧录至外部存储器中,并可通过特定配置使STM32从该外置闪存启动。 #### 配备必要的工具与资源 为了实现这一目标,需准备如下几项: - **硬件设备**:具备OCTOSPI接口的STM32板卡;连接PC端用于编程调试的USB转串口模块或其他兼容方式。 - **软件平台**:安装好STM32CubeMX来初始化项目设置并生成初始代码框架[^1]。 - **驱动库文件**:确保包含了对所选QSPI Flash的支持(例如W25Q256JV),这些通常由供应商提供或可从官方文档获取[^3]。 #### 编程流程概述 当一切就绪之后,则按照下面的方式来进行具体的操作: 编写应用程序时要考虑到最终会部署在外设Flash上的情况,在main函数之前定义一个特殊的向量表地址指向外部内存区域。这一步骤至关重要因为只有这样才能让CPU知道应该在哪里查找中断服务例程(ISR)入口点。 ```c #define VECT_TAB_OFFSET 0x8000 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */ /** * @brief Main program block */ int main(void) { /* Reset of all peripherals, Initializes the Systick timer and sets up SystemCoreClock variable */ HAL_Init(); /* Configure the system clock to achieve required frequency */ SystemClock_Config(); // ...其余初始化工作... } ``` 接着就是完成对外部Flash的具体读写控制逻辑实现了。这里以常见的擦除、编程为例展示部分核心代码片段: ```c /* Erase one sector (4KB) at specified address */ static uint8_t QSPI_Erase_Sector(uint32_t SectorAddress) { QSPI_CommandTypeDef s_command; /* Initialize the erase command */ s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; s_command.AddressSize = QSPI_ADDRESS_24_BITS; s_command.DummyCycles = 0; /* Send "Sector Erase" instruction followed by target location info */ s_command.Instruction = SECTOR_ERASE_CMD; s_command.Address = SectorAddress; if(HAL_QSPI_Command(&hqspi,&s_command,QSPI_TIMEOUT_DEFAULT_VALUE)!=HAL_OK){ return ERROR; } while(__HAL_QSPI_GET_FLAG(&hqspi,QSPI_FLAG_BUSY)){ ; } return SUCCESS; } /* Write data into external flash memory starting from given position */ static void QSPI_Write_Data(uint8_t* pData,uint32_t WriteAddr,uint16_t Size) { QSPI_CommandTypeDef s_command; /* Set write enable latch with WREN command */ s_command.Instruction=WRITE_ENABLE_CMD; ... } ``` 值得注意的是,上述`SECTOR_ERASE_CMD` 和 `WRITE_ENABLE_CMD` 定义应参照具体的QSPI Flash器件数据手册中的命令集说明[^4]。 最后,借助于STM32CubeProgrammer 或者其他第三方工具加载编译好的二进制映像到指定位置即可完成整个过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值