ZHCUAO0C November 2022 – November 2023 TMS320F280033 , TMS320F280034 , TMS320F280034-Q1 , TMS320F280036-Q1 , TMS320F280036C-Q1 , TMS320F280037 , TMS320F280037-Q1 , TMS320F280037C , TMS320F280037C-Q1 , TMS320F280038-Q1 , TMS320F280038C-Q1 , TMS320F280039 , TMS320F280039-Q1 , TMS320F280039C , TMS320F280039C-Q1
设置数据并向有效的闪存或 OTP 存储器地址发出编程命令
概要
Fapi_StatusType Fapi_issueProgrammingCommand(
uint32 *pu32StartAddress,
uint16 *pu16DataBuffer,
uint16 u16DataBufferSizeInWords,
uint16 *pu16EccBuffer,
uint16 u16EccBufferSizeInBytes,
Fapi_FlashProgrammingCommandType oMode)
参数
pu32StartAddress [in] | 闪存中的起始地址,用于对数据和 ECC 进行编程 | |
pu16DataBuffer [in] | 指向数据缓冲区地址的指针。数据缓冲区应为 128 位对齐。 | |
u16DataBufferSizeInWords [in] | 数据缓冲区中 16 位字的数量 | |
pu16EccBuffer [in] | 指向 ECC 缓冲区地址的指针 | |
u16EccBufferSizeInBytes [in] | ECC 缓冲区中的 8 位字节数 | |
oMode [in] | 表示要使用的编程模式: | |
Fapi_DataOnly | 仅对数据缓冲区进行编程 | |
Fapi_AutoEccGeneration | 对数据缓冲区进行编程,并自动生成 ECC 并对其进行编程。 | |
Fapi_DataAndEcc | 对数据和 ECC 缓冲区进行编程 | |
Fapi_EccOnly | 仅对 ECC 缓冲区进行编程 |
说明
该函数根据提供的参数设置闪存状态机的编程寄存器,为用户提供了适用于不同场景的四种不同编程模式,如表 3-1 中所述。
编程模式 (oMode) | 使用的参数 | 用途 |
---|---|---|
Fapi_DataOnly | pu32StartAddress、 pu16DataBuffer、 u16DataBufferSizeInWords | 当任何自定义编程实用程序或用户应用(嵌入/使用闪存 API)必须单独对数据和相应 ECC 进行编程时使用。使用 Fapi_DataOnly 模式对数据进行编程,然后使用 Fapi_EccOnly 模式对 ECC 进行编程。通常大多数编程实用程序不会单独计算 ECC,而是使用 Fapi_AutoEccGeneration 模式。但是,某些安全应用程序可能需要在其闪存映像中插入有意的 ECC 错误(使用 Fapi_AutoEccGeneration 模式时无法实现),从而在运行时检查单错校正和双错检测 (SECDED) 模块的运行状况。在这种情况下,ECC 是单独计算的(使用AppendixF 中提供的 ECC 计算算法或使用 Fapi_calculateEcc() 函数(如适用))。应用程序可能希望根据需要在主阵列数据或 ECC 中插入错误。在这种情况下,在错误插入之后,可以使用 Fapi_DataOnly 模式和 Fapi_EccOnly 模式分别对数据和 ECC 进行编程。 |
Fapi_AutoEccGeneration | pu32StartAddress、 pu16DataBuffer、 u16DataBufferSizeInWords | 当任何自定义编程实用程序或用户应用(其在运行时嵌入/使用闪存 API 对闪存进行编程从而存储数据或进行固件更新)必须同时对数据和 ECC 进行编程而不插入任何有意错误时使用。该模式是常用的模式。 |
Fapi_DataAndEcc | pu32StartAddress、 pu16DataBuffer、 u16DataBufferSizeInWords、 pu16EccBuffer、 u16EccBufferSizeInBytes | 该模式的用途与同时使用 Fapi_DataOnly 和 Fapi_EccOnly 模式的用途没有什么不同。但是,当可以同时对数据和计算出的 ECC 进行编程时,该模式会很有用。 |
Fapi_EccOnly | pu16EccBuffer、 u16EccBufferSizeInBytes | 请参阅 Fapi_DataOnly 模式的用途描述。 |
编程模式:
Fapi_DataOnly – 该模式将只对闪存中指定地址的数据部分进行编程。其编程范围从 1 位至 8 个 16 位字。但是,请注意该函数的限制条件中对闪存编程数据大小的限制。提供的编程起始地址加上数据缓冲区长度无法跨越 128 位对齐地址边界。使用该模式时将忽略参数 4 和 5。
Fapi_AutoEccGeneration – 该模式将对闪存中提供的数据以及自动生成的 ECC 进行编程。针对在 64 位存储器边界上对齐的每项 64 位数据计算 ECC。因此,在使用该模式时,应针对给定的 64 位对齐存储器地址,同时对所有 64 位数据进行编程。未提供的数据全部视作 1 (0xFFFF)。针对 64 位数据计算 ECC 并对其进行编程后,即使在该 64 位数据中将位从 1 编程为 0,也无法对此类 64 位数据进行重新编程(除非扇区被擦除),因为新的 ECC 值将与先前编程的 ECC 值相冲突。使用该模式时,如果起始地址进行了 128 位对齐,则可以根据需要同时对 8 个或 4 个 16 位字进行编程。如果起始地址进行了 64 位对齐而不是 128 位对齐,则只能同时对 4 个 16 位字进行编程。该选项还存在 Fapi_DataOnly 的数据限制。忽略参数 4 和 5
下面我们举例说明:
SECTIONS
{
.text : > FLASH, ALIGN(4)
.cinit : > FLASH, ALIGN(4)
.const : > FLASH, ALIGN(4)
.init_array : > FLASH, ALIGN(4)
.switch : > FLASH, ALIGN(4)
}
如果不在闪存中对齐这些段,则需要跟踪段中不完整的 64 位字,并将这些字与其他段中的字组合在一起,从而使 64 位字变得完整。这不容易做到。因此,建议将段在 64 位边界上对齐。
某些第三方闪存编程工具或 TI 闪存编程内核示例 (C2000Ware) 或任何自定义闪存编程解决方案可能假定传入数据流全部为 128 位对齐,并且可能没有预想到某段的起始地址未对齐。因此,假设提供的地址为 128 位对齐,则可能会尝试对最大可能的(128 位)字进行一次编程。当地址未对齐时,这可能会导致出现故障。因此,建议使用 ALIGN(8) 将所有段(已映射到闪存)在 128 位边界上对齐。
Fapi_DataAndEcc – 该模式将在指定地址的闪存中对提供的数据和 ECC 进行编程。提供的数据必须在 64 位存储器边界上对齐,并且数据长度必须与提供的 ECC 相关联。这意味着,如果数据缓冲区长度为 4 个 16 位字,则 ECC 缓冲区长度必须为 1 字节。如果数据缓冲区长度为 8 个 16 位字,则 ECC 缓冲区的长度必须为 2 字节。如果起始地址进行了 128 位对齐,则应根据需要同时对 8 或 4 个 16 位字进行编程。如果起始地址进行了 64 位对齐而不是 128 位对齐,则应同时对 4 个 16 位字进行编程。
pu16EccBuffer 的 LSB 与主阵列的低 64 位相对应,pu16EccBuffer 的 MSB 与主阵列的高 64 位相对应。
Fapi_calculateEcc() 函数可用于计算给定 64 位对齐地址和相应数据的 ECC。
Fapi_EccOnly – 该模式将仅在指定的地址处(应为该函数提供闪存主阵列地址,而不是相应的 ECC 地址)对闪存 ECC 存储空间中的 ECC 部分进行编程。它可以对 2 字节(ECC 存储器中某一位置的 LSB 和 MSB)或 1 字节(ECC 存储器中某一位置的 LSB)编程。
pu16EccBuffer 的 LSB 与主阵列的低 64 位相对应,pu16EccBuffer 的 MSB 与主阵列的高 64 位相对应。
使用该模式时将忽略参数二和三。
此外,用户应用程序应使用 Fapi_doVerify() 函数来验证闪存是否已正确编程。
该函数不会等到编程操作结束;它只是发出命令并返回。因此,用户应用程序必须等待 FMC 完成编程操作,然后才能返回到任何类型的闪存访问。应将 Fapi_checkFsmForReady() 函数用于监测已发出命令的状态。
限制
返回值
实现示例
该示例未显示擦除操作。请注意,扇区在重新编程之前应被擦除。
#include “F021_F28003x_C28x.h”
#define CPUCLK_FREQUENCY 120 /* 120 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, CPUCLK_FREQUENCY);
if(oReturnCheck != Fapi_Status_Success)
{
Example_Error(oReturnCheck);
}
//
// Fapi_setActiveFlashBank function initializes Flash banks
// and FMC for erase and program operations.
//
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 *
//
.
.
.
.
//
// Example is done here
//
Example_Done();
}