本帖最后由 qintian0303 于 2025-3-22 10:47 编辑
OSPI(Octal Serial Peripheral Interface)是一种基于传统SPI协议扩展的高速串行接口,通过8线并行数据传输显著提升通信速率,其核心特性包括支持双倍数据速率(DDR)模式、最高200MHz时钟频率,以及兼容标准SPI、双线SPI和四线SPI等多种工作模式。相较于传统SPI的单线或四线半双工传输,OSPI利用IO0至IO7八条数据线实现并行通信,单周期可传输8位数据,理论带宽可达传统SPI的八倍,这使得OSPI特别适用于大容量Flash存储器(如64MB MX25LM51245G)和需要高速数据存取的场景(如AI模型加载或GUI资源存储)。硬件连接方面,OSPI除时钟线(SCLK)和片选线(CS)外,需严格匹配八条数据线的PCB阻抗与走线长度以保障信号完整性,而传统SPI仅需四根基础信号线(SCK/MOSI/MISO/CS),硬件设计复杂度显著更低。协议层面,OSPI支持HyperBus等高级特性并内置ECC校验机制,而SPI主要用于低速传感器或EEPROM通信。这种性能差异使OSPI成为物联网设备和高性能嵌入式系统中扩展外部存储的首选方案。
本次的STM32L562E-DK上使用的大容量Flash芯片就是基于OSPI进行的,先看一下硬件:
本次的开发板板载的是一颗MX25LM51245GXDI0A,MX25LM51245GXDI0A是一款512Mbit(64MB)容量的Octal SPI Flash芯片,采用8线并行通信接口,支持单线、双线、四线及八线模式。其工作电压范围为1.7-2.0V,与STM32L562E-DK开发板的1.8V供电设计完全匹配。
我们使用STM32CubeMX进行OPSI的配置:
注意看一下引脚的配置是否和板卡匹配:
这么高速的传播速度当然要开启DMA和中断了。
接下来回到我们的工程里面进行MX25LM51245GXDI0A的驱动,STM32L5的固件包中提供了这款芯片的驱动:
我们移植过来进行一下具体驱动内容的查看,在使用过程中需要继续初始化OSPI的配置:
<article data-content="[{"type":"block","id":"Jj88-1742566111658","name":"code","data":{"wrap":false,"tokensPerLine":[],"language":"","theme":"default"},"nodes":[{"type":"block","id":"iKa3-1742566111657","name":"code-line","data":{},"nodes":[{"type":"text","id":"0Euo-1742566111656","leaves":[{"text":"OSPI_OctalModeCfg(&hospi1);\r","marks":[]}]}]},{"type":"block","id":"7ZEW-1742566123652","name":"code-line","data":{},"nodes":[{"type":"text","id":"i8Od-1742566123651","leaves":[{"text":"\r","marks":[]}]}]},{"type":"block","id":"Vfas-1742566123654","name":"code-line","data":{},"nodes":[{"type":"text","id":"tTG6-1742566123653","leaves":[{"text":" sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;\r","marks":[]}]}]},{"type":"block","id":"7Xpl-1742566123656","name":"code-line","data":{},"nodes":[{"type":"text","id":"Zvoi-1742566123655","leaves":[{"text":" sCommand.FlashId = HAL_OSPI_FLASH_ID_1;\r","marks":[]}]}]},{"type":"block","id":"vC1z-1742566123658","name":"code-line","data":{},"nodes":[{"type":"text","id":"EW3S-1742566123657","leaves":[{"text":" sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;\r","marks":[]}]}]},{"type":"block","id":"wkfn-1742566123660","name":"code-line","data":{},"nodes":[{"type":"text","id":"PJTI-1742566123659","leaves":[{"text":" sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;\r","marks":[]}]}]},{"type":"block","id":"EVDw-1742566123662","name":"code-line","data":{},"nodes":[{"type":"text","id":"xXIW-1742566123661","leaves":[{"text":" sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;\r","marks":[]}]}]},{"type":"block","id":"9GZR-1742566123664","name":"code-line","data":{},"nodes":[{"type":"text","id":"ckLL-1742566123663","leaves":[{"text":" sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;\r","marks":[]}]}]},{"type":"block","id":"G7Qn-1742566123666","name":"code-line","data":{},"nodes":[{"type":"text","id":"Bd7i-1742566123665","leaves":[{"text":" sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;\r","marks":[]}]}]},{"type":"block","id":"iiEq-1742566123668","name":"code-line","data":{},"nodes":[{"type":"text","id":"RzpE-1742566123667","leaves":[{"text":" sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;\r","marks":[]}]}]},{"type":"block","id":"wJzL-1742566123670","name":"code-line","data":{},"nodes":[{"type":"text","id":"e857-1742566123669","leaves":[{"text":" sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;\r","marks":[]}]}]},{"type":"block","id":"QQeu-1742566123672","name":"code-line","data":{},"nodes":[{"type":"text","id":"DpWo-1742566123671","leaves":[{"text":" sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;\r","marks":[]}]}]},{"type":"block","id":"S02R-1742566123674","name":"code-line","data":{},"nodes":[{"type":"text","id":"xyAt-1742566123673","leaves":[{"text":" sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;","marks":[]}]}]}],"state":{}}]"><div yne-bulb-block="code" data-theme="default" style="white-space-collapse: preserve;" data-language="">OSPI_OctalModeCfg(&hospi1);
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;</div></article>
主要的控制程序包括读字节、写字节、和块擦除等等如下:
擦除命令:
<article data-content="[{"type":"block","id":"ASnM-1742569915008","name":"code","data":{"wrap":false,"tokensPerLine":[],"language":"","theme":"default"},"nodes":[{"type":"block","id":"RPBA-1742569915007","name":"code-line","data":{},"nodes":[{"type":"text","id":"WGBq-1742569915006","leaves":[{"text":" /* Enable write operations ------------------------------------------- */\r","marks":[]}]}]},{"type":"block","id":"e183-1742569940258","name":"code-line","data":{},"nodes":[{"type":"text","id":"dqxp-1742569940257","leaves":[{"text":"OSPI_WriteEnable(&hospi1);\r","marks":[]}]}]},{"type":"block","id":"WyR7-1742569940260","name":"code-line","data":{},"nodes":[{"type":"text","id":"O2Jj-1742569940259","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"3PLX-1742569940262","name":"code-line","data":{},"nodes":[{"type":"text","id":"XF6O-1742569940261","leaves":[{"text":"/* Erasing Sequence -------------------------------------------------- */\r","marks":[]}]}]},{"type":"block","id":"NdZG-1742569940264","name":"code-line","data":{},"nodes":[{"type":"text","id":"CjOw-1742569940263","leaves":[{"text":"sCommand.Instruction = OCTAL_SECTOR_ERASE_CMD;\r","marks":[]}]}]},{"type":"block","id":"tH7S-1742569940266","name":"code-line","data":{},"nodes":[{"type":"text","id":"rO0n-1742569940265","leaves":[{"text":"sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;\r","marks":[]}]}]},{"type":"block","id":"q1JB-1742569940268","name":"code-line","data":{},"nodes":[{"type":"text","id":"6z8l-1742569940267","leaves":[{"text":"sCommand.Address = address;\r","marks":[]}]}]},{"type":"block","id":"Pwq2-1742569940270","name":"code-line","data":{},"nodes":[{"type":"text","id":"okGc-1742569940269","leaves":[{"text":"sCommand.DataMode = HAL_OSPI_DATA_NONE;\r","marks":[]}]}]},{"type":"block","id":"C5kz-1742569940272","name":"code-line","data":{},"nodes":[{"type":"text","id":"wFXD-1742569940271","leaves":[{"text":"sCommand.DummyCycles = 0;\r","marks":[]}]}]},{"type":"block","id":"C7GX-1742569940274","name":"code-line","data":{},"nodes":[{"type":"text","id":"CIVK-1742569940273","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"E41N-1742569940276","name":"code-line","data":{},"nodes":[{"type":"text","id":"eIh8-1742569940275","leaves":[{"text":"if (HAL_OSPI_Command_IT(&hospi1, &sCommand) != HAL_OK)\r","marks":[]}]}]},{"type":"block","id":"SL2e-1742569940278","name":"code-line","data":{},"nodes":[{"type":"text","id":"oekm-1742569940277","leaves":[{"text":"{\r","marks":[]}]}]},{"type":"block","id":"elwD-1742569940280","name":"code-line","data":{},"nodes":[{"type":"text","id":"p6Gp-1742569940279","leaves":[{"text":" Error_Handler();\r","marks":[]}]}]},{"type":"block","id":"gnti-1742569940282","name":"code-line","data":{},"nodes":[{"type":"text","id":"NvXV-1742569940281","leaves":[{"text":"}","marks":[]}]}]}],"state":{}}]"><div yne-bulb-block="code" data-theme="default" style="white-space-collapse: preserve;" data-language=""> /* Enable write operations ------------------------------------------- */
OSPI_WriteEnable(&hospi1);
/* Erasing Sequence -------------------------------------------------- */
sCommand.Instruction = OCTAL_SECTOR_ERASE_CMD;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.Address = address;
sCommand.DataMode = HAL_OSPI_DATA_NONE;
sCommand.DummyCycles = 0;
if (HAL_OSPI_Command_IT(&hospi1, &sCommand) != HAL_OK)
{
Error_Handler();
}</div></article>
写命令:
<article data-content="[{"type":"block","id":"JtjQ-1742569986663","name":"code","data":{"wrap":false,"tokensPerLine":[],"language":"","theme":"default"},"nodes":[{"type":"block","id":"QLCH-1742569986662","name":"code-line","data":{},"nodes":[{"type":"text","id":"jGGx-1742569986661","leaves":[{"text":" /* Configure automatic polling mode to wait for end of erase ------ */ \r","marks":[]}]}]},{"type":"block","id":"lk6N-1742569987970","name":"code-line","data":{},"nodes":[{"type":"text","id":"2GB7-1742569987969","leaves":[{"text":"OSPI_AutoPollingMemReady(&hospi1);\r","marks":[]}]}]},{"type":"block","id":"eCPZ-1742569987972","name":"code-line","data":{},"nodes":[{"type":"text","id":"tMKt-1742569987971","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"PvSn-1742569987974","name":"code-line","data":{},"nodes":[{"type":"text","id":"nvLY-1742569987973","leaves":[{"text":"/* Enable write operations ---------------------------------------- */\r","marks":[]}]}]},{"type":"block","id":"mFTo-1742569987976","name":"code-line","data":{},"nodes":[{"type":"text","id":"Ssht-1742569987975","leaves":[{"text":"OSPI_WriteEnable(&hospi1);\r","marks":[]}]}]},{"type":"block","id":"igEG-1742569987978","name":"code-line","data":{},"nodes":[{"type":"text","id":"tiWP-1742569987977","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"BdeJ-1742569987980","name":"code-line","data":{},"nodes":[{"type":"text","id":"zEfJ-1742569987979","leaves":[{"text":"/* Writing Sequence ----------------------------------------------- */\r","marks":[]}]}]},{"type":"block","id":"7Ecu-1742569987982","name":"code-line","data":{},"nodes":[{"type":"text","id":"D6EV-1742569987981","leaves":[{"text":"sCommand.Instruction = OCTAL_PAGE_PROG_CMD;\r","marks":[]}]}]},{"type":"block","id":"XkJw-1742569987984","name":"code-line","data":{},"nodes":[{"type":"text","id":"Ffid-1742569987983","leaves":[{"text":"sCommand.DataMode = HAL_OSPI_DATA_8_LINES;\r","marks":[]}]}]},{"type":"block","id":"eHxU-1742569987986","name":"code-line","data":{},"nodes":[{"type":"text","id":"EV2G-1742569987985","leaves":[{"text":"// sCommand.NbData = BUFFERSIZE;","marks":[]}]}]},{"type":"block","id":"FSri-1742570598733","name":"code-line","data":{},"nodes":[{"type":"text","id":"1rrH-1742570598731","leaves":[{"text":"sCommand.Address = address+tmp_flag*4-4;\r\r","marks":[]}]}]},{"type":"block","id":"gmwn-1742569987988","name":"code-line","data":{},"nodes":[{"type":"text","id":"nSAL-1742569987987","leaves":[{"text":"sCommand.NbData = 4;\r","marks":[]}]}]},{"type":"block","id":"Om6D-1742569987990","name":"code-line","data":{},"nodes":[{"type":"text","id":"aw5w-1742569987989","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"oZkl-1742569987992","name":"code-line","data":{},"nodes":[{"type":"text","id":"zImB-1742569987991","leaves":[{"text":"if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)\r","marks":[]}]}]},{"type":"block","id":"lavS-1742569987994","name":"code-line","data":{},"nodes":[{"type":"text","id":"Z2f6-1742569987993","leaves":[{"text":"{\r","marks":[]}]}]},{"type":"block","id":"SR9z-1742569987996","name":"code-line","data":{},"nodes":[{"type":"text","id":"NJVF-1742569987995","leaves":[{"text":"Error_Handler();\r","marks":[]}]}]},{"type":"block","id":"7jvV-1742569987998","name":"code-line","data":{},"nodes":[{"type":"text","id":"fD4K-1742569987997","leaves":[{"text":"}\r","marks":[]}]}]},{"type":"block","id":"mIzL-1742569988000","name":"code-line","data":{},"nodes":[{"type":"text","id":"1Yig-1742569987999","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"8ZaM-1742569988002","name":"code-line","data":{},"nodes":[{"type":"text","id":"uWU4-1742569988001","leaves":[{"text":"if (HAL_OSPI_Transmit_DMA(&hospi1, bTxBuffer) != HAL_OK)\r","marks":[]}]}]},{"type":"block","id":"8PXm-1742569988004","name":"code-line","data":{},"nodes":[{"type":"text","id":"etBt-1742569988003","leaves":[{"text":"{\r","marks":[]}]}]},{"type":"block","id":"RkNe-1742569988006","name":"code-line","data":{},"nodes":[{"type":"text","id":"BALb-1742569988005","leaves":[{"text":"Error_Handler();\r","marks":[]}]}]},{"type":"block","id":"ejDL-1742569988008","name":"code-line","data":{},"nodes":[{"type":"text","id":"t9oN-1742569988007","leaves":[{"text":"}","marks":[]}]}]}],"state":{}}]"><div yne-bulb-block="code" data-theme="default" style="white-space-collapse: preserve;" data-language=""> /* Configure automatic polling mode to wait for end of erase ------ */
OSPI_AutoPollingMemReady(&hospi1);
/* Enable write operations ---------------------------------------- */
OSPI_WriteEnable(&hospi1);
/* Writing Sequence ----------------------------------------------- */
sCommand.Instruction = OCTAL_PAGE_PROG_CMD;
sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
// sCommand.NbData = BUFFERSIZE;
sCommand.Address = address+tmp_flag*4-4;
sCommand.NbData = 4;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Transmit_DMA(&hospi1, bTxBuffer) != HAL_OK)
{
Error_Handler();
}</div></article>
读命令:
<article data-content="[{"type":"block","id":"XQc5-1742570048044","name":"code","data":{"wrap":false,"tokensPerLine":[],"language":"","theme":"default"},"nodes":[{"type":"block","id":"JtFF-1742570048043","name":"code-line","data":{},"nodes":[{"type":"text","id":"oISa-1742570048042","leaves":[{"text":" /* Configure automatic polling mode to wait for end of program ---- */ \r","marks":[]}]}]},{"type":"block","id":"BIFv-1742570049492","name":"code-line","data":{},"nodes":[{"type":"text","id":"MY2h-1742570049491","leaves":[{"text":"OSPI_AutoPollingMemReady(&hospi1);\r","marks":[]}]}]},{"type":"block","id":"mPlw-1742570049494","name":"code-line","data":{},"nodes":[{"type":"text","id":"eG0r-1742570049493","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"1VMN-1742570049496","name":"code-line","data":{},"nodes":[{"type":"text","id":"us7T-1742570049495","leaves":[{"text":"/* Reading Sequence ----------------------------------------------- */\r","marks":[]}]}]},{"type":"block","id":"6ow3-1742570049498","name":"code-line","data":{},"nodes":[{"type":"text","id":"HZJ8-1742570049497","leaves":[{"text":"sCommand.Instruction = OCTAL_IO_READ_CMD;\r","marks":[]}]}]},{"type":"block","id":"Rc1h-1742570049500","name":"code-line","data":{},"nodes":[{"type":"text","id":"BlRI-1742570049499","leaves":[{"text":"sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ;","marks":[]}]}]},{"type":"block","id":"Y08U-1742570610714","name":"code-line","data":{},"nodes":[{"type":"text","id":"F4G3-1742570610713","leaves":[{"text":"sCommand.Address = address;\r","marks":[]}]}]},{"type":"block","id":"TIAP-1742570610965","name":"code-line","data":{},"nodes":[{"type":"text","id":"VwRt-1742570610964","leaves":[{"text":"sCommand.NbData = tmp_flag*4;\r","marks":[]}]}]},{"type":"block","id":"Nf3B-1742570049502","name":"code-line","data":{},"nodes":[{"type":"text","id":"NwKC-1742570049501","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"O1oC-1742570049504","name":"code-line","data":{},"nodes":[{"type":"text","id":"GCl0-1742570049503","leaves":[{"text":"if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)\r","marks":[]}]}]},{"type":"block","id":"kjOL-1742570049506","name":"code-line","data":{},"nodes":[{"type":"text","id":"WPIe-1742570049505","leaves":[{"text":"{\r","marks":[]}]}]},{"type":"block","id":"X4bs-1742570049508","name":"code-line","data":{},"nodes":[{"type":"text","id":"tsz6-1742570049507","leaves":[{"text":"Error_Handler();\r","marks":[]}]}]},{"type":"block","id":"5HxP-1742570049510","name":"code-line","data":{},"nodes":[{"type":"text","id":"wAyM-1742570049509","leaves":[{"text":"}\r","marks":[]}]}]},{"type":"block","id":"Oc2a-1742570049512","name":"code-line","data":{},"nodes":[{"type":"text","id":"OgF0-1742570049511","leaves":[{"text":"","marks":[]}]}]},{"type":"block","id":"wWLd-1742570049514","name":"code-line","data":{},"nodes":[{"type":"text","id":"VPpJ-1742570049513","leaves":[{"text":"if (HAL_OSPI_Receive_DMA(&hospi1, aRxBuffer) != HAL_OK)\r","marks":[]}]}]},{"type":"block","id":"C16n-1742570049516","name":"code-line","data":{},"nodes":[{"type":"text","id":"mUBJ-1742570049515","leaves":[{"text":"{\r","marks":[]}]}]},{"type":"block","id":"3EAg-1742570049518","name":"code-line","data":{},"nodes":[{"type":"text","id":"DygL-1742570049517","leaves":[{"text":"Error_Handler();\r","marks":[]}]}]},{"type":"block","id":"CtH1-1742570049520","name":"code-line","data":{},"nodes":[{"type":"text","id":"ktTo-1742570049519","leaves":[{"text":"}","marks":[]}]}]}],"state":{}}]"><div yne-bulb-block="code" data-theme="default" style="white-space-collapse: preserve;" data-language=""> /* Configure automatic polling mode to wait for end of program ---- */
OSPI_AutoPollingMemReady(&hospi1);
/* Reading Sequence ----------------------------------------------- */
sCommand.Instruction = OCTAL_IO_READ_CMD;
sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ;
sCommand.Address = address;
sCommand.NbData = tmp_flag*4;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (HAL_OSPI_Receive_DMA(&hospi1, aRxBuffer) != HAL_OK)
{
Error_Handler();
}</div></article>
为了方便测试,我们引入了串口,每一次我们发送0x01后会执行一次“擦除——写——读”的操作,然后将读到的数据发送出来,每一次写的位置都是后面的位置(通过tmp_flag计数进行递增),每一次读出来的数量+4个,为什么一定要进行擦除?这是因为Flash是上电不丢失的存储介质,如果对应的位置不是1就不能进行写入的,更准确的说是写入的数据与存储的数据不一致,只有在擦除后为0xff的时候,写入的数据才会正确的存储起来,擦除的时机我们可以相对把握一下。
接下来看一下串口接收的效果:
|
|