将闪存从千兆位改为千兆位时,无法使用 KEIL 和 ulink pro 对闪存进行编程 我们有 i.MX RT1173 交叉处理器 我们使用 1 千兆外置四极管或非闪存 (IS25LE02GG-RHLE) 来启动连接到 flexspi1 和 port1 的映像。 1 Gb 闪存和 2 Gbit 闪存之间的区别仅在于设备 ID 和大小变化,其余的编程都是一样的。 最近,我们将闪存从千兆位变为双千兆位 (is25le02gg-rhle).为了测试,我没有更改源代码中的任何内容,甚至连微控制器的配置也没有更改。 我尝试使用旧的闪存算法文件闪存,但闪存编程一开始就失败了,错误如下 在闪存方面,我们使用 KEil uversion 和 ulinkpro 擦除失败! 错误:闪存下载失败 -"Cortex-M7" 请问这里面有什么问题? 我上网查了一些资料,发现如果两个闪存的 JEDEC ID 不同,闪存算法将无法编程。 我没有以前的 Flash 算法源代码,因此我使用 KEIL 中给出的模板创建了自己的 Flash 算法。 我进行了修改,可以创建"NewDevice.FLM" 我把上述文件放到了下面的位置。但是,当我打开 KEIL 并转到实用程序并尝试添加时,仍然找不到 NewDevice.FLM 。因此,我无法使用 NewDevice.FLM 对闪存进行编程。 我不确定我的 Flash 算法有多好,因为我是用模板编写的,但还是附上供您参考。 附上文件以供参考。 Re: unable to program my flash using KEIL and ulink pro when changed flash from 1Gigabit to 2Gigabit 感谢您的教程,对我帮助很大...... 编程和擦除正在进行,但验证失败。我遇到以下错误 因此,我用这个 FLM 对闪光灯进行编程。 擦除和编程正在进行,但验证失败。我遇到了以下错误: 我在我的 1Gigabit 板上测试了这个算法,只是为了检查算法是否正常工作。 加载 " C:\\ khushboo_flash_new\\ 设备\\ Device_Release\\ Source\\ Master\\ 输出\\ prostarnew_combined.Hex " 全芯片擦除完成。 编程完成。 30040020H 处内容不匹配(Flash=6FH Required=FFH) !30040020H (Flash=6FH Required=FFH) ! 内容不匹配:30040021H (Flash=DFH Required=FFH) ! 内容不匹配:30040022H (Flash=7BH Required=FFH) ! 内容不匹配:30040023H (Flash=07H Required=FFH) ! 内容不匹配:30040024H (Flash=BFH Required=FFH) ! 内容不匹配:30040025H (Flash=E9H Required=FFH) ! 内容不匹配:30040026H (Flash=7DH Required=FFH) ! 内容不匹配:30040027H (Flash=C9H Required=FFH) ! 内容不匹配:30040028H (Flash=F7H Required=FFH) ! 内容不匹配:30040029H (Flash=7FH Required=FFH) ! 目录不匹配:3004002AH (Flash=CFH Required=FFH) ! 内容不匹配:3004002BH (Flash=39H Required=FFH) ! 内容不匹配:3004002CH (Flash=03H Required=FFH) ! 内容不匹配:3004002DH (Flash=01H Required=FFH) ! 内容不匹配:3004002EH (Flash=18H Required=FFH) ! 内容不匹配:3004002FH (Flash=01H Required=FFH) ! 内容不匹配:30040030H (Flash=8CH Required=FFH) ! 内容不匹配:30040031H (Flash=1BH Required=FFH) ! 内容不匹配:30040032H (Flash=C0H Required=FFH) ! 内容不匹配:30040034H (Flash=01H Required=FFH) ! 内容不匹配:30040035H (Flash=DEH Required=FFH) ! 内容不匹配:30040036H (Flash=ACH Required=FFH) ! 内容不匹配处:30040037H (Flash=A7H Required=FFH) ! 页面内容不匹配:30040038H (Flash=D6H Required=FFH) ! 内容不匹配:30040039H (Flash=EFH Required=FFH) ! 页面内容不匹配:3004003AH (Flash=F7H Required=FFH) ! 内容不匹配:3004003BH (Flash=8BH Required=FFH) ! 内容不匹配:3004003CH (Flash=FBH Required=FFH) ! 内容不匹配:3004003DH (Flash=FBH Required=FFH) ! 内容不匹配:3004003EH (Flash=FDH Required=FFH) ! 内容不匹配:3004003FH (Flash=A8H Required=FFH) ! 内容不匹配:30040040H (Flash=8AH Required=FFH) ! 内容不匹配:30040041H (Flash=EEH Required=FFH) ! 内容不匹配:30040042H (Flash=5BH Required=FFH) ! 内容不匹配:30040043H (Flash=E7H Required=FFH) ! 内容不匹配:30040044H (Flash=64H Required=FFH) ! 内容不匹配:30040045H (Flash=9EH Required=FFH) ! 内容不匹配:30040046H (Flash=73H Required=FFH) ! 目录不匹配:30040047H (Flash=8EH Required=FFH) ! 内容不匹配:30040048H (Flash=7CH Required=FFH) ! 内容不匹配:30040049H (Flash=DFH Required=FFH) ! 内容不匹配:3004004DH (Flash=1BH Required=FFH) ! 内容不匹配:3004004EH (Flash=99H Required=FFH) ! 内容不匹配:3004004FH (Flash=19H Required=FFH) ! 30040050H 处内容不匹配(Flash=99H Required=FFH) !30040050H (Flash=99H Required=FFH) ! 页面内容不匹配:30040051H (Flash=59H Required=FFH) ! 内容不匹配:30040052H (Flash=72H Required=FFH) ! 内容不匹配:30040053H (Flash=D5H Required=FFH) ! 页面内容不匹配:30040054H (Flash=18H Required=FFH) ! 内容不匹配:30040055H (Flash=23H Required=FFH) ! 内容不匹配:30040056H (Flash=B4H Required=FFH) ! 目录不匹配:30040057H (Flash=F3H Required=FFH) ! 内容不匹配:30040058H (Flash=66H Required=FFH) ! 页面内容不匹配:30040059H (Flash=76H Required=FFH) ! 页面内容不匹配:3004005AH (Flash=F2H Required=FFH) ! 内容不匹配:3004005BH (Flash=3BH Required=FFH) ! 内容不匹配:3004005EH (Flash=59H Required=FFH) ! 内容不匹配:3004005FH (Flash=9CH Required=FFH) ! 内容不匹配:30040060H (Flash=CCH Required=FFH) ! 内容不匹配:30040061H (Flash=4CH Required=FFH) ! 内容不匹配:30040062H (Flash=88H Required=FFH) ! 内容不匹配:30040064H (Flash=5AH Required=FFH) ! 目录不匹配:30040066H (Flash=C9H Required=FFH) ! 目录不匹配:30040067H (Flash=ADH Required=FFH) ! 目录不匹配:30040068H (Flash=AAH Required=FFH) ! 内容不匹配:30040069H (Flash=02H Required=FFH) ! 内容不匹配:3004006AH (Flash=80H Required=FFH) ! 内容不匹配:3004006BH (Flash=AFH Required=FFH) ! 内容不匹配:3004006CH (Flash=BBH Required=FFH) ! 内容不匹配:3004006DH (Flash=1BH Required=FFH) ! 内容不匹配:3004006EH (Flash=FEH Required=FFH) ! 内容不匹配:30040070H (Flash=B5H Required=FFH) ! 内容不匹配:30040071H (Flash=FEH Required=FFH) ! 目录不匹配:30040072H (Flash=3FH Required=FFH) ! 内容不匹配:30040073H (Flash=EEH Required=FFH) ! 页面内容不匹配:30040074H (Flash=EFH Required=FFH) ! 页面内容不匹配:30040075H (Flash=F7H Required=FFH) ! 页面内容不匹配:30040076H (Flash=FBH Required=FFH) ! 目录不匹配:30040077H (Flash=41H Required=FFH) ! 目录不匹配:30040078H (Flash=F7H Required=FFH) ! 页面内容不匹配:30040079H (Flash=F3H Required=FFH) ! 页面内容不匹配:3004007AH (Flash=F4H Required=FFH) ! 内容不匹配:3004007BH (Flash=E5H Required=FFH) ! 内容不匹配:3004007CH (Flash=FEH Required=FFH) ! 内容不匹配:3004007DH (Flash=7EH Required=FFH) ! 内容不匹配:3004007EH (Flash=BFH Required=FFH) ! 内容不匹配:3004007FH (Flash=1FH Required=FFH) ! 内容不匹配:30040080H (Flash=3CH Required=FFH) ! 30040081H 处内容不匹配:30040081H (Flash=4FH Required=FFH) ! 页面内容不匹配:30040082H (Flash=E6H Required=FFH) ! 内容不匹配:30040083H (Flash=53H Required=FFH) ! 目录不匹配:30040084H (Flash=DCH Required=FFH) ! 内容不匹配:30040085H (Flash=DFH Required=FFH) ! 内容不匹配:30040086H (Flash=EFH Required=FFH) ! 内容不匹配:30040087H (Flash=F7H Required=FFH) ! 内容不匹配:30040088H (Flash=03H Required=FFH) ! 内容不匹配:30040089H (Flash=10H Required=FFH) ! 页面内容不匹配:3004008AH (Flash=D7H Required=FFH) ! 内容不匹配:3004008BH (Flash=BEH Required=FFH) ! 内容不匹配:3004008CH (Flash=F7H Required=FFH) ! 错误太多,无法显示! 错误:Flash Download failed -"Cortex-M7" Flash Load finished at 11:48:11 我所做的改变 : 在 FlashDevc. struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, " KSIS25LE01G (128MB)", EXTSPI, 0x30000000, // AHB base 0x08000000、// 128 MB (1 Gbit) 256, // 页面大小 0, 0xFF, 100, // 程序超时 6000, // 擦除超时 0x001000, 0x000000, SECTOR_END }; FlashPrg.c #include"..\FlashOS.H" // FlashOS 结构 #include"fsl_flexspi.h" #include"app.h" /* 外部函数声明 */ extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src); extern status_t flexspi_nor_flash_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t length); extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId); extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base); extern status_t flexspi_nor_erase_chip(FLEXSPI_Type *base); extern void flexspi_nor_flash_init(FLEXSPI_Type *base); #define FLEXSPI_BASE (FLEXSPI1) #define FLASH_BASE_ADR (0x30000000) /* 强制闪存编程功能(由 FlashOS 调用): int Init(无符号长 adr, // 初始化闪存 无符号长 clk、 无符号长 fnc); int UnInit (unsigned long fnc); // 取消闪存初始化 int EraseSector (unsigned long adr); // 擦除扇区功能 int ProgramPage (unsigned long adr, // Program Page Function) 无符号长 sz、 无符号 char *buf); 可选的 Flash 编程函数(由 FlashOS 调用): int BlankCheck(无符号长 adr,//空白校验 无符号长 sz、 无符号 char pat); int eraseChip (void);//擦除完整设备 无符号长验证(无符号长 adr, // 验证函数 无符号长 sz、 无符号 char *buf); - 如果闪存空间未映射到 CPU 内存空间,则有必要进行 BlanckCheck 检查 - 如果闪存空间未映射到 CPU 内存空间,则有必要进行验证 - 如果未提供 EraseChip,则调用所有扇区的 EraseSector */ /* * 初始化闪存编程功能 * 参数:adr:设备基本地址 * clk: 时钟频率(赫兹) * fnc: 功能代码(1 - 擦除,2 - 编程,3 - 校验) * 返回值:0 - 确定,1 - 失败 */ int Init(无符号长 adr、无符号长 clk、无符号长 fnc) { (void)adr; (void)clk; (void)fnc; flexspi_nor_flash_init(FLEXSPI_BASE); return (0); // 无错误完成 } /* * 去初始化闪存编程功能 * 参数:fnc: 功能代码(1 - 擦除,2 - 编程,3 - 校验) * 返回值:0 - 确定,1 - 失败 */ int UnInit(无符号长 fnc) { (void)fnc; return (0); // 无错误完成 } /* * 擦除全部闪存 * 返回值:0 - 确定,1 - 失败 */ int EraseChip (void) { status_t status = flexspi_nor_erase_chip(FLEXSPI_BASE); 如果 (status != kStatus_Success) { 返回 (1); } 不然 { 返回 (0); } } /* * 擦除闪存中的扇区 * 参数: adr:扇区地址 * 返回值:0 - 确定,1 - 失败 */ int EraseSector (unsigned long adr) { /* 将 AHB 总线地址转换为 Flash 内部地址 */ status_t status = flexspi_nor_flash_erase_sector(FLEXSPI_BASE, adr - FLASH_BASE_ADR); 如果 (status != kStatus_Success) { 返回 (1); } 不然 { 返回 (0); } } /* * 闪存中的程序页 * 参数: adr:页面起始地址 * sz: 页面大小 * buf:页面数据 * 返回值:0 - 确定,1 - 失败 */ int ProgramPage(无符号长 adr、无符号长 sz、无符号 char *buf) { /* 将 AHB 总线地址转换为 Flash 内部地址 */ status_t status = flexspi_nor_flash_program(FLEXSPI_BASE, adr - FLASH_BASE_ADR, (const uint32_t *)buf,sz); 如果 (status != kStatus_Success) { 返回 (1); } 不然 { 返回 (0); } } 目标选择 : khush_THF_0-1763443524441.png khush_THF_1-1763443601226.png 将生成的 .FLM 复制到 c:\Keil_v5\ARM\Flash\ 在我的主项目中添加了该算法: khush_THF_2-1763443717229.png 然后尝试使用新创建的 flm 闪存我的主图像 结果失败了,出现了我上面提到的错误。 当我启动板的时候它会一直持续到引导加载程序然后说找不到有效的图片 Re: unable to program my flash using KEIL and ulink pro when changed flash from 1Gigabit to 2Gigabit 你好@khush_THF、
我使用带有 W25Q512NWEIQ 闪存的 RT1170-EVKB 板在本地测试了本教程。它能在 Keil 中正确编译并生成闪存下载算法。其实现相对简单——它只涉及将相关的 LUT、Pinmux/配置文件和其他其他元器件从 SDK 中的 flexspi_polling 项目移植到 Keil 的 _Template 项目。
此外,我们建议在继续操作之前尝试使用高效密码学标准(SEC)工具在串行下载模式下刷新映像,以确保硬件正常运行。
希望对你有所帮助!
致以最诚挚的问候, Gavin Re: unable to program my flash using KEIL and ulink pro when changed flash from 1Gigabit to 2Gigabit 谢谢 🙂 这个博客真的很有用,但我在给闪存编程时还是出现了一些错误。 我遵循的步骤 我下载了代码 : RT-UFL v1.0 下载地址: https://github.com/JayHeng/RT-UFL/archive/refs/tags/v1.0.zip 然后,我走上了这条路 ..\RT-UFL-1.0\RT-UFL-1.0\版本\mdk 然后使用我的 KIEL ID 打开 MIMXRT_FLEXSPI_UV5.uvprojx。 为了测试算法,我在我的板上测试了具有 1 千兆闪存的算法。 在 flashv.c 下由于我的是 MIMXRT1173,因此未在下面添加注释 struct FlashDevice const FlashDevice = { FLASH_DRV_VERS, // 驱动程序版本,请勿修改! " MIMXRT_FLEXSPI ",//设备名称 EXTSPI,//设备类型 0x30000000,//设备起始地址 0 x04000000,//以字节为单位的设备大小 256,//编程页面大小 0,//保留,必须 为 0 0xFF,//擦除内存的初始内容 100 毫秒 15000,//扇区擦除超时 15000 毫秒 // 指定扇区大小和地址 0x1000, 0x00000000, // 扇区大小 4kB (256 扇区) SECTOR_END }; 它成功编译了然后我把文件 MIMXRT_FLEXSPI_UV5_UFL.FLM " 放到了 c:\Keil_v5\ARM\Flash\。 然后,我打开了我的主项目,想在闪存中为哪个图像编程。 在我的 KEIL 中添加了闪光算法: khush_THF_2-1762747156628.png 然后我尝试闪存,结果出现以下错误 khush_THF_0-1762746958043.png khush_THF_1-1762747108003.png Re: unable to program my flash using KEIL and ulink pro when changed flash from 1Gigabit to 2Gigabit 我做了一些更改,它也被列入了我的 KEIL 中。 " flash 超时。RESET目标然后重试 " 在 KEIL 中它显示以下错误 Er ase Failed! 错误:Flash 下载失败-" Cortex-M7 " khush_THF_0-1762507173641.png khush_THF_1-1762507219355.png 更新了 flashprg.c /////**************************************************************************//** //// * @文件 FlashPrg.c ///* @brief 适用于新设备闪存的闪存编程函数 //// * 版本V1.0.0 //// * @ 日期 10.2018年1月 //// ******************************************************************************/ /////* ///* 版权所有 (c) 2010-2018 Arm Limited。保留所有权利。 //// * //// * SPDX-License-Identifier:Apache-2.0 //// * //// * 根据阿帕奇许可证 2.0 版(许可证)授权;您可以 //// * 除非遵守许可协议,否则不得使用本文件。 //// * 您可从以下网址获取许可证副本 //// * //// *www.apache.org/licenses/LICENSE-2.0 //// * //// * 除非适用法律要求或书面同意,软件 //// * 根据许可协议发布的内容是按原样发布的,不包含以下内容 //// * 任何明示或暗示的保证或条件。 //// * 有关许可和权限的具体语言,请参阅许可。 //// * 许可中的限制。 //// */ //// #include ".\FlashOS.H" // FlashOS 结构 #include #include //#include"FlashOS.h"/* 在 MDK 包中提供 Keil 头文件 */ 静态 内联 void _alg_disable_irq(void){ __asm volatile("cpsid i"); } 静态 内联 void _alg_enable_irq(void){ __asm volatile("cpsie i"); } /********************** 用户配置 ************************/ #ifndefFLEXSPI1_BASE #defineflexspi1_base (0x400CC000u) /* FlexSPI1 寄存器(必要时调整) */ #endif #defineflash_ahb_base (0x30000000u) /* 映射的 XIP 基 */ #defineflash_total_sz (0x08000000u) /* 128MB (1Gb) */ /********************** ISSI Opcodes/Consts ************************/ #defineCMD_RDID 0x9F #defineCMD_WREN 0x06 #defineCMD_RDSR 0x05 #defineCMD_READ 0x03 #defineCMD_PP 0x02 #defineCMD_SE_4K 0x20 #defineCMD_BE_64K 0xD8 #defineCMD_CE 0xC7 /* 银行地址寄存器(BAR)。 #defineCMD_RDBR_16 0x16 #defineCMD_WRBRV_17 0x17 #defineJEDEC_MFG 0x9D #defineJEDEC_MEMTYPE 0x60 #defineJEDEC_CAP 0x21 #definePAGE_SIZE 256u #defineSECTOR_SIZE 0x1000u /********************** 最小 FlexSPI 注册表 *********************/ /* 这是一个缩小的子集,足以处理 IP 命令和 LUT。*/ 类型 结构{ 易变 uint32_tMCR0; // 0x000 易变 uint32_tMCR1; // 0x004 易变 uint32_tMCR2; // 0x008 易变 uint32_tAHBCR; // 0x00C 易变 uint32_tINTEN; // 0x010 易变 uint32_tINTR; // 0x014 易变 uint32_tLUTKEY; // 0x018 易变 uint32_tLUTCR; // 0x01C 易变 uint32_tAHBRXBUF0CR0;// 0x020 易变 uint32_tAHBRXBUF1CR0;// 0x024 易变 uint32_tAHBRXBUF2CR0;// 0x028 易变 uint32_tAHBRXBUF3CR0;// 0x02C 易变 uint32_tAHBRXBUF4CR0;// 0x030 易变 uint32_tAHBRXBUF5CR0;// 0x034 易变 uint32_tAHBRXBUF6CR0;// 0x038 易变 uint32_tAHBRXBUF7CR0;// 0x03C uint32_t RESERVED0[24]; // 0x040...0x09C 易变 uint32_t FLSHCR0[4];// 0x0A0...0x0AC 易变 uint32_t FLSHCR1[4];// 0x0B0...0x0BC 易变 uint32_t FLSHCR2[4];// 0x0C0...0x0CC 易变 uint32_tFLSHCR4; // 0x0D0 uint32_t 保留1[8]; // 0x0D4...0x0F0 易变 uint32_tIPCR0; // 0x0F4 串行闪存地址 易变 uint32_tIPCR1; // 0x0F8 SeqID/SeqNum + DataSize 易变 uint32_tIPCR2; // 0x0FC(如果存在;不一定使用) volatil e uint32_t IP CMD;//0x100 触发器 易变 uint32_tIPRXFCR; // 0x104 RX FIFO 控制 易变 uint32_tIPTXFCR; // 0x108 TX FIFO 控制 易变 uint32_t DLLCR[2]; // 0x10C... uint32_t 保留2[26]; // 至 0x180 易变 uint32_tTXDATAn; // 重复写入。 易变 uint32_tRXDATAn; // 重复读取。 uint32_t 保留3[70]; // ... 易变 uint32_t LUT[64]; // 0x200..LUT (64 x 32 位) }FLEXSPI_Regs; #defineFLEXSPI1 ((FLEXSPI_Regs *)flexspi1_base) /* 位/键 */ #defineMCR0_MDIS (1u<<1) #defineintr_ipcmddone (1u<<1) #defineINTR_IPRXWA (1u<<2) #defineINTR_IPTXWE (1u<<3) #defineintr_iprxwater intr_iprxwa #defineintr_iptxwater intr_iptxwe #defineLUTKEY_VALUE (0x5AF05AF0u) #defineLUTCR_UNLOCK (0x02u) #defineLUTCR_LOCK (0x01u) /* IPCR1 助手:布局因每个 RT 而异;我们将其编码为[SEQID:0..5][SEQNUM:8..10][IDATSZ:16..31] */ #defineIPCR1_SEQID(x) ((x) & 0x3Fu) #defineIPCR1_SEQNUM(x) (((x) & 0x7u) << 8) #defineIPCR1_IDATSZ(x) (((x) & 0xFFFFu) << 16) /* LUT 编码助手(简化) */ #defineLUT_OP(op,pads,imm) ( ((op)&0x3F) |(((pads)&3)<<8) |(((imm)&0xFF)<<10) ) #defineLUT_CMD(c) LUT_OP(0x01,0,c) #defineLUT_ADDR(位) LUT_OP(0x02,0,(位)) #defineLUT_READ(len) LUT_OP(0x09,0,(len)) #defineLUT_WRITE(len) LUT_OP(0x08,0,(len)) #defineLUT_STOP() LUT_OP(0x00,0,0) /******************* 3 字节 LUT(24 位)***********************/ 枚举{ L_WREN=0, L_RDSR=4, L_RDID=8, L_READ=12, L_PP=16, L_SE4K=20, L_BE64=24, L_CE=28, L_RDBR=32, L_WRBR=36}; 静态 const uint32_tLUT_3B[] ={ /* L_WREN */ LUT_CMD(CMD_WREN)、 LUT_STOP(), 0, 0, /* L_RDSR */ LUT_CMD(CMD_RDSR)、 LUT_READ(1), 0, 0, /* L_RDID */ LUT_CMD(CMD_RDID)、 LUT_READ(3), 0, 0, /* L_READ */ LUT_CMD(CMD_READ)、 LUT_ADDR(24), LUT_READ(0), LUT_STOP(), /* L_PP */ LUT_CMD(CMD_PP)、 LUT_ADDR(24), LUT_WRITE(0), LUT_STOP(), /* L_SE4K */ LUT_CMD(CMD_SE_4K)、LUT_ADDR(24), 0, 0, /* L_BE64 */ LUT_CMD(CMD_BE_64K)、LUT_ADDR(24),0, 0, /* L_CE */ LUT_CMD(CMD_CE)、 LUT_STOP(), 0, 0, /* L_RDBR */ LUT_CMD(CMD_RDBR_16)、 LUT_READ(1), 0, 0, /* L_WRBR */ LUT_CMD(cmd_wrbrv_17)、 LUT_WRITE(1), 0, 0, }; /******************* 低级帮助程序 *********************/ 静态 void flexspi_wait_ip_done(void) { 虽然(!(FLEXSPI1->INTR &intr_ipcmddone)){/* 自旋 */} FLEXSPI1->INTR =intr_ipcmddone;/* 清除 */ } 静态 void flexspi_load_lut(const uint32_t *lut, 无符号 字数) { FLEXSPI1->MCR0 |=MCR0_MDIS; /* 禁用 */ FLEXSPI1->LUTKEY =LUTKEY_VALUE; FLEXSPI1->LUTCR =LUTCR_UNLOCK; 为(无符号i=0; i<字数 &&i<64; ++i) { FLEXSPI1->LUT[i] = LUT[i]; } FLEXSPI1->LUTCR =LUTCR_LOCK; FLEXSPI1->MCR0 &= ~MCR0_MDIS; /* 启用 */ } /* 发布 IP 命令序列。如果 tx!=NULL -> 写入;如果 rx!=NULL -> 读取。len 以字节为单位。*/ 静态 void flexspi_ip_xfer(uint8_t seqIdx, uint32_t addr, void *buf, uint32_t ......。, int is_read) { /* 清除 FIFO */ FLEXSPI1->IPRXFCR = 1;/* 清除 RX FIFO */ FLEXSPI1->IPTXFCR = 1;/* TX FIFO 清除 */ FLEXSPI1->IPCR0 =addr; /* 串行闪存地址(使用低24b) */ FLEXSPI1->IPCR1 = IPCR1_SEQID(seqIdx) | IPCR1_SEQNUM(1) | IPCR1_IDATSZ(len); 如果(!is_read &&buf &&len) { /* 以字为单位推送 TX 数据 */ const uint8_t *p =(const uint8_t*)buf; 为(uint32_ti=0;i<len;){ uint32_tw=0; 无符号n=0; 为(; n<4 &&i<len; ++n,++i) w |=((uint32_t)p[i]) <<(8*n); FLEXSPI1->TXDATAn =w; } } FLEXSPI1 -> IPCMD = 1; /* 触发器 */ flexspi_wait_ip_done(); 如果(is_read &&buf &&len) { uint8_t *p =(uint8_t*)buf; 为(uint32_ti=0;i<len;){ uint32_tw = FLEXSPI1->RXDATAn; 为(无符号n=0;n<4 &&i<len;++n,++i) p[i] =(uint8_t)(w >>(8*n)); } } } 静态 void 鹪鹩(虛擬){ flexspi_ip_xfer(L_WREN、 0, NULL, 0, 0); } 静态 uint8_t rdsr(uint8_trdsr (){ uint8_tsr=0; flexspi_ip_xfer(L_RDSR、0,&sr、1,1); 返回sr; } 静态 int wait_wip(uint32_t ms){ 当(ms--){ 如果((rdsr() & 1u)==0) 返回 0; } 返回 1; } /* 从绝对地址计算 BAR。BANK = 128MB 范围的 [26:24] 位。*/ 静态 int set_bank_for_addr(uint32_t absAdr){ uint8_t银行 =(uint8_t)((absAdr -flash_ahb_base) >> 24);/* 0..7 */ uint8_tcur=0; flexspi_ip_xfer(L_RDBR、0,&cur、1,1); 如果((cur & 0x07) ==bank) 返回 0; 鹪鹩(); flexspi_ip_xfer(L_WRBR、0,&银行1,0); 返回 0; } /*********************** FlashOS API ************************/ int 初始化(无符号 长 adr, 无符号 长 时钟, 无符号 长 fnc) { (( void)adr; (( void )adr)clk; ((void)adr; ()fnc; /*--------------------功能安全:禁用 IRQ 以避免 ISR/XIP 总线冲突--------------------*/ __asm volatile("cpsid i"); // 在闪存操作激活时屏蔽所有中断 /*--------------------可选的:禁用监视程序(如果在启动时启用)--------------------*/ // RT117x 的示例:禁用 WDOG3 和 RTWDOG(如需要) // wdog3->wcr&= ~wdog_wcr_wde_mask; // rtwdog->cs = (rtwdog->cs& ~rtwdog_cs_en_mask) | rtwdog_cs_update_mask; ---------------- 最简 FlexSPI 启动 ---------------- */ //确保时钟和键盘多路复用器在外部配置(启动代码)。 //为了功能安全起见,在编程期间禁用 AHB 预取/缓存。 FLEXSPI1->AHBCR = 0x00000000u; // 禁用 AHB 预取/缓存 /*--------------------清除并加载 LUT 表(3 字节操作)--------------------*/ 为(无符号i = 0; i < 64; i++) FLEXSPI1->LUT[i] = 0; flexspi_load_lut(LUT_3B、 sizeof(LUT_3B)/sizeof(uint32_t)); /*--------------------验证 JEDEC ID(可选的强制执行)--------------------*/ uint8_t id[3] ={0}; flexspi_ip_xfer(L_RDID、 0, id、 3, 1); // 取消下面几行的注释,以执行严格的 JEDEC ID 匹配 // if (id[0] != JEDEC_MFG || id[1] != JEDEC_MEMTYPE || id[2] != JEDEC_CAP) { // __asm volatile ("cpsie i"); // 返回前重新启用 IRQ // 返回 1; // } ---------------- 将银行寄存器设置为 0(起始窗口 0x000000�0xFFFFFF) ---------------- */ 如果(set_bank_for_addr(flash_ahb_base)){ __asm volatile("cpsie i"); 返回 1; } ---------------- 安全启动后重新启用 IRQ */ __asm volatile("cpsie i"); 返回 0; // 成功 } int UnInit(无符号 长 fnc) { (void)fnc; 返回 0; } int 擦除芯片(无效) { _alg_disable_irq(); 鹪鹩(); flexspi_ip_xfer(L_CE、 0, NULL, 0, 0); intrc = wait_wip(100000); // 100 s _alg_enable_irq(); 返回rc; } int 擦除扇区(无符号 长 adr) { _alg_disable_irq(); 如果(set_bank_for_addr((uint32_t)adr)) { _alg_enable_irq(); 返回 1; } 鹪鹩(); flexspi_ip_xfer(L_SE4K,(uint32_t)adr、 NULL, 0, 0); intrc = wait_wip(6000); _alg_enable_irq(); 返回rc; } int 程序页(无符号 长 adr, 无符号 长 sz, 无符号 字符串 *buf) { 而(sz){ 无符号page_off =(无符号)(adr &(PAGE_SIZE-1)); 无符号块 =PAGE_SIZE -page_off; 如果(chunk>sz) chunk=(无符号)sz; 如果(set_bank_for_addr((uint32_t)adr)) 返回 1; 鹪鹩(); flexspi_ip_xfer(L_PP、(uint32_t)adr,buf,chunk、 0); 如果(wait_wip(1000)) 返回 1; adr +=chunk; buf +=chunk; sz -=chunk } 返回 0; } /*********************** FlashDevice ************************/ /* 使用 EXTSPI 设备类型;扇区布局使用偏移量(不是绝对地址)。*/ /* 集成说明: * - 如果您的 FlexSPI1 寄存器基数不同,请更新 FLEXSPI1_BASE。 * - 确保启动时配置了 FlexSPI1 和焊盘的时钟/pinmux。 * - 该算法使用单 SPI(1-1-1)操作,以实现最大兼容性。 * - 为了提高速度,可以添加快速读取 (0x0B),并使用哑循环和四倍使能。 */ 更新了 FlashDev.c ///**************************************************************************//** // * @文件 FlashDev.c //* @brief 新设备闪存的闪存设备描述 // *@versionV1.0.0 // * @日期 10.2018 年 1 月 // ******************************************************************************/ ///* //* 版权所有 (c) 2010-2018 Arm Limited。保留所有权利。 // * // * SPDX-License-Identifier:Apache-2.0 // * // * 根据 Apache 许可 2.0 版(许可)授权;您可以 // * 除非遵守许可协议,否则不得使用本文件。 // * 您可以从以下网址获取许可证副本 // * // *www.apache.org/licenses/LICENSE-2.0 // * // 除非适用法律要求或书面同意,软件 // * 根据许可协议发布的内容是按原样发布的,不包含以下内容 // * 任何明示或暗示的保证或条件。 // * 有关许可和权限的具体语言,请参阅许可。 // * 许可证规定的限制。 // */ // #include ".\FlashOS.H" // FlashOS 结构 #defineflash_ahb_base (0x30000000u) /* 映射的 XIP 基 */ #defineflash_total_sz (0x08000000u) /* 128MB (1Gb) */ 结构FlashDevice constFlashDevice = { flash_drv_vers、 " PKISSI 1Gb (128MB) SPI 或非 3B+BAR @0x30000000-SDKFree ", EXTSPI、 flash_ahb_base、 flash_total_sz、 256, /* 页 */ 0, 0xFF, 100, /* 程序超时(毫秒) */ 6000, /* 扇区擦除超时(毫秒) */ 0x1000, 0x00000000, /* 从偏移 0 开始的 4KB 扇区 */ SECTOR_END }; Re: unable to program my flash using KEIL and ulink pro when changed flash from 1Gigabit to 2Gigabit 你好@khush_THF、
感谢您对 NXP MIMXRT 系列的关注!
您的算法文件放入相应文件夹后无法识别。这可能是因为 *.FLM 文件无效,因此 Keil 无法识别。您可以试试 JLink 的通用下载算法RT-UFL。它可与市场上大多数闪存一起使用,但需要 JLink。
中文指导博客:
痞子衡嵌入式:超级下载算法RT-UFL v1.0在Keil MDK下的使用 - 痞子衡 - 博客园
致以最诚挚的问候, Gavin
View full article