// ----------------------------------------------------------------------------- /// @file InternalFlash.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 InternalFlash.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include "Logger.h" #include "MemoryDevice.h" #include "InternalFlash.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- static ErrorStatus read(const struct MemoryDevice* self, uint32_t* buffer, uint32_t address, unsigned int length); static ErrorStatus write(const struct MemoryDevice* self, uint32_t* buffer, uint32_t address, unsigned int length); static ErrorStatus erasePage(const struct MemoryDevice* self, unsigned int page); // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus InternalFlash_construct(struct InternalFlash* self) { ErrorStatus returnValue = SUCCESS; if (!self->initialized) { if (returnValue == SUCCESS) { returnValue = MemoryDevice_construct(&self->memoryDevice, INTERNAL_FLASH_BASE_ADDRESS, (INTERNAL_FLASH_BASE_ADDRESS + (INTERNAL_FLASH_NUMBER_OF_PAGES * INTERNAL_FLASH_PAGE_SIZE)), read, write, erasePage); } if (returnValue == SUCCESS) { self->startAddress = INTERNAL_FLASH_BASE_ADDRESS; self->endAddress = (INTERNAL_FLASH_BASE_ADDRESS + (INTERNAL_FLASH_NUMBER_OF_PAGES * INTERNAL_FLASH_PAGE_SIZE)); self->pageSize = INTERNAL_FLASH_PAGE_SIZE; self->initialized = true; } } else { returnValue = ERROR; } return returnValue; } void InternalFlash_destruct(struct InternalFlash* self) { if (self->initialized) { MemoryDevice_destruct(&self->memoryDevice); self->initialized = false; } } ErrorStatus InternalFlash_write(const struct InternalFlash* self, uint32_t* buffer, uint32_t address, unsigned int length) { ErrorStatus returnValue = SUCCESS; FLASH_Status FLASHStatus = FLASH_COMPLETE; uint32_t _address = address; uint32_t _endAddress = address + (length * 4); if (self->initialized) { if (returnValue == SUCCESS) { // Verify start address boundaries if ((_address < self->startAddress) && (_address >= self->endAddress)) { // Start address is NOT OK returnValue = ERROR; } } if (returnValue == SUCCESS) { // Verify end address boundaries if ((_endAddress >= self->endAddress)) { // End address is NOT OK returnValue = ERROR; } } // Boundaries OK - Write to FLASH if (returnValue == SUCCESS) { // Unlock the FLASH bank FLASH_Unlock(); // Loop writing until end address is reached int bufferIndex = 0; while((_address < _endAddress) && (FLASHStatus == FLASH_COMPLETE)) { FLASHStatus = FLASH_ProgramWord(_address, buffer[bufferIndex++]); // 32bit data register requires increment by 4 for next word address _address = _address + 4; } // After programming, lock the FLASH FLASH_Lock(); } } else { returnValue = ERROR; LOGGER_ERROR(mainLog, "BOEH"); } return returnValue; } ErrorStatus InternalFlash_read(const struct InternalFlash* self, uint32_t* buffer, uint32_t address, unsigned int length) { ErrorStatus returnValue = SUCCESS; uint32_t _address = address; uint32_t _endAddress = address + (length * 4); if (self->initialized) { if (returnValue == SUCCESS) { // Verify start address boundaries if ((_address < self->startAddress) && (_address >= self->endAddress)) { // Start address is NOT OK returnValue = ERROR; } } if (returnValue == SUCCESS) { // Verify end address boundaries if ((_endAddress >= self->endAddress)) { // End address is NOT OK returnValue = ERROR; } } // Boundaries OK - Read from FLASH if (returnValue == SUCCESS) { // Loop reading until end address is reached int bufferIndex = 0; while(_address < _endAddress) { buffer[bufferIndex++] = *(uint32_t*) _address; // 32bit data register requires increment by 4 for next word address _address = _address + 4; } } } else { returnValue = ERROR; } return returnValue; } ErrorStatus InternalFlash_erasePage(const struct InternalFlash* self, unsigned int page) { ErrorStatus returnValue = SUCCESS; FLASH_Status FLASHStatus; if (self->initialized) { // Unlock the FLASH bank FLASH_Unlock(); FLASHStatus = FLASH_ErasePage(self->startAddress + (self->pageSize * page)); // After programming, lock the FLASH FLASH_Lock(); if (FLASHStatus != FLASH_COMPLETE) { returnValue = ERROR; } } else { returnValue = ERROR; } return returnValue; } static ErrorStatus read(const struct MemoryDevice* self, uint32_t* buffer, uint32_t address, unsigned int length) { return InternalFlash_read((const struct InternalFlash*)self, buffer, address, length); } static ErrorStatus write(const struct MemoryDevice* self, uint32_t* buffer, uint32_t address, unsigned int length) { return InternalFlash_write((const struct InternalFlash*)self, buffer, address, length); } static ErrorStatus erasePage(const struct MemoryDevice* self, unsigned int page) { return InternalFlash_erasePage((const struct InternalFlash*)self, page); }