2013-05-19 16:37:30 +02:00
|
|
|
#include <stdlib.h> /* abort */
|
|
|
|
#include <stdio.h> /* fopen/fread/fwrite/fseek */
|
|
|
|
#include <assert.h> /* assert */
|
|
|
|
#include <string.h> /* memset */
|
2013-05-16 01:18:02 +02:00
|
|
|
#include <unistd.h>
|
2012-12-14 06:25:02 +01:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include "pios_flash_ut_priv.h"
|
|
|
|
|
|
|
|
enum flash_ut_magic {
|
2013-05-19 16:37:30 +02:00
|
|
|
FLASH_UT_MAGIC = 0x321dabc1,
|
2012-12-14 06:25:02 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct flash_ut_dev {
|
2013-05-19 16:37:30 +02:00
|
|
|
enum flash_ut_magic magic;
|
|
|
|
const struct pios_flash_ut_cfg *cfg;
|
|
|
|
bool transaction_in_progress;
|
|
|
|
FILE *flash_file;
|
2012-12-14 06:25:02 +01:00
|
|
|
};
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
static struct flash_ut_dev *PIOS_Flash_UT_Alloc(void)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = malloc(sizeof(struct flash_ut_dev));
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
flash_dev->magic = FLASH_UT_MAGIC;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return flash_dev;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
int32_t PIOS_Flash_UT_Init(uintptr_t *flash_id, const struct pios_flash_ut_cfg *cfg)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
/* 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);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = PIOS_Flash_UT_Alloc();
|
|
|
|
assert(flash_dev);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
flash_dev->cfg = cfg;
|
|
|
|
flash_dev->transaction_in_progress = false;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
flash_dev->flash_file = fopen(FLASH_IMAGE_FILE, "rb+");
|
|
|
|
if (flash_dev->flash_file == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
if (fseek(flash_dev->flash_file, flash_dev->cfg->size_of_flash, SEEK_SET) != 0) {
|
|
|
|
return -2;
|
|
|
|
}
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
*flash_id = (uintptr_t)flash_dev;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
int32_t PIOS_Flash_UT_Destroy(uintptr_t flash_id)
|
|
|
|
{
|
2013-05-16 01:18:02 +02:00
|
|
|
/* Check inputs */
|
|
|
|
assert(flash_id);
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (void *)flash_id;
|
2013-05-16 01:18:02 +02:00
|
|
|
|
|
|
|
if (flash_dev->flash_file == NULL) {
|
2013-05-19 16:37:30 +02:00
|
|
|
return -1;
|
2013-05-16 01:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fclose(flash_dev->flash_file);
|
|
|
|
|
|
|
|
free(flash_dev);
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
unlink(FLASH_IMAGE_FILE);
|
2013-05-16 01:18:02 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-14 06:25:02 +01:00
|
|
|
/**********************************
|
|
|
|
*
|
|
|
|
* Provide a PIOS flash driver API
|
|
|
|
*
|
|
|
|
*********************************/
|
|
|
|
#include "pios_flash.h"
|
|
|
|
|
2012-12-15 05:13:33 +01:00
|
|
|
static int32_t PIOS_Flash_UT_StartTransaction(uintptr_t flash_id)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(!flash_dev->transaction_in_progress);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
flash_dev->transaction_in_progress = true;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2012-12-15 05:13:33 +01:00
|
|
|
static int32_t PIOS_Flash_UT_EndTransaction(uintptr_t flash_id)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(flash_dev->transaction_in_progress);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
flash_dev->transaction_in_progress = false;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2012-12-15 05:13:33 +01:00
|
|
|
static int32_t PIOS_Flash_UT_EraseSector(uintptr_t flash_id, uint32_t addr)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(flash_dev->transaction_in_progress);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) {
|
|
|
|
assert(0);
|
|
|
|
}
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
unsigned char *buf = malloc(flash_dev->cfg->size_of_sector);
|
|
|
|
assert(buf);
|
|
|
|
memset((void *)buf, 0xFF, flash_dev->cfg->size_of_sector);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
size_t s;
|
|
|
|
s = fwrite(buf, 1, flash_dev->cfg->size_of_sector, flash_dev->flash_file);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(s == flash_dev->cfg->size_of_sector);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
static int32_t PIOS_Flash_UT_WriteData(uintptr_t flash_id, uint32_t addr, uint8_t *data, uint16_t len)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
/* Check inputs */
|
|
|
|
assert(data);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(flash_dev->transaction_in_progress);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) {
|
|
|
|
assert(0);
|
|
|
|
}
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
size_t s;
|
|
|
|
s = fwrite(data, 1, len, flash_dev->flash_file);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(s == len);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
static int32_t PIOS_Flash_UT_ReadData(uintptr_t flash_id, uint32_t addr, uint8_t *data, uint16_t len)
|
2012-12-14 06:25:02 +01:00
|
|
|
{
|
2013-05-19 16:37:30 +02:00
|
|
|
/* Check inputs */
|
|
|
|
assert(data);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
struct flash_ut_dev *flash_dev = (struct flash_ut_dev *)flash_id;
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(flash_dev->transaction_in_progress);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
if (fseek(flash_dev->flash_file, addr, SEEK_SET) != 0) {
|
|
|
|
assert(0);
|
|
|
|
}
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
size_t s;
|
|
|
|
s = fread(data, 1, len, flash_dev->flash_file);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
assert(s == len);
|
2012-12-14 06:25:02 +01:00
|
|
|
|
2013-05-19 16:37:30 +02:00
|
|
|
return 0;
|
2012-12-14 06:25:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Provide a flash driver to external drivers */
|
|
|
|
const struct pios_flash_driver pios_ut_flash_driver = {
|
2013-05-19 16:37:30 +02:00
|
|
|
.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,
|
2012-12-14 06:25:02 +01:00
|
|
|
};
|