当前位置: 首页 > 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模式比较方便。

http://www.xdnf.cn/news/1005355.html

相关文章:

  • 【微软RDP协议】微软RDP协议技术架构特点与跨地域应用实践
  • Qt 环境搭建全流程详解:从下载到创建首个项目
  • 服务器部署普罗米修斯监控CentOS8
  • 2025 TechViz 新功能:3D协作,技术进化,体验升级
  • TypeScript 项目配置
  • 时事新闻:2025 伦敦科技周
  • Odoo 基于规则的线索自动分配实践指南
  • C++ STL容器汇总
  • 大中台应用的层次抽象
  • bisheng系列(三)- 本地部署(后端 1.2版本)
  • 亚马逊云服务器配置推荐
  • PCL 导入VS配置的大量依赖项名称快速读取
  • LLaMA Factory 微调教程:如何构建高质量数据集?
  • 重启杀手--误操作梳理
  • 命令模式:解耦请求与执行的优雅之道
  • 高可靠性隔离驱动设计:NSi6602B-DSWR双通道栅极驱动器技术解析
  • stm32温湿度-超声波-LCD1602结合项目(Proteus仿真程序)
  • 判断一阶微分方程是线性齐次、线性非齐次或非线性,以及非线性方程是半线性或拟线性
  • 前端Vue3国际化开发 :使用vue-i18n库和Element Plus 组件实现
  • Tensorflow 基础知识:变量、常量、占位符、Session 详解
  • strncpy_s与_TRUNCATE
  • 汉化langfuse踩坑记录--docker卷挂载未生效问题修复及langfuse启动
  • 基于 SpringBoot + Vue 在线点餐系统(前后端分离)
  • javascript入门
  • LangGraph--搭建官方机器人聊天(带工具的)教程
  • vue 导航 + router-view 局部刷新
  • AI技术专题:电商AI专题
  • java使用aspose读取word里的图片
  • YOLOv8 模块添加与修改讲解:从源码修改到配置文件配置
  • Nacos服务注册失败解决方案