ZHCADD5B November   2023  – August 2025 F29H850TU , F29H859TU-Q1 , TMS320F28P650DH , TMS320F28P650DK , TMS320F28P650SH , TMS320F28P650SK , TMS320F28P659DH-Q1 , TMS320F28P659DK-Q1 , TMS320F28P659SH-Q1

 

  1.   1
  2.   摘要
  3.   商标
  4. 简介
  5. EEPROM 与片上闪存的区别
  6. 概述
    1. 3.1 基本概念
    2. 3.2 单存储单元方法
    3. 3.3 乒乓方法
    4. 3.4 创建 EEPROM 节(页)和页标识
  7. 软件说明
  8. 乒乓仿真
    1. 5.1 用户配置
      1. 5.1.1 EEPROM_PingPong_Config.h
      2. 5.1.2 F28P65x_EEPROM_PingPong.c
    2. 5.2 测试示例
  9. EEPROM 函数
    1. 6.1  EEPROM_Config_Check
    2. 6.2  Configure_Protection_Masks
    3. 6.3  EEPROM_Write
    4. 6.4  EEPROM_Read
    5. 6.5  EEPROM_Erase
      1. 6.5.1 Erase_Bank
    6. 6.6  EEPROM_GetValidBank
    7. 6.7  EEPROM_UpdateBankStatus
    8. 6.8  EEPROM_UpdatePageStatus
    9. 6.9  EEPROM_UpdatePageData
    10. 6.10 EEPROM_Get_64_Bit_Data_Address
    11. 6.11 EEPROM_Program_64_Bits
    12. 6.12 EEPROM_CheckStatus
    13. 6.13 ClearFSMStatus
  10. 单存储单元仿真
    1. 7.1 用户配置
      1. 7.1.1 EEPROM_Config.h
      2. 7.1.2 F28P65x_EEPROM.c
    2. 7.2 EEPROM 函数
      1. 7.2.1  EEPROM_Config_Check
      2. 7.2.2  Configure_Protection_Masks
      3. 7.2.3  EEPROM_Write
      4. 7.2.4  EEPROM_Read
      5. 7.2.5  EEPROM_Erase
      6. 7.2.6  EEPROM_GetValidBank
      7. 7.2.7  EEPROM_Get_64_Bit_Data_Address
      8. 7.2.8  EEPROM_UpdateBankStatus
      9. 7.2.9  EEPROM_UpdatePageStatus
      10. 7.2.10 EEPROM_UpdatePageData
      11. 7.2.11 EEPROM_Get_64_Bit_Data_Address
      12. 7.2.12 EEPROM_Program_64_Bits
      13. 7.2.13 EEPROM_CheckStatus
      14. 7.2.14 ClearFSMStatus
    3. 7.3 测试示例
  11. 应用集成
    1. 8.1 软件功能和流程
  12. 适配其他第 3 代 C2000 MCU
  13. 10闪存 API
    1. 10.1 闪存 API 检查清单
      1. 10.1.1 使用闪存 API 时的注意事项
  14. 11源文件清单
  15. 12排查
    1. 12.1 通用
  16. 13结语
  17. 14参考资料
  18. 15修订历史记录

EEPROM_GetValidBank

EEPROM_GetValidBank() 函数的功能是查找当前 EEPROM 组和页面。EEPROM_Write() 和 EEPROM_Read() 函数都会调用此函数。GetValidBank 流程展示了搜索当前 EEPROM 组和页面所需的总体流程。

TMS320F28P650DK9 TMS320F280039C GetValidBank 流程图 6-1 GetValidBank 流程

进入此函数时,EEPROM 组指针和页面指针被设置为 FIRST_AND_LAST_SECTOR 中指定的第一个扇区的开头:

RESET_BANK_POINTER;
RESET_PAGE_POINTER;     

这些指针的地址在 EEPROM_Config.h 文件中针对所使用的特定器件和 EEPROM 配置进行定义。

接下来,会找到当前 EEPROM 组。如 GetValidBank 流程所示,EEPROM 组可以具有三种不同的状态:空、当前和已使用。

空 EEPROM 组由 128 个状态位全部为 1 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) 表示。当前 EEPROM 组由最高有效 64 位被设置为 0x5A5A5A5A5A5A5A5A、其余 64 位被设置为 1 (0x5A5A5A5A5A5A5A5AFFFFFFFFFFFFFFFF) 表示。已使用的 EERPOM 组由全部 128 位被设置为 0x5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A 表示。可以根据需要更改这些值。

首先测试空 EEPROM 组。如果遇到此状态,则表示该 EEPROM 组尚未使用,无需进一步搜索。

if(Bank_Status[0] == EMPTY_BANK)        // Check for Unused EEPROM Bank
{
    Bank_Counter = i;  // Set EEPROM Bank Counter to number of current page
    return;            // If EEPROM Bank is Unused, return as EEPROM is empty
}

如果未遇到空 EEPROM 组,则接下来测试当前 EEPROM 组。如果 EEPROM 组是当前 EEPROM 组,则会更新 EEPROM 组计数器,并且页面指针被设置为 EEPROM 组的第一页,以启用对当前页面的测试。然后退出该循环,因为不需要进一步的 EEPROM 组搜索。

if(Bank_Status[0] == CURRENT_BANK && Bank_Status[4] != CURRENT_BANK)      // Check for Current Bank
{
    Bank_Counter = i;      // Set Bank Counter to number of current bank
    // Set Page Pointer to first page in current bank    
    Page_Pointer = Bank_Pointer + 8; 
    break;      // Break from loop as current bank has been found
}

最后,对已使用的 EEPROM 组进行测试。在这种情况下,EEPROM 组已使用,EEPROM 组指针更新到下一个 EEPROM 组,以测试其状态。

// Check for Used Bank
if(Bank_Status[0] == CURRENT_BANK && Bank_Status[4] == CURRENT_BANK)         
// If Bank has been used, set pointer to next bank
    Bank_Pointer += Bank_Size;          

找到当前 EEPROM 组后,需要找到当前页面。一个页面可以具有三种不同的状态:空、当前和已使用。

空页面由 128 个状态位全为 1 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) 表示。当前页面由最高有效 64 位被设置为 0x5F5F5F5F5F5F5F5F、其余 64 位被设置为 1 (0x5F5F5F5F5F5F5F5FFFFFFFFFFFFFFFFF) 表示。已使用的页面由全部 128 位被设置为 0x5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F 表示。可以根据需要更改这些值。

首先会测试组和当前页面。如果页面的当前状态为这两种状态之一,则表示找到了正确的页面,并退出该循环,因为不需要进一步的搜索。

// Check for Blank Page or Current Page
if(Page_Status[0] == BLANK_PAGE)
{
        Page_Counter = i;  // Set Page Counter to number of current page
        break;  // Break from loop as current page has been found
}

if (Page_Status[0] == CURRENT_PAGE && Page_Status[4] != CURRENT_PAGE)
{
       Page_Counter = i + 1;//Increment Page Counter as one has been used
       break; // Break from loop as current page has been found
}

如果页面状态不是这两种状态中的任何一种,则唯一的其他可能性是“已使用的页面”。在这种情况下,页面指针会更新到下一个页面,以测试其状态。

// Check for Used Page
if(Page_Status[0] == CURRENT_PAGE && Page_Status[4] == CURRENT_PAGE)
{
// If page has been used, set pointer to next page
        Page_Pointer += EEPROM_PAGE_DATA_SIZE + 8;
}

此时,当前 EEPROM 组和页面已找到,调用函数可以继续运行。最后,此函数会检查是否所有 EEPROM 组和页面均已使用。这种情况下,需要擦除该扇区。活动单元将被切换,写入/擦除保护掩码将被重新配置,并且 Erase_Inactive_Unit 标志将被设置。

if (!ReadFlag)
{
    if (Bank_Counter == NUM_EEPROM_BANKS - 1 && 
            Page_Counter == NUM_EEPROM_PAGES)     
    {
        EEPROM_UpdatePageStatus();
        EEPROM_UpdateBankStatus();
        EEPROM_ACTIVE_UNIT ^= 1;


        uint64 WE_Protection_AB_Mask = Configure_Protection_Masks(
                                             FIRST_AND_LAST_SECTOR[EEPROM_ACTIVE_UNIT], 
                                                NUM_EEPROM_SECTORS);


        WE_Protection_A_Mask = 0xFFFFFFFF ^(uint32)WE_Protection_AB_Mask;
        WE_Protection_B_Mask = 0x00000FFF ^ WE_Protection_AB_Mask >> 32;

        Erase_Inactive_Unit = 1;  
        RESET_BANK_POINTER;   
        RESET_PAGE_POINTER;                     
    }
}

可以通过测试 EEPROM 组和页面计数器来执行该检查。表示已满 EEPROM 的 EEPROM 组和页面的数量取决于应用。如上述代码片段中所示针对当前 EEPROM 组和页面执行测试时,会设置这些计数器。然而,当设置了 Read_Flag 时,不会进行此检查。这是为了防止在从已满 EEPROM 单元读取时过早擦除非活动 EEPROM 单元。