先看板子原理图:
再看代码结构:
也就是在BSP里,没有看到对qspi或者spi flash的支持。
看到的spi.c,里面也只有一个spi的初始化。
但是qspi和spi是两个不一样的驱动。
但既然板子上有spi flash,就需要使用它。
spi flash可以有什么使用呢。
比如,你可以存储应用数据,用户信息。
还有就是可以存储固件,用于OTA的设计。特别是对于有远程更新app的需求来说,这个就必须用起来了。
板子联网后,通过网络把程序传输过来的,你要把这个程序文件放到哪里呢,不要告诉我这个程序直接放到STM32自带的FLASH吧,而且,自带的FLASH空间有限,估计也不允许你再存一个备份用于更新吧。
这时候SPI_FLASH就起作用了。
把要更新的程序,可以是STM32本身的程序,也可以是WiFI模块的固件,先传到SPI_FLASH里,然后再从SPI_FLASH拷贝到FLASH。
至于STM32的BOOT程序设计及更新,还有跳转,可以参考我另一篇文章,
https://cloud.tencent.com/developer/article/1599222
当然,不管怎么样呢,既然硬件上,放了这个资源,不可能不使用吧,是吧。
那我们就把它驱动起来吧。
参考了STM32的资料,以及网上关于QSPI的使用。然后整理起来,在这板子进行验证了。下面大概描述一下驱动过程。
为了和原来代码框架比较接近,我就直接在BSP的spi.c spi.h上,添加对QSPI_FLASH的支持。
文件网址:
https://github.com/xidongliang/TencentOS_tiny_EVB_MX_Plus_QSPI
直接从git上,下载这两个文件替换或合并进去 就差不多了。
当然,还要在keil工程里,启用QSPI的宏定义,把它开出来。这样在编译的时候,才能把QSPI的库编译进去。
同时,还需要在keil工程里,将qpis的系统库文件添加到工程目录里,否则编译的时候,会提示各种函数找不到,会编译不过。
首先第一件事就是初始化啦:
void QSPI_FLASH_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* 使能 QSPI 及 GPIO 时钟 */
QSPI_FLASH_CLK_ENABLE();
QSPI_FLASH_CLK_GPIO_ENABLE();
QSPI_FLASH_BK1_IO0_CLK_ENABLE();
QSPI_FLASH_BK1_IO1_CLK_ENABLE();
//QSPI_FLASH_BK1_IO2_CLK_ENABLE();
//QSPI_FLASH_BK1_IO3_CLK_ENABLE();
QSPI_FLASH_CS_GPIO_CLK_ENABLE();
//设置引脚
/*!< 配置 QSPI_FLASH 引脚: CLK */
GPIO_InitStruct.Pin = QSPI_FLASH_CLK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = QSPI_FLASH_CLK_GPIO_AF;
HAL_GPIO_Init(QSPI_FLASH_CLK_GPIO_PORT, &GPIO_InitStruct);
/*!< 配置 QSPI_FLASH 引脚: IO0 */
GPIO_InitStruct.Pin = QSPI_FLASH_BK1_IO0_PIN;
GPIO_InitStruct.Alternate = QSPI_FLASH_BK1_IO0_AF;
HAL_GPIO_Init(QSPI_FLASH_BK1_IO0_PORT, &GPIO_InitStruct);
/*!< 配置 QSPI_FLASH 引脚: IO1 */
GPIO_InitStruct.Pin = QSPI_FLASH_BK1_IO1_PIN;
GPIO_InitStruct.Alternate = QSPI_FLASH_BK1_IO1_AF;
HAL_GPIO_Init(QSPI_FLASH_BK1_IO1_PORT, &GPIO_InitStruct);
#if 0
/*!< 配置 QSPI_FLASH 引脚: IO2 */
GPIO_InitStruct.Pin = QSPI_FLASH_BK1_IO2_PIN;
GPIO_InitStruct.Alternate = QSPI_FLASH_BK1_IO2_AF;
HAL_GPIO_Init(QSPI_FLASH_BK1_IO2_PORT, &GPIO_InitStruct);
/*!< 配置 QSPI_FLASH 引脚: IO3 */
GPIO_InitStruct.Pin = QSPI_FLASH_BK1_IO3_PIN;
GPIO_InitStruct.Alternate = QSPI_FLASH_BK1_IO3_AF;
HAL_GPIO_Init(QSPI_FLASH_BK1_IO3_PORT, &GPIO_InitStruct);
#endif
/*!< 配置 SPI_FLASH_SPI 引脚: NCS */
GPIO_InitStruct.Pin = QSPI_FLASH_CS_PIN;
GPIO_InitStruct.Alternate = QSPI_FLASH_CS_GPIO_AF;
HAL_GPIO_Init(QSPI_FLASH_CS_GPIO_PORT, &GPIO_InitStruct);
/* QSPI_FLASH 模式配置 */
QSPIHandle.Instance = QUADSPI;
QSPIHandle.Init.ClockPrescaler = 2;
QSPIHandle.Init.FifoThreshold = 4;
QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
QSPIHandle.Init.FlashSize = 23;
QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_8_CYCLE;
QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0;
HAL_QSPI_Init(&QSPIHandle);
/*初始化QSPI接口*/
BSP_QSPI_Init();
}
初始化里,要把IO2和IO3去掉。因为使用硬件电路只使用了IO0,IO1。
初始化的工作,就是把GPIO设置正确的模式,并把QSPI启用就行了。基本问题不大。
接下来就是读写函数了。
封装了几个函数。具体代码各位可以直接git上下载下来阅读和调试。如果调试遇到问题,可留言评论交流。
其中主要的函数有:
一个是初始化函数,
读ID函数。
读数据函数。
写数据函数。
对应用层来说,该SPI_FLASH 一定有8M空间可用。
在读或者写的时候,把要访问的地址和长度确定一下就行了。使用起来还是比较方便的。
不过,值得注意的是,这里面的读写的函数都是原始数据流的形式。如果有对文件格式要求的,最好需要移植一个fat文件格式库吧。这里就不介绍怎么做文件格式操作了。
这个板子本身硬件资源有限,达不到做linux或者精简版linux的级别。当然,这个就是一个tinyOS。里面貌似也有关于fatfs的代码。
但是还没有添加对SPI_FLASH的支持。
其实到了这一步,添加支持就很方便了。
在这个disk_read里添加QSPI的读写就可以了。当然,笔者还没有去验证,但是理论上是可行的,有能力的读者可以自己去尝试。或者也可以留言交流。
我估计这个tinyOS系统,也在陆续完善,很多偏应用层的东西,还在慢慢维护和支持,也需要各开发者贡献自己的demo和库吧。
https://github.com/xidongliang/TencentOS_tiny_EVB_MX_Plus_QSPI
笔者也曾想过,是否要将这个QSPI的驱动支持,提交到TencentOS_tiny的git中。
主要是笔者对git的使用不太熟悉。还有一个还是,建议还是由官方的技术人员来验证并添加支持,这样可保证代码风格,系统功能等的
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。