// ----------------------------------------------------------------------------- /// @file PowerLossDetector.c /// @brief Description // ----------------------------------------------------------------------------- // Micro-Key bv // Industrieweg 28, 9804 TG Noordhorn // Postbus 92, 9800 AB Zuidhorn // The Netherlands // Tel: +31 594 503020 // Fax: +31 594 505825 // Email: support@microkey.nl // Web: www.microkey.nl // ----------------------------------------------------------------------------- /// $Revision$ /// $Author$ /// $Date$ // (c) 2017 Micro-Key bv // ----------------------------------------------------------------------------- /// @file PowerLossDetector.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include "FreeRTOS.h" #include "task.h" #include "PowerLossDetector.h" #include "Logger.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- #define PLD_MASK_FREE (0xFFFFFFFF) #define PLD_MASK_BUSY (0xDEADC01A) #define PLD_MASK_USED (0x00000000) // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- struct PowerLossDetector { bool initialized; bool loaded; unsigned int pageNumber; unsigned int startAddress; unsigned int length; struct MemoryDevice* memoryDevice; }; // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- static struct PowerLossDetector _plDetector = {.initialized = false, .loaded = false}; struct PowerLossDetector* const plDetector = &_plDetector; // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus PowerLossDetector_construct(struct MemoryDevice* memoryDevice, unsigned int pageNumber, unsigned int startAddress, unsigned int length) { ErrorStatus returnValue = SUCCESS; if (!plDetector->initialized) { if (returnValue == SUCCESS) { plDetector->pageNumber = pageNumber; plDetector->startAddress = startAddress; plDetector->length = length; } if (returnValue == SUCCESS) { if (memoryDevice != NULL) { if (memoryDevice->initialized) { plDetector->memoryDevice = memoryDevice; plDetector->initialized = true; LOGGER_DEBUG(mainLog, "PowerLossDetector constructed"); } else { returnValue = ERROR; } } else { returnValue = ERROR; } } } else { returnValue = ERROR; } return returnValue; } extern void PowerLossDetector_destruct(void) { plDetector->initialized = false; } void PowerLossDetector_setBusyFlag(void) { bool freeAddressFound = false; uint32_t buffer; unsigned int flagAddress; unsigned int loopcounter; // Find the first available free address for (loopcounter = plDetector->startAddress; loopcounter < (plDetector->startAddress + plDetector->length); loopcounter += 4) { MemoryDevice_read(plDetector->memoryDevice, &buffer, loopcounter, 1); if (buffer == PLD_MASK_FREE) { // Found free space flagAddress = loopcounter; freeAddressFound = true; LOGGER_DEBUG(mainLog, "Found free address at: %X", loopcounter); break; } } // In case no free address has been found, the complete page must be cleared // After clearing, the address to write the busy flag to is equal to the start address if (!freeAddressFound) { MemoryDevice_erasePage(plDetector->memoryDevice, plDetector->pageNumber); flagAddress = plDetector->startAddress; } buffer = PLD_MASK_BUSY; MemoryDevice_write(plDetector->memoryDevice, &buffer, flagAddress, 1); } extern void PowerLossDetector_clearBusyFlag(void) { uint32_t buffer; unsigned int loopcounter; // Find the first available free address for (loopcounter = plDetector->startAddress; loopcounter < (plDetector->startAddress + plDetector->length); loopcounter += 4) { MemoryDevice_read(plDetector->memoryDevice, &buffer, loopcounter, 1); if (buffer == PLD_MASK_BUSY) { // Found the busy flag buffer = PLD_MASK_USED; LOGGER_DEBUG(mainLog, "Found busyFlag at address %X", loopcounter); MemoryDevice_write(plDetector->memoryDevice, &buffer, loopcounter, 1); break; } } } bool PowerLossDetection_isFlagSet(void) { bool returnValue = false; uint32_t buffer; unsigned int loopcounter; // Find the first available free address for (loopcounter = plDetector->startAddress; loopcounter < (plDetector->startAddress + plDetector->length); loopcounter += 4) { MemoryDevice_read(plDetector->memoryDevice, &buffer, loopcounter, 1); if (buffer == PLD_MASK_BUSY) { // Found the busy flag returnValue = true; LOGGER_DEBUG(mainLog, "Found busyFlag at address %X", loopcounter); break; } } return returnValue; }