【简介】
我们在上一篇基于S32K146 完成了片内flash 驱动的编写(【S32K146】S32K146片内flash编程),RT-thread 将常用的存储设备抽象成MTD(Memory Technology Device)设备驱动,S32K146 的片内有1M的NOR flash,大部分都是空闲未使用状态,本次试验将使用后512K进行验证将这部分flash 通过RT-thread 的MTD nor 设备进行管理。
【MTD驱动适配】
MTD NOR 设备通过结构体struct rt_mtd_nor_device 进行管理,包含了设备基类结构体,Flash 块大小,块起始地址,块结束地址,以及NOR 设备操作方法,定义如下:
struct rt_mtd_nor_device { struct rt_device parent; rt_uint32_t block_size; /* The Block size in the flash */ rt_uint32_t block_start; /* The start of available block*/ rt_uint32_t block_end; /* The end of available block */ /* operations interface */ const struct rt_mtd_nor_driver_ops* ops; }; struct rt_mtd_nor_driver_ops { rt_err_t (*read_id) (struct rt_mtd_nor_device* device); rt_ssize_t (*read) (struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_size_t length); rt_ssize_t (*write) (struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_size_t length); rt_err_t (*erase_block)(struct rt_mtd_nor_device* device, rt_off_t offset, rt_size_t length); };
我们按照老套路将片内flash 相关操作函数及属性信息填充到struct rt_mtd_nor_device 结构并注册到系统内部交由系统管理完成驱动的适配,具体适配函数如下:
#include <rtthread.h> #include <rtdevice.h> #include "board.h" struct mflash_mtd { struct rt_mtd_nor_device mtd_device; struct rt_mutex lock; flash_ssd_config_t SSDConfig; uint32_t mflash_start; void * user_data; }; rt_ssize_t mlash_write(struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_size_t length) { status_t ret; uint32_t dest; struct mflash_mtd * p_mflash_mtd = (struct mflash_mtd *)device; dest = p_mflash_mtd->mflash_start + offset; if((dest + length) > (device->block_end*device->block_size)) return 0; ret = FLASH_DRV_Program(&p_mflash_mtd->SSDConfig,dest,length,data); return ret == STATUS_SUCCESS ? length : 0; } rt_ssize_t mflash_read(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_size_t length) { uint32_t dest; struct mflash_mtd * p_mflash_mtd = (struct mflash_mtd *)device; dest = p_mflash_mtd->mflash_start + offset; if((dest + length) > (device->block_end*device->block_size)) return 0; for(uint32_t i=0; i < length; i++) { data[i] = *((__IO rt_uint8_t*)dest); dest++; } return length; } rt_err_t mflash_erase_block(struct rt_mtd_nor_device* device, rt_off_t offset, rt_size_t length) { status_t ret; uint32_t addr; struct mflash_mtd * p_mflash_mtd = (struct mflash_mtd *)device; addr = p_mflash_mtd->mflash_start + offset; ret = FLASH_DRV_EraseSector(&p_mflash_mtd->SSDConfig,addr,length); return ret == STATUS_SUCCESS ? RT_EOK : -1; } const static struct rt_mtd_nor_driver_ops mflash_ops = { .read_id = NULL, .read = mflash_read, .write = mlash_write, .erase_block = mflash_erase_block, }; int rt_hw_mflash_init(void) { static struct mflash_mtd mflash; mflash.mtd_device.ops = &mflash_ops; mflash.mtd_device.block_size = FEATURE_FLS_PF_BLOCK_SECTOR_SIZE; mflash.mtd_device.block_start = 128; mflash.mtd_device.block_end = 255; mflash.mflash_start = 0X80000; FLASH_DRV_Init(&Flash_InitConfig0,&mflash.SSDConfig); rt_mtd_nor_register_device("mflash",&mflash.mtd_device); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_mflash_init);
将上述设备驱动注册进入系统后通过list device 命令查看系统设备节点发现mflash 对应的MTD设备已经按照预期注册进系统:
【测试验证】
我们在RT-thread 下编写如下测试代码验证mtd 驱动的读写功能
static void mflash(int argc,char *argv[]) { static rt_device_t mtd = RT_NULL; if(!strcmp(argv[1], "open")) { mtd = rt_device_find("mflash"); if(!mtd) rt_kprintf("rt find device failed.\n"); else rt_kprintf("rt find device ok.\n"); } else if(!strcmp(argv[1], "erase")) { rt_mtd_nor_erase_block((struct rt_mtd_nor_device*)mtd,0x00,4096); } else if(!strcmp(argv[1], "write")) { char * writetest = " hello world "; rt_mtd_nor_write((struct rt_mtd_nor_device*)mtd,0,writetest,16); } else if(!strcmp(argv[1], "read")) { char readbuff[16]; rt_mtd_nor_read((struct rt_mtd_nor_device*)mtd,0,readbuff,16); rt_kprintf("read test data is %s \n",readbuff); } } MSH_CMD_EXPORT(mflash, mflash mtd test);
上述代码运行验证如下,open/erase/write 后去读取测试数据和测试代码写入的一致,至此已经将片内flash 对接到Rt-thread 的MTD驱动。