środa, 26 lipca 2017

[27] STM32F4 - Emulacja pamięci EEPROM, biblioteki STD

Ten post chciałbym poświęcić na przygotowanie programu umożliwiającego wykonanie emulacji pamięci EEPROM.

Informacje odnoście metody jaką należy zastosować można znaleźć w nocie aplikacyjnej AN3969.

[Źródłó: http://www.st.com/en/evaluation-tools/stm32f4discovery.html]

Opis:


Do zapisu danych dostępne są dwa bloki o numerach 2 i 3, każdy o wielkości 16kByte. Pozwala to na uzyskanie pamięci w której można przechowywać ustawienia konfiguracyjne itp. 

Adresy startowe bloków to odpowiednio 0x08008000 oraz 0x800C0000. Rozmiar sektora wynosi 0x4000.

Zapis danych musi być poprzedzony ich wyczyszczeniem.

Program:


Do przygotowania poniższych kodów wykorzystałem przykłady od firmy ST.

Funkcja inicjalizująca całą pamięć, oraz sprawdzająca poprawność jej uruchomienia:

  1. uint8_t Internal_FLASH_Init(void)
  2. {
  3.   uint16_t PageStatus0;
  4.   uint16_t PageStatus1;
  5.   uint16_t indexLoop;
  6.   int16_t x = -1;
  7.   int32_t read_value;
  8.   uint16_t dat;
  9.     /* Unlocks the FLASH control register access */
  10.   FLASH_Unlock();
  11.     /* Write page adress */
  12.   PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
  13.   PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
  14.     /* Check status */
  15.     if(PageStatus0 == MEMORY_ERASED)
  16.     {
  17.         if (PageStatus1 == MEMORY_VALID_PAGE)
  18.         {  


  19.  /* First sector to erase, set voltage level */
  20.             if(FLASH_EraseSector(PAGE0_ID,(uint8_t)VoltageRange_3) != FLASH_COMPLETE) {
  21.                 return 0; /* Error */
  22.             }
  23.     }
  24.         else if (PageStatus1 == MEMORY_RECEIVE_DATA)
  25.         {
  26.             if(FLASH_EraseSector(PAGE0_ID, (uint8_t)VoltageRange_3) != FLASH_COMPLETE){
  27.                 return 0; /* Error */
  28.             }
  29.             if(FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, MEMORY_VALID_PAGE) != FLASH_COMPLETE){
  30.                 return 0; /* Error */
  31.             }
  32.     }
  33.     else
  34.         {
  35.             if (Internal_Flash_Format() != FLASH_COMPLETE) {
  36.                 return 0; /* Error */
  37.             }
  38.     }
  39.     }
  40.     else if(PageStatus0 == MEMORY_RECEIVE_DATA)
  41.     {
  42.         if (PageStatus1 == MEMORY_VALID_PAGE)
  43.         {
  44.             x=-1;
  45.             for (indexLoop = 0; indexLoop < FLASH_MAX_ADDRESS; indexLoop++)
  46.       {
  47.                 if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == indexLoop) { x = indexLoop; }
  48.         if (indexLoop != x)
  49.                 {
  50.                     read_value = Internal_FLASH_Read(indexLoop);
  51.                     if (read_value >= 0)
  52.                     {
  53.                         dat=(uint16_t)(read_value);
  54.                        
  55.                         if (Internal_Flash_VerifyPage(indexLoop, dat) != FLASH_COMPLETE) {
  56.                             return 0; /* Error */
  57.                         }
  58.           }
  59.         }
  60.       }
  61.                        
  62.             if(FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, MEMORY_VALID_PAGE) != FLASH_COMPLETE) {
  63.                     return 0; /* Error */
  64.             }
  65.            
  66.             if(FLASH_EraseSector(PAGE1_ID, (uint8_t)VoltageRange_3) != FLASH_COMPLETE) {
  67.                     return 0; /* Error */
  68.             }
  69.     }
  70.         else if (PageStatus1 == MEMORY_ERASED)
  71.         {
  72.             if(FLASH_EraseSector(PAGE1_ID, (uint8_t)VoltageRange_3) != FLASH_COMPLETE) {
  73.                     return 0; /* Error */
  74.             }
  75.             if(FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, MEMORY_VALID_PAGE) != FLASH_COMPLETE) {
  76.                     return 0; /* Error */
  77.             }  
  78.     }
  79.         else
  80.         {
  81.             if(Internal_Flash_Format() != FLASH_COMPLETE) {
  82.                     return 0; /* Error */
  83.             }  
  84.     }
  85.     }
  86.     else if(PageStatus0 == MEMORY_VALID_PAGE)
  87.     {
  88.         if (PageStatus1 == MEMORY_VALID_PAGE)
  89.         {
  90.             if(Internal_Flash_Format() != FLASH_COMPLETE) {
  91.                     return 0; /* Error */
  92.             }  
  93.     }
  94.         else if (PageStatus1 == MEMORY_ERASED)
  95.         {
  96.             if(FLASH_EraseSector(PAGE1_ID, (uint8_t)VoltageRange_3) != FLASH_COMPLETE) {
  97.                     return 0; /* Error */
  98.             }  
  99.     }
  100.     else
  101.         {
  102.             x=-1;
  103.             for (indexLoop = 0; indexLoop < FLASH_MAX_ADDRESS; indexLoop++)
  104.             {
  105.                 if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == indexLoop)
  106.                 {
  107.                     x = indexLoop;
  108.         }
  109.                 if (indexLoop != x)
  110.                 {
  111.                     read_value = Internal_FLASH_Read(indexLoop);
  112.                     if (read_value >= 0)
  113.                     {
  114.                         dat=(uint16_t)(read_value);
  115.                        
  116.                         if(Internal_Flash_VerifyPage(indexLoop, dat) != FLASH_COMPLETE) {
  117.                             return 0; /* Error */
  118.                         }  
  119.           }
  120.         }
  121.       }
  122.             if(FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, MEMORY_VALID_PAGE)!= FLASH_COMPLETE) {
  123.                 return 0; /* Error */
  124.             }  
  125.             if(FLASH_EraseSector(PAGE0_ID, (uint8_t)VoltageRange_3)!= FLASH_COMPLETE) {
  126.                 return 0; /* Error */
  127.             }  
  128.         }
  129.     }
  130.     else
  131.     {          
  132.         if(Internal_Flash_Format()!= FLASH_COMPLETE) {
  133.                 return 0; /* Error */
  134.         }
  135.     }
  136.    
  137.   return 1;
  138. }

Odczyt z pamięci Flash.

  1. uint16_t Internal_FLASH_Read(uint16_t readAddress)
  2. {
  3.   uint16_t return_value=0;
  4.   uint16_t value = 0;
  5.   uint16_t checkPage = 0;
  6.   uint16_t AddressValue = 0;
  7.   uint32_t Address = 0;
  8.   uint32_t PageStartAddress = 0;
  9.   if(readAddress>=FLASH_MAX_ADDRESS){ return 0; /* Error*/ }
  10.   checkPage=Internal_Flash_CheckValidPage(READ_FROM_PAGE);
  11.   if(checkPage==MEMORY_PAGE0)
  12.   {
  13.     PageStartAddress = (uint32_t)PAGE0_BASE_ADDRESS;
  14.     Address = (uint32_t)(PAGE0_END_ADDRESS-1);
  15.   }
  16.   else if(checkPage==MEMORY_PAGE1)
  17.   {
  18.     PageStartAddress = (uint32_t)PAGE1_BASE_ADDRESS;
  19.     Address = (uint32_t)(PAGE1_END_ADDRESS-1);
  20.   }
  21.   else
  22.   {
  23.     return  0; /* Error*/
  24.   }    
  25.   while (Address > (PageStartAddress + 2))
  26.   {
  27.     AddressValue = (*(volatile uint16_t*)Address);
  28.     if (AddressValue == readAddress)
  29.     {
  30.       value = (*(volatile uint16_t*)(Address - 2));
  31.       return_value=0;
  32.       break;
  33.     }
  34.     else
  35.     {
  36.       Address = Address - 4;
  37.     }
  38.   }
  39.   if(return_value==0) {
  40.         return (uint16_t)value;
  41.   }
  42.    
  43.   return return_value;
  44. }


Zapis danych do pamięci:

  1. uint8_t Internal_FLASH_Write(uint16_t Address, uint16_t Data)
  2. {
  3.   uint16_t Status = MEMORY_NO_ERROR;
  4.    
  5.   if(Address>=FLASH_MAX_ADDRESS) { return 1; }
  6.    
  7.   if(Internal_Flash_VerifyPage(Address, Data) == MEMORY_PAGE_FULL) {
  8.           if(Internal_Flash_TranferPage(Address, Data) != FLASH_COMPLETE) {
  9.                 return 2;
  10.             }
  11.     }
  12.    
  13.   return 0;
  14. }

Pozostałe funkcje są funkcjami statycznymi. Zostały one zdefiniowane bezpośrednio w bibliotece.

Cały kod można pobrać z dysku Google pod tym linkiem.