#include /* abort */ #include /* fopen/fread/fwrite/fseek */ #include /* assert */ #include /* memset */ #include #include #include "pios_flash_ut_priv.h" enum flash_ut_magic { FLASH_UT_MAGIC = 0x321dabc1, }; struct flash_ut_dev { enum flash_ut_magic magic; const struct pios_flash_ut_cfg *cfg; bool transaction_in_progress; FILE *flash_file; }; static struct flash_ut_dev *PIOS_Flash_UT_Alloc(void) { struct flash_ut_dev *flash_dev = malloc(sizeof(struct flash_ut_dev)); flash_dev->magic = FLASH_UT_MAGIC; return flash_dev; } int32_t PIOS_Flash_UT_Init(uintptr_t *flash_id, const struct pios_flash_ut_cfg *cfg) { /* Check inputs */ assert(flash_id); assert(cfg); assert(cfg->size_of_flash); assert(cfg->size_of_sector); assert((cfg->size_of_flash % cfg->size_of_sector) == 0); struct flash_ut_dev *flash_dev = PIOS_Flash_UT_Alloc(); assert(flash_dev); flash_dev->cfg = cfg; flash_dev->transaction_in_progress = false; flash_dev->flash_file = fopen(FLASH_IMAGE_FILE, "rb+"); if (flash_dev->flash_file == NULL) { return -1; } if (fseek(flash_dev->flash_file, flash_dev->cfg->size_of_flash, SEEK_SET) != 0) { return -2; } *flash_id = (uintptr_t)flash_dev; return 0; } int32_t PIOS_Flash_UT_Destroy(uintptr_t flash_id) { /* Check inputs */ assert(flash_id); struct flash_ut_dev *flash_dev = (void *)flash_id; if (flash_dev->flash_file == NULL) { return -1; } fclose(flash_dev->flash_file); free(flash_dev); unlink(FLASH_IMAGE_FILE); return 0; } /********************************** * * Provide a PIOS flash driver API * *********************************/ #include "pios_flash.h" static int32_t PIOS_Flash_UT_StartTransaction(uintptr_t flash_id) { struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id; assert(!flash_dev->transaction_in_progress); flash_dev->transaction_in_progress = true; return 0; } static int32_t PIOS_Flash_UT_EndTransaction(uintptr_t flash_id) { struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id; assert(flash_dev->transaction_in_progress); flash_dev->transaction_in_progress = false; return 0; } static int32_t PIOS_Flash_UT_EraseSector(uintptr_t flash_id, uint32_t addr) { struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id; assert(flash_dev->transaction_in_progress); if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) { assert(0); } unsigned char *buf = malloc(flash_dev->cfg->size_of_sector); assert(buf); memset((void *)buf, 0xFF, flash_dev->cfg->size_of_sector); size_t s; s = fwrite(buf, 1, flash_dev->cfg->size_of_sector, flash_dev->flash_file); assert(s == flash_dev->cfg->size_of_sector); return 0; } static int32_t PIOS_Flash_UT_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t *data, uint16_t len) { /* Check inputs */ assert(data); struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id; assert(flash_dev->transaction_in_progress); if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) { assert(0); } size_t s; s = fwrite(data, 1, len, flash_dev->flash_file); assert(s == len); return 0; } static int32_t PIOS_Flash_UT_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t *data, uint16_t len) { /* Check inputs */ assert(data); struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id; assert(flash_dev->transaction_in_progress); if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) { assert(0); } size_t s; s = fread(data, 1, len, flash_dev->flash_file); assert(s == len); return 0; } /* Provide a flash driver to external drivers */ const struct pios_flash_driver pios_ut_flash_driver = { .start_transaction = PIOS_Flash_UT_StartTransaction, .end_transaction = PIOS_Flash_UT_EndTransaction, .erase_sector = PIOS_Flash_UT_EraseSector, .write_data = PIOS_Flash_UT_WriteData, .read_data = PIOS_Flash_UT_ReadData, };