/*
* nvram.c
*
* Created on: 4 Jun 2017
* Author: Mike
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l1xx_hal.h"
#include "nvram.h"
// NVRAM hardware erases to all 0x
nvram_info_t const HARDWARE_ERASED = {.u32 = 0UL};
// Marked as erased change to all 1
nvram_info_t const MARKED_ERASED = {.u32 = ~0UL};
// marked as unusable change pattern to something in between
nvram_info_t const MARKED_UNUSABLE = {.u32 = 0x555555FFUL};
nvram_info_t NVRAM_Base[NVRAM_WORDS] __attribute__((section(".NVRAM_Data"))); // set by linker
static void
WriteNVRAM(int offset, nvram_info_t data)
{
HAL_FLASHEx_DATAEEPROM_Unlock();
HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_WORD, (uint32_t)(&NVRAM_Base[offset]), data.u32);
HAL_FLASHEx_DATAEEPROM_Lock();
}
static void
EraseNVRAM(int offset)
{
HAL_FLASHEx_DATAEEPROM_Unlock();
HAL_FLASHEx_DATAEEPROM_Erase(FLASH_TYPEERASEDATA_WORD, (uint32_t)(&NVRAM_Base[offset]));
HAL_FLASHEx_DATAEEPROM_Lock();
}
void write_nvram_data(nvram_info_t data)
{
#if defined SEMIHOSTING
#endif
int base = 0;
/* search blank */
for (int ptr = 0; ptr < NVRAM_WORDS; ptr++)
{
// erase the entry just found
if (NVRAM_Base[ptr].data.tag == data.data.tag)
{
// erase previous data, delete any entries that have a matching tag
#if defined SEMIHOSTING
printf("marked erased %d\n", ptr
);
#endif
WriteNVRAM(ptr, MARKED_ERASED);
base = ptr;
}
}
// search forward for next erased or empty element, use it
for (int offset = 1; offset < NVRAM_WORDS + 1; offset++)
{
int index = (base + offset) % NVRAM_WORDS;
if (NVRAM_Base[index].u32 == MARKED_ERASED.u32 || NVRAM_Base[index].u32 == HARDWARE_ERASED.u32)
{
if (NVRAM_Base[index].u32 != HARDWARE_ERASED.u32)
{
#if defined SEMIHOSTING
#endif
EraseNVRAM(index);
}
#if defined SEMIHOSTING
printf("write %d=%d\n", index
, data.
data.
pos);
#endif
WriteNVRAM(index, data);
// now check to see if it actually went
if (NVRAM_Base[index].u32 != data.u32)
{
#if defined SEMIHOSTING
printf("unusable %d\n", index
);
#endif
WriteNVRAM(index, MARKED_UNUSABLE); // mark as neither unused or used
continue;
}
return;
}
}
}
nvram_info_t *find_nvram_data(uint8_t searchTag)
{
#if defined SEMIHOSTING
#endif
for (int ptr = 0; ptr < NVRAM_WORDS; ptr++)
{
if (NVRAM_Base[ptr].data.tag == searchTag)
{
#if defined SEMIHOSTING
printf("found %d=%d\n", ptr
, NVRAM_Base
[ptr
].
data.
pos);
#endif
return &NVRAM_Base[ptr];
}
}
return NULL;
}
void erase_nvram()
{
#if defined SEMIHOSTING
#endif
for (int ptr = 0; ptr < NVRAM_WORDS; ptr++)
EraseNVRAM(ptr);
}