一、创建RT-Thread工程
这里我使用RT-Thread studio创建了STM32L431的工程。接下来的操作都在rtthread studio中进行。
具体的教程可以看RT-Thread的 官方文档
创建工程时已经配置了log串口为UART1,所以编译之后就会有日志1s一次的循环输出。
二、通过cubeMX配置QSPI
2.1 创建工程是之后,需要点击工程内的cubeMX进行QSPI的管脚以及参数配置。
2.2 在board.h中打开QSPI的宏定义,
#define BSP_USING_QSPI
同时将QSPI的初始化函数复制到borad.c中,在启动初始化参与编译。
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(qspiHandle->Instance==QUADSPI)
{
/* USER CODE BEGIN QUADSPI_MspInit 0 */
/* USER CODE END QUADSPI_MspInit 0 */
/* QUADSPI clock enable */
__HAL_RCC_QSPI_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**QUADSPI GPIO Configuration
PB0 ------> QUADSPI_BK1_IO1
PB1 ------> QUADSPI_BK1_IO0
PB10 ------> QUADSPI_CLK
PB11 ------> QUADSPI_BK1_NCS
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN QUADSPI_MspInit 1 */
/* USER CODE END QUADSPI_MspInit 1 */
}
}
2.3 在RT-Thread setting中勾选SPI和SFUD组件。
2.4 在main.c添加spi的头文件以及调用初始化
#include "drv_qspi.h"
#include "spi_flash_sfud.h"
#include "drv_common.h"
#define QSPI_BUS_NAME "spi"
#define QSPI_DEVICE_NAME "qspi1"
#define W25Q_FLASH_NAME "W25Q64JV"
#define QSPI_CS_PIN GET_PIN(B, 11)
int main(void)
{
int count = 1;
stm32_qspi_bus_attach_device(QSPI_BUS_NAME, QSPI_DEVICE_NAME, QSPI_CS_PIN, 2, RT_NULL, RT_NULL);
rt_sfud_flash_probe(W25Q_FLASH_NAME, QSPI_DEVICE_NAME);
while (count++)
{
LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
}
return RT_EOK;
}
三、添加FAL库
3.1 在RT-Thread setting中添加FAL库
3.2 修改分区配置
将FAL库目录中sampleportingfal_cfg.h复制到inc目录下修改分区与BootLoader中一致
在drivers目录中drv_flash_l4.c对于stm32_onchip_flash的定义那么为"onchip_flash",因此分区表的偏上flash名称也要修改。
外部flash的名称使用rtconfig.h配置的宏定义
#define FAL_PART_TABLE
{
{FAL_PART_MAGIC_WORD, "bl", "onchip_flash", 0, 64*1024, 0},
{FAL_PART_MAGIC_WORD, "app", "onchip_flash", 64*1024, 192*1024, 0},
{FAL_PART_MAGIC_WORD, "ef", FAL_USING_NOR_FLASH_DEV_NAME, 0, 1024*1024, 0},
{FAL_PART_MAGIC_WORD, "download", FAL_USING_NOR_FLASH_DEV_NAME, 1024*1024, 512*1024, 0},
{FAL_PART_MAGIC_WROD, "factory", FAL_USING_NOR_FLASH_DEV_NAME, (1024+512)*1024, 512*1024, 0},
}
最后调用fal_init(),进行初始化。
四、中断向量和烧录地址
本次主要开发的是app的代码,所以需要从我们之前实现的BootLoader中跳转到app来执行,app代码的修改可以参考RT-Thread官方文档的通用BootLoader说明。
4.1 修改中断向量
在main.c增加如下代码
/**
* Function ota_app_vtor_reconfig
* Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
#define NVIC_VTOR_MASK 0x3FFFFF80
/* Set the Vector Table base location by user application firmware definition */
SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
//SCB->VTOR = FLASH_BASE | 0x00010000UL; /* Vector Table Relocation in Internal FLASH */
//__enable_irq();
return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
其中RT_APP_PART_ADDR的宏定义在fal_cfg.h中增加,由于我们BootLoader中设定的app分区地址为0x08010000,这里需要设置为0x08010000,以确保中断向量的跳转地址正确。
4.2 修改烧录地址
在RT-Thread studio中修改烧录地址,打开linkscriptsSTM32L431RCTxlink.lds,按照下图修改后保存。
在keil中修改烧录地址如下:
4.3 app代码修改
#include "fal.h"
#define APP_VERSION "V1.0.0"
int main(void)
{
int count = 1;
LOG_D("Hello RT-Thread!");
stm32_qspi_bus_attach_device(QSPI_BUS_NAME, QSPI_DEVICE_NAME, QSPI_CS_PIN, 2, RT_NULL, RT_NULL);
rt_sfud_flash_probe(W25Q_FLASH_NAME, QSPI_DEVICE_NAME);
fal_init();
LOG_D("//------------------welcome to app------------------//");
LOG_D("//------------------app version %s------------------//", APP_VERSION);
LOG_D("//------------------app init succsee----------------//");
while (count++)
{
rt_thread_mdelay(1000);
}
return RT_EOK;
}
5.2 烧录app
烧录RT-Thread生成的app bin文件,地址选择0x08010000
五、烧录启动
5.1 烧录bootloader
使用ST-LINK Utility,连接设备全擦芯片,之后烧录BootLoader
5.2 烧录app
烧录RT-Thread生成的app bin文件,地址选择0x08010000
BootLoader和app烧录完整之后,复位。
5.3 启动日志
原作者:路飞的皮孩
|