Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
NXP 微控制器
FAL
NXP-MCXN947
FRDM-MCXN947 Flash实践----使用RTT fal组件
发布于 2024-04-23 17:50:11 浏览:322
订阅该版
[tocm] 感谢RTT和NXP组织的测评活动以及提供的FRDM-MCXN947开发板,我做的是“FRDM-MCXN947上的Flash实践”,看原理图和手册可知,板子上有MCX_N947芯片内置的2MB flash和外挂的8MB大小的flash(通过spi进行访问,芯片是W25Q64JVSSIQ),在RTT中封装了统一的flash抽象层(FAL模块),对上提供统一的flash访问接口以及基于 Finsh/MSH 的测试命令,对下可以关联多个flash设备,用户只需要封装好对应的flash设备的操作接口即可,使用非常方便。本篇文章主要参考了NXP官网的demo中flash相关操作接口的使用,基于RTT的fal组件,实现了对FRDM开发板上内置和外挂flash的相关操作测评。 ## 其他参考 - [FRDM-MCXN947片上Flash实践](https://club.rt-thread.org/ask/article/acdce3db4145b144.html "FRDM-MCXN947片上Flash实践")这篇文章主要用的MTD nor设备驱动来操作开发板的flash,相关接口的实现大同小异,只是对上提供的抽象不同。 ## 代码工程 使用MDK工程,注意需要先在env工具中使能fal组件,之后会自动更新keil工程,之后添加对应的.c源文件和头文件包含路径。 源码仓库:https://gitee.com/chengqisi/rt-thread。 对应提交: https://gitee.com/chengqisi/rt-thread/compare/b76dca8f4f70b006db4ce52d8481839524187ec0...390b4381e4395736ac92750ed24812f06b0d2e5e ## 开发板资源概述 如下图,截取自芯片手册,说明了mcx_n947芯片内置的2MB flash以及FlexSPI控制器的相关地址。 内置flash:起始地址0x0,长度0x200000; 外挂flash:起始地址0x8000000,外挂flash的长度为0x800000. ![02.png](https://oss-club.rt-thread.org/uploads/20240421/2f4ae734ffb851c2fbd2e586b2adac00.png.webp) 如果想要把flash map到安全区域,只需要参考手册中说明,修改地址的相关bit位即可。 ![03.png](https://oss-club.rt-thread.org/uploads/20240421/fea415c7c30331bc4afa0c7a3dbf1e3e.png.webp) 同时需要注意内置flash的起始部分特定长度需要作为程序和数据的存储区域,不能由fal组件控制访问。具体信息开始参考链接脚本。 ```c #if (defined(__qspi_xip__)) #define m_interrupts_start 0x80001000 #define m_interrupts_size 0x00000400 #define m_text_start 0x80001400 #define m_text_size 0x0FFFEC00 #else #define m_interrupts_start 0x00000000 #define m_interrupts_size 0x00000400 #define m_text_start 0x00000400 #define m_text_size 0x000BFC00 #endif #define m_flash1_start 0x00100000 #define m_flash1_size 0x00100000 ``` MDK工程中没有定义`__qspi_xip__`宏,链接脚本中使用了内置flash的前1MB,所以fal可以访问的内置flash地址是0x100000,长度是0x100000. ## FAL组件适配说明 参考链接:[RTT fal组件](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/fal/fal?id=_1%e3%80%81fal%e4%bb%8b%e7%bb%8d "RTT fal组件") 之前RTT的测评活动中关于fal组件的文章:[PSOC6上的flash实践](https://docs.qq.com/doc/DZmpvR0xocFpVVGhQ "PSOC6上的flash实践") ### 大体流程为: 1、使能fal组件;(注意需要手动添加调用fal_init接口) 2、手写fal_cfg.h配置文件,并在fal_cfg.h中对内置和外挂flash的分区进行划分; 3、分别实现内置和外挂flash的相关接口(init,read,write,erase);注意fal的相关读写擦接口的参数是offset偏移,需要转换为驱动接口需要的地址。 4、fal相关shell命令测试。 fal_cfg.h中相关配置参考: ```c extern const struct fal_flash_dev mcxn947_onchip_flash; extern const struct fal_flash_dev mcxn947_flexspi_norflash; // extern struct fal_flash_dev nor_flash0; /* flash device table */ #define FAL_FLASH_DEV_TABLE \ { \ &mcxn947_onchip_flash, \ &mcxn947_flexspi_norflash, \ } /* ====================== Partition Configuration ========================== */ #ifdef FAL_PART_HAS_TABLE_CFG /* partition table */ #define FAL_PART_TABLE \ { \ {FAL_PART_MAGIC_WORD, "bl", "mcxn947_onchip", 0, 64*1024, 0}, \ {FAL_PART_MAGIC_WORD, "app", "mcxn947_onchip", 64*1024, 704*1024, 0}, \ {FAL_PART_MAGIC_WORD, "easyflash", NOR_FLASH_DEV_NAME, 0, 64*1024, 0 }, \ {FAL_PART_MAGIC_WORD, "download", NOR_FLASH_DEV_NAME, 64*1024, 704*1024, 0},\ } ``` ## 内置flash适配 nxp的flash相关操作接口都在fsl_flash.c里,但nxp官网的demo在操作内置flash时,增加了一层封装在mflash_drv.c里,主要做了擦写操作的地址对齐检查,所以内置flash的适配可以参考nxp的demo实现。 注意:擦除的粒度为sector,大小为8192byte; 写入的粒度为page,大小为128byte。 读取不做限制,直接用的memcpy实现。 相关接口实现参考: ```c static int read(long offset, uint8_t *buf, size_t size) { assert(offset + size <= mcxn947_onchip_flash.len); uint32_t addr = mcxn947_onchip_flash.addr + offset; return mflash_drv_read(addr, (uint32_t*)buf, size); } static int write(long offset, const uint8_t *buf, size_t size) { assert(offset + size <= mcxn947_onchip_flash.len); int32_t writed = 0; uint32_t addr = mcxn947_onchip_flash.addr + offset; uint8_t *p = (uint8_t *)buf; while(writed < size) { int32_t ret = mflash_drv_page_program(addr, (uint32_t*)p); switch(ret) { case kStatus_Success : addr += MFLASH_PAGE_SIZE; p += MFLASH_PAGE_SIZE; writed += MFLASH_PAGE_SIZE; break; case kStatus_Busy : break; default : goto RET; } } RET: return writed; } static int erase(long offset, size_t size) { assert(offset + size <= mcxn947_onchip_flash.len); uint32_t addr = mcxn947_onchip_flash.addr + offset; int32_t erased = 0; while(erased < size) { int32_t ret = mflash_drv_sector_erase(addr); switch(ret) { case kStatus_Success : addr += MFLASH_SECTOR_SIZE; erased += MFLASH_SECTOR_SIZE; break; case kStatus_Busy : break; default : goto RET; } } RET: return erased; } ``` 使用的相关驱动接口为:mflash_drv_read,mflash_drv_page_program,mflash_drv_sector_erase。 ## 外挂flash适配 参考nxp的demo,使用flexspi对外置flash进行访问。 注意 init flexspi前需要先设置时钟;写入的粒度为page,大小为128byte。 ```c static int init(void) { /* Flexspi frequency 48MHz */ CLOCK_SetClkDiv(kCLOCK_DivFlexspiClk, 1U); CLOCK_AttachClk(kFRO_HF_to_FLEXSPI); /*!< Switch FLEXSPI to FRO_HF */ /* Clean up FLEXSPI NOR flash driver Structure */ memset(&norConfig, 0U, sizeof(flexspi_nor_config_t)); if((FLEXSPI_NorFlash_GetConfig(FlexSpiInstance, &norConfig, &option) == kStatus_Success) && (FLEXSPI_NorFlash_Init(FlexSpiInstance, &norConfig) == kStatus_Success)) { return kStatus_Success; } return kStatus_Fail; } static int read(long offset, uint8_t *buf, size_t size) { assert(offset + size <= mcxn947_flexspi_norflash.len); uint32_t addr = mcxn947_flexspi_norflash.addr + offset; return FLEXSPI_NorFlash_Read(FlexSpiInstance, &norConfig,buf,addr,size); } static int write(long offset, const uint8_t *buf, size_t size) { assert(offset + size <= mcxn947_flexspi_norflash.len); int32_t writed = 0; uint32_t addr = mcxn947_flexspi_norflash.addr + offset; uint8_t *p = (uint8_t *)buf; while(writed < size) { int32_t ret = FLEXSPI_NorFlash_ProgramPage(FlexSpiInstance, &norConfig, addr, (const uint32_t *)p); switch(ret) { case kStatus_Success : addr += norConfig.pageSize; p += norConfig.pageSize; writed += norConfig.pageSize; break; case kStatus_Busy : break; default : goto RET; } } RET: return writed; } static int erase(long offset, size_t size) { assert(offset + size <= mcxn947_flexspi_norflash.len); uint32_t addr = mcxn947_flexspi_norflash.addr + offset; if(kStatus_Success == FLEXSPI_NorFlash_Erase(FlexSpiInstance, &norConfig, addr, size)) return (size % norConfig.sectorSize) ? ((size / norConfig.sectorSize + 1) * norConfig.sectorSize) : size; } ``` 使用的相关驱动接口为:FLEXSPI_NorFlash_Init,FLEXSPI_NorFlash_Read,FLEXSPI_NorFlash_ProgramPage,FLEXSPI_NorFlash_Erase。 ## fal组件msh命令测试 待补充。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
酒酿圆子
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
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
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部