#include "stm8l10x_clk.h" #include "eeprom.h" #include "main.h" #include "watchdog.h" #define OPERATION_TIMEOUT ((uint16_t)0x2000) extern u8* serial_alt; static FunctionalState fs; //static FLASH_Status_TypeDef fst; //uint8_t tmp; u8 EEPROM_CalcCrcFunc(u8* address, u8 len) { u8 crc = 0; //int bit_cnt; u8 data; u8 feedback_bit; while (len--) { data = *address++; //for (bit_cnt = 8; bit_cnt > 0; bit_cnt--) for (int j = 0; j < 8; j++) { feedback_bit = (u8)((data ^ crc) & 0x01); crc >>= 1; data >>= 1; if (feedback_bit > 0) crc ^= ((0x18 >> 1) | 0x80); } } return crc; } static FLASH_Status_TypeDef EEPROM_WaitForLastOperation(void) { uint32_t timeout = OPERATION_TIMEOUT; uint8_t My_FlagStatus = 0x00; /* Wait until operation completion or write protected page occured */ while ((My_FlagStatus == 0x00) && (timeout != 0x00)) { My_FlagStatus = (uint8_t)(FLASH->IAPSR & (FLASH_IAPSR_EOP | FLASH_IAPSR_WR_PG_DIS)); timeout--; } if (timeout == 0x00 ) { My_FlagStatus = FLASH_Status_TimeOut; } return((FLASH_Status_TypeDef)My_FlagStatus); } uint16_t Address; u8* pData; static void EEPROM_Unlock(FLASH_MemType_TypeDef FLASH_MemType) { /* Check parameter */ assert_param(IS_MEMORY_TYPE(FLASH_MemType)); //FLASH_MemType = FLASH_MemType_Data; /* Unlock program memory */ if (FLASH_MemType == FLASH_MemType_Program) { FLASH->PUKR = FLASH_RASS_KEY1; FLASH->PUKR= FLASH_RASS_KEY2; } /* Unlock data memory */ if (FLASH_MemType == FLASH_MemType_Data) { FLASH->DUKR = FLASH_RASS_KEY2; /* Warning: keys are reversed on data memory !!! */ FLASH->DUKR = FLASH_RASS_KEY1; } } static void EEPROM_Lock(FLASH_MemType_TypeDef FLASH_MemType) { /* Check parameter */ assert_param(IS_MEMORY_TYPE(FLASH_MemType)); /* Lock memory */ FLASH->IAPSR &= FLASH_MemType; } static u8 EEPROM_ProgramWord(void) { u8 retval = 1; EEPROM_Unlock(FLASH_MemType_Program); //disableInterrupts(); //ResetWatchdog(); FLASH->CR2 |= FLASH_CR2_WPRG; *((PointerAttr uint8_t*)Address++) = *((uint8_t*)(pData++)); /* Write one byte - from lowest address*/ *((PointerAttr uint8_t*)Address++) = *((uint8_t*)(pData++)); /* Write one byte*/ *((PointerAttr uint8_t*)Address++) = *((uint8_t*)(pData++)); /* Write one byte*/ *((PointerAttr uint8_t*)Address++) = *((uint8_t*)(pData++)); /* Write one byte*/ if(EEPROM_WaitForLastOperation() != FLASH_Status_Successful_Operation) { retval = 0; } //enableInterrupts(); EEPROM_Lock(FLASH_MemType_Program); return retval; } u8 EEPROM_CopyScratchPad(u8 numSlot, u8* buffer) { u8 retval, retval_1; u8* adr; u8 i; CLK_MasterPrescalerConfig(CLK_MasterPrescaler_HSIDiv8); fs = FLASH_GetReadOutProtectionStatus(); if(fs != DISABLE || numSlot >= SLOTS_AMOUNT) { return 0; } Address = (uint16_t)(EEPROM + ((uint16_t)numSlot << 3)); pData = buffer; adr = (PointerAttr uint8_t*)Address; ResetWatchdog(); //disableInterrupts(); retval_1 = EEPROM_ProgramWord(); retval = EEPROM_ProgramWord(); //enableInterrupts(); i = 0xFF; while(i--); CLK_MasterPrescalerConfig(CLK_Prescaler); for(i = 0; i < 8; i++) { if(adr[i] != buffer[i]) { return 0; } } return 1; } static u32 CounterBlock[CNT_SLOTS_NMB]; static u32 ReferenceBlock[CNT_SLOTS_NMB]; static u8 iCounterBlock; extern volatile u32 eeprom_counter; static u8 EEPROM_ProgramCounterBlock(void) { int i; u8 retval = 1; u32* adr; Address = (u16)CNT_ADDRESS; adr = (PointerAttr u32*)Address; pData = (u8*)CounterBlock; for(i = 0; i < CNT_SLOTS_NMB; i++) { EEPROM_ProgramWord(); if(adr[i] != CounterBlock[i]) { retval = 0; } } return retval; } static u8 idx[CNT_SLOTS_NMB]; static u8 EEPROM_GetMinIdx() { u8 i, j, min; for(i = 0, min = 0; i < CNT_SLOTS_NMB; i++) { if(CounterBlock[i] < CounterBlock[min]) { for(j = 0; j < CNT_SLOTS_NMB; j++) { if(i == idx[j]) { break; } } if(j == CNT_SLOTS_NMB) { min = i; } } } return min; } static u8 EEPROM_CreateReferenceBlock(u8 minIdx) { u8 i, n; u32 value = CounterBlock[minIdx]; for(i = 0; i < CNT_SLOTS_NMB; i++) { ReferenceBlock[minIdx++] = value++; if(minIdx >= CNT_SLOTS_NMB) { minIdx = 0; } } for(i = 0, n = 0; i < CNT_SLOTS_NMB; i++) { if(CounterBlock[i] != ReferenceBlock[i]) { n++; } } if(n > CORRECTION_CNT_SLOTS_NMB) { return 0; } if(n > 0) { for(i = 0; i < CNT_SLOTS_NMB; i++) { CounterBlock[i] = ReferenceBlock[i]; } return 2; } return 1; } static u8 EEPROM_CorrectCounterBlock() { u8 i, min, retval; for(i = 0; i < CNT_SLOTS_NMB; i++) { idx[i] = NO_IDX; } for(i = 0; i <= CORRECTION_CNT_SLOTS_NMB; i++) { min = EEPROM_GetMinIdx(); retval = EEPROM_CreateReferenceBlock(min); if(retval > 0) { iCounterBlock = min; eeprom_counter = CounterBlock[iCounterBlock]; break; } idx[i] = min; } return retval; } static u8 EEPROM_TestCounter(void) { u32* adr; int i; Address = (u16)CNT_ADDRESS; adr = (PointerAttr u32*)Address; for(i = 0; i < CNT_SLOTS_NMB; i++) { if(adr[i] != CNT_EMPTY) { break; } } if(i == CNT_SLOTS_NMB) { //NextCounter = CNT_SLOTS_NMB; eeprom_counter = 0; iCounterBlock = 0; for(i = 0; i < CNT_SLOTS_NMB; i++) { CounterBlock[i] = i; } return EEPROM_ProgramCounterBlock(); } for(i = 0; i < CNT_SLOTS_NMB; i++) { CounterBlock[i] = adr[i]; } switch(EEPROM_CorrectCounterBlock()) { case 1: break; case 2: return EEPROM_ProgramCounterBlock(); case 0: return 0; } return 1; } u32 next_counter; u8 EEPROM_IncrementCounter(void) { u32* adr; //u8 retval = 1; if(eeprom_counter == INVALID_COUNTER) { return 0; } if(eeprom_counter >= CNT_MAX_VALUE) { eeprom_counter = CNT_MAX_VALUE; return 0; } next_counter = eeprom_counter + CNT_SLOTS_NMB; Address = (u16)(CNT_ADDRESS + (iCounterBlock << 2)); adr = (PointerAttr u32*)Address; pData = (u8*)&next_counter; EEPROM_ProgramWord(); /* if(*adr != next_counter) { retval = 0; } */ eeprom_counter++; if(++iCounterBlock >= CNT_SLOTS_NMB) { iCounterBlock = 0; } return 1; } /* u32 EEPROM_GetCounter(void) { return 0;//NextCounter - CNT_SLOTS_NMB; } */ void EEPROM_InitCounter(void) { eeprom_counter = 0; if(EEPROM_TestCounter() == 0) { eeprom_counter = INVALID_COUNTER; } }