// ----------------------------------------------------------------------------- /// @file CachedStorage.c /// @brief EEPROM driver including local caching (for one page) // ----------------------------------------------------------------------------- // 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 CachedStorage.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include "Logger.h" #include #include "CachedStorage.h" #include "InternalFlash.h" #include "stm32f10x_flash.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus CachedStorage_construct(struct CachedStorage* self, struct MemoryDevice* memoryDevice, unsigned int pageNumber) { ErrorStatus returnValue = SUCCESS; if (!self->initialized) { if (returnValue == SUCCESS) { if (pageNumber > 0) { self->pageNumber = pageNumber; } else { returnValue = ERROR; } } if (returnValue == SUCCESS) { self->memoryDevice = memoryDevice; } if (returnValue == SUCCESS) { self->cacheSize = CACHED_STORAGE_PAGESIZE / 4; MemoryDevice_read(self->memoryDevice, (uint32_t*)self->storage, self->memoryDevice->startAddress + self->memoryDevice->pageSize * self->pageNumber, self->cacheSize); self->initialized = true; self->dirty = false; LOGGER_DEBUG(mainLog, "Created Cached Storage at page: %d", self->pageNumber); } } return returnValue; } void CachedStorage_destruct(struct CachedStorage* self) { if (self->initialized) { self->initialized = false; } } void CachedStorage_writeByte(struct CachedStorage* self, int offset, uint8_t value) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE) { if(value != self->storage[offset]) { self->storage[offset] = value; self->dirty = true; } } } } void CachedStorage_writeHalfWord(struct CachedStorage* self, int offset, uint16_t _value) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE - 1) { uint16_t value = _value; if((value & 0xFF) != self->storage[offset + 1]) { self->storage[offset + 1] = value & 0xFF; self->dirty = true; } value >>= 8; if((value & 0xFF) != self->storage[offset]) { self->storage[offset] = value & 0xFF; self->dirty = true; } } } } void CachedStorage_writeWord(struct CachedStorage* self, int offset, uint32_t _value) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE - 3) { uint32_t value = _value; if((value & 0xFF) != self->storage[offset + 3]) { self->storage[offset + 3] = value & 0xFF; self->dirty = true; } value >>= 8; if((value & 0xFF) != self->storage[offset + 2]) { self->storage[offset + 2] = value & 0xFF; self->dirty = true; } value >>= 8; if((value & 0xFF) != self->storage[offset + 1]) { self->storage[offset + 1] = value & 0xFF; self->dirty = true; } value >>= 8; if((value & 0xFF) != self->storage[offset]) { self->storage[offset] = value & 0xFF; self->dirty = true; } } } } void CachedStorage_writeBlob(struct CachedStorage* self, int offset, const void* blob, size_t blobSize) { if (self->initialized) { if(offset + blobSize <= CACHED_STORAGE_PAGESIZE) { memcpy(&self->storage[offset], blob, blobSize); self->dirty = true; } } } uint8_t CachedStorage_readByte(struct CachedStorage* self, int offset) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE) { return self->storage[offset]; } else { return 0; } } else { return 0; } } uint16_t CachedStorage_readHalfWord(struct CachedStorage* self, int offset) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE - 1) { return self->storage[offset + 1] | (self->storage[offset] << 8); } else { return 0; } } else { return 0; } } uint32_t CachedStorage_readWord(struct CachedStorage* self, int offset) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE - 3) { return self->storage[offset + 3] | (self->storage[offset + 2] << 8) | (self->storage[offset + 1] << 16) | (self->storage[offset] << 24); } else { return 0; } } else { return 0; } } const void* CachedStorage_readBlob(struct CachedStorage* self, int offset) { if (self->initialized) { if(offset < CACHED_STORAGE_PAGESIZE) { return &self->storage[offset]; } else { return NULL; } } else { return NULL; } } void CachedStorage_commit(struct CachedStorage* self) { if (self->initialized) { if(self->dirty) { MemoryDevice_read(self->memoryDevice, (uint32_t*)self->tempBuffer, self->memoryDevice->startAddress + self->memoryDevice->pageSize * self->pageNumber, self->cacheSize); if(memcmp(self->tempBuffer, self->storage, (sizeof(self->storage) / sizeof(self->storage[0]))) != 0) { if (self->memoryDevice->needsEraseBeforeWrite) { MemoryDevice_erasePage(self->memoryDevice, self->pageNumber); } MemoryDevice_write(self->memoryDevice, (uint32_t*)self->storage, self->memoryDevice->startAddress + self->memoryDevice->pageSize * self->pageNumber, self->cacheSize); } else { LOGGER_DEBUG(mainLog, "CachedStorage content unchanged, did not write"); } self->dirty = false; } else { LOGGER_DEBUG(mainLog, "CachedStorage content unchanged, did not write"); } } }