mirror of https://github.com/rusefi/ChibiOS.git
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10978 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
8f814aba60
commit
f16a0581ce
|
@ -112,15 +112,21 @@ uint16_t crc16(uint16_t crc, const uint8_t *data, size_t n) {
|
|||
return crc;
|
||||
}
|
||||
|
||||
static flash_offset_t mfs_get_bank_offset(MFSDriver *mfsp, mfs_bank_t bank) {
|
||||
|
||||
return bank == MFS_BANK_0 ? flashGetSectorOffset(mfsp->config->flashp,
|
||||
mfsp->config->bank0_start) :
|
||||
flashGetSectorOffset(mfsp->config->flashp,
|
||||
mfsp->config->bank1_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash write.
|
||||
* @note If the option @p MFS_CFG_WRITE_VERIFY is enabled then the flash
|
||||
* is also read back for verification.
|
||||
* @brief Flash read.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] offset flash offset
|
||||
* @param[in] n number of bytes to be read
|
||||
* @param[out] rp pointer to the data buffer
|
||||
* @param[in] rp pointer to the data buffer
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
|
||||
|
@ -128,13 +134,41 @@ uint16_t crc16(uint16_t crc, const uint8_t *data, size_t n) {
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_flash_write(MFSDriver *devp,
|
||||
flash_offset_t offset,
|
||||
size_t n, const
|
||||
uint8_t *p) {
|
||||
static mfs_error_t mfs_flash_read(MFSDriver *mfsp, flash_offset_t offset,
|
||||
size_t n, const uint8_t *rp) {
|
||||
flash_error_t ferr;
|
||||
|
||||
ferr = flashProgram(devp->config->flashp, offset, n, p);
|
||||
ferr = flashRead(mfsp->config->flashp, offset, n, rp);
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
|
||||
return MFS_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash write.
|
||||
* @note If the option @p MFS_CFG_WRITE_VERIFY is enabled then the flash
|
||||
* is also read back for verification.
|
||||
*
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] offset flash offset
|
||||
* @param[in] n number of bytes to be writen
|
||||
* @param[out] wp pointer to the data buffer
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
|
||||
* failures.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_flash_write(MFSDriver *mfsp,
|
||||
flash_offset_t offset,
|
||||
size_t n,
|
||||
uint8_t *wp) {
|
||||
flash_error_t ferr;
|
||||
|
||||
ferr = flashProgram(mfsp->config->flashp, offset, n, wp);
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
|
@ -145,7 +179,7 @@ static mfs_error_t mfs_flash_write(MFSDriver *devp,
|
|||
/**
|
||||
* @brief Erases and verifies all sectors belonging to a bank.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] bank bank to be erased
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
|
@ -154,30 +188,72 @@ static mfs_error_t mfs_flash_write(MFSDriver *devp,
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_bank_erase(MFSDriver *devp, mfs_bank_t bank) {
|
||||
static mfs_error_t mfs_bank_erase(MFSDriver *mfsp, mfs_bank_t bank) {
|
||||
flash_sector_t sector, end;
|
||||
|
||||
if (bank == MFS_BANK_0) {
|
||||
sector = devp->config->bank0_start;
|
||||
end = devp->config->bank0_start + devp->config->bank0_sectors;
|
||||
sector = mfsp->config->bank0_start;
|
||||
end = mfsp->config->bank0_start + mfsp->config->bank0_sectors;
|
||||
}
|
||||
else {
|
||||
sector = devp->config->bank1_start;
|
||||
end = devp->config->bank1_start + devp->config->bank1_sectors;
|
||||
sector = mfsp->config->bank1_start;
|
||||
end = mfsp->config->bank1_start + mfsp->config->bank1_sectors;
|
||||
}
|
||||
|
||||
while (sector < end) {
|
||||
flash_error_t ferr;
|
||||
|
||||
ferr = flashStartEraseSector(devp->config->flashp, sector);
|
||||
ferr = flashStartEraseSector(mfsp->config->flashp, sector);
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
ferr = flashWaitErase(devp->config->flashp);
|
||||
ferr = flashWaitErase(mfsp->config->flashp);
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
ferr = flashVerifyErase(devp->config->flashp, sector);
|
||||
ferr = flashVerifyErase(mfsp->config->flashp, sector);
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
|
||||
sector++;
|
||||
}
|
||||
|
||||
return MFS_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases and verifies all sectors belonging to a bank.
|
||||
*
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] bank bank to be erased
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_ERR_NOT_ERASED if the bank is not erased
|
||||
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
|
||||
* failures.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_bank_verify_erase(MFSDriver *mfsp, mfs_bank_t bank) {
|
||||
flash_sector_t sector, end;
|
||||
|
||||
if (bank == MFS_BANK_0) {
|
||||
sector = mfsp->config->bank0_start;
|
||||
end = mfsp->config->bank0_start + mfsp->config->bank0_sectors;
|
||||
}
|
||||
else {
|
||||
sector = mfsp->config->bank1_start;
|
||||
end = mfsp->config->bank1_start + mfsp->config->bank1_sectors;
|
||||
}
|
||||
|
||||
while (sector < end) {
|
||||
flash_error_t ferr;
|
||||
|
||||
ferr = flashVerifyErase(mfsp->config->flashp, sector);
|
||||
if (ferr == FLASH_ERROR_VERIFY) {
|
||||
return MFS_ERR_NOT_ERASED;
|
||||
}
|
||||
if (ferr != FLASH_NO_ERROR) {
|
||||
return MFS_ERR_FLASH_FAILURE;
|
||||
}
|
||||
|
@ -191,7 +267,7 @@ static mfs_error_t mfs_bank_erase(MFSDriver *devp, mfs_bank_t bank) {
|
|||
/**
|
||||
* @brief Writes the validation header in a bank.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] bank bank to be validated
|
||||
* @param[in] cnt value for the flash usage counter
|
||||
* @return The operation status.
|
||||
|
@ -201,17 +277,17 @@ static mfs_error_t mfs_bank_erase(MFSDriver *devp, mfs_bank_t bank) {
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_bank_set_header(MFSDriver *devp,
|
||||
static mfs_error_t mfs_bank_set_header(MFSDriver *mfsp,
|
||||
mfs_bank_t bank,
|
||||
uint32_t cnt) {
|
||||
flash_sector_t sector;
|
||||
mfs_bank_header_t header;
|
||||
|
||||
if (bank == MFS_BANK_0) {
|
||||
sector = devp->config->bank0_start;
|
||||
sector = mfsp->config->bank0_start;
|
||||
}
|
||||
else {
|
||||
sector = devp->config->bank1_start;
|
||||
sector = mfsp->config->bank1_start;
|
||||
}
|
||||
|
||||
header.magic1 = MFS_BANK_MAGIC_1;
|
||||
|
@ -222,8 +298,8 @@ static mfs_error_t mfs_bank_set_header(MFSDriver *devp,
|
|||
(const uint8_t *)&header,
|
||||
sizeof (flash_sector_t) - sizeof (uint16_t));
|
||||
|
||||
return mfs_flash_write(devp,
|
||||
flashGetSectorOffset(devp->config->flashp, sector),
|
||||
return mfs_flash_write(mfsp,
|
||||
flashGetSectorOffset(mfsp->config->flashp, sector),
|
||||
sizeof (mfs_bank_header_t),
|
||||
(const uint8_t *)&header);
|
||||
}
|
||||
|
@ -231,7 +307,7 @@ static mfs_error_t mfs_bank_set_header(MFSDriver *devp,
|
|||
/**
|
||||
* @brief Copies all records from a bank to another.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] sbank source bank
|
||||
* @param[in] dbank destination bank
|
||||
* @return The operation status.
|
||||
|
@ -241,11 +317,11 @@ static mfs_error_t mfs_bank_set_header(MFSDriver *devp,
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_bank_copy(MFSDriver *devp,
|
||||
static mfs_error_t mfs_bank_copy(MFSDriver *mfsp,
|
||||
mfs_bank_t sbank,
|
||||
mfs_bank_t dbank) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
(void)sbank;
|
||||
(void)dbank;
|
||||
|
||||
|
@ -255,16 +331,16 @@ static mfs_error_t mfs_bank_copy(MFSDriver *devp,
|
|||
/**
|
||||
* @brief Selects a bank as current.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] bank bank to be erased
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static mfs_error_t mfs_bank_mount(MFSDriver *devp, mfs_bank_t bank) {
|
||||
static mfs_error_t mfs_bank_mount(MFSDriver *mfsp, mfs_bank_t bank) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
(void)bank;
|
||||
|
||||
return MFS_NO_ERROR;
|
||||
|
@ -273,26 +349,36 @@ static mfs_error_t mfs_bank_mount(MFSDriver *devp, mfs_bank_t bank) {
|
|||
/**
|
||||
* @brief Determines the state of a flash bank.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] bank the bank identifier
|
||||
* @param[out[ statep bank state
|
||||
* @param[out] cntp bank counter value, only valid if the bank is not
|
||||
* in the @p MFS_BANK_GARBAGE or @p MFS_BANK_ERASED
|
||||
* states.
|
||||
*
|
||||
* @return The bank state.
|
||||
* @retval MFS_BANK_ERASED if the bank is fully erased.
|
||||
* @retval MFS_BANK_OK if the bank contains valid data.
|
||||
* @retval MFS_BANK_PARTIAL if the bank contains errors but the data is still
|
||||
* readable.
|
||||
* @retval MFS_BANK_GARBAGE if the bank contains unreadable garbage.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_ERR_FLASH_FAILURE if the flash memory is unusable because HW
|
||||
* failures.
|
||||
*/
|
||||
static mfs_bank_state_t mfs_get_bank_state(MFSDriver *devp,
|
||||
mfs_bank_t bank,
|
||||
uint32_t *cntp) {
|
||||
static mfs_error_t mfs_get_bank_state(MFSDriver *mfsp,
|
||||
mfs_bank_t bank,
|
||||
mfs_bank_state_t *statep,
|
||||
uint32_t *cntp) {
|
||||
mfs_error_t err;
|
||||
|
||||
(void)devp;
|
||||
(void)bank;
|
||||
(void)cntp;
|
||||
/* Special case where the block is fully erased.*/
|
||||
err = mfs_bank_verify_erase(mfsp, bank);
|
||||
if (err == MFS_NO_ERROR) {
|
||||
*statep = MFS_BANK_ERASED;
|
||||
return MFS_BANK_OK;
|
||||
}
|
||||
|
||||
/* Reading the header of the current bank into the transient buffer.*/
|
||||
RET_ON_ERROR(mfs_flash_read(mfsp,
|
||||
mfs_get_bank_offset(mfsp, bank),
|
||||
sizeof (mfs_bank_header_t),
|
||||
(void *)&mfsp->buffer.bhdr));
|
||||
|
||||
return MFS_BANK_OK;
|
||||
}
|
||||
|
@ -300,7 +386,7 @@ static mfs_bank_state_t mfs_get_bank_state(MFSDriver *devp,
|
|||
/**
|
||||
* @brief Performs a flash partition mount attempt.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_WARN_REPAIR if the operation has been completed but a
|
||||
|
@ -310,13 +396,13 @@ static mfs_bank_state_t mfs_get_bank_state(MFSDriver *devp,
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
||||
static mfs_error_t mfs_try_mount(MFSDriver *mfsp) {
|
||||
mfs_bank_state_t sts0, sts1;
|
||||
uint32_t cnt0 = 0, cnt1 = 0;
|
||||
|
||||
/* Assessing the state of the two banks.*/
|
||||
sts0 = mfs_get_bank_state(devp, MFS_BANK_0, &cnt0);
|
||||
sts1 = mfs_get_bank_state(devp, MFS_BANK_1, &cnt1);
|
||||
RET_ON_ERROR(mfs_get_bank_state(mfsp, MFS_BANK_0, &sts0, &cnt0));
|
||||
RET_ON_ERROR(mfs_get_bank_state(mfsp, MFS_BANK_1, &sts1, &cnt1));
|
||||
|
||||
/* Handling all possible scenarios, each one requires its own recovery
|
||||
strategy.*/
|
||||
|
@ -324,33 +410,33 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
|
||||
case PAIR(MFS_BANK_ERASED, MFS_BANK_ERASED):
|
||||
/* Both banks erased, first initialization.*/
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_NO_ERROR;
|
||||
|
||||
case PAIR(MFS_BANK_ERASED, MFS_BANK_OK):
|
||||
/* Normal situation, bank one is used.*/
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
return MFS_NO_ERROR;
|
||||
|
||||
case PAIR(MFS_BANK_ERASED, MFS_BANK_PARTIAL):
|
||||
/* Bank zero is erased, bank one has problems.*/
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_ERASED, MFS_BANK_GARBAGE):
|
||||
/* Bank zero is erased, bank one is not readable.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_OK, MFS_BANK_ERASED):
|
||||
/* Normal situation, bank zero is used.*/
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_NO_ERROR;
|
||||
|
||||
case PAIR(MFS_BANK_OK, MFS_BANK_OK):
|
||||
|
@ -358,13 +444,13 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
older one.*/
|
||||
if (cnt0 > cnt1) {
|
||||
/* Bank 0 is newer.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
}
|
||||
else {
|
||||
/* Bank 1 is newer.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
}
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
|
@ -373,31 +459,31 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
if (cnt0 > cnt1) {
|
||||
/* Normal bank zero is more recent than the partial bank one, the
|
||||
partial bank needs to be erased.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
}
|
||||
else {
|
||||
/* Partial bank one is more recent than the normal bank zero.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
}
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_OK, MFS_BANK_GARBAGE):
|
||||
/* Bank zero is normal, bank one is unreadable.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_PARTIAL, MFS_BANK_ERASED):
|
||||
/* Bank zero has problems, bank one is erased.*/
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_PARTIAL, MFS_BANK_OK):
|
||||
|
@ -405,16 +491,16 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
if (cnt1 > cnt0) {
|
||||
/* Normal bank one is more recent than the partial bank zero, the
|
||||
partial bank has to be erased.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
}
|
||||
else {
|
||||
/* Partial bank zero is more recent than the normal bank one.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
}
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
|
@ -422,59 +508,59 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
/* Both banks have problems.*/
|
||||
if (cnt0 > cnt1) {
|
||||
/* Bank zero is newer, copying in bank one and using it.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
}
|
||||
else {
|
||||
/* Bank one is newer, copying in bank zero and using it.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt1 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
}
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_PARTIAL, MFS_BANK_GARBAGE):
|
||||
/* Bank zero has problems, bank one is unreadable.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_0, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_1, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_ERASED):
|
||||
/* Bank zero is unreadable, bank one is erased.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_OK):
|
||||
/* Bank zero is unreadable, bank one is normal.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_1));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_PARTIAL):
|
||||
/* Bank zero is unreadable, bank one has problems.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(devp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_copy(mfsp, MFS_BANK_1, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, cnt0 + 1));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
case PAIR(MFS_BANK_GARBAGE, MFS_BANK_GARBAGE):
|
||||
/* Both banks are unreadable, reinitializing.*/
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(devp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(devp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(devp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_0));
|
||||
RET_ON_ERROR(mfs_bank_erase(mfsp, MFS_BANK_1));
|
||||
RET_ON_ERROR(mfs_bank_set_header(mfsp, MFS_BANK_0, 1));
|
||||
RET_ON_ERROR(mfs_bank_mount(mfsp, MFS_BANK_0));
|
||||
return MFS_WARN_REPAIR;
|
||||
|
||||
default:
|
||||
|
@ -492,53 +578,53 @@ static mfs_error_t mfs_try_mount(MFSDriver *devp) {
|
|||
/**
|
||||
* @brief Initializes an instance.
|
||||
*
|
||||
* @param[out] devp pointer to the @p MFSDriver object
|
||||
* @param[out] mfsp pointer to the @p MFSDriver object
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
void mfsObjectInit(MFSDriver *devp) {
|
||||
void mfsObjectInit(MFSDriver *mfsp) {
|
||||
|
||||
osalDbgCheck(devp != NULL);
|
||||
osalDbgCheck(mfsp != NULL);
|
||||
|
||||
devp->state = MFS_STOP;
|
||||
devp->config = NULL;
|
||||
mfsp->state = MFS_STOP;
|
||||
mfsp->config = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates a MFS driver.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] config pointer to the configuration
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void mfsStart(MFSDriver *devp, const MFSConfig *config) {
|
||||
void mfsStart(MFSDriver *mfsp, const MFSConfig *config) {
|
||||
|
||||
osalDbgCheck((devp != NULL) && (config != NULL));
|
||||
osalDbgAssert(devp->state != MFS_UNINIT, "invalid state");
|
||||
osalDbgCheck((mfsp != NULL) && (config != NULL));
|
||||
osalDbgAssert(mfsp->state != MFS_UNINIT, "invalid state");
|
||||
|
||||
if (devp->state == MFS_STOP) {
|
||||
if (mfsp->state == MFS_STOP) {
|
||||
|
||||
devp->config = config;
|
||||
devp->state = MFS_READY;
|
||||
mfsp->config = config;
|
||||
mfsp->state = MFS_READY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates a MFS driver.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
void mfsStop(MFSDriver *devp) {
|
||||
void mfsStop(MFSDriver *mfsp) {
|
||||
|
||||
osalDbgCheck(devp != NULL);
|
||||
osalDbgAssert(devp->state != MFS_UNINIT, "invalid state");
|
||||
osalDbgCheck(mfsp != NULL);
|
||||
osalDbgAssert(mfsp->state != MFS_UNINIT, "invalid state");
|
||||
|
||||
if (devp->state != MFS_STOP) {
|
||||
if (mfsp->state != MFS_STOP) {
|
||||
|
||||
devp->state = MFS_STOP;
|
||||
mfsp->state = MFS_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,7 +633,7 @@ void mfsStop(MFSDriver *devp) {
|
|||
* @details This functions checks the storage internal state and eventually
|
||||
* performs the required initialization or repair operations.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
* @retval MFS_WARN_REPAIR if the operation has been completed but a
|
||||
|
@ -557,14 +643,14 @@ void mfsStop(MFSDriver *devp) {
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
mfs_error_t mfsMount(MFSDriver *devp) {
|
||||
mfs_error_t mfsMount(MFSDriver *mfsp) {
|
||||
unsigned i;
|
||||
|
||||
/* Attempting to mount the managed partition.*/
|
||||
for (i = 0; i < MFS_CFG_MAX_REPAIR_ATTEMPTS; i++) {
|
||||
mfs_error_t err;
|
||||
|
||||
err = mfs_try_mount(devp);
|
||||
err = mfs_try_mount(mfsp);
|
||||
if (!MFS_IS_ERROR(err))
|
||||
return err;
|
||||
}
|
||||
|
@ -575,9 +661,9 @@ mfs_error_t mfsMount(MFSDriver *devp) {
|
|||
/**
|
||||
* @brief Unmounts a manage flash storage.
|
||||
*/
|
||||
mfs_error_t mfsUnmount(MFSDriver *devp) {
|
||||
mfs_error_t mfsUnmount(MFSDriver *mfsp) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
|
||||
return MFS_NO_ERROR;
|
||||
}
|
||||
|
@ -585,7 +671,7 @@ mfs_error_t mfsUnmount(MFSDriver *devp) {
|
|||
/**
|
||||
* @brief Retrieves and reads a data record.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] id record numeric identifier
|
||||
* @param[in,out] np on input is the maximum buffer size, on return it is
|
||||
* the size of the data copied into the buffer
|
||||
|
@ -597,10 +683,10 @@ mfs_error_t mfsUnmount(MFSDriver *devp) {
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
mfs_error_t mfsReadRecord(MFSDriver *devp, uint32_t id,
|
||||
mfs_error_t mfsReadRecord(MFSDriver *mfsp, uint32_t id,
|
||||
uint32_t *np, uint8_t *buffer) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
(void)id;
|
||||
(void)np;
|
||||
(void)buffer;
|
||||
|
@ -611,7 +697,7 @@ mfs_error_t mfsReadRecord(MFSDriver *devp, uint32_t id,
|
|||
/**
|
||||
* @brief Creates or updates a data record.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] id record numeric identifier
|
||||
* @param[in] n size of data to be written, it cannot be zero
|
||||
* @param[in] buffer pointer to a buffer for record data
|
||||
|
@ -622,10 +708,10 @@ mfs_error_t mfsReadRecord(MFSDriver *devp, uint32_t id,
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
mfs_error_t mfsWriteRecord(MFSDriver *devp, uint32_t id,
|
||||
mfs_error_t mfsWriteRecord(MFSDriver *mfsp, uint32_t id,
|
||||
uint32_t n, const uint8_t *buffer) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
(void)id;
|
||||
(void)n;
|
||||
(void)buffer;
|
||||
|
@ -636,7 +722,7 @@ mfs_error_t mfsWriteRecord(MFSDriver *devp, uint32_t id,
|
|||
/**
|
||||
* @brief Erases a data record.
|
||||
*
|
||||
* @param[in] devp pointer to the @p MFSDriver object
|
||||
* @param[in] mfsp pointer to the @p MFSDriver object
|
||||
* @param[in] id record numeric identifier
|
||||
* @return The operation status.
|
||||
* @retval MFS_NO_ERROR if the operation has been successfully completed.
|
||||
|
@ -645,9 +731,9 @@ mfs_error_t mfsWriteRecord(MFSDriver *devp, uint32_t id,
|
|||
*
|
||||
* @api
|
||||
*/
|
||||
mfs_error_t mfsEraseRecord(MFSDriver *devp, uint32_t id) {
|
||||
mfs_error_t mfsEraseRecord(MFSDriver *mfsp, uint32_t id) {
|
||||
|
||||
(void)devp;
|
||||
(void)mfsp;
|
||||
(void)id;
|
||||
|
||||
return MFS_NO_ERROR;
|
||||
|
|
|
@ -112,10 +112,11 @@ typedef enum {
|
|||
MFS_NO_ERROR = 0,
|
||||
MFS_WARN_REPAIR = 1,
|
||||
MFS_WARN_GC = 2,
|
||||
MFS_ERR_NOT_FOUND = -1,
|
||||
MFS_ERR_CRC = -2,
|
||||
MFS_ERR_FLASH_FAILURE = -3,
|
||||
MFS_ERR_INTERNAL = -4
|
||||
MFS_ERR_NOT_ERASED = -1,
|
||||
MFS_ERR_NOT_FOUND = -2,
|
||||
MFS_ERR_CRC = -3,
|
||||
MFS_ERR_FLASH_FAILURE = -4,
|
||||
MFS_ERR_INTERNAL = -5
|
||||
} mfs_error_t;
|
||||
|
||||
/**
|
||||
|
@ -206,7 +207,7 @@ typedef struct {
|
|||
*/
|
||||
flash_sector_t bank1_start;
|
||||
/**
|
||||
* #brief Number of sectors for bank 1.
|
||||
* @brief Number of sectors for bank 1.
|
||||
*/
|
||||
flash_sector_t bank1_sectors;
|
||||
} MFSConfig;
|
||||
|
@ -246,6 +247,14 @@ typedef struct {
|
|||
* @note Zero means that ther is not a record with that id.
|
||||
*/
|
||||
flash_offset_t instances[MFS_CFG_MAX_RECORDS];
|
||||
/**
|
||||
* @brief Transient buffer.
|
||||
*/
|
||||
union {
|
||||
mfs_data_header_t dhdr;
|
||||
mfs_bank_header_t bhdr;
|
||||
uint8_t data[32];
|
||||
} buffer;
|
||||
} MFSDriver;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
* @return An error code.
|
||||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_ERROR_ERASE if the erase operation failed.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*/
|
||||
flash_error_t flashWaitErase(BaseFlash *devp) {
|
||||
|
||||
|
|
|
@ -218,6 +218,7 @@ typedef struct {
|
|||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_READ if the read operation failed.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -235,6 +236,7 @@ typedef struct {
|
|||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_PROGRAM if the program operation failed.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -248,6 +250,7 @@ typedef struct {
|
|||
* @return An error code.
|
||||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -262,6 +265,7 @@ typedef struct {
|
|||
* @return An error code.
|
||||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -278,6 +282,7 @@ typedef struct {
|
|||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_ERASE if the erase operation failed.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -290,9 +295,10 @@ typedef struct {
|
|||
* @param[in] ip pointer to a @p BaseFlash or derived class
|
||||
* @param[in] sector sector to be verified
|
||||
* @return An error code.
|
||||
* @retval FLASH_NO_ERROR if there is no erase operation in progress.
|
||||
* @retval FLASH_NO_ERROR if the sector is erased.
|
||||
* @retval FLASH_BUSY_ERASING if there is an erase operation in progress.
|
||||
* @retval FLASH_ERROR_VERIFY if the verify operation failed.
|
||||
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue