请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:EK-TM4C123GXL 主题中讨论的其他器件:TM4C123、 TM4C123GH6PM
大家好:)
我想在 tm4c123板的 Flash 存储器中写入和读取数据
我使用了此 valvano 代码:
// FlashProgram.c //在 LM4F120/TM4C123上运行 //提供用于初始化闪存存储器、将 // 32位数据写入闪存、将一组32位数据写入闪存、 //以及擦除1KB 块的函数。 // Daniel Valvano // 2014年10月21日 //此示例随书 一起提供:"嵌入式系统:与 Arm Cortex M 微控制器的实时交互"、 ISBN:978-1463590154、Jonathan Valvano、版权所有(c) 2014 "嵌入式系统:用于 ARM Cortex-M 微控制器的实时操作系统"、 ISBN: 978-1466468863、Jonathan Valvano、版权所有(c) 2014 版权所有(Jonathan W. Valvano、valvano@mail.utexas.edu) 您可以使用、编辑、运行或分发此文件 只要上述版权声明仍然存在 、此软件就"按原样"提供。 本 软件不适用任何明示、暗示或法定的保证、包括但不限于对适销性和特定用途适用性的暗示保证。 在任何情况 下、对于任何原因造成的特殊、偶然或必然损害、VALVANO 概不负责。 有关我的课程、我的研究和我的书籍的更多信息、请参阅 users.ece.utexas.edu/.../ * /#include #include "FlashProgram.h" #define FLASH_FMA_R (*((volatile uint32_t *) 0x400FD000) #define FLASH_FMA_OFFSET_MAX 0x0003FFFF //地址偏移最大 值#define FLASH_FMD_R (*((volatile uint32_t *) 0x400FD004) #define FLASH_FMC_R (*((volatile uint32_t *) 0x400FD008) #define FLASH_FMC_WRKEY 0xA4420000 //闪存写入密钥(FLASH_BOOTCFG_R SET 的 KEY 位) #define FLASH_FMC_WRCKEY2 0x71D50000 //闪存写入密钥(FLASH_BOOTCFG_R 的 KEY 位被清除) #define FLASH_FMC_MERASE 0x00000004 //整体擦除闪存 存储器#define FLASH_FMC_ERASE 0x00000002 //擦除闪存存储器#define FLASH_FMC_WRITE 页 0x00000001 //将一个字写入闪存 #define FLASH_FMC2_R (*((volatile uint32_t *) 0x400FD020) #define FLASH_FMC2_WRBUF 0x00000001 //缓冲闪存写入 #define FLASH_FWBW_R (*((volatile UINT32_t *) 0x400FD100) #define FLASH_BOOTCFG_R (*((volatile UINT32_t *) 0x400FE1D0) )#define FLASH_BOOTCFG_KEY 0x00000010 //键选择 void DisableInterrupts (void);//禁用中断 void EnableInterrupts (void);//启用中断 long StartCrisical (void);//前面的 I 位,禁用中断 void EndCrisical (long SR);//将 I 位恢复为先前的值 void WaitForInterrupt (void); //低功耗模式 //检查地址偏移对于写入操作是否有效 //写入地址必须是4字节对齐且在范围 内静态 int WriteAddrValid (uint32_t addr){ //检查地址偏移是否适用于写入 //必须是4字节对齐 返回((((addr % 4)=0)&& (Addr <= FLASH_FMA_OFFSET_MAX)); } //检查地址偏移量是否对批量写入操作有效 //批量写入地址必须是32字(128字节)对齐并且在范围 内静态 int MassWriteAddrValid (uint32_t addr){ //检查地址偏移量是否对批量写入有效 //必须是32字( 128字节)(ADDR)(128) = 0)&&(addr <= FLASH_FMA_OFFSET_MAX); } //检查地址偏移对于擦除操作是否有效 //擦除地址必须是1KB 对齐且在范围 内静态 int EraseAddrValid (uint32_t addr){ //检查地址偏移是否适用于擦除 //必须是1KB 对齐 返回((((addr % 1024)=0)&&(addr <= FLASH_FMA_OFFSET)}); }MAX} //------ Flash_Init ------------ //此函数对于 LM3S811 //微控制器上的闪存存储器的写入和擦除操作至关重要。 但较新的处理器的工作方式略有 不同//对于 TM4C123、 闪存和 EEPROM 存储器的时序参数// 与 PLL 一起配置。 这个函数原型被保留为 //尝试使 之更容易在// LM3S811、TM4C123和 TM4C1294之间重复使用程序代码。 //输入:systemClockFreqMHz 系统时钟频率(单位为 MHz) //输出:none void Flash_Init (uint8_t systemClockFreqMHz){ //不执行任何操作;在 PLL_Init()中配置的闪存和 EEPROM 存储器 //如果处理器正在闪存存储器中执行代码, //假设所有内容都已正确配置 }--- Flash_Write ------------ //将32位数据写入闪存的给定地址。 //输入:Addr 4字节对齐的要写入的闪存存储器地址 // 数据32位数据 //输出:'NOERROR'(如果成功),'ERROR'(如果失败)(在 FlashProgram.h 中定义) //注意:在写入 int Flash_Write (uint32_t addr,uint32_t data)时禁用中断{ uint32_t flashkey; if (WriteAddrValid (addr))){ DisableInterrupts(); //可以是可选步骤 //等待硬件空闲 while (flash_FMC_R&(flash_FMC_write|flash_FMC_ERASE|flash_FMC_MERASE)){ //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; FLASH_FMD_R =数据; FLASH_FMA_R = addr; if (flash_BOOTCFG_R&flash_BOOTCFG_KEY){ //默认情况下,键为0xA442 闪存密钥= FLASH_FMC_WRKEY; } 否则{ //否则,键为0x71D5 闪存密钥= FLASH_FMC_WRKEY2; } FLASH_FMC_R =(闪存键|FLASH_FMC_WRITE); //开始写入 while (flash_FMC_R&flash_FMC_write){ //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; //等待完成(~3到4 μ s) EnableInterrupts(); 返回 NOERROR; } 返回错误; } //----- Flash_WriteArray ---------- //从给定地址开始将一组32位数据写入闪存。 //输入:指向32位数据数组的源指针 // ADDR 4字节对齐的闪存存储器地址、用于开始写入 // 32位写入的计数// 输出:成功写入的次数;返回值=如果完全成功则计数 //注意:在80MHz 时,需要678微秒才能写入10个字 //注意:在写入 int Flash_WriteArray 时禁用中断(uint32_t *源、uint32_t addr、uint16_t count){ uint16_enfulls = 0; while (((successfullWrites < count)&&(Flash_Write (addr + 4* successfullWrites、source[successfullWrites])=NOERROR)){ 成功写入=成功写入+ 1; } 返回成功写入; } //--- Flash_FastWrite ---------- //从给定地址开始将一组32位数据写入闪存。 //这是 Flash_WriteArray()的两倍,但地址必须 //对齐128字节,并且计数必须<= 32。 //输入:指向32位数据数组的源指针 // ADDR 128字节对齐的闪存存储器地址、用于开始写入 // 32位写入的计数数量(<=32) //输出:成功写入的数量;返回值=完全成功时计数 //注意:在80MHz 时、写入10个字需要335uec //注意:在写入 int Flash_FastWrite 时禁用中断(uint32_t * source、uint32_t addr、uint16_t){uint32_t flasht key}计数 ; uint32_t volatile * flash_FWBn_R =(uint32_t volatile*) 0x400FD100; int 写入= 0; if (MassWriteAddrValid (addr))}{ DisableInterrupts(); //可以是可选步骤 while (flash_FMC2_R&flash_FMC2_WRBUF){ //等待硬件空闲 //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; while ((写入< 32)&&(写入< count)){ FLASH_FWBn_R[写入]=源[写入]; 写入=写入+ 1; } FLASH_FMA_R = addr; if (flash_BOOTCFG_R&flash_BOOTCFG_KEY){ //默认情况下,键为0xA442 闪存密钥= FLASH_FMC_WRKEY; } 否则{ //否则,键为0x71D5 闪存密钥= FLASH_FMC_WRKEY2; } FLASH_FMC2_R =(闪存键|FLASH_FMC2_WRBUF); //开始写入 while (flash_FMC2_R&flash_FMC2_WRBUF){ //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; //等待完成(~3到4 μ s) EnableInterrupts(); } 返回写入; }//------- Flash_Erase ------------ //擦除1KB 的闪存块。 //输入:Addr 1KB 对齐的闪存存储器地址擦除 //输出:'NOERROR'如果成功,'ERROR'如果失败(在 FlashProgram.h 中定义) //注意:在擦除 int Flash_Erase (uint32_t addr)时禁用中断{ uint32_t flashkey; if (EraseAddrValid (addr)){ DisableInterrupts(); //可以是可选步骤 //等待硬件空闲 while (flash_FMC_R&(flash_FMC_write|flash_FMC_ERASE|flash_FMC_MERASE)){ //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; FLASH_FMA_R = addr; if (flash_BOOTCFG_R&flash_BOOTCFG_KEY){ //默认情况下,键为0xA442 闪存密钥= FLASH_FMC_WRKEY; } 否则{ //否则,键为0x71D5 闪存密钥= FLASH_FMC_WRKEY2; } FLASH_FMC_R =(闪存键|FLASH_FMC_ERASE); //开始擦除1KB 块 while (flash_FMC_R&flash_FMC_erase){ //稍后执行:如果时间过长,则返回错误 //请记住重新启用中断 }; //等待完成(~3到4 μ s) EnableInterrupts(); 返回 NOERROR; } 返回错误; }
秘书长的报告
但是
EnableInterrupts();和 DisableInterrupts();函数会显示此错误消息:
..\Flash.AXF:错误:L6218E:未定义符号 DisableInterrupts (引用自 fm.o)。
..\Flash.AXF:错误:L6218E:未定义符号 EnableInterrupts (引用自 fm.o)。