SPRADE8 November   2023 TMS320F28P650DH , TMS320F28P650DK , TMS320F28P650SH , TMS320F28P650SK , TMS320F28P659DH-Q1 , TMS320F28P659DK-Q1 , TMS320F28P659SH-Q1

 

  1.   EEPROM Emulation for Generation 3 C2000 Real Time Controllers
  2.   Trademarks
  3. Introduction
  4. Difference Between EEPROM and On-Chip Flash
  5. Overview
    1. 3.1 Basic Concept
    2. 3.2 Single-Unit Method
    3. 3.3 Ping-Pong Method
    4. 3.4 Creating EEPROM Sections (Pages) and Page Identification
  6. Software Description
    1. 4.1 Software Functionality and Flow
  7. Ping-Pong Emulation
    1. 5.1 User-Configuration
      1. 5.1.1 EEPROM_Config.h
      2. 5.1.2 F28P65x_EEPROM.c
    2. 5.2 EEPROM Functions
      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_Get_64_Bit_Data_Address
      10. 5.2.10 EEPROM_Program_64_Bits
      11. 5.2.11 EEPROM_CheckStatus
      12. 5.2.12 ClearFSMStatus
    3. 5.3 Testing Example
  8. Single-Unit Emulation
    1. 6.1 User-Configuration
      1. 6.1.1 EEPROM_Config.h
      2. 6.1.2 F28P65x_EEPROM.c
    2. 6.2 EEPROM Functions
      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_Erase
      5. 6.2.5  EEPROM_GetValidBank
      6. 6.2.6  EEPROM_Get_64_Bit_Data_Address
      7. 6.2.7  EEPROM_UpdateBankStatus
      8. 6.2.8  EEPROM_UpdatePageStatus
      9. 6.2.9  EEPROM_Get_64_Bit_Data_Address
      10. 6.2.10 EEPROM_Program_64_Bits
      11. 6.2.11 EEPROM_CheckStatus
      12. 6.2.12 ClearFSMStatus
    3. 6.3 Testing Example
  9. Application Integration
  10. Adapting to Other Gen 3 C2000 MCUs
  11. Flash API
    1. 9.1 Flash API Checklist
      1. 9.1.1 Flash API Do's and Do Not's
  12. 10Source File Listing
  13. 11Conclusion
  14. 12References

EEPROM_Config_Check

The EEPROM_Config_Check() function provides general error-checking and configures Write/Erase protection masks required by the Flash API. This function should be called before programming or reading from the emulated EEPROM Unit(s).

First, the function verifies that the Flash Bank selected for EEPROM Emulation is valid. A valid Flash Bank selection must not select Bank 0 for emulation and must be supported by the specific device variant. For example, only some F28p65x variants have Flash Banks 2-4, while others do not. To verify this information, see the device-specific data sheet.

if (FLASH_BANK_SELECT == FlashBank0StartAddress)
{
    return 0xFFFF;
}

if (FLASH_BANK_SELECT == FlashBank2StartAddress)
{
#if !defined(F28P65xDKx) && !defined(F28P65xSKx) && !defined(F28P65xSHx)   
        return 0xFFFF;
#endif
} else if (FLASH_BANK_SELECT == FlashBank3StartAddress) // If using Bank 3
{
#if !defined(F28P65xDKx) && !defined(F28P65xSKx)   
        return 0xFFFF;
#endif
} else if (FLASH_BANK_SELECT == FlashBank4StartAddress) 
{
#if !defined(F28P65xDKx) && !defined(F28P65xSKx) && !defined(F28P65xSHx)   
        return 0xFFFF;
#endif
}

Second, the validity of Flash Sectors selected for emulation is examined. This function checks for:

  • FIRST_AND_LAST_SECTOR indicating two different numbers of Flash Sectors between the two units
    uint16 NUM_EEPROM_SECTORS_1 = FIRST_AND_LAST_SECTOR[0][1] - FIRST_AND_LAST_SECTOR[0][0] + 1;
    uint16 NUM_EEPROM_SECTORS_2 = FIRST_AND_LAST_SECTOR[1][1] - FIRST_AND_LAST_SECTOR[1][0] + 1;
    
    if (NUM_EEPROM_SECTORS_1 != NUM_EEPROM_SECTORS_2)
    {
        return 0xEEEE;
    }
  • More Flash Sectors selected for emulation than available within the Flash Bank
    if (NUM_EEPROM_SECTORS > NUM_FLASH_SECTORS || NUM_EEPROM_SECTORS == 0)
    {
        return 0xEEEE;
    }
  • Invalid combinations for First and Last Sectors selected for emulation
    if (NUM_EEPROM_SECTORS > 1)
    {
        // Check if FIRST_AND_LAST_SECTOR is sorted in increasing order 
        // and doesn't have duplicates
        if (FIRST_AND_LAST_SECTOR[0][1] <= FIRST_AND_LAST_SECTOR[0][0])
        {
            return 0xEEEE;
        }
        if (FIRST_AND_LAST_SECTOR[1][1] <= FIRST_AND_LAST_SECTOR[1][0])
        {
            return 0xEEEE;
        }
    
        // Check if FIRST_AND_LAST_SECTOR contains invalid sector
        if (FIRST_AND_LAST_SECTOR[0][1] > NUM_FLASH_SECTORS - 1 || FIRST_AND_LAST_SECTOR[0][1] < 1)
        {
            return 0xEEEE;
        }
        if (FIRST_AND_LAST_SECTOR[1][1] > NUM_FLASH_SECTORS - 1 || FIRST_AND_LAST_SECTOR[1][1] < 1)
        {
            return 0xEEEE;
        }
    
    } else // If only using 1 sector
    {
    
        // Verify that only sector is valid
        if (FIRST_AND_LAST_SECTOR[0][0] > NUM_FLASH_SECTORS - 1 || 
                FIRST_AND_LAST_SECTOR[1][0] > NUM_FLASH_SECTORS - 1) {
            return 0xEEEE;
        }
    }
  • Overlapping Sectors between the two units
  • if (FIRST_AND_LAST_SECTOR[0][0] <= FIRST_AND_LAST_SECTOR[1][1] && FIRST_AND_LAST_SECTOR[1][0] <= FIRST_AND_LAST_SECTOR[0][1]) { return 0xEEEE; }

If using Page Mode, the following will also be checked for

  • Check if total size of EEPROM Banks + Pages will fit in the Flash Sectors selected.
    // Calculate size of each EEPROM Bank (16 bit words)
    Bank_Size = 8 + ((EEPROM_PAGE_DATA_SIZE + 8) * NUM_EEPROM_PAGES);
    
    // Calculate amount of available space (16 bit words)
    uint32 Available_Words = NUM_EEPROM_SECTORS * FLASH_SECTOR_SIZE;
    
    // Check if size of EEPROM Banks and Pages will fit in EEPROM sectors
    if (Bank_Size * NUM_EEPROM_BANKS > Available_Words)
    {
        return 0xCCCC;
    }
  • Verify that the two EEPROM units do not have overlapping protection masks
    // Verify that the two EEPROM units do not have overlapping protection 
    // masks
    // First, get sectors for both units
    uint64 WE_Protection_AB_Sectors_Unit_0 = Configure_Protection_Masks(FIRST_AND_LAST_SECTOR[0], NUM_EEPROM_SECTORS);
    uint64 WE_Protection_AB_Sectors_Unit_1 = Configure_Protection_Masks(FIRST_AND_LAST_SECTOR[1], NUM_EEPROM_SECTORS);
    
    if (WE_Protection_AB_Sectors_Unit_0 & WE_Protection_AB_Sectors_Unit_1)
    {
        return 0xEEEE;
    }
    

It also warns you with the appropriate return code if one of the following conditions is detected:

  • Space for one or more EEPROM Banks is left in Flash after configuring EEPROM Bank and Page size
    // Notify for extra space (more than one EEPROM bank leftover)
    if (Available_Words - (Bank_Size * NUM_EEPROM_BANKS ) >= Bank_Size)
    {
        Warning_Flags += 1;
    }
  • If each page consists of less than 5 16-bit words (this wastes space as the 64-Bit Mode could be used without the need for Status Codes)
    if (EEPROM_PAGE_DATA_SIZE < 5)
    {
        Warning_Flags += 2;
    }

If using sectors in the 32-127 range (for F28P65x devices) and not using all eight sectors allocated to a single bit in the Write/Erase Protection Mask, a warning is issued. Any unused sectors within the eight designed by a single bit cannot be properly be protected from erase. For more information on how the Write/Erase Protection Masks correspond to sectors, see the TMS320F28P65x Flash API Version 3.00.00.00 Reference Guide.

uint16 i;
for (i = 0; i < 2; i++)
{
    // If using any sectors from 32-127
    if (FIRST_AND_LAST_SECTOR[i][1] > 31) {

        // If all sectors use protection mask B
        if (FIRST_AND_LAST_SECTOR[i][0] > 31)
        {
            // If using less than 8 sectors
            if (NUM_EEPROM_SECTORS < 8)
            {

                Warning_Flags += 4;
                break;

            } else {
                // If sectors are multiples of 8
                if ((FIRST_AND_LAST_SECTOR[i][0] % 8) != 0 || 
                       ((FIRST_AND_LAST_SECTOR[i][1] + 1) % 8 != 0))
                {
                    Warning_Flags += 4;
                    break;
            }
            }
        } else { // If only last sector is using protection mask B

            // If not a multiple of 8
            if ((FIRST_AND_LAST_SECTOR[i][1] + 1) % 8 != 0) {

                Warning_Flags += 4;
                break;
            }
        }
    }
}

This function also prepares Flash for Emulation by erasing the Sectors to be used for programming.

    // Combine sectors from both units and separate them by which 
    // protection register they use (A or B)
uint32 Combined_WE_Protection_A_Sectors = 
                               (uint32)WE_Protection_AB_Sectors_Unit_0 | 
                                 (uint32)WE_Protection_AB_Sectors_Unit_1;
uint32 Combined_WE_Protection_B_Sectors = 
                                 WE_Protection_AB_Sectors_Unit_0 >> 32 | 
                                   WE_Protection_AB_Sectors_Unit_1 >> 32;

// Create protection masks accordingly
WE_Protection_A_Mask = 0xFFFFFFFF ^ Combined_WE_Protection_A_Sectors;
WE_Protection_B_Mask = 0x00000FFF ^ Combined_WE_Protection_B_Sectors;

Erase_Bank();

Finally, Write/Erase Protection masks are configured for the Active EEPROM Unit.

// Configure Write/Erase Protection Masks used by the Flash API
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;