TMS320F280049系列文章之第N章 Bootloader(TMS320F28004x Flash API Reference Guide)的学习

TMS320F280049系列文章目录

第一章 获取相关组件(注意:下载或安装不要有中文路径)
第二章 新建工程(注意:代码移植时,索引路径需要重新设置(绝对地址))
… …
第N章 Bootloader(TMS320F28004x Flash API Reference Guide)的学习


文章目录


前言

本文章采用CCS10.3.1(CCS软件版本)及C2000Ware_4_01(SDK-设计资源)进行TMS320F280049(DSP芯片)系列学习

  • TMS320F28004x Flash API Reference Guide官方手册的学习/翻译(如果有不对的地方,在后续的学习过程中会优化更新)

第N章 Bootloader(TMS320F28004x Flash API Reference Guide)的学习

1.介绍

  • TI的TMS320F28004x Flash API库(F021_API_F28004x_FPU32.lib或F021_ROM_API_F28004x_FPU32.lib)功能,可用于删除、程序和验证TMS320F28004x设备上的Flash

1.1 参考材料

  • TMS320F28004x Delfino™ Microcontrollers Data Manual
  • TMS320F28004x™Piccolo Microcontrollers Technical Reference Manual

1.2 函数列表格式

  • 函数、内在编译器或宏的条目的通用格式
1.2.1 function_name()函数的简短描述
  • 概述
parameter_1 [in]       Type details of parameter_1
parameter_2 [out]      Type details of parameter_2
parameter_n [in/out]   Type details of parameter_3 
  • 因素
  • 参数传递的分类如下:
    • in - 表示函数在参数中使用了一个或多个值,而不存储任何变化
    • out - 表示函数保存了一个或多个参数中的值。您可以检查保存的值,找出有关应用程序的有用信息
    • in/out - 表示函数更改了您给它的参数中的一个或多个值,并保存结果。您可以检查保存的值,找出有用的信息,有关您的应用程序
  • 描述
  • 描述函数。本节还介绍了任何特殊的特性或限制,可能应用:
    • 在某些条件下,功能块或可能块所请求的操作
    • 函数具有可能不明显的前置条件
    • 函数有限制或特殊行为
  • 条件
  • 指定在此函数使用时存在的任何限制
  • 返回值
  • 指定函数返回的任何值
  • 请参阅
  • 列出与该函数相关的其他函数或数据类型
  • 示例实施
  • 提供一个示例(或对示例的引用),说明函数的使用。随着Flash API函数,这些示例可能使用C2000Ware中提供的device_support或driverlib中的函数,演示在应用程序中使用给定的Flash API函数

2.TMS320F28004x Flash API 概述

2.1 介绍

  • Flash API是一个例程库,当以正确的顺序使用正确的参数调用时,它会擦除、编程或验证Flash内存(Flash API也可用于编程和验证OTP内存)

注:请阅读Flash和OTP内存映射和Flash等待状态的数据手册规格说明书

2.2 API概述

  • Table 1 初始化功能
API函数描述
Fapi_initializeAPI()初次使用或频率更改初始化API
  • Table 2 Flash状态机(FSM)功能
API函数描述
Fapi_setActiveFlashBank()初始化Flash存储控制器(FMC)和块的擦除和程序命令
Fapi_issueAsyncCommandWithAddress()针对给定的地址向FSM发出擦除扇区命令
Fapi_issueProgrammingCommand()设置编程所需的寄存器,并向FSM发出该命令
Fapi_issueProgrammingCommandForEccAddress()将一个ECC地址重新映射到主数据空间,然后调用Fapi_issueProgrammingCommand()来编程ECC
Fapi_issueFsmSuspendCommand()暂停FSM命令、程序数据和擦除扇区
Fapi_issueAsyncCommand()针对不需要地址的操作,向FSM发出命令(清除状态、程序恢复、删除恢复、清除更多)
Fapi_checkFsmForReady()返回Flash状态机(FSM)是否准备就绪或是否繁忙
Fapi_getFsmStatus()从Flash存储控制器返回FMSTAT状态寄存器值
  • Table 3 读取功能
API函数描述
Fapi_doBlankCheck()根据已擦除的状态验证指定的Flash存储范围
Fapi_doVerify()根据提供的值验证指定的Flash存储范围
Fapi_calculatePsa()计算指定Flash存储范围的PSA值
Fapi_doPsaVerify()根据提供的PSA值验证指定的Flash存储范围
  • Table 4 信息功能
API函数描述
Fapi_getLibraryInfo()返回特定于API库的已编译版本的信息
  • Table 5 实用程序功能
API函数描述
Fapi_flushPipeline()刷新FMC中的数句缓存
Fapi_calculateEcc()计算所提供的地址和64位的ECC
Fapi_isAddressEcc()确定该地址是否落在ECC范围内
Fapi_remapEccAddress()将ECC地址重新映射到相应的主地址
Fapi_calculateFletcherChecksum()函数计算指定的内存范围的Fletcher校验和

注:
Fapi_getDeviceInfo()和Fapi_getBankSectors()在TMS320F28004x Flash API中已被删除,因为用户可以获得这些信息(例如:bank数、pin数、扇区数等等,从TRM中提供的其他资源)
不再提供Fapi_UserDefinedFunctions.c文件,因为该文件中的函数现在合并在Flash API库中(有关使用Flash API时维护看门狗服务的信息,请查看第2.3.3节)

2.3 API使用

  • 描述使用各种API函数的流程
2.3.1 初始化流程
2.3.1.1 设备通电后
  • 在设备第一次通电后,必须先调用Fapi_initializeAPI () 函数,然后才能使用其他API函数 (Fapi_getLibrarylnfo ()函数除外)
  • 此过程将初始化API的内部结构
2.3.1.2 FMC和块设置
  • 在第一次执行Fash操作之前,必须调用Fapi_setActiveFlashBank () 函数
  • 在F28004x设备上只有一个FMC,尽管有两个Flash块,因此,调用这个函数一次,并使用Fapi_FlashBank0作为传递的参数就足够了
  • 在切换Flash块时无需调用此功能
2.3.1.3 关于系统频率变化
  • 如果在对Fapi_initializeAPI ()函数进行初始调用后更改了系统操作频率,则必须再次调用该函数,才能使用任何其他API函数(Fapi_getLibrarylnfo ()函数除外)
  • 此过程将更新API的内部状态变量
2.3.2 API构建
2.3.2.1 对象库文件
  • Flash API对象文件以标准的通用对象文件格式(COFF)分布

注:编译需要启用“启用对GCC扩展的支持”选项(编译器6.4.0及以上版本默认启用此选项)

2.3.2.2 分配文件
  • 以下API文件分布在C2000Ware\libraries\flash_api\f28004x\文件夹中:

  • Library文件
    • TMS320F28004x Flash API被嵌入到该设备的引导ROM中。这不同于其他API的C28x设备中完全是软件。
    • 提供了一个软件库(F021_API_F28004x_FPU32.lib)和一个BootROM API符号库(F021_ROM_API_F28004x_FPU32.lib)
    • 为了使应用程序能够删除或编写Flash/OTP,这两个库文件中的一个应该包含在应用程序中符号库的优先项

  • Include文件
    • F021_F28004x_C28xh:主文件包括TMS320F28004x设备。此文件设置特定于编译的定义,包含F021.h主文件包含文件

  • 以下包括的文件不应该直接包含在用户的代码中,但在这里列出以供用户参考:
    • F021.h:包括文件列出所有公共API函数,并包括所有其他包括文件
    • Init.h:定义API初始化结构
    • Registers_C28x.h:小端闪存控制器寄存器结构
    • Registers.h:所有寄存器实现通用的定义,包括适当的寄存器,包括所选设备类型的文件
    • type.h:包含API使用的所有枚举和结构
    • Constants/Constants.h:一些C2000设备常见的常数定义
    • Constants/F28004x.h:F28004x器件的常数定义

2.3.3 API使用关键
  • 以下是一些关于API使用的重要事实:
    • Flash API函数的名称以前缀“Fapi_”开头
    • Flash API不配置PLL。用户应用程序应该根据需要配置PLL,并将配置好的CPUCLK值传递给Fapi_initializeAPI()函数(此函数的详细信息将在本文档后面给出)
    • 在调用Flash API函数之前,请始终按照设备数据手册配置等待状态。如果应用程序配置的等待状态不适合应用程序的操作频率,则Flash API将发出一个错误。更多细节请参见Fapi_Set激活库()功能
    • Flash API的执行是可中断的。但是,不应该有正在进行擦除/程序操作的任何读取/获取访问。在单银行设备中,Flash API函数、调用Flash API函数的用户应用程序函数以及任何ISR(中断服务例程)都必须从RAM中执行。例如,下面显示的整个代码片段应该从RAM执行,而不仅仅是Flash API函数。这样做的原因是,Fapi_issueAsyncCommandWithAddress()函数向FSM发出了擦除命令,但它不会等待擦除操作结束。只要FSM忙于当前的操作,就不应该有Flash访问。在双银行设备中,Flash API可以从一个银行执行,以对另一个块执行擦除/程序操作
//
// Erase a Sector
//
oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,(uint32*)0x0080000);
//
// Wait until the erase operation is over
//
while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}

• Flash API不配置(启用/禁用)看门狗。用户应用程序可以配置看门狗,并根据需要为其提供服务。因此,不再提供Fapi_ServiceWatchdogTimer()函数
• Flash API在内部使用EALLOW和EDIS来允许/不允许写入受保护的寄存器
• 主阵列闪存编程必须与64位地址边界对齐,并且在每个写/删除周期中,每个64位字只能被编程一次
• 允许对数据和ECC分别进行编程。然而,每个64位数据字和16位ECC字在每次写入/擦除周期中只能被编程一次
• DCSM OTP编程必须与128位地址边界对齐,每个128位字只能编程一次。例外情况是:-DCSM OTP中的DCSM Zx-LINKPOINTER1和Zx-LINKPOINTER2的值应该一起编程,并且可以根据DCSM操作的要求一次编程1位。–DCSM OTP中的DCSM Zx-LINKPOINTER3值可以在64位边界上一次编程1位,以将其与Zx-脉冲交换锁分离,后者只能编程一次
• TMS320F28004x设备中没有泵浦信号量
• 不应该为链接指针的位置编程ECC。当为程序操作提供的起始地址是三个链接指针地址中的任何一个时,API就会跳过对ECC进行编程。API将使用Fapi_DataOnly模式来编程这些位置,即使用户将Fapi_AutoEccGeneration或Fapi_DataAndEcc模式作为编程模式参数。不支持编程这些位置的Fapi_EccOnly模式。用户应用程序在这里应该谨慎行事。应注意为应用程序中的链接指针位置维护一个单独的结构/部分。不要将这些字段与其他DCSM OTP设置混合。如果其他字段与链接指针混合,API也会跳过针对非链接指针位置的编程ECC。这将导致应用程序中的ECC错误
• 当使用INTOSC作为时钟源时,一些SYSCLK频率范围需要一个额外的等待状态来执行擦除和程序操作。操作结束后,不需要额外的等待状态。详情请参考数据手册
• 为了避免区域1和区域2之间的冲突,在DCSM寄存器中提供了一个信号量(FLSEM)来配置Flash寄存器。用户应用程序应该在初始化Flash和调用Flash API函数之前配置这个信号量寄存器。详情请参考TMS320F28004x短笛微控制器技术参考手册
• 请注意,Flash API函数不配置任何DCSM寄存器。用户应用程序应该确保配置所需的DCSM设置。例如,如果一个区域是安全的,那么应该从同一区域执行Flash API,以便能够擦除或编程该区域的Flash扇区。或者这个区域应该被解锁。如果没有,FlashAPI写入Flash寄存器将不会成功。Flash API不检查对Flash寄存器的写入是否正在完成。它按照擦除/程序序列的需要写入它们,并在写入完成后返回。这将导致Flash API返回错误的成功状态。例如,调用Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector,Adderes)时可以返回成功状态,但这并不意味着扇区擦除成功。应该使用Fapi_getFSMStatus()和Fapi_doBlankCheck()来检查清除状态
• Flash API已嵌入到此设备的ROM中。为了在ROM中使用Flash API,用户必须在C2000Ware_x_xx_xx_xx\libraries\flash_api\f28004x\lib.中嵌入C2000Ware中提供的F021_ROM_API_F28004x_FPU32.lib(ROM API符号)库当使用ROM API时,不需要将F021_API_F28004x_FPU32.lib(软件API)嵌入到应用程序中以实现Flash擦除/程序的目的。当使用ROM API时,请确保不要在链接器命令文件中为API库分配flash加载地址和ram运行地址,因为它已经存在于ROM中。但是,任何调用Flash API函数的应用程序函数必须从RAM(单个银行设备)或没有针对闪存删除/程序操作的其他银行(双银行设备)执行。还要注意,不应该有任何访问正在进行闪存擦除/程序操作的闪存库/OTP的权限

3.API函数

3.1 初始化函数

3.1.1 Fapi_initializeAPI()(初始化Flash API)
  • 格式
  • Fapi_StatusType Fapi_initializeAPI(Fapi_FmcRegistersType *poFlashControlRegister, uint32 u32HclkFrequency)
  • 参数
  • poFlashControlRegister [in]:指向闪存控制器寄存器的基本地址的指针。使用F021_CPU0_BASE_ADDRESS
  • u32HclkFrequency [in]:系统时钟频率,单位为MHz
  • 描述
  • 在执行任何其他Flash API操作之前,需要此函数来初始化Flash API
  • 如果系统频率或RWAIT发生变化,也必须调用此函数

注:在调用此函数之前,必须设置RWAIT寄存器值

  • 返回值
  • Fapi_Status_Success(成功)
  • 示例
#include “F021_F28004x_C28x.h”
#define CPUCLK_FREQUENCY 100 /* 100 MHz System frequency */

int main(void)
{
	//
	// Initialize System Control
	//
	Device_init();
	//
	// Call Flash Initialization to setup flash waitstates
	// This function must reside in RAM
	//
	Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
	//
	// Jump to RAM and call the Flash API functions
	//
	Example_CallFlashAPI();
}

#pragma CODE_SECTION(Example_CallFlashAPI, ramFuncSection);
void Example_CallFlashAPI(void)
{
	Fapi_StatusType oReturnCheck;
	EALLOW;
	//
	// This function is required to initialize the Flash API based on
	// System frequency before any other Flash API operation can be performed
	// Note that the FMC register base address and system frequency are passed as the parameters
	//
	oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Fapi_setActiveFlashBank function initializes Flash banks
	// and FMC for erase and program operations.
	// Note: It does not matter which bank is passed as the parameter to initialize.
	// Both Banks and FMC get initialized with one function call unlike F2837xS.
	// Hence, there is no need to execute Fapi_setActiveFlashBank() for each bank.
	//
	oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Bank0 Erase Program
	//
	/* User code for further Bank0 flash operations */
	.
	.
	.
	.
	//
	// Bank1 Erase Program
	//
	//
	// There is no need to call Fapi_initializeAPI() and Fapi_setActiveFlashBank()
	// when switching to Bank1 Flash operations
	//
	/* User code for further Bank1 flash operations */
	.
	.
	.
	.
	EDIS;
	//
	// Example is done here
	//
	Example_Done();
}

3.2 Flash状态机功能

3.2.1 Fapi_setActiveFlashBank()(初始化FMC的擦除和程序操作。在F28004x设备上只有一个FMC,尽管有两个闪存bank。因此,调用这个函数一次,并使用Fapi_FlashBank0作为传递的参数就足够了。在切换闪存存储组时,无需调用此功能)
  • 格式
  • Fapi_StatusType Fapi_setActiveFlashBank(Fapi_FlashBankType oNewFlashBank)
  • 参数
  • oNewFlashBank [in]:应使用Fapi_FlashBank0,这将为两个bank配置FMC,不需要用Fapi_FlashBank1作为参数来调用这个函数
  • 描述
  • 此功能设置闪存控制器,以便对bank执行进一步的操作。需要在Fapi_initializeAPI()函数之后和执行任何其他Flash API操作之前调用此函数
  • 返回值
  • Fapi_Status_Success(成功)
  • Fapi_Error_InvalidBank(故障:指定的bank在设备上不存在)
  • Fapi_Error_InvalidHclkValue(故障:系统时钟不匹配指定的等待值)
  • Fapi_Error_OtpChecksumMismatch(故障:计算的TI OTP校验和与TI OTP中的值不匹配)
  • 示例
  • 同3.1.1示例
3.2.2 Fapi_issueAsyncCommandWithAddress()(向Flash状态机发出带有用户提供的扇区地址的擦除命令)
  • 格式
  • Fapi_StatusType Fapi_issueAsyncCommandWithAddress(Fapi_FlashStateCommandsType oCommand, uint32 *pu32StartAddress)
  • 参数
  • oCommand [in]:要向FSM发出的命令,请使用“Fapi_EraseSector”
  • pu32StartAddress [in]:用于擦除操作的闪存扇区地址
  • 描述
  • 此函数向用户提供的扇区地址的Flash状态机发出擦除命令。此函数不会等到擦除操作结束;它只是发出命令并返回。因此,当使用Fapi_EraseSector命令时,此函数总是返回成功状态。用户应用程序必须等待FMC完成擦除操作,然后才能返回到任何类型的Flash访问。Fapi_checkFsmForReady()函数可用于监视已发出的命令的状态

注:
此函数在发出erase命令后不检查FMSTAT。当FSM完成了擦除操作时,用户应用程序必须检查FMSTAT值。FMSTAT表示在擦除操作过程中是否出现了任何故障。用户应用程序可以使用Fapi_getFSMStatus函数来获取FMSTAT值。此外,用户应用程序应该使用Fapi_doBlankCheck()功能来验证Flash是否被删除

  • 返回值
  • Fapi_Status_Success(成功)
  • Fapi_Error_FeatureNotAvailable(失败:用户请求的是不支持的命令)
  • Fapi_Error_FlashRegsNotWritable(失败: Flash寄存器写入失败。用户应确保该API是在与目标地址相同的区域执行的,或者用户应在flash操作前解锁)
  • 示例
#include “F021_F28004x_C28x.h”
#define CPUCLK_FREQUENCY 100 /* 100 MHz System frequency */

int main(void)
{
	//
	// Initialize System Control
	//
	Device_init();
	//
	// Call Flash Initialization to setup flash waitstates
	// This function must reside in RAM
	//
	Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
	//
	// Jump to RAM and call the Flash API functions
	//
	Example_CallFlashAPI();
}

#pragma CODE_SECTION(Example_CallFlashAPI, ramFuncSection);
void Example_CallFlashAPI(void)
{
	Fapi_StatusType oReturnCheck;
	Fapi_FlashStatusType oFlashStatus;
	EALLOW;
	//
	// This function is required to initialize the Flash API based on
	// System frequency before any other Flash API operation can be performed
	// Note that the FMC register base address and system frequency are passed as the parameters
	//
	oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Fapi_setActiveFlashBank function initializes Flash banks
	// and FMC for erase and program operations.
	// Note: It does not matter which bank is passed as the parameter to initialize.
	// Both Banks and FMC get initialized with one function call unlike F2837xS.
	// Hence, there is no need to execute Fapi_setActiveFlashBank() for each bank.
	//
	oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Bank0 Flash operations
	//
	//
	// Erase Bank0 Sector4
	//
	oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32 *)0x84000);
	//
	// Wait until FSM is done with erase sector operation
	//
	while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error (oReturnCheck);
	}
	//
	// Read FMSTAT contents to know the status of FSM
	// after erase command to see if there are any erase operation
	// related errors
	//
	oFlashStatus = Fapi_getFsmStatus();
	if (oFlashStatus!=0)
	{
		FMSTAT_Fail();
	}
	//
	// Do blank check.
	// Verify that the sector is erased.
	//
	oReturnCheck = Fapi_doBlankCheck((uint32 *)0x84000, 0x800, &oFlashStatusWord);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// * User code for further Bank0 flash operations *
	//
	.
	.
	.
	.
	//
	// Bank1 Flash operations
	//
	//
	
	// There is no need to call Fapi_initializeAPI() and Fapi_setActiveFlashBank()
	// when switching to Bank1 Flash operations
	//
	
	//
	// Erase Bank1 Sector2
	//
	oReturnCheck = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32 *)0x92000);
	
	//
	// Wait until FSM is done with erase sector operation
	//
	while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
	
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error (oReturnCheck);
	}
	
	//
	// Read FMSTAT register contents to know the status of FSM
	// after erase command to see if there are any erase operation
	// related errors
	//
	oFlashStatus = Fapi_getFsmStatus();
	if (oFlashStatus != 0)
	{
		FMSTAT_Fail();
	}
	//
	// Do blank check.
	// Verify that the sector is erased.
	//
	oReturnCheck = Fapi_doBlankCheck((uint32 *)0x92000, 0x800, &oFlashStatusWord);
	
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	
	//
	// * User code for further Bank1 flash operations *
	//
	.
	.
	.
	.
	EDIS;
	
	//
	// Example is done here
	//
	Example_Done();
}
3.2.3 Fapi_issueProgrammingCommand()(设置数据,并发出程序命令到有效的Flash或OTP内存地址)
  • 格式
  • Fapi_StatusType Fapi_issueProgrammingCommand(uint32 *pu32StartAddress, uint16 *pu16DataBuffer, uint16 u16DataBufferSizeInWords, uint16 *pu16EccBuffer, uint16 u16EccBufferSizeInBytes, Fapi_FlashProgrammingCommandType oMode)
  • 参数
  • pu32StartAddress [in]:在Flash中的启动地址中,数据和ECC将被编程
  • pu16DataBuffer [in]:指向数据缓冲区地址的指针
  • u16DataBufferSizeInWords [in]:数据缓冲区中的16位字数
  • pu16EccBuffer [in]:指向ECC缓冲区地址的指针
  • u16EccBufferSizeInBytes [in]:ECC缓冲区中的8位字节数
  • oMode [in]:指示要使用的编程模式:
    • Fapi_DataOnly 程序只提供数据缓冲区
    • Fapi_AutoEccGeneration 编程的数据缓冲区和自动生成和编程的ECC
    • Fapi_DataAndEcc 程序的数据和ECC缓冲区
    • Fapi_EccOnly 程序只有ECC缓冲区

注:
pu16EccBuffer应包含与128位对齐的主阵列/OTP地址处的数据相对应的ECC。pu16体外缓冲器的LSB对应于主阵列的下64位,而pu16体外缓冲器的MSB对应于主阵列的上64位

  • 描述
  • 此函数根据所提供的参数设置Flash状态机的编程寄存器。它为用户提供了四种不同的编程模式,供用户在不同的场景中使用,如表所示(使用不同的编程模式)
编程模式(oMode)使用的参数使用目的
Fapi_DataOnlypu32StartAddress, pu16DataBuffer, u16DataBufferSizeInWords当任何自定义编程实用程序或用户应用程序(嵌入/使用Flash API)必须分别对数据和相应的ECC进行编程时使用。数据使用Fapi_DataOnly模式进行编程,然后使用Fapi_EccOnly模式进行编程的ECC。通常,大多数编程实用程序并不单独计算ECC,而是使用Fapi_AutoEccGeneration模式。然而,一些安全应用程序可能需要在其Flash映像中插入有意的ECC错误(使用Fapi_AutoEccGeneration模式时不可能),以在运行时检查SECDED(单错误纠正和双错误检测)模块的运行状况。在这种情况下,ECC是单独计算的(使用附录E中提供的ECC计算算法或在适用时使用Fapi_calculateEcc()函数)。应用程序可能希望根据需要在主阵列数据或ECC中插入错误。在这种情况下,在错误插入后,可以使用Fapi_DataOnly模式和Fapi_EccOnly模式分别对数据和ECC进行编程
Fapi_AutoEccGenerationpu32StartAddress, pu16DataBuffer, u16DataBufferSizeInWords当任何自定义编程实用程序或用户应用程序(嵌入/使用Flash API在运行时编写Flash以存储数据或执行固件更新)必须将数据和ECC一起编写程序而不插入任何有意的错误时使用。这是最显著使用的模式
Fapi_DataAndEccpu32StartAddress, pu16DataBuffer, u16DataBufferSizeInWords, pu16EccBuffer, u16EccBufferSizeInBytes该模式的目的与同时使用Fapi_DataOnly模式和Fap_EccOnly模式并没有什么不同。但是,当数据和计算出的ECC可以同时进行编程时,这种模式是有益的
Fapi_EccOnlypu16EccBuffer, u16EccBufferSizeInBytes请参阅针对Fapi_DataOnly模式给出的使用目的

注:用户必须始终为他们的Flash编程ECC,因为ECC检查是在通电时启用的

  • Programming modes:
  • Fapi_DataOnly-此模式仅在指定地址对Flash中的数据部分进行编程。它可以从1位到8 16位的单词。但是,请查看为此函数提供的限制,以了解flash编程数据大小的限制。提供的程序起始地址加上数据缓冲区长度不能跨越128位对齐的地址边界。当使用此模式时,参数4和参数5将被忽略
  • Fapi_AutoEccGeneration-此模式将在Flash中编程所提供的数据以及自动生成的ECC。对在64位内存边界上对齐的每个64位数据计算ECC。因此,当使用这种模式时,应该为一个给定的64位对齐的内存地址对所有的64位数据进行同时编程。未提供的数据被视为所有1(0x FFFF)。一旦对64位数据计算ECC并编程,这些64位就不能重新编程(除非扇区被擦除),因为新的ECC值将与先前编程的ECC值发生冲突。当使用此模式时,如果起始地址是128位对齐的,那么可以根据需要同时编程8位或4个16位字。如果起始地址是64位对齐,而不是128位对齐,则只能同时编程4个16位字。此选项也存在Fapi_DataOnly的数据限制。参数4和参数5将被忽略

注:
Fapi_AutoEccGeneration模式将在Flash中编程所提供的数据部分以及自动生成的ECC。对64位对齐的地址和相应的64位数据计算ECC。未提供的任何数据都将被视为0x FFFF。请注意,当编写一个自定义编程实用程序,该程序在代码项目的输出文件中流,并将每个部分一次编写到flash时,这具有实际意义。如果一个64位字跨越多个部分(即包含一个部分的结束和另一个部分的开始),那么在编程第一个部分时,不能假设64位字中缺失的数据值为0x FFFF。当您去编程第二部分时,您将无法为第一个64位字的ECC进行编程,因为它已经(错误地)使用假设的0x FFFF对缺失的值进行了计算和编程。避免此问题的一种方法是在代码项目的链接器命令文件中的64位边界上对齐链接到flash的所有部分
下面是一个示例:

SECTIONS
{
	.text   : > FLASH, PAGE = 0, ALIGN(4)
	.cinit  : > FLASH, PAGE = 0, ALIGN(4)
	.const  : > FLASH, PAGE = 0, ALIGN(4)
	.econst : > FLASH, PAGE = 0, ALIGN(4)
	.pinit  : > FLASH, PAGE = 0, ALIGN(4)
	.switch : > FLASH, PAGE = 0, ALIGN(4)
}

如果不在flash中对齐这些部分,则需要跟踪一个部分中不完整的64位单词,并将它们与完成64位单词的其他部分中的单词结合起来。这将是很难做到的。因此,建议在64位边界上对齐您的部分

  • Fapi_DataAndEcc-此模式将在指定的地址为Flash中提供的数据和ECC进行编程。所提供的数据必须在64位内存边界上对齐,并且数据的长度必须与所提供的ECC相关联。这意味着,如果数据缓冲区长度为4 16位字,则ECC缓冲区必须为1字节。如果数据缓冲区长度为8 16位字,则ECC缓冲区的长度必须为2字节。如果起始地址是128位对齐的,则应根据需要同时编程8位或4个16位字。如果起始地址是64位对齐,而不是128位对齐,那么应该同时只编写4个16位字。pu16Ecc缓冲器的LSB对应于主阵列的下64位,pu16e缓冲器的MSB对应于主阵列的上64位。Fapi_calculateEcc()函数可用于计算一个给定的64位对齐地址和相应的数据的ECC
  • Fapi_EccOnly-此模式将只对指定的地址(应提供闪存主阵列地址,而不是相应的ECC地址)的闪存ECC内存空间中的ECC部分进行编程。它可以编程2个字节(LSB和MSB在ECC内存中的一个位置),也可以编程1个字节(LSB在ECC内存中的一个位置)。pu16Ecc缓冲器的LSB对应于主阵列的下64位,pu16e缓冲器的MSB对应于主阵列的上64位。在使用此模式时,将忽略参数2和参数3

注:
pu16数据缓冲和pu16Ecc缓冲的长度不能超过8和2
此函数在发出程序命令后不检查FMSTAT。当FSM完成程序操作时,用户应用程序必须检查FMSTAT值。FMSTAT表示在程序操作过程中是否出现了任何故障。用户应用程序可以使用Fapi_getFsmStatus函数来获取FMSTAT值。此外,用户应用程序应该使用Fapi_doVerify()功能来验证Flash程序是否正确编程

  • 这个函数不会等到程序操作结束;它只是发出命令并返回。因此,用户应用程序必须等待FMC完成程序操作,然后才能返回到任何类型的Flash访问。Fapi_checkFsmForReady()函数应用于监视已发出的命令的状态
  • 条件
  • 如上所述,该函数一次只能编程128位(给定提供的地址是128位对齐)。如果用户想要编程的次数更多,那么应该在一个循环中调用这个函数,每次编程128位(或根据应用程序需要的64位)
  • 主阵列闪存编程必须与64位地址边界对齐,每个64位字只能编程一次
  • 可以对数据和ECC单独编程。然而,每个64位数据字和16位ECC字在每次写入或擦除周期中只能被编程一次
  • DCSM OTP编程必须与128位地址边界对齐,每个128位字只能编程一次。例外情况是:- DCSM OTP中的DCSM Zx-LINKPOINTER1和Zx-LINKPOINTER2的值应该一起编程,并且可以根据DCSM操作的要求一次编程1位;– DCSM OTP中的DCSM Zx-LINKPOINTER3值可以在64位边界上一次编程1位,以将其与Zx-脉冲交换锁分离,后者只能编程一次
  • ECC不应该为链接指针的位置进行编程。API将为这些位置发出Fapi_DataOnly命令
  • 返回值
  • Fapi_Status_Success(成功)
  • Fapi_Error_AsyncIncorrectDataBufferLength(失败:数据缓冲区大小指定不正确)
  • Fapi_Error_AsyncIncorrectEccBufferLength(失败:指定的ECC缓冲区大小不正确)
  • Fapi_Error_AsyncDataEccBufferLengthMismatch(失败:数据缓冲区大小不是64位对齐或数据长度跨越128位对齐的内存边界)
  • Fapi_Error_FlashRegsNotWritable(失败: Flash寄存器写入失败。用户应该确保API执行的是与flash操作的目标地址相同的区域,或者用户应该在flash操作之前解锁。
  • 示例(此示例不显示擦除操作。请注意,一个扇区在它可以被重新编程之前应该被擦除)
#include “F021_F28004x_C28x.h”
#define CPUCLK_FREQUENCY 100 /* 100 MHz System frequency */
int main(void)
{
	//
	// Initialize System Control
	//
	Device_init();
	//
	// Call Flash Initialization to setup flash waitstates
	// This function must reside in RAM
	//
	Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
	//
	// Jump to RAM and call the Flash API functions
	//
	Example_CallFlashAPI();
}

#pragma CODE_SECTION(Example_CallFlashAPI, ramFuncSection);
void Example_CallFlashAPI(void)
{
	Fapi_StatusType oReturnCheck;
	Fapi_FlashStatusType oFlashStatus;
	uint16 au16DataBuffer[8] = {0x0001, 0x0203, 0x0405, 0x0607, 0x0809, 0x0A0B, 0x0C0D, 0x0E0F};
	uint32 *DataBuffer32 = (uint32 *)au16DataBuffer;
	uint32 u32Index = 0;
	EALLOW;
	//
	// This function is required to initialize the Flash API based on
	// System frequency before any other Flash API operation can be performed
	// Note that the FMC register base address and system frequency are passed as the parameters
	//
	oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Fapi_setActiveFlashBank function initializes Flash banks
	// and FMC for erase and program operations.
	// Note: It does not matter which bank is passed as the parameter to initialize.
	// Both Banks and FMC get initialized with one function call unlike F2837xS.
	// Hence, there is no need to execute Fapi_setActiveFlashBank() for each bank.
	//
	oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	//
	// Bank0 Program
	//
	//
	// Program 0x200 16-bit words in Bank0 Sector 4
	//
	for (u32Index = 0x84000; (u32Index < 0x84200) && (oReturnCheck == Fapi_Status_Success); u32Index += 8)
	{
		//
		// Issue program command
		//
		oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, au16DataBuffer, 8, 0, 0, Fapi_AutoEccGeneration);
		//
		// Wait until the Flash program operation is over
		//
		while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
		
		if (oReturnCheck != Fapi_Status_Success)
		{
			Example_Error (oReturnCheck);
		}
		//
		// Read FMSTAT register contents to know the status of FSM after
		// program command to see if there are any program operation related errors
		//
		oFlashStatus = Fapi_getFsmStatus();
		
		if (oFlashStatus != 0)
		{
			//
			//Check FMSTAT and debug accordingly
			//
			FMSTAT_Fail();
		}
		
		//
		// Verify the programmed values
		//
		oReturnCheck = Fapi_doVerify((uint32 *)u32Index, 4, DataBuffer32, &oFlashStatusWord);
		if (oReturnCheck != Fapi_Status_Success)
		{
			//
			// Check Flash API documentation for possible errors
			//
			Example_Error(oReturnCheck);
		}
	}
	
	//
	// * User code for further Bank0 flash operations *
	//
	.
	.
	.
	.
	//
	// Bank1 Program
	//
	
	//
	// There is no need to call Fapi_initializeAPI() and Fapi_setActiveFlashBank()
	// when switching to Bank1 Flash operations
	//
	
	//
	// Program 0x200 16-bit words in Bank1 Sector 2
	//
	for(u32Index = 0x92000; (u32Index < 0x92200) && (oReturnCheck == Fapi_Status_Success); u32Index += 8)
	{
		//
		// Issue program command
		//
		oReturnCheck = Fapi_issueProgrammingCommand((uint32 *)u32Index, au16DataBuffer, 8,0, 0, Fapi_AutoEccGeneration);
		
		//
		// Wait until the Flash program operation is over
		//
		while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
		
		if (oReturnCheck != Fapi_Status_Success)
		{
			Example_Error (oReturnCheck);
		}
		
		//
		// Read FMSTAT register contents to know the status of FSM after
		// program command to see if there are any program operation related errors
		//
		oFlashStatus = Fapi_getFsmStatus();
		
		if (oFlashStatus != 0)
		{
			//
			//Check FMSTAT and debug accordingly
			//
			FMSTAT_Fail();
		}
		
		//
		// Verify the programmed values
		//
		oReturnCheck = Fapi_doVerify((uint32 *)u32Index, 4, DataBuffer32, &oFlashStatusWord);
		
		if (oReturnCheck != Fapi_Status_Success)
		{
		//
			// Check Flash API documentation for possible errors
			//
			Example_Error(oReturnCheck);
		}
	}
	//
	// * User code for further Bank1 flash operations *
	//
	.
	.
	.
	.
	EDIS;
	//
	// Example is done here
	//
	Example_Done();
}
3.2.4 Fapi_issueProgrammingCommandForEccAddresses()(将一个ECC地址重新映射到数据地址,并调用Fapi_issueProgrammingCommand())
  • 格式
  • Fapi_StatusType Fapi_issueProgrammingCommandForEccAddress(uint32 *pu32StartAddress, uint16 *pu16EccBuffer, uint16 u16EccBufferSizeInBytes)
  • 参数
  • pu32StartAddress [in]:ECC编程Flash中的ECC启动地址
  • pu16EccBuffer [in]:指向ECC缓冲区地址的指针
  • u16EccBufferSizeInBytes [in]:ECC缓冲区中的字节数如果字节数为1,则会被编程为LSB(64位以下的ECC)。不能使用此功能单独编程。如果字节数为2,则ECC的LSB和MSB字节都被编程
  • 描述
  • 该函数将把ECC内存空间中的一个地址重新映射到相应的数据地址空间,然后调用Fapi_issueProgrammingCommand()对所提供的ECC数据进行编程。使用Fapi_EccOnly模式的Fapi_issueProgrammingCommand()的相同限制也适用于此功能。pu16Ecc缓冲器的LSB对应主阵列的下64位,pu16Ecc缓冲器的MSB对应主阵列的上64位

注:
pu16ec缓冲器的长度不能超过2
此函数在发出程序命令后不检查FMSTAT。当FSM完成程序操作时,用户应用程序必须检查FMSTAT值。FMSTAT表示在程序操作过程中是否出现了任何故障。用户应用程序可以使用Fapi_getFSMStatus函数来获取FMSTAT值

  • 返回值
  • Fapi_Status_Success(成功)
  • Fapi_Error_AsyncIncorrectEccBufferLength(失败:指定的数据缓冲区大小不正确)
  • Fapi_Error_FlashRegsNotWritable(失败: Flash寄存器写入失败。用户应该确保API执行的是与flash操作的目标地址相同的区域,或者用户应该在flash操作之前解锁
3.2.5 Fapi_issueFsmSuspendCommand()(发出Flash状态机挂起命令)
  • 格式
  • Fapi_StatusType Fapi_issueFsmSuspendCommand(void)
  • 参数
  • None
  • 描述
  • 此函数发出一个立即暂停的命令,它将暂停FSM命令,程序和删除扇区,当它们是当前的活动命令。使用Fapi_getFsmStatus()来检查该操作是否成功
  • 返回值
  • Fapi_Status_Success(成功)
3.2.6 Fapi_issueAsyncCommand()(向Flash状态机发出命令。请参见有关此函数可以发出的命令列表的说明)
  • 格式
  • Fapi_StatusType Fapi_issueAsyncCommand(Fapi_FlashStateCommandsType oCommand)
  • 参数
  • oCommand [in]:要向FSM发出的命令
  • 描述
  • 此函数向Flash状态机发出一个命令,以获取不需要任何额外信息(如地址)的命令。典型的命令是清除状态、程序恢复、擦除恢复和清除_更多。这个函数不会等到命令结束;它只是发出命令并返回。因此,用户应用程序必须等待FMC完成给定的命令,然后才能返回到任何类型的Flash访问。Fapi_checkFsmForReady()函数可用于监视已发出的命令的状态
  • 以下是这些命令的详细信息:
    • Fapi_ClearStatus:执行此命令将清除FMSTAT寄存器中的ILA、PGV、EV、CSTAT、电压表和INVDAT位。Flash API在发出程序或擦除命令之前发出此命令
    • Fapi_ClearMore:执行此命令清除清除状态命令清除的一切,此外,清除FMSTAT寄存器中的ESUSP和PSUSP位
    • Fapi_ProgramResume:执行此命令将恢复先前挂起的程序操作。当挂起处于非活动状态时,发出恢复命令将无效。请注意,在暂停以前的程序操作时,无法启动新的程序操作
    • Fapi_EraseResume:执行此命令将恢复先前挂起的擦除操作。当挂起处于非活动状态时,发出恢复命令将无效。请注意,在暂停以前的擦除操作时,无法启动新的擦除操作

注:
此函数在发出该命令后不检查FMSTAT。当FSM完成操作时,用户应用程序必须检查FMSTAT值。FMSTAT表示在操作过程中是否出现了任何故障。用户应用程序可以使用Fapi_getFsmStatus函数来获取FMSTAT值

  • 返回值
  • Fapi_Status_Success(成功)
  • 示例
#include “F021_F28004x_C28x.h”
#define CPUCLK_FREQUENCY 100 /* 100 MHz System frequency */

int main(void)
{
	//
	// Initialize System Control
	//
	Device_init();
	//
	// Call Flash Initialization to setup flash waitstates
	// This function must reside in RAM
	//
	Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, DEVICE_FLASH_WAITSTATES);
	//
	// Jump to RAM and call the Flash API functions
	//
	Example_CallFlashAPI();
}

#pragma CODE_SECTION(Example_CallFlashAPI, ramFuncSection);
void Example_CallFlashAPI(void)
{
	Fapi_StatusType oReturnCheck;
	Fapi_FlashStatusType oFlashStatus;
	uint16 au16DataBuffer[8] = {0x0001, 0x0203, 0x0405, 0x0607, 0x0809, 0x0A0B, 0x0C0D, 0x0E0F};
	uint32 *DataBuffer32 = (uint32 *)au16DataBuffer;
	uint32 u32Index = 0;
	
	//
	// Bank0 operations
	//
	EALLOW;
	
	//
	// This function is required to initialize the Flash API based on
	// System frequency before any other Flash API operation can be performed
	// Note that the FMC register base address and system frequency are passed as the parameters
	//
	oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 100);
	
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	
	//
	// Fapi_setActiveFlashBank function initializes Flash banks
	// and FMC for erase and program operations.
	// Note: It does not matter which bank is passed as the parameter to initialize.
	// Both Banks and FMC get initialized with one function call unlike F2837xS.
	// Hence, there is no need to execute Fapi_setActiveFlashBank() for each bank.
	//
	oReturnCheck = Fapi_setActiveFlashBank(Fapi_FlashBank0);
	
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error(oReturnCheck);
	}
	
	//
	// Issue an async command
	//
	oReturnCheck = Fapi_issueAsyncCommand(Fapi_ClearMore);
	
	//
	// Wait until the Fapi_ClearMore operation is over
	//
	while (Fapi_checkFsmForReady() != Fapi_Status_FsmReady){}
	
	if (oReturnCheck != Fapi_Status_Success)
	{
		Example_Error (oReturnCheck);
	}
	
	//
	// Read FMSTAT register contents to know the status of FSM after
	// program command to see if there are any program operation related errors
	//
	oFlashStatus = Fapi_getFsmStatus();
	
	if (oFlashStatus != 0)
	{
		//
		//Check FMSTAT and debug accordingly
		//
		FMSTAT_Fail();
	}
	
	//
	// * User code for further Bank0 and Bank1 flash operations *
	//
	.
	.
	.
	.
	EDIS;
	//
	// Example is done here
	//
	Example_Done();
}
3.2.7 Fapi_checkFsmForReady()(返回Flash状态机的状态)
  • 格式
  • Fapi_StatusType Fapi_checkFsmForReady(void)
  • 参数
  • None
  • 描述
  • 此函数返回Flash状态机的状态,指示它是否准备好接受一个新的命令。主要的用途是检查一个擦除或程序操作是否已完成
  • 返回值
  • Fapi_Status_FsmBusy(FSM很忙,除了暂停命令外不能接受新命令)
  • Fapi_Status_FsmReady(FSM已准备好接受新的命令)
3.2.8 Fapi_getFsmStatus()(返回FMSTAT寄存器的值)
  • 格式
  • Fapi_FlashStatusType Fapi_getFsmStatus(void)
  • 参数
  • None
  • 描述
  • 此函数返回FMSTAT寄存器的值。此寄存器允许用户应用程序确定擦除或程序操作是成功完成、正在进行、挂起或失败。用户应用程序应该检查这个寄存器的值,以确定在每次擦除和程序操作后是否有任何故障
  • 返回值(FMSTAT寄存器字段描述)
    FMSTAT寄存器字段描述
    FMSTAT寄存器字段描述

3.3 读功能

3.3.1 Fapi_doBlankCheck()(验证指定区域是否被擦除值)
  • 格式
  • Fapi_StatusType Fapi_doBlankCheck(uint32 *pu32StartAddress, uint32 u32Length, Fapi_FlashStatusWordType *poFlashStatusWord)
  • 参数
  • pu32StartAddress [in]:从区域到空白检查的开始地址
  • u32Length [in]:32位字中区域的空白校验长度
  • poFlashStatusWord [out]:如果结果不是Fapi_Status_Success,则返回操作的状态
    ->au32StatusWord[0] 第一个非空位置的地址
    ->au32StatusWord[1] 首先在非空白位置读取数据
    ->au32StatusWord[2] 比较数据的值(总是0xFFFFFFFF)
    ->au32StatusWord[3] N/A
  • 描述
  • 此函数检查从指定的32位字长度的指定地址开始的闪存是否为空白(擦除状态)。如果找到非空白位置,则将在poFlashStatusWord参数中返回相应的地址和数据
  • 条件
  • 被选空的区域不能跨越银行地址边界
  • 返回值
  • 发现Fapi_Status_Success(成功)指定的Flash位置处于擦除状态
  • Fapi_Error_Fail(失败:指定的区域不是空)
3.3.2 Fapi_doVerify()(根据所提供的数据验证所指定的区域)
  • 格式
  • Fapi_StatusType Fapi_doVerify(uint32 *pu32StartAddress, uint32 u32Length, uint32 *pu32CheckValueBuffer, Fapi_FlashStatusWordType *poFlashStatusWord)
  • 参数
  • pu32StartAddress [in]:要验证的区域的起始地址
  • u32Length [in]:用32位的单词来验证的区域引擎
  • pu32CheckValueBuffer[in]:要验证区域的缓冲区的地址
  • poFlashStatusWord [out]:如果结果不是Fapi_Status_Success,则返回操作的状态
    ->au32StatusWord[0] 第一次验证故障位置的地址
    ->au32StatusWord[1] 首先读取数据时,验证故障位置
    ->au32StatusWord[2] 比较数据值
    ->au32StatusWord[3] N/A
  • 描述
  • 该函数从指定地址的32位字的长度开始,根据提供的数据验证设备。如果一个位置无法进行比较,这些结果将在poFlashStatusWord参数中返回
  • 条件
  • 被验证的区域不能跨越银行地址边界
  • 返回值
  • Fapi_Status_Success(成功:指定的区域匹配提供的数据)
  • Fapi_Error_Fail(失败:指定的区域与提供的数据不匹配)
3.3.3 Fapi_calculatePsa()(计算指定区域的PSA)
  • 格式
  • uint32 Fapi_calculatePsa(uint32 *pu32StartAddress, uint32 u32Length, uint32 u32PsaSeed, Fapi_FlashReadMarginModeType oReadMode)
  • 参数
  • pu32StartAddress [in]:要计算PSA值的区域的起始地址
  • u32Length [in]:以32位字表示的区域长度来计算PSA值
  • u32PsaSeed [in]:PSA计算的种子值
  • oReadMode [in]:仅适用于正常模式。使用Fapi_NormalRead
  • 描述
  • 该函数使用u32PsaSeed值计算从u32长度32位字开始指定的区域的PSA值
  • 条件
  • 正在计算PSA的区域不能跨越银行地址边界
  • 返回值
  • PSA值
3.3.4 Fapi_doPsaVerify()(根据指定的PSA值验证指定的区域)
  • 格式
  • Fapi_StatusType Fapi_doPsaVerify(uint32 *pu32StartAddress, uint32 u32Length, uint32 u32PsaValue, Fapi_FlashStatusWordType *poFlashStatusWord)
  • 参数
  • pu32StartAddress [in]:要验证PSA值的区域的起始地址
  • u32Length [in]:在32位字中的区域长度,以验证PSA值
  • u32PsaValue [in]:用PSA值来比较区域与
  • poFlashStatusWord [out]:如果结果不是Fapi_Status_Success,则返回操作的状态
    ->au32StatusWord[0] 实际PSA
  • 描述
  • 该函数根据指定的32位字长度的指定地址开始提供的PSA值验证设备。计算出的PSA值在软件统计软件word参数中返回
  • 条件
  • 被验证的区域不能跨越bank地址边界
  • 返回值
  • Fapi_Status_Success(成功)
  • Fapi_Error_Fail(失败:指定的区域与提供的数据不匹配)

3.4 信息功能

3.4.1 Fapi_getLibraryInfo()(返回有关此Flash API编译的信息)
  • 格式
  • Fapi_LibraryInfoType Fapi_getLibraryInfo(void)
  • 参数
  • None
  • 描述
  • 此函数返回特定于Flash API库编译的信息。该信息在一个结构体Fapi_LibraryInfoType中返回。成员内容如下:
  • u8ApiMajorVersion – 此API编译的主要版本号
  • u8ApiMinorVersion – 此API编译的次要版本号,F28004x设备的次要版本是56
  • u8ApiRevision – 此API编译的修订版本号。最新的API版本是1。在TMS320F28004x FlashAPI V.1.56.00.00中,Fapi_doPsaVerify()和Fapi_CalculatePsa()不支持ECC内存地址范围。这个限制在V.1.56.01.00中不存在
  • oApiProductionStatus – 此编译的生产状态(阿尔法内部、阿尔法、内部、测试版、生产)
  • u32ApiBuildNumber – 此编译的生成号。用于区分不同的alpha和beta构建
  • u8ApiTechnologyType – 表示API支持的Flash技术。此字段返回的一个值为0x4
  • u8ApiTechnologyRevision – 表示对API所支持的技术的修订版本
  • u8ApiEndianness – 对于F28004x设备,此字段总是返回为1(小Endian)
  • u32ApiCompilerVersion – 用于编译API的代码编写器Studio代码生成工具的版本号
  • 返回值
  • Fapi_LibraryInfoType(给出了关于这个API编译的检索信息)

3.5 其他功能

3.5.1 Fapi_flushPipeline()(刷新FMC管道缓冲区)
  • 格式
  • void Fapi_flushPipeline(void)
  • 参数
  • None
  • 描述
  • 此函数将刷新FMC数据缓存。必须在擦除或程序操作后第一次非apiFlash之前刷新数据缓存
  • 返回值
  • None
3.5.2 Fapi_calculateEcc()(计算一个64位值的ECC)
  • 格式
  • uint8 Fapi_calculateEcc(uint32 u32Address, uint64 u64Data)
  • 参数
  • u32Address [in]:用来计算ECC的64位值的地址
  • u64Data [in]:用于计算ECC的64位值(应按小环境顺序)
  • 描述
  • 这个函数将计算一个包括地址在内的64位对齐字的ECC。不再需要为这个函数提供一个左移的地址。TMS320F28004x Flash API负责处理它
  • 返回值
  • 8位计算出的ECC(应忽略16位返回值的上8位)
3.5.3 Fapi_isAddressEcc()(指示是否有一个地址位于闪存控制器ECC空间中)
  • 格式
  • boolean Fapi_isAddressEcc(uint32 u32Address)
  • 参数
  • u32Address [in]:地址,以确定它是否位于ECC地址空间中
  • 描述
  • 如果地址在ECC地址空间中,则此函数返回True,如果不是,则返回False
  • 返回值
  • FALSE(地址不在ECC地址空间中)
  • TRUE(地址在ECC地址空间中)
3.5.4 Fapi_remapEccAddress()(获取ECC地址,并将其重新映射到主地址空间)
  • 格式
  • uint32 Fapi_remapEccAddress(uint32 u32EccAddress)
  • 参数
  • u32EccAddress [in]:要重新映射的ECC地址
  • 描述
  • 此函数返回给定的Flash ECC地址的主阵列Flash地址。当用户希望在一个已知的ECC地址上编程ECC数据时,可以使用此函数来获取相应的主阵列地址。请注意,Fapi_issueProgrammingCommand()函数需要一个主数组地址,而不是ECC地址(即使是Fapi_EccOnly模式)
  • 返回值
  • 32位主闪存地址
3.5.5 Fapi_calculateFletcherChecksum()(根据给定的地址和长度计算弗莱彻校验和)
  • 格式
  • uint32 Fapi_calculateFletcherChecksum(uint16 *pu16Data, uint16 u16Length)
  • 参数
  • pu16Data [in]:从中开始计算校验和的地址
  • u16Length [in]:在计算中使用的16位字数
  • 描述
  • 该函数生成一个32位弗莱彻校验和,从提供的地址开始生成指定的16位字的校验和
  • 返回值
  • 32位弗莱彻校验和值

4.推荐的FSM流

4.1 厂家的新设备

  • 设备已从工厂删除。建议使用,但不需要对接收到的设备进行空白检查,以验证它们是否已被清除

4.2 推荐擦除流程

  • 下图描述了清除设备上的扇区的流程。有关更多信息,请参阅第3.2.2节
    建议的擦除流程

4.3 推荐程序流程

  • 下图描述了为设备编程的流程。此流假定用户已按照建议的删除流删除了所有受影响的扇区或库。更多信息请参考第4.2节
    推荐的程序流程

5.附录

5.1 附录A 闪存状态机命令

闪存状态机命令

5.2 附录B TMS320F28004x Flash API库

5.3 附录C

5.3.1 类型定义
#if defined(__TMS320C28XX__)
typedef unsigned char boolean;
typedef unsigned int uint8; /*This is 16 bits in C28x*/
typedef unsigned int uint16;
typedef unsigned long int uint32;
typedef unsigned long long int uint64;
typedef unsigned int uint16_least;
typedef unsigned long int uint32_least;
typedef signed int sint16_least;
typedef signed long int sint32_least;
#else
typedef unsigned char boolean;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long int uint64;
typedef signed char sint8;
typedef signed short sint16;
typedef signed int sint32;
typedef signed long long int sint64;
typedef unsigned int uint8_least;
typedef unsigned int uint16_least;
typedef unsigned int uint32_least;
typedef signed int sint8_least;
typedef signed int sint16_least;
typedef signed int sint32_least;
typedef float float32;
typedef double float64;
#endif
5.3.2 定义
#if (defined(__TMS320C28xx__) && __TI_COMPILER_VERSION__ < 6004000)
#if !defined(__GNUC__)
#error “F021 Flash API requires GCC language extensions. Use the –gcc option.”
#endif
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif
5.3.3 列举
5.3.3.1 Fapi_CpuType(这将用于指示正在使用的Cpu的类型)
typedef enum
{
	Cpu_ARM7,
	Cpu_M3,
	Cpu_R4,
	Cpu_R4F,
	Cpu_C28,
	Cpu_Undefined
} ATTRIBUTE_PACKED Fapi_CpuType;
5.3.3.2 Fapi_FlashProgrammingCommandsType(这包含了在Fapi_IssueProgrammingCommand()中使用的所有可能的模式)
typedef enum
{
	Fapi_AutoEccGeneration, /* Command will autogenerate the ecc for the provided data buffer */
	Fapi_DataOnly,          /* Command will only process the data buffer */
	Fapi_EccOnly,           /* Command will only process the ecc buffer */
	Fapi_DataAndEcc         /* Command will process data and ecc buffers */
} ATTRIBUTE_PACKED Fapi_FlashProgrammingCommandsType;
5.3.3.3 Fapi_FlashBankType(这是用于指示正在使用的是哪个闪存库)
typedef enum
{
	Fapi_FlashBank0,
	Fapi_FlashBank1, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank2, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank3, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank4, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank5, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank6, /*Not used in TMS320F28004x Flash API*/
	Fapi_FlashBank7  /*Not used in TMS320F28004x Flash API*/
} ATTRIBUTE_PACKED Fapi_FlashBankType;
5.3.3.4 Fapi_FlashStateCommandsType(这包含了所有可能的闪存状态机命令)
typedef enum
{
	Fapi_ProgramData    = 0x0002,
	Fapi_EraseSector    = 0x0006,
	Fapi_EraseBank      = 0x0008, /*Not available in TMS320F28004x devices */
	Fapi_ValidateSector = 0x000E, /*Not available in TMS320F28004x devices */
	Fapi_ClearStatus    = 0x0010,
	Fapi_ProgramResume  = 0x0014,
	Fapi_EraseResume    = 0x0016,
	Fapi_ClearMore      = 0x0018
} ATTRIBUTE_PACKED Fapi_FlashStateCommandsType;
5.3.3.5 Fapi_FlashReadMarginModeType(这包含了所有可能的闪存状态机命令)
typedef enum
{
	Fapi_NormalRead = 0x0,
	Fapi_RM0        = 0x1, /*Technology used in TMS320F28004x does not need this*/
	Fapi_RM1        = 0x2  /*Technology used in TMS320F28004x does not need this*/
} ATTRIBUTE_PACKED Fapi_FlashReadMarginModeType;
5.3.3.6 Fapi_StatusType(这是包含所有可能返回的状态代码的主类型)
typedef enum
{
	Fapi_Status_Success=0,          /* Function completed successfully */
	Fapi_Status_FsmBusy,            /* FSM is Busy */
	Fapi_Status_FsmReady,           /* FSM is Ready */
	Fapi_Status_AsyncBusy,          /* Async function operation is Busy */
	Fapi_Status_AsyncComplete,      /* Async function operation is Complete */
	Fapi_Error_Fail = 500,          /* Generic Function Fail code */
	Fapi_Error_StateMachineTimeout, /* State machine polling never returned ready and timed out */
	Fapi_Error_OtpChecksumMismatch, /* Returned if OTP checksum does not match expected value */
	Fapi_Error_InvalidDelayValue,   /* Returned if the Calculated RWAIT value exceeds 15 - Legacy Error */
	Fapi_Error_InvalidHclkValue,    /* Returned if FClk is above max FClk value - FClk is a calculated from SYSCLK and RWAIT */
	Fapi_Error_InvalidCpu,          /* Returned if the specified Cpu does not exist */
	Fapi_Error_InvalidBank,         /* Returned if the specified bank does not exist */
	Fapi_Error_InvalidAddress,      /* Returned if the specified Address does not exist in Flash or OTP */
	Fapi_Error_InvalidReadMode,     /* Returned if the specified read mode does not exist */
	Fapi_Error_AsyncIncorrectDataBufferLength,
	Fapi_Error_AsyncIncorrectEccBufferLength,
	Fapi_Error_AsyncDataEccBufferLengthMismatch,
	Fapi_Error_FeatureNotAvailable, /* FMC feature is not available on this device */
	Fapi_Error_FlashRegsNotWritable /* Returned if Flash registers are not writable due to security */
} ATTRIBUTE_PACKED Fapi_StatusType;
5.3.3.7 Fapi_ApiProductionStatusType(这列出了API可能存在的不同生产状态值)
typedef enum
{
	Alpha_Internal, /* For internal TI use only. Not intended to be used by customers */
	Alpha,          /* Early Engineering release. May not be functionally complete */
	Beta_Internal,  /* For internal TI use only. Not intended to be used by customers */
	Beta,           /* Functionally complete, to be used for testing and validation */
	Production      /* Fully validated, functionally complete, ready for production use */
} ATTRIBUTE_PACKED Fapi_ApiProductionStatusType;
5.3.4 结构
5.3.4.1 Fapi_FlashStatusWordType(此结构用于返回需要更多灵活性的函数中的状态值)
typedef struct
{
	uint32 au32StatusWord[4];
} ATTRIBUTE_PACKED Fapi_FlashStatusWordType;
5.3.4.2 Fapi_LibraryInfoType(这是用于返回API信息的结构)
typedef struct
{
	uint8 u8ApiMajorVersion;
	uint8 u8ApiMinorVersion;
	uint8 u8ApiRevision;
	Fapi_ApiProductionStatusType oApiProductionStatus;
	uint32 u32ApiBuildNumber;
	uint8 u8ApiTechnologyType;
	uint8 u8ApiTechnologyRevision;
	uint8 u8ApiEndianness;
	uint32 u32ApiCompilerVersion;
} Fapi_LibraryInfoType;

5.4 附录D 功能详细信息

  • 功能第3节3.3.4和第3.3.3节使用了并行签名分析(PSA)算法。这些功能通常用于验证在闪存中编程的特定模式,而不传输完整的数据模式。PSA签名是基于这个引数多项式:
f(X) = 1 + X + X^2 + X^22 + X^31

uint32 calculatePSA (uint32* pu32StartAddress, uint32 u32Length, /* Number of 32-bit words */ uint32 u32InitialSeed)
{
	uint32 u32Seed, u32SeedTemp;
	u32Seed = u32InitialSeed;
	
	while (u32Length--)
	{
		u32SeedTemp = (u32Seed << 1) ^ *(pu32StartAddress++);
		
		if (u32Seed & 0x80000000)
		{
			u32SeedTemp ^= 0x00400007; /* XOR the seed value with mask */
		}
		u32Seed = u32SeedTemp;
	}	
	return u32Seed;
}

5.5 附录E 功能详细信息

  • 下面的函数可以用于计算一个给定的64位对齐地址(不需要左移该地址)和相应的64位数据的ECC
//
//Calculate the ECC for an address/data pair
//
uint16 CalcEcc(uint32 address, uint64 data)
{
	const uint32 addrSyndrome[8] = {0x554ea, 0x0bad1, 0x2a9b5, 0x6a78d, 0x19f83, 0x07f80, 0x7ff80, 0x0007f};
	const uint64 dataSyndrome[8] = {0xb4d1b4d14b2e4b2e, 0x1557155715571557, 0xa699a699a699a699, 0x38e338e338e338e3, 0xc0fcc0fcc0fcc0fc, 0xff00ff00ff00ff00, 0xff0000ffff0000ff, 0x00ffff00ff0000ff};
	const uint16 parity = 0xfc;
	uint64 xorData;
	uint32 xorAddr;
	uint16 bit, eccBit, eccVal;
	
	//
	//Extract bits "20:2" of the address
	//
	address = (address >> 2) & 0x7ffff;
	
	//
	//Compute the ECC one bit at a time.
	//
	eccVal = 0;
	
	for (bit = 0; bit < 8; bit++)
	{
		//
		//Apply the encoding masks to the address and data
		//
		xorAddr = address & addrSyndrome[bit];
		xorData = data & dataSyndrome[bit];
		
		//
		//Fold the masked address into a single bit for parity calculation.
		//The result will be in the LSB.
		//
		xorAddr = xorAddr ^ (xorAddr >> 16);
		xorAddr = xorAddr ^ (xorAddr >> 8);
		xorAddr = xorAddr ^ (xorAddr >> 4);
		xorAddr = xorAddr ^ (xorAddr >> 2);
		xorAddr = xorAddr ^ (xorAddr >> 1);
		
		//
		//Fold the masked data into a single bit for parity calculation.
		//The result will be in the LSB.
		//
		xorData = xorData ^ (xorData >> 32);
		xorData = xorData ^ (xorData >> 16);
		xorData = xorData ^ (xorData >> 8);
		xorData = xorData ^ (xorData >> 4);
		xorData = xorData ^ (xorData >> 2);
		xorData = xorData ^ (xorData >> 1);
		
		//
		//Merge the address and data, extract the ECC bit, and add it in
		//
		eccBit = ((uint16)xorData ^ (uint16)xorAddr) & 0x0001;
		eccVal |= eccBit << bit;
	}
	
	//
	//Handle the bit parity. For odd parity, XOR the bit with 1
	//
	eccVal ^= parity;
	return eccVal;
}

总结

本章为TMS320F280049学习系列文章 第N章:Bootloader(TMS320F28004x Flash API Reference Guide)的学习

  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值