Skip to content

Commit

Permalink
STORAGE: add boot sector write, data store or request (unverified)
Browse files Browse the repository at this point in the history
  • Loading branch information
polesskiy-dev committed Sep 19, 2023
1 parent d9fdfcb commit d362d22
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#
#Sat Sep 16 11:25:52 CEST 2023
#Tue Sep 19 20:57:24 CEST 2023
default.languagetoolchain.version=4.30
default.Pack.dfplocation=/Applications/microchip/mplabx/v6.10/packs/Microchip/SAMD21_DFP/3.6.144
default.com-microchip-mplab-mdbcore-PK5Tool-PK5ToolImpl.md5=03e12bb97e05706420942b3ce207925c
conf.ids=default
default.languagetoolchain.dir=/Applications/microchip/xc32/v4.30/bin
default.com-microchip-mplab-nbide-toolchain-xc32-XC32LanguageToolchain.md5=453816bbff5fc8c544047982c7194139
host.id=0
host.id=f1rj-pf5j-g
configurations-xml=20c1654d5495177208af758828956b2d
com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=ff725c3d3fe40010a04a4bae132aaf51
proj.dir=/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/iot-risk-data-logger-nfc-samd21.X
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,9 @@
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/storage/storage_manager.h</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/driver/usb/usbfsv1/src/drv_usbfsv1.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/libraries/active-object-fsm/src/fsm/fsm.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/diskImage.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/storage/storage_manager_fsm.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/usb/src/usb_device.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/system/console/src/sys_console_usb_cdc.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/exceptions.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/init/init_manager.h</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/tasks.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/initialization.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/sensors/sht3x-temperature-humidity/sht3x_fsm.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/system/time/src/sys_time.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/startup_xc32.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/storage/storage_manager.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/system/time/sys_time.h</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/main.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/storage/storage_manager_fsm.c</file>
<file>file:/Users/artempolisskyi/projects/iot-risk-data-logger-nfc-samd21/firmware/src/config/default/driver/memory/src/drv_memory.c</file>
</group>
</open-files>
</project-private>
15 changes: 11 additions & 4 deletions firmware/src/storage/storage_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ TActiveObject *STORAGE_Initialize(void) {
// init AO fields
storageAO.drvMemoryHandle = drvMemoryHandle;
storageAO.transferHandle = DRV_I2C_TRANSFER_HANDLE_INVALID;
storageAO.pagesToProcessAmount = 0;
storageAO.page = 0;
storageAO.flash.currentPage = 0;
STORAGE_CLearPageBuffer(&storageAO);

// error on driver opening error
Expand All @@ -60,6 +59,14 @@ TActiveObject *STORAGE_Initialize(void) {
(uintptr_t) &storageAO
);

// for tests, empty some memory if needed
// DRV_MEMORY_AsyncErase(
// storageAO->drvMemoryHandle,
// &(storageAO->transferHandle),
// DRV_MEMORY_BOOT_SECTOR_FLASH_ADDRESS,
// 32 // amount of 4096 blocks to delete
// );

return (TActiveObject *) &storageAO;
};

Expand All @@ -86,8 +93,8 @@ void STORAGE_Tasks(void) {
if (FSM_IsValidState(nextState)) FSM_TraverseNextState(&storageAO.super, nextState);
};

void STORAGE_CLearPageBuffer(TSTORAGEActiveObject *const AO) {
memset(AO->pageBuffer, 0, DRV_AT25DF_PAGE_SIZE);
void STORAGE_CLearPageBuffer(TSTORAGEActiveObject *const storageAO) {
memset(storageAO->pageBuffer, 0, DRV_AT25DF_PAGE_SIZE);
}

void STORAGE_TransferEventHandler(DRV_MEMORY_EVENT event, DRV_MEMORY_COMMAND_HANDLE commandHandle, uintptr_t context) {
Expand Down
26 changes: 17 additions & 9 deletions firmware/src/storage/storage_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ extern "C" {

#define STORAGE_QUEUE_MAX_CAPACITY (8)
#define READ_BLOCK_SIZE (1)
#define PARTITION_0_ADDRESS (512)
#define BOOT_SECTOR_SIZE (4096) // 1 erase block equal
#define PARTITION_0_ADDRESS (0x200) // 512KB
#define BOOT_SECTOR_SIZE (0x1000) // 1 erase block equal (4096)
#define LOG_DATA_START_ADDRESS (BOOT_SECTOR_SIZE) // 1st page after boot sector
#define END_OF_PAGE_ADDRESS (DRV_AT25DF_PAGE_SIZE - 1)
#define READ_BLOCKS_IN_PAGE (DRV_AT25DF_PAGE_SIZE / READ_BLOCK_SIZE)
#define WRITE_BLOCKS_IN_PAGE (1)
#define BOOT_SECTOR_PAGES_TO_VALIDATE (1) // Amount of pages on flash to verify with boot sector header in NVM
#define IS_EQUAL_PAGES (0)
#define IS_ENOUGH_PLACE_TO_STORE (0)
#define ERASED_PAGE_PATTERN (0xFF)

extern const unsigned char FATBootSectorImage[DRV_MEMORY_BOOT_SECTOR_SIZE_PAGES * DRV_AT25DF_PAGE_SIZE];

Expand All @@ -49,6 +53,7 @@ typedef enum {
STORAGE_ST_WRITE_BOOT_SECTOR,
STORAGE_ST_FIND_LAST_NONEMPTY_PAGE,
STORAGE_ST_STORE_DATA_IN_TAIL,
STORAGE_ST_STORE_DATA,
STORAGE_ST_ERROR,
STORAGE_STATES_MAX
} STORAGE_STATE;
Expand All @@ -73,12 +78,15 @@ typedef enum {
* @extends TActiveObject
*/
typedef struct {
TActiveObject super;
DRV_HANDLE drvMemoryHandle;
DRV_MEMORY_COMMAND_HANDLE transferHandle;
uint8_t pagesToProcessAmount;
uint16_t page;
uint8_t pageBuffer[DRV_AT25DF_PAGE_SIZE];
TActiveObject super; /**< base class */
DRV_HANDLE drvMemoryHandle; /**< MEMORY driver handle */
DRV_MEMORY_COMMAND_HANDLE transferHandle; /**< MEMORY driver transfer handle */
struct {
uint8_t currentPage; /**< current page to process */
} flash; /**< flash memory state representation */
void* dataToStore; /**< pointer to data to store in flash */
size_t dataToStoreSize; /**< size of data to store in flash */
uint8_t pageBuffer[DRV_AT25DF_PAGE_SIZE]; /**< page buffer to read to or to write from*/
} TSTORAGEActiveObject;

/**
Expand All @@ -104,7 +112,7 @@ void STORAGE_Tasks(void);
* @brief Clean page buffer
* @memberof TSTORAGEActiveObject
*/
void STORAGE_CLearPageBuffer(TSTORAGEActiveObject *AO);
void STORAGE_CLearPageBuffer(TSTORAGEActiveObject *storageAO);

/**
* @brief Callback for SPI (MEMORY) ISR on success/error transfer.
Expand Down
120 changes: 101 additions & 19 deletions firmware/src/storage/storage_manager_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ static const TState *_writeMemoryBootSector(TActiveObject *const AO, TEvent even

static const TState *_verifyMemoryBootSector(TActiveObject *const AO, TEvent event);

static const TState *_findLastNonEmptyPage(TActiveObject *const AO, TEvent event);
static const TState *_findLastLogsNonEmptyPage(TActiveObject *const AO, TEvent event);

static const TState *_storeDataInTail(TActiveObject *const AO, TEvent event);

static const TState *_storeData(TActiveObject *const AO, TEvent event);

// error on MEMORY transfer queuing
static inline void _dispatchErrorOnInvalidTransfer(TSTORAGEActiveObject *const storageAO) {
if (DRV_I2C_TRANSFER_HANDLE_INVALID == storageAO->transferHandle) {
Expand All @@ -23,26 +25,28 @@ static inline void _dispatchErrorOnInvalidTransfer(TSTORAGEActiveObject *const s

/* states */
const TState storageStatesList[STORAGE_STATES_MAX] = {
[STORAGE_NO_STATE] = {.name = STORAGE_NO_STATE},
[STORAGE_ST_INIT] = {.name = STORAGE_ST_INIT},
[STORAGE_ST_READ_BOOT_SECTOR] = {.name = STORAGE_ST_READ_BOOT_SECTOR},
[STORAGE_ST_VERIFY_BOOT_SECTOR] = {.name = STORAGE_ST_VERIFY_BOOT_SECTOR},
[STORAGE_ST_WRITE_BOOT_SECTOR] = {.name = STORAGE_ST_WRITE_BOOT_SECTOR},
[STORAGE_ST_FIND_LAST_NONEMPTY_PAGE] = {.name = STORAGE_ST_FIND_LAST_NONEMPTY_PAGE},
[STORAGE_ST_IDLE] = {.name = STORAGE_ST_IDLE},
[STORAGE_ST_STORE_DATA_IN_TAIL] = {.name = STORAGE_ST_STORE_DATA_IN_TAIL},
[STORAGE_ST_ERROR] = {.name = STORAGE_ST_ERROR}
[STORAGE_NO_STATE] = {.name = STORAGE_NO_STATE},
[STORAGE_ST_INIT] = {.name = STORAGE_ST_INIT},
[STORAGE_ST_READ_BOOT_SECTOR] = {.name = STORAGE_ST_READ_BOOT_SECTOR},
[STORAGE_ST_VERIFY_BOOT_SECTOR] = {.name = STORAGE_ST_VERIFY_BOOT_SECTOR, .onExit = (TStateHook) STORAGE_CLearPageBuffer},
[STORAGE_ST_WRITE_BOOT_SECTOR] = {.name = STORAGE_ST_WRITE_BOOT_SECTOR},
[STORAGE_ST_FIND_LAST_NONEMPTY_PAGE] = {.name = STORAGE_ST_FIND_LAST_NONEMPTY_PAGE, .onEnter = (TStateHook) STORAGE_CLearPageBuffer, .onExit = (TStateHook) STORAGE_CLearPageBuffer},
[STORAGE_ST_IDLE] = {.name = STORAGE_ST_IDLE, .onEnter = (TStateHook) STORAGE_CLearPageBuffer},
[STORAGE_ST_STORE_DATA_IN_TAIL] = {.name = STORAGE_ST_STORE_DATA_IN_TAIL, .onEnter = (TStateHook) STORAGE_CLearPageBuffer},
[STORAGE_ST_STORE_DATA] = {.name = STORAGE_ST_STORE_DATA, .onExit = (TStateHook) STORAGE_CLearPageBuffer},
[STORAGE_ST_ERROR] = {.name = STORAGE_ST_ERROR}
};

/* state transitions table */
const TEventHandler storageTransitionTable[STORAGE_STATES_MAX][STORAGE_SIG_MAX] = {
[STORAGE_ST_INIT]= {[STORAGE_CHECK_MEMORY_BOOT_SECTOR] = _readMemoryBootSector, [STORAGE_ERROR]=_error},
[STORAGE_ST_READ_BOOT_SECTOR]= {[STORAGE_TRANSFER_SUCCESS]=_verifyMemoryBootSector, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_ERROR]=_error},
[STORAGE_ST_VERIFY_BOOT_SECTOR]= {[STORAGE_WRITE_MEMORY_BOOT_SECTOR]=_writeMemoryBootSector, [STORAGE_VERIFY_MEMORY_BOOT_SECTOR_SUCCESS]=_findLastNonEmptyPage, [STORAGE_ERROR]=_error},
[STORAGE_ST_WRITE_BOOT_SECTOR]= {[STORAGE_TRANSFER_SUCCESS]=_findLastNonEmptyPage /* TODO check whether STORAGE_TRANSFER_SUCCESS occurs after all 10 blocks or after each*/, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_ERROR]=_error},
[STORAGE_ST_FIND_LAST_NONEMPTY_PAGE]= {[STORAGE_TRANSFER_SUCCESS]=_findLastNonEmptyPage, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_FIND_LAST_NON_EMPTY_PAGE_SUCCESS]=_idle, [STORAGE_ERROR]=_error},
[STORAGE_ST_VERIFY_BOOT_SECTOR]= {[STORAGE_VERIFY_MEMORY_BOOT_SECTOR_SUCCESS]=_findLastLogsNonEmptyPage, [STORAGE_WRITE_MEMORY_BOOT_SECTOR]=_writeMemoryBootSector, [STORAGE_ERROR]=_error},
[STORAGE_ST_WRITE_BOOT_SECTOR]= {[STORAGE_TRANSFER_SUCCESS]=_findLastLogsNonEmptyPage /* TODO check whether STORAGE_TRANSFER_SUCCESS occurs after all 10 blocks or after each*/, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_ERROR]=_error},
[STORAGE_ST_FIND_LAST_NONEMPTY_PAGE]= {[STORAGE_TRANSFER_SUCCESS]=_findLastLogsNonEmptyPage, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_FIND_LAST_NON_EMPTY_PAGE_SUCCESS]=_idle, [STORAGE_ERROR]=_error},
[STORAGE_ST_IDLE]= {[STORAGE_STORE_DATA_IN_TAIL]=_storeDataInTail, [STORAGE_ERROR]=_error},
[STORAGE_ST_STORE_DATA_IN_TAIL]= {[STORAGE_TRANSFER_SUCCESS]=_idle, [STORAGE_ERROR]=_error},
[STORAGE_ST_STORE_DATA_IN_TAIL]= {[STORAGE_TRANSFER_SUCCESS]=_storeData, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_ERROR]=_error},
[STORAGE_ST_STORE_DATA]= {[STORAGE_TRANSFER_SUCCESS]=_idle, [STORAGE_TRANSFER_FAIL]=_error, [STORAGE_STORE_DATA_IN_TAIL]=_storeDataInTail, [STORAGE_ERROR]=_error},
[STORAGE_ST_ERROR]= {[STORAGE_ERROR]=_error},
};

Expand All @@ -62,7 +66,8 @@ static const TState *_readMemoryBootSector(TActiveObject *const AO, TEvent event
storageAO->drvMemoryHandle,
&(storageAO->transferHandle),
storageAO->pageBuffer,
DRV_MEMORY_BOOT_SECTOR_FLASH_ADDRESS + PARTITION_0_ADDRESS, // let's check from meaningful partition data starts
DRV_MEMORY_BOOT_SECTOR_FLASH_ADDRESS +
PARTITION_0_ADDRESS, // let's check from meaningful partition data starts
BOOT_SECTOR_PAGES_TO_VALIDATE * READ_BLOCKS_IN_PAGE
);

Expand All @@ -74,7 +79,8 @@ static const TState *_readMemoryBootSector(TActiveObject *const AO, TEvent event
static const TState *_verifyMemoryBootSector(TActiveObject *const AO, TEvent event) {
TSTORAGEActiveObject *storageAO = (TSTORAGEActiveObject *) AO;

if (IS_EQUAL_PAGES == memcmp(storageAO->pageBuffer, (FATBootSectorImage + PARTITION_0_ADDRESS), DRV_AT25DF_PAGE_SIZE)) {
if (IS_EQUAL_PAGES ==
memcmp(storageAO->pageBuffer, (FATBootSectorImage + PARTITION_0_ADDRESS), DRV_AT25DF_PAGE_SIZE)) {
ActiveObject_Dispatch(&(storageAO->super), (TEvent) {.sig = STORAGE_VERIFY_MEMORY_BOOT_SECTOR_SUCCESS});
} else {
ActiveObject_Dispatch(&(storageAO->super), (TEvent) {.sig = STORAGE_WRITE_MEMORY_BOOT_SECTOR});
Expand All @@ -97,17 +103,93 @@ static const TState *_writeMemoryBootSector(TActiveObject *const AO, TEvent even

_dispatchErrorOnInvalidTransfer(storageAO);

// set current page to next after boot sector
storageAO->flash.currentPage = DRV_MEMORY_BOOT_SECTOR_SIZE_PAGES;

return &(storageStatesList[STORAGE_ST_WRITE_BOOT_SECTOR]);
}

static const TState *_findLastNonEmptyPage(TActiveObject *const AO, TEvent event) {
// TODO implement this
static const TState *_findLastLogsNonEmptyPage(TActiveObject *const AO, TEvent event) {
TSTORAGEActiveObject *storageAO = (TSTORAGEActiveObject *) AO;

DRV_MEMORY_AsyncRead(
storageAO->drvMemoryHandle,
&(storageAO->transferHandle),
storageAO->pageBuffer,
(storageAO->flash.currentPage * DRV_AT25DF_PAGE_SIZE) +
BOOT_SECTOR_SIZE, // offset from boot sector check page by page
READ_BLOCKS_IN_PAGE
);

// if storageAO.pageBuffer empty - inspected page is suitable for new data, if not, then increment storageAO.page and repeat
if (IS_EQUAL_PAGES == memcmp(storageAO->pageBuffer, (void *) ERASED_PAGE_PATTERN, DRV_AT25DF_PAGE_SIZE)) {
ActiveObject_Dispatch(&(storageAO->super), (TEvent) {.sig = STORAGE_FIND_LAST_NON_EMPTY_PAGE_SUCCESS});
} else {
storageAO->flash.currentPage++;
ActiveObject_Dispatch(&(storageAO->super), (TEvent) {.sig = STORAGE_FIND_LAST_NON_EMPTY_PAGE});
}

return &(storageStatesList[STORAGE_ST_FIND_LAST_NONEMPTY_PAGE]);
}

static const TState *_storeDataInTail(TActiveObject *const AO, TEvent event) {
// TODO implement this
TSTORAGEActiveObject *storageAO = (TSTORAGEActiveObject *) AO;

// read current page
DRV_MEMORY_AsyncRead(
storageAO->drvMemoryHandle,
&(storageAO->transferHandle),
storageAO->pageBuffer,
(storageAO->flash.currentPage * DRV_AT25DF_PAGE_SIZE),
READ_BLOCKS_IN_PAGE
);

_dispatchErrorOnInvalidTransfer(storageAO);

storageAO->dataToStore = event.payload;
storageAO->dataToStoreSize = event.size;

return &(storageStatesList[STORAGE_ST_STORE_DATA_IN_TAIL]);
}

static const TState *_storeData(TActiveObject *const AO, TEvent event) {
TSTORAGEActiveObject *storageAO = (TSTORAGEActiveObject *) AO;

uint8_t freePlaceInPageAddr = 0;

// find free place in page (should be equal to data size)
while (freePlaceInPageAddr < END_OF_PAGE_ADDRESS) {
if (IS_ENOUGH_PLACE_TO_STORE ==
memcmp(storageAO->pageBuffer + freePlaceInPageAddr, (void *) ERASED_PAGE_PATTERN,
storageAO->dataToStoreSize))
break;
freePlaceInPageAddr += storageAO->dataToStoreSize; // offset is same as data size
};

if (freePlaceInPageAddr >= END_OF_PAGE_ADDRESS) {
// no free place in page, increment page and repeat
storageAO->flash.currentPage++;
ActiveObject_Dispatch(&(storageAO->super), (TEvent) {
.sig = STORAGE_STORE_DATA_IN_TAIL,
.payload = storageAO->dataToStore,
.size = storageAO->dataToStoreSize
});

return &(storageStatesList[STORAGE_ST_STORE_DATA]);
};

// append data to page buffer
memcpy(storageAO->pageBuffer + freePlaceInPageAddr, storageAO->dataToStore, storageAO->dataToStoreSize);

// write page buffer to flash
DRV_MEMORY_AsyncWrite(
storageAO->drvMemoryHandle,
&(storageAO->transferHandle),
storageAO->pageBuffer,
(storageAO->flash.currentPage * DRV_AT25DF_PAGE_SIZE),
WRITE_BLOCKS_IN_PAGE);

_dispatchErrorOnInvalidTransfer(storageAO);

return &(storageStatesList[STORAGE_ST_STORE_DATA]);
}

0 comments on commit d362d22

Please sign in to comment.