当前位置: 首页 > news >正文

Flash数据写入及ECC纠错关键函数:Fapi_issueProgrammingCommand()

这个函数是我在学习ecc过程中最大的阻碍了。最近重新看了文档并且完成了代码的移植,想对这个函数进行一下详细的说明。具体的参考文档如下,可以自行下载:

通过网盘分享的文件:TI_F28004X文档
链接: https://pan.baidu.com/s/1cwt--BRsx7UTLY8S-rBKpw?pwd=hbgy 提取码: hbgy 
--来自百度网盘超级会员v8的分享

这里面包含了,F28004X的数据手册和技术参考手册,以及TI提供的Flash_API的使用说明。

之前的文章将Flash_API例程移植到程序代码流程及遇到的问题-CSDN博客对TI提供的例程进行了说明,这里面最复杂的函数可以说就是Fapi_issueProgrammingCommand()了。作为将数据写入flash并且生成ecc的函数,它也是整个流程中最重要的一个函数了。

它有AutoEccGeneration,DataOnly,DataandECC和EccOnly四种模式 ,其中Auto可以理解为全自动,不需要用户去定义任何关于ECC的设置,程序自动就可以在对应的地址生成ECC代码。但是在调试程序的时候,我们为了验证ECC的效果会给数据设置错误,来验证ECC的纠错能力,这种情况下使用Auto模式是不合适的。

手册中提出:AutoEccGeneration program data and ECC together without inserting any intentional errors. 就是说自动情况下用户不能干预这个过程,没有办法引入错误。但是可以使用:Data和ECConly模式来分别处理(Fapi_DataOnly mode and Fapi_EccOnly modes can be used to program the data and ECC respectively.); 或者采用DataAndEcc模式,它可以被看作两种only模式的结合,(is not different than that of using Fapi_DataOnly and Fap_EccOnly modes together. ).并且手册中也更推荐我们使用后者,说他具有可以同时对数据和ECC进行执行操作的优点(However, this mode is beneficial when both the data and the calculated ECC can be programmed at the same time. )。

所以这四种模式中,使用最为广泛的是AutoDataAndEcc这两种。前者的程序执行不受任何外部影响,是全自动的,用起来简单直接。但是,如果用户想要手动对数据进行处理(比如反转一位数据),就是用后者。

下面对函数中所需参数进行解释:

1. pu32StartAddress[in]: 所使用的flash的起始地址;

2. pu16DataBuffer[in]: 指向数据缓冲区地址的指针;

3. u16DataBufferSizeInWords[in]: 数据缓冲区中16位数据的数量;这里特别解释一下:16位数据=一个字,也就是数据缓冲区中有多少个字需要写入

4. pu16EccBuffer[in]:指向ECC的地址指针;

5.u16EccBufferSizeInBytes[in]:ECC区域写入的8位数据的数量;8位数据=一个字节。这里是根据ECC的计算得到的,64位数据得到8位ECC,也就是说8位数据可以生成1位ECC,ECC的计算最少需要8为数据来完成,所以这里的参数以一个字节为单位。

针对这一点:Fapi_AutoEccGeneration 规定了:一次性要写入64位或者成倍数量的数据(When using this mode, all the 64 bits of the data should be programmed at the same time for a given 64-bit aligned memory address.)也就是说u16DataBufferSizeInWords[in]至少是4且应为四的倍数。使用Auto的时候,参数4,5设置为0即可 ( Arguments 4 and 5 are ignored.)。

而Fapi_DataAndEcc则进一步指出了 data与ecc的关系:如果数据缓冲区的长度是4个字,ECC的数据应为1个字节,如果是8个字应该对应2个字节ECC数据 (If the data buffer length is 4 16-bit words, the ECC buffer must be 1 byte. If the data buffer length is 8 16-bit words, the ECC buffer must be 2 bytes in length. )。也就是说,对于128位对齐的地址,可以一次性写入4/8个16位的字,但是对于64位对齐的地址一次性只能写入4个16位的字。
文档里面还在提醒中明确了:数据缓冲区的最大长度不能超过8,那对应的ECC缓冲区长度不能超过2 (The length of pu16DataBuffer and pu16EccBuffer cannot exceed 8 and 2, respectively.)。也就是说如果想要对某一个地址范围内的数据进行ECC验证,需要使用循环进行操作,每次最多输入8个字(64位)的数据。

这个地方真的地址,位数感觉很乱,经常犯傻。

这个函数给出了一些状态码,在调试程序的过程中可以通过打印状态值来查看具体错误的原因:

Return Value
• Fapi_Status_Success (success)
• Fapi_Error_AsyncIncorrectDataBufferLength (failure: Data buffer size specifiedis incorrect)
• Fapi_Error_AsyncIncorrectEccBufferLength (failure: ECC buffer size specified is incorrect)
• Fapi_Error_AsyncDataEccBufferLengthMismatch (failure: Data buffer size either is not 64-bit
aligned or data length crosses the 128-bit aligned memory boundary)
• Fapi_Error_FlashRegsNotWritable (failure: Flash register writes failed. The user should make sure that the API is executing frm the same zone as that of the target address for flash operation OR the user should unlock before the flash operation.

下面给个例子:

1.AutoEccGeneration:定义了一个长度位256的数组,数组中的数据类型位uint16_t。自动模式下设置了一次写入8个数据,那么每次数组Buffer的指针也就需要+8才能,完成循环操作。

    #pragma DATA_SECTION(Buffer, "DataBufferSection")#define  WORDS_IN_FLASH_BUFFER    0xFFuint16_t Buffer[WORDS_IN_FLASH_BUFFER + 1];    Fapi_StatusType  oReturnCheck;Fapi_FlashStatusType  oFlashStatus;Fapi_FlashStatusWordType  oFlashStatusWord;uint16 i=0;uint32 u32Index = 0;for (i=0, u32Index = Bzero_Sector6_start;(u32Index < (Bzero_Sector6_start + WORDS_IN_FLASH_BUFFER)) &&(oReturnCheck == Fapi_Status_Success); i+= 8, u32Index+= 8){//只能分块写入oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, Buffer+i, 8,0, 0, Fapi_AutoEccGeneration);while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);}

2. DataAndEcc模式:

在这个模式下不能自动生成ecc,需要使用提供的Fapi_calculateEcc( uint32 Address, uint64 Data)函数来先对对应数据的ecc进行计算: 

需要提供带计算数据的地址以及64位数据,因此需要把存储在buffer中的数据给组合成64位的。我在这里是分别对低64位和高64位数据的ecc进行计算,得到ECC_LB和ECC_HB两部分:

       #define  WORDS_IN_FLASH_BUFFER    0xFFuint16_t Buffer[WORDS_IN_FLASH_BUFFER + 1];uint32   *Buffer32 = (uint32 *)Buffer;uint64   *data_low, *data_high;uint8    ECC_LB,ECC_HB;uint8    eccbuffer[2];// 构造低64-bit和高64bitdata_low = (uint64*)(Buffer32+i);data_high = (uint64*)(Buffer32+i+2);ECC_LB = Fapi_calculateEcc(u32Index, *data_low);ECC_HB = Fapi_calculateEcc(u32Index+4, *data_high);eccbuffer[0] = ECC_LB;eccbuffer[1] = ECC_HB;

这样就能够完成数据和ecc的写入: 

oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, Buffer + i, 8, eccbuffer, 1, Fapi_DataAndEcc);

所以还是使用auto模式比较方便。

相关文章:

  • Acrobat 中使用 JavaScript 禁止 PDF 打印
  • CSS实现元素撑满剩余空间的5种方法
  • linux中的locate命令
  • 探索MCP Server Chart:AI赋能的统计图表自动生成工具
  • 柑橘检测模型
  • 中国AI Top30 访问量排行榜 - 2025年05月
  • 基于mapreduce的气候分析系统设计与实现
  • 刀客doc:WPP走下神坛
  • 论文参考文献干干货
  • LeetCode 1143. 最长公共子序列 | 动态规划详解
  • 【MV】为什么需要DeepSeek 的分析: AI 替代编舞师
  • Java高频面试之并发编程-28
  • 剑指offer23_树的子结构
  • 深度学习之模型压缩三驾马车:基于ResNet18的模型剪枝实战(3)
  • ubuntu安装libevent
  • 如何连上Nacos
  • 产品成本分析怎么做?从0到1搭建全生命周期分析框架!
  • JDK版本如何丝滑切换
  • BeanUtil.copyProperties()进行属性拷贝时如何忽略NULL值——CopyOptions配置详解
  • CKA考试知识点分享(12)---configmap
  • 大厂做网站/谷歌google play下载
  • 网站服务器租用需要注意的点/大连seo网站推广
  • 辽宁电力建设监理有限公司网站/黑帽seo是什么
  • wordpress 做外贸站/网络推广和信息流优化一样么
  • ic外贸网站建设/一个新产品的营销方案
  • 深圳优秀网站建设定制/自媒体推广渠道有哪些