rt_thread 使用ulog存储日志文件到外部flash
本次记录基于STM32F407利用SPI1总线挂在外部flash芯片w25q128实现存储日志功能
一、开启组件
1.1 ulog组件开启
具体参数定义参考rt_thread的教程文件,
参考链接
1.2 开启fal功能
开启后需要从rt_thread的components/fal将samples下的port文件夹内的文件拷贝到其他地方进行相应修改,注意添加scons文件将其编译包含到功能内。
主要修改部分位于fal_cfg.h内的分区表
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include <rtconfig.h>
#include <board.h>
#define FLASH_SIZE_GRANULARITY_16K (4 * 16 * 1024)
#define FLASH_SIZE_GRANULARITY_64K (1 * 64 * 1024)
#define FLASH_SIZE_GRANULARITY_128K (7 * 128 * 1024)
#define STM32_FLASH_START_ADRESS_16K STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)
#define BOOTLOADER_START_ADDR 0
#define BOOTLOADER_ROM_SIZE (64*1024) //64K
#define APP_ROM_START_ADDR (BOOTLOADER_START_ADDR + BOOTLOADER_ROM_SIZE)
#define APP_ROM_SIZE (400*1024) //400K
#define CONFIG_FILE_START_ADDR (APP_ROM_START_ADDR + APP_ROM_SIZE)
#define CONFIG_FILE_SIZE (10*1024) //10k
#define FACTORY_ROM_START_ADDR 0 //出厂ROM地址
#define FACTORY_ROM_SIZE (2*1024*1024) //出厂ROM大小 2M
#define APP_DOWNLOAD_ADDR (FACTORY_ROM_START_ADDR + FACTORY_ROM_SIZE) //IAP存放地址
#define APP_DOWNLOAD_SIZE (4*1024*1024) //IAP存放地址空间4M
#define LOG_STORE_START_ADDR (APP_DOWNLOAD_ADDR + APP_DOWNLOAD_SIZE) //日志记录地址
#define LOG_STORE_SIZE (10*1024*1024) //LOG记录大小 10M
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32f2_onchip_flash;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32f2_onchip_flash, \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "bl", "stm32_onchip", BOOTLOADER_START_ADDR, BOOTLOADER_ROM_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "app", "stm32_onchip", APP_ROM_START_ADDR, APP_ROM_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "cfg", "stm32_onchip", CONFIG_FILE_START_ADDR, CONFIG_FILE_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "rom", FAL_USING_NOR_FLASH_DEV_NAME, FACTORY_ROM_START_ADDR, FACTORY_ROM_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "download", FAL_USING_NOR_FLASH_DEV_NAME, APP_DOWNLOAD_ADDR, APP_DOWNLOAD_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "log", FAL_USING_NOR_FLASH_DEV_NAME, LOG_STORE_START_ADDR, LOG_STORE_SIZE, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
void spi_flash_init(void);
.h文件内需要根据自己的情况进行相应的修改,此处我们启用了外部flash,使用了SFUD 模块,因此需要度SFUD进行相应的修改。
1.3 SFUD开启
针对SFUD需要进行相关修改参考如下
红框的名称需要和fal_cfg.h内的对应起来。该结构体内的blk_size和write_gran需要和实际使用的存储信息一一对应。
需要注意的是fal的sample文件夹内的fal_flash_sfud_port.c文件内
static int read(long offset, uint8_t *buf, size_t size)
//相关修改为
static int read( rt_uint32_t offset, uint8_t *buf, size_t size)
//其他的也需要做相应修改
开始SFUD功能后需要手动注册下外部存储设备,参考注册代码如下:
#include "rtdevice.h"
#include "fal_cfg.h"
#include "drv_spi.h"
#include "spi_flash_sfud.h"
rt_spi_flash_device_t sf_flash_device;
void spi_flash_init(void)
{
rt_hw_spi_device_attach("spi1","w25q128",GPIOD,GPIO_PIN_3);
sf_flash_device = rt_sfud_flash_probe(FAL_USING_NOR_FLASH_DEV_NAME,"w25q128");
if(sf_flash_device != RT_NULL)
{
rt_kprintf("rt sfud flash success");
}
else {
rt_kprintf("rt sfud flash error");
}
}
其中"spi1"为挂载到哪一条spi总线上,"w25q128"为挂载后的名称,FAL_USING_NOR_FLASH_DEV_NAME为挂载flash设备的名称,在fal_cfg.h的分区列表内需要用到。
1.4 EasyFlash功能包
EasyFlash打开方式见截图
ENV这个可以理解为参数存储功能,此处需要需要注意EasyFlash会地址分配问题。我目前将片外flash分配了3个分区,具体空间地址如下:
分区名 | 起始地址 | 分配大小 |
---|---|---|
ROM | 0 | 0x0020 0000 |
download | 0x0020 0000 | 0x0040 0000 |
log | 0x0060 0000 | 0x00A0 0000 |
因此针对我的存储区域StartAddr则为log对应的地址,0x600000–6291456, log size 注意并不是我们log取的10M的大小,而是需要除去env所占空间大小,easyflash默认env区域配置大小为8k空间,因此剩余log的大小实际上为9FE000-10477568,此处我设定log大小为8M大小。
1.5 ulog_easyflash
我们需要配置ulog_easyflash功能包来配合ulog进行日志文件存储功能。
经过打开以上插件后则可以进行相关功能操作了
二、功能调用
2.1 初始化接口
启动后需要手动启动相关接口初始化代码
spi_flash_init();
fal_init();
easyflash_init();
ulog_ef_filter_cfg_load();
ulog_ef_backend_init();
spi_flash_init()完成的功能是挂载spi外部功能
fal_init()调用接口完成fal初始化
easyflash_init()完成了easyflash功能包的初始化
ulog_ef_filter_cfg_load()以及ulog_ef_backend_init()默认加入了开机自启动,但是可能存在先启动了这两个程序再启动easyflash_init的情况导致系统启动失败的情况。
完成以上操作后,系统提示如下
完成以上操作后则会将输出的LOG_X指令保存到flash内。
2.2 ulog使用
在终端界面输入查询指令
ulog_flash read
系统会读取所有的日志文件,指令后面带参数则从后往前读取相应的记录数据,如
ulog_flash read 200
ulog_flash read 400