ZHCADD5A November   2023  – April 2024 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. 软件说明
    1. 4.1 软件功能和流程
  8. 乒乓仿真
    1. 5.1 用户配置
      1. 5.1.1 EEPROM_PingPong_Config.h
      2. 5.1.2 F28P65x_EEPROM_PingPong.c
    2. 5.2 EEPROM 函数
      1. 5.2.1  EEPROM_Config_Check
      2. 5.2.2  Configure_Protection_Masks
      3. 5.2.3  EEPROM_Write
      4. 5.2.4  EEPROM_Read
      5. 5.2.5  EEPROM_Erase
        1. 5.2.5.1 Erase_Bank
      6. 5.2.6  EEPROM_GetValidBank
      7. 5.2.7  EEPROM_UpdateBankStatus
      8. 5.2.8  EEPROM_UpdatePageStatus
      9. 5.2.9  EEPROM_UpdatePageData
      10. 5.2.10 EEPROM_Get_64_Bit_Data_Address
      11. 5.2.11 EEPROM_Program_64_Bits
      12. 5.2.12 EEPROM_CheckStatus
      13. 5.2.13 ClearFSMStatus
    3. 5.3 测试示例
  9. 单存储单元仿真
    1. 6.1 用户配置
      1. 6.1.1 EEPROM_Config.h
      2. 6.1.2 F28P65x_EEPROM.c
    2. 6.2 EEPROM 函数
      1. 6.2.1  EEPROM_Config_Check
      2. 6.2.2  Configure_Protection_Masks
      3. 6.2.3  EEPROM_Write
      4. 6.2.4  EEPROM_Read
      5. 6.2.5  EEPROM_Erase
      6. 6.2.6  EEPROM_GetValidBank
      7. 6.2.7  EEPROM_Get_64_Bit_Data_Address
      8. 6.2.8  EEPROM_UpdateBankStatus
      9. 6.2.9  EEPROM_UpdatePageStatus
      10. 6.2.10 EEPROM_UpdatePageData
      11. 6.2.11 EEPROM_Get_64_Bit_Data_Address
      12. 6.2.12 EEPROM_Program_64_Bits
      13. 6.2.13 EEPROM_CheckStatus
      14. 6.2.14 ClearFSMStatus
    3. 6.3 测试示例
  10. 应用集成
  11. 适配其他第 3 代 C2000 MCU
  12. 闪存 API
    1. 9.1 闪存 API 检查清单
      1. 9.1.1 使用闪存 API 时的注意事项
  13. 10源文件清单
  14. 11故障排除
    1. 11.1 常见问题
  15. 12结语
  16. 13参考资料
  17. 14修订历史记录

EEPROM_GetValidBank

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

GUID-AA2211D9-B5A8-42B4-B020-F5CC6E2BDD70-low.gif图 5-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 单元。