Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
NXP 微控制器
littlefs
NXP-MCXN947
FRDM-MCXN947 Flash实践--W25Q64
发布于 2024-03-28 21:58:39 浏览:483
订阅该版
[tocm] # 概述 FRDM-MCXN947 板子上片外挂载了一颗W25Q64 的norflash,该flash 可以支持xip 启动运行,本次试验在上一篇([FRDM-MCXN947片上Flash实践](https://club.rt-thread.org/ask/article/acdce3db4145b144.html "FRDM-MCXN947片上Flash实践"))的基础上,适配片外的flah 驱动至MTD NOR设备,并挂载至littlefs文件系统验证flash驱动。 # 适配NOR flash驱动 从板子的原理图可以看出,W25Q64 芯片通过flexspi和mcu连接。 ![19675.jpg](https://oss-club.rt-thread.org/uploads/20240328/7aaacf775085293092d90a7f490678d7.jpg) 根据上一篇的littlefs 适配物理层设备主要依赖需要flash 的write/read/erase 三个函数,我们记忆此基础上实现W25Q64的操作函数实现和littlefs的对接。 - pinmux初始化 /bsp/nxp/mcx/mcxn/frdm-mcxn947/board/MCUX_Config/board/pin_mux.c BOARD_InitBootPins(void) 函数内追加pin脚初始化。 ```c diff --git a/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/MCUX_Config/board/pin_mux.c b/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/MCUX_Config/board/pin_mux.c index 392a3ef26b..38d5a3900d 100644 --- a/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/MCUX_Config/board/pin_mux.c +++ b/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/MCUX_Config/board/pin_mux.c @@ -149,6 +149,259 @@ void BOARD_InitBootPins(void) PORT1->PCR[5] = PORT_PCR_MUX(9) | PORT_PCR_PS(0) | PORT_PCR_PE(0) | PORT_PCR_IBE(1); /* ENET0_TXEN */ PORT1->PCR[6] = PORT_PCR_MUX(9) | PORT_PCR_PS(0) | PORT_PCR_PE(0) | PORT_PCR_IBE(1); /* ENET0_TXD0 */ PORT1->PCR[7] = PORT_PCR_MUX(9) | PORT_PCR_PS(0) | PORT_PCR_PE(0) | PORT_PCR_IBE(1); /* ENET0_TXD1 */ + /* OSPI */ + const port_pin_config_t port3_0_pinB17_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_SS0_b */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_0 (pin B17) is configured as FLEXSPI0_A_SS0_b */ + PORT_SetPinConfig(PORT3, 0U, &port3_0_pinB17_config); + + const port_pin_config_t port3_10_pinF17_config = {/* Internal pull-up resistor is enabled */ + kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA2 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_10 (pin F17) is configured as FLEXSPI0_A_DATA2 */ + PORT_SetPinConfig(PORT3, 10U, &port3_10_pinF17_config); + + const port_pin_config_t port3_11_pinF16_config = {/* Internal pull-up resistor is enabled */ + kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA3 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_11 (pin F16) is configured as FLEXSPI0_A_DATA3 */ + PORT_SetPinConfig(PORT3, 11U, &port3_11_pinF16_config); + + const port_pin_config_t port3_12_pinG16_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA4 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_12 (pin G16) is configured as FLEXSPI0_A_DATA4 */ + PORT_SetPinConfig(PORT3, 12U, &port3_12_pinG16_config); + + const port_pin_config_t port3_13_pinH16_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA5 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_13 (pin H16) is configured as FLEXSPI0_A_DATA5 */ + PORT_SetPinConfig(PORT3, 13U, &port3_13_pinH16_config); + + const port_pin_config_t port3_14_pinH17_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA6 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_14 (pin H17) is configured as FLEXSPI0_A_DATA6 */ + PORT_SetPinConfig(PORT3, 14U, &port3_14_pinH17_config); + + const port_pin_config_t port3_15_pinH15_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA7 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_15 (pin H15) is configured as FLEXSPI0_A_DATA7 */ + PORT_SetPinConfig(PORT3, 15U, &port3_15_pinH15_config); + + const port_pin_config_t port3_6_pinD17_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DQS */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_6 (pin D17) is configured as FLEXSPI0_A_DQS */ + PORT_SetPinConfig(PORT3, 6U, &port3_6_pinD17_config); + + const port_pin_config_t port3_7_pinD14_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_SCLK */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_7 (pin D14) is configured as FLEXSPI0_A_SCLK */ + PORT_SetPinConfig(PORT3, 7U, &port3_7_pinD14_config); + + const port_pin_config_t port3_8_pinE14_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA0 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_8 (pin E14) is configured as FLEXSPI0_A_DATA0 */ + PORT_SetPinConfig(PORT3, 8U, &port3_8_pinE14_config); + + const port_pin_config_t port3_9_pinF15_config = {/* Internal pull-up/down resistor is disabled */ + kPORT_PullDisable, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Pin is configured as FLEXSPI0_A_DATA1 */ + kPORT_MuxAlt8, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT3_9 (pin F15) is configured as FLEXSPI0_A_DATA1 */ + PORT_SetPinConfig(PORT3, 9U, &port3_9_pinF15_config); } ``` - clock初始化 bsp/nxp/mcx/mcxn/frdm-mcxn947/board/board.c 文件rt_hw_board_init 函数内添加以下补丁使能flexspi clock ```c @@ -86,11 +86,13 @@ void rt_hw_board_init() CLOCK_AttachClk(kPLL0_to_CTIMER2); CLOCK_AttachClk(kPLL0_to_CTIMER3); CLOCK_AttachClk(kPLL0_to_CTIMER4); + CLOCK_AttachClk(kPLL0_to_FLEXSPI); CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u); CLOCK_SetClkDiv(kCLOCK_DivCtimer1Clk, 1u); CLOCK_SetClkDiv(kCLOCK_DivCtimer2Clk, 1u); CLOCK_SetClkDiv(kCLOCK_DivCtimer3Clk, 1u); CLOCK_SetClkDiv(kCLOCK_DivCtimer4Clk, 1u); + CLOCK_SetClkDiv(kCLOCK_DivFlexspiClk, 2U); SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); /* set pend exception priority */ ``` - W25Q64初始化处理 添加以下接口自动初始化W25Q64 flash ```c int rt_hw_nor_flash_init(void) { static struct norflash_mtd norflash; status_t sta; norflash.mtd_device.ops = &norflash_ops; norflash.mtd_device.block_size = SECTOR_SIZE; norflash.mtd_device.block_start = 0; norflash.mtd_device.block_end = 16383; norflash.mflash_start = 0x80000000; norflash.page_size = 256; flexspi_nor_flash_init(); sta = flexspi_nor_enable_octal_mode(EXAMPLE_FLEXSPI); if (sta != kStatus_Success) { rt_kprintf("enable_octal_mode failed %x\n",sta); return RT_ERROR; } rt_mtd_nor_register_device("norflash",&norflash.mtd_device); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_nor_flash_init); ``` ```c void flexspi_nor_flash_init(void) { flexspi_config_t config; /* To store custom's LUT table in local. */ uint32_t tempCustomLUT[CUSTOM_LUT_LENGTH] = {0U}; FLEXSPI_Type *base = FLEXSPI0; /*Get FLEXSPI default settings and configure the flexspi. */ FLEXSPI_GetDefaultConfig(&config); /*Set AHB buffer size for reading data through AHB bus. */ config.ahbConfig.enableAHBPrefetch = true; config.rxSampleClock = kFLEXSPI_ReadSampleClkLoopbackFromDqsPad; config.enableCombination = true; config.ahbConfig.enableAHBBufferable = true; config.ahbConfig.enableAHBCachable = true; FLEXSPI_Init(base, &config); /* Configure flash settings according to serial flash feature. */ FLEXSPI_SetFlashConfig(base, &deviceconfig, kFLEXSPI_PortA1); /* Copy LUT information from flash region into RAM region, because flash will be reset and back to single mode; In lately time, LUT table assignment maybe failed after flash reset due to LUT read entry is application's required mode(such as octal DDR mode) and flash is being in single SDR mode, they don't matched. */ uint32_t TempFastReadSDRLUTCommandSeq[4]; memcpy(TempFastReadSDRLUTCommandSeq, FastReadSDRLUTCommandSeq, sizeof(FastReadSDRLUTCommandSeq)); /* Copy LUT information from flash region into RAM region, because LUT update maybe corrupt read sequence(LUT[0]) * and load wrong LUT table from FLASH region. */ memcpy(tempCustomLUT, customLUTOctalMode, sizeof(tempCustomLUT)); /* Update LUT table into a specific mode, such as octal SDR mode or octal DDR mode based on application's * requirement. */ FLEXSPI_UpdateLUT(base, 0, tempCustomLUT, CUSTOM_LUT_LENGTH); /* Do software reset. */ FLEXSPI_SoftwareReset(base); EXAMPLE_FLASH_RESET_CONFIG(); /* FAST_READ4B: back to single mode and update read LUT entry into FAST_READ4B after flash reset, to make sure fetch code/data from flash is right. */ FLEXSPI_UpdateLUT(base, 4 * NOR_CMD_LUT_SEQ_IDX_READ, TempFastReadSDRLUTCommandSeq, 4); } status_t flexspi_nor_enable_octal_mode(FLEXSPI_Type *base) { flexspi_transfer_t flashXfer; status_t status; /* Copy LUT information from flash region into RAM region, because flash boot mode maybe not same with application's required mode. If yes, doesn't need to memory copy operation; if no, need to memory opeation before flash access failure due to mismatch LUT read command sequence. */ uint32_t TempOctalReadDDRLUTCommandSeq[4]; memcpy(TempOctalReadDDRLUTCommandSeq, OctalReadDDRLUTCommandSeq, sizeof(OctalReadDDRLUTCommandSeq)); uint32_t writeValue = FLASH_ENABLE_OCTAL_CMD; /* Write enable */ status = flexspi_nor_write_enable(base, 0, false); if (status != kStatus_Success) { return status; } /* Enable quad mode. */ flashXfer.deviceAddress = 0; flashXfer.port = FLASH_PORT; flashXfer.cmdType = kFLEXSPI_Write; flashXfer.SeqNumber = 1; flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ENTEROPI; flashXfer.data = &writeValue; flashXfer.dataSize = 1; status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { return status; } status = flexspi_nor_wait_bus_busy(base, true); /* 8DTRD: enter octal DDR and update read LUT entry into 8DTRD. */ FLEXSPI_UpdateLUT(base, 4 * NOR_CMD_LUT_SEQ_IDX_READ, TempOctalReadDDRLUTCommandSeq, 4); /* Do software reset. */ FLEXSPI_SoftwareReset(base); return status; } ``` - W25Q64 erase 函数 调用flexspi 驱动接口实现如下erase 函数 ```c status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) { status_t status; flexspi_transfer_t flashXfer; #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN flexspi_cache_status_t cacheStatus; flexspi_nor_disable_cache(&cacheStatus); #endif /* Write enable */ status = flexspi_nor_write_enable(base, 0, true); if (status != kStatus_Success) { return status; } flashXfer.deviceAddress = address; flashXfer.port = FLASH_PORT; flashXfer.cmdType = kFLEXSPI_Command; flashXfer.SeqNumber = 1; flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASESECTOR; status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { return status; } status = flexspi_nor_wait_bus_busy(base, true); /* Do software reset. */ FLEXSPI_SoftwareReset(base); #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN flexspi_nor_enable_cache(cacheStatus); #endif return status; } ``` - W25Q64 write 函数 使用flexspi接口实现 write 函数 ```c #define FLASH_PAGE_SIZE 256 status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src) { status_t status; flexspi_transfer_t flashXfer; #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN flexspi_cache_status_t cacheStatus; flexspi_nor_disable_cache(&cacheStatus); #endif /* Write neable */ status = flexspi_nor_write_enable(base, dstAddr, true); if (status != kStatus_Success) { return status; } /* Prepare page program command */ flashXfer.deviceAddress = dstAddr; flashXfer.port = FLASH_PORT; flashXfer.cmdType = kFLEXSPI_Write; flashXfer.SeqNumber = 1; flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM; flashXfer.data = (uint32_t *)src; flashXfer.dataSize = FLASH_PAGE_SIZE; status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { return status; } status = flexspi_nor_wait_bus_busy(base, true); /* Do software reset. */ FLEXSPI_SoftwareReset(base); #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN flexspi_nor_enable_cache(cacheStatus); #endif return status; } ``` - W25Q64 read 函数 read 函数按照内存的方式访问0x80000000地址即可再次就不展开read 函数的实现了 - 更新kconfig 更新kconfig 添加配置菜单项 ```c $ git diff bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig diff --git a/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig b/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig index fe4f9ffaa6..3c0df28a29 100644 --- a/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig +++ b/bsp/nxp/mcx/mcxn/frdm-mcxn947/board/Kconfig @@ -171,6 +171,11 @@ endmenu menu "Board extended module Drivers" + config BSP_USING_NORFLASH + select RT_USING_MTD_NOR + bool "Using mcxn947 norflash(w25q64) driver" + default n + endmenu endmenu ``` 使用env 工具开启对应的配置,默认配置是关闭状态 ![32170.jpg](https://oss-club.rt-thread.org/uploads/20240329/e37dc2903f1bfe2992bb9cfd738d02b6.jpg.webp) # 加入MTD驱动管理 将上述实现的flash 的操作接口通过MTD NOR设备注册至系统,添加如下代码自动注册设备。 ```c struct norflash_mtd { struct rt_mtd_nor_device mtd_device; struct rt_mutex lock; uint32_t mflash_start; uint16_t page_size; void * user_data; }; rt_ssize_t norlash_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 norflash_mtd * p_mflash_mtd = (struct norflash_mtd *)device; dest = 0x00 + offset; if((length) > ((device->block_end*device->block_size))) return 0; for(uint32_t i = 0;i < length; i += 256) { //dest = dest + (i*256); //data = &data[1*256]; ret = flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, dest, (void *)data); if(ret != kStatus_Success) break; } return ret == kStatus_Success ? length : 0; } rt_ssize_t norflash_read(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_size_t length) { uint32_t dest; struct norflash_mtd * p_mflash_mtd = (struct norflash_mtd *)device; dest = p_mflash_mtd->mflash_start + offset; if((dest + length) > (p_mflash_mtd->mflash_start + (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 norflash_erase_block(struct rt_mtd_nor_device* device, rt_off_t offset, rt_size_t length) { status_t ret; uint32_t addr; struct norflash_mtd * p_mflash_mtd = (struct norflash_mtd *)device; addr = offset+0x00; ret = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, addr); return ret == kStatus_Success ? RT_EOK : -1; } const static struct rt_mtd_nor_driver_ops norflash_ops = { .read_id = NULL, .read = norflash_read, .write = norlash_write, .erase_block = norflash_erase_block, }; int rt_hw_nor_flash_init(void) { static struct norflash_mtd norflash; status_t sta; norflash.mtd_device.ops = &norflash_ops; norflash.mtd_device.block_size = SECTOR_SIZE; norflash.mtd_device.block_start = 0; norflash.mtd_device.block_end = 16383; norflash.mflash_start = 0x80000000; norflash.page_size = 256; flexspi_nor_flash_init(); sta = flexspi_nor_enable_octal_mode(EXAMPLE_FLEXSPI); if (sta != kStatus_Success) { rt_kprintf("enable_octal_mode failed %x\n",sta); return RT_ERROR; } rt_mtd_nor_register_device("norflash",&norflash.mtd_device); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_nor_flash_init); ``` 更新程序后输入msh />list device 命令发现norflash 驱动已经被系统识别 ```c msh />list device device type ref count -------- -------------------- ---------- norflash MTD Device 0 mflash MTD Device 1 pin Pin Device 0 uart5 Character Device 0 uart4 Character Device 2 uart2 Character Device 0 ``` # 配置little norflash 参数 - 按照W25Q64 的page =256, block = 4096 配置littlefs flash 参数 ![9656.jpg](https://oss-club.rt-thread.org/uploads/20240329/fa33fb40406c0d90903620687894ec5e.jpg.webp) - 自动挂载文件系统 添加如下代码自动挂载norflash 驱动至littlefs ```c static int littlefs_mount_norflash(void) { if(rt_device_find("norflash") == RT_NULL) { return -RT_EIO; } int ret = dfs_mount("norflash", "/", "lfs", 0, 0); if (ret != 0) { rt_kprintf("ret: %d\n",ret); LOG_E("norflash mount to '/' failed!"); ret = dfs_mkfs("lfs","norflash"); if(ret != 0) return ret; ret = dfs_mount("norflash", "/", "lfs", 0, 0); if(ret != 0) return ret; } return RT_EOK; } INIT_ENV_EXPORT(littlefs_mount_norflash); ``` 自动加载后运行程序,发现flash 已经按照预期的方式挂载到文件系统了,64M 的flash 相对之前的内部的1M空间富裕的多了。一下子实现鸟枪换炮了。 ![20240329-004831.gif](https://oss-club.rt-thread.org/uploads/20240329/d992712ff19e8fdc61ed370765e67f07.gif) 测试代码已提交如下路径: [https://gitee.com/andeyqi/rt-thread/tree/NXP_BSP/](https://gitee.com/andeyqi/rt-thread/tree/NXP_BSP/ "https://gitee.com/andeyqi/rt-thread/tree/NXP_BSP/")
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
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
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
11
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部