【简介】
我们在上一篇基于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驱动。

我要赚赏金
