Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
flash
NXP 微控制器
NXP-MCXN236
NXP MCXN236测评-FLASH
发布于 2024-06-27 17:51:20 浏览:297
订阅该版
[tocm] # 使用内部flash适配MTD NOR 设备驱动 RT-thread 将常用的存储设备抽象成MTD(Memory Technology Device)设备驱动,MCXN236 的片内有1M的NOR flash,大部分都是空闲未使用状态,本次试验将使用后512K进行验证将这部分flash 通过RT-thread 的MTD nor 设备进行管理。 ## 添加flash驱动文件 默认的link 文件是将所有的flash 空间划分给用户使用的,我们更新link 文件保留后512KB的空间用于MTD设备驱动管理,最终交给文件系统管理,按照如下修改方式释放后512KB的空间不使用。 ```c +++ b/bsp/nxp/mcx/mcxn/frdm-mcxn236/board/linker_scripts/MCXN236_flash.icf @@ -41,7 +41,7 @@ define symbol m_interrupts_start = 0x00000000; define symbol m_interrupts_end = 0x000003FF; define symbol m_text_start = 0x00000400; -define symbol m_text_end = 0x000FFFFF; +define symbol m_text_end = 0x0007FFFF; define symbol m_data_start = 0x20000000; define symbol m_data_end = 0x20037FFF; diff --git a/bsp/nxp/mcx/mcxn/frdm-mcxn236/project.ewp b/bsp/nxp/mcx/mcxn/frdm-mcxn236/project.ewp ``` MTD NOR 设备通过结构体struct rt_mtd_nor_device 进行管理,包含了设备基类结构体,Flash 块大小,块起始地址,块结束地址,以及NOR 设备操作方法,定义如下: ```c 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); }; ``` 以上配置信息主要包括nor flash 的每个block 的大小及起始块和结束块已经nor flash 分读id,读/写及块擦除的ops 信息,rt-thread 系统内已经集成了nor flash 的驱动框架,我们只要填充好上述结构体注册到系统内部即完成了rt-thread 的nor flash驱动适配。 我们要实现内部flash 的读写擦除接口,需要使用nxp的flash 驱动文件fsl_flash.c,该文件现在的bsp是美有集成到工程内部的,我们需要修改/bsp/nxp/mcx/mcxn/Libraries/MCXN947/SConscript 脚本文件添加驱动文件即对应的文件include路径,对应修改如下: ```c index e9bab825e0..1fc44958cd 100644 --- a/bsp/nxp/mcx/mcxn/Libraries/MCXN236/SConscript +++ b/bsp/nxp/mcx/mcxn/Libraries/MCXN236/SConscript @@ -2,7 +2,7 @@ Import('rtconfig') from building import * cwd = GetCurrentDir() -path = [cwd + '/../CMSIS/Core/Include', cwd + '/MCXN236', cwd + '/MCXN236/drivers'] +path = [cwd + '/../CMSIS/Core/Include', cwd + '/MCXN236', cwd + '/MCXN236/drivers',cwd + '/MCXN236/drivers/romapi/flash/'] src = Split(''' MCXN236/system_MCXN236.c ''') @@ -55,6 +55,7 @@ src += ['MCXN236/drivers/fsl_mrt.c'] src += ['MCXN236/drivers/fsl_reset.c'] src += ['MCXN236/drivers/fsl_spc.c'] src += ['MCXN236/drivers/fsl_vref.c'] +src += ['MCXN236/drivers/romapi/flash/src/fsl_flash.c'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path) ``` 更新配置脚本文件后,env下使用scons --target=iar命令更新IAR工程,重新生成的IAR工程里已经包含了flash 驱动文件了。 ## 适配MTD设备驱动 添加完依赖的驱动文件后,我们基于sdk的flash驱动文件适配MTD NOR 设备驱动需要底层适配的接口及参数配置。 使用fsl_flash.c 驱动库适配mtd nor flash read函数: ```c 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; } ``` 使用fsl_flash.c 驱动库适配mtd nor flash write函数: ```c static flash_config_t g_flash_instance = {0}; static uint32_t g_pflashBlockBase = 0; static uint32_t g_pflashTotalSize = 0; static uint32_t g_pflashSectorSize = 0; static uint32_t g_pflashPageSize = 0; struct mflash_mtd { struct rt_mtd_nor_device mtd_device; struct rt_mutex lock; uint32_t mflash_start; uint8_t page_size; 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; for(uint32_t i = 0;i < length; i += 128) { ret = FLASH_Program(&g_flash_instance, dest, (uint8_t *)data, 128); if(ret != kStatus_Success) break; } return ret == kStatus_Success ? length : 0; } ``` 使用fsl_flash.c 驱动库适配mtd nor flash erase函数: ```c 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_Erase(&g_flash_instance, addr, FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES, kFLASH_ApiEraseKey); return ret == kStatus_Success ? RT_EOK : -1; } ``` 添加接口在driver 初始化阶段调用flash 初始化处理,配置flashblock信息,向系统注册mtd nor flash驱动 ```c int rt_hw_mflash_init(void) { static struct mflash_mtd mflash; mflash.mtd_device.ops = &mflash_ops; mflash.mtd_device.block_size = FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES; mflash.mtd_device.block_start = 64; mflash.mtd_device.block_end = 127; mflash.mflash_start = 64*FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES; mflash.page_size = FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES; status_t result; result = FLASH_Init(&g_flash_instance); if (result != kStatus_Success) return result; result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashBlockBaseAddr, &g_pflashBlockBase); if (result != kStatus_Success) return result; result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashSectorSize, &g_pflashSectorSize); if (result != kStatus_Success) return result; result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashTotalSize, &g_pflashTotalSize); if (result != kStatus_Success) return result; result = FLASH_GetProperty(&g_flash_instance, kFLASH_PropertyPflashPageSize, &g_pflashPageSize); rt_mtd_nor_register_device("mflash",&mflash.mtd_device); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_mflash_init); ``` flash 驱动依赖了mtd nor 驱动框架,在kconfig 文件内追加配置项目将mtd nor 驱动框架加入工程编译。 ```c --- a/bsp/nxp/mcx/mcxn/frdm-mcxn236/board/Kconfig +++ b/bsp/nxp/mcx/mcxn/frdm-mcxn236/board/Kconfig @@ -19,6 +19,11 @@ menu "On-chip Peripheral Drivers" select RT_USING_PIN default y + config BSP_USING_MFLASH + select RT_USING_MTD_NOR + bool "Using mcxn236 mflash driver" + default n + menuconfig BSP_USING_UART bool "Enable UART" default y ``` 然后在env 环境下使能BSP_USING_MFLASH 配置,并更新工程,此时mtd nor设备驱动就被加载到工程内部了。 ![mflash_config.png](https://oss-club.rt-thread.org/uploads/20240627/4f3114ad514fbeb5793d030fbbf1d764.png.webp) 烧写后输入list device 命令可以看到MTD 驱动已经被注册到系统内部了。 ```c msh >list device device type ref count -------- -------------------- ---------- mflash MTD Device 0 pin Pin Device 0 uart5 Character Device 0 uart4 Character Device 2 uart2 Character Device 0 ``` 我们继续添加mflash 测试代码验证mtd 驱动接口,open 用于打开设备获取driver handler,write/read 分别用于读写flash 验证。 ```c 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,8192); } 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); ``` 使用上面的测试命令输入mflash open、mflash write,mflash read 进行写入回读验证,测试命令写入的 " hello world "字符串已经被正常的读取回来了,说明法flash 的读写功能都是正常的。 ```c msh > msh > msh >mflash open rt find device ok. msh >mflash write msh > msh >mflash read read test data is hello world ```
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
andeyqi
这家伙很懒,什么也没写!
文章
7
回答
6
被采纳
0
关注TA
发私信
相关文章
1
试贴-消灭0主题
2
LPC M4的一些资料
3
LPC4088的临时分支
4
lpc1788 ad 不稳定
5
1788 LCD控制器缓冲区字节问题
6
一起来学习LPC4088吧
7
上传LPC4088的realtouch主工程
8
RealBoard 4088预定帖 [第一批板子不多,预定提前结束]
9
晒RealBoard LPC4088开箱照啦,速带小板凳前来围观
10
4088主程序需要的SD卡资源
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部