You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
12 KiB
C

/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_efl_lld.c
* @brief PLATFORM Embedded Flash subsystem low level driver source.
*
* @addtogroup HAL_EFL
* @{
*/
#include "hal.h"
#if (HAL_USE_EFL == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief EFL1 driver identifier.
*/
#if (PLATFORM_EFL_USE_EFL1 == TRUE) || defined(__DOXYGEN__)
EFlashDriver EFLD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
static const flash_descriptor_t efl_lld_descriptor = {
.attributes = FLASH_ATTR_ERASED_IS_ONE |
FLASH_ATTR_MEMORY_MAPPED |
FLASH_ATTR_ECC_CAPABLE |
FLASH_ATTR_ECC_ZERO_LINE_CAPABLE,
.page_size = 0,
.sectors_count = 0,
.sectors = NULL,
.sectors_size = 0,
.address = (uint8_t *)0,
.size = 0
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level Embedded Flash driver initialization.
*
* @notapi
*/
void efl_lld_init(void) {
#if PLATFORM_EFL_USE_EFL1 == TRUE
/* Driver initialization.*/
eflObjectInit(&EFLD1);
#endif
}
/**
* @brief Configures and activates the Embedded Flash peripheral.
*
* @param[in] eflp pointer to a @p EFlashDriver structure
*
* @notapi
*/
void efl_lld_start(EFlashDriver *eflp) {
if (eflp->state == FLASH_STOP) {
/* Enables the peripheral.*/
#if PLATFORM_EFL_USE_EFL1 == TRUE
if (&EFLD1 == eflp) {
}
#endif
}
/* Configures the peripheral.*/
}
/**
* @brief Deactivates the Embedded Flash peripheral.
*
* @param[in] eflp pointer to a @p EFlashDriver structure
*
* @notapi
*/
void efl_lld_stop(EFlashDriver *eflp) {
if (eflp->state == FLASH_READY) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if PLATFORM_EFL_USE_EFL1 == TRUE
if (&EFLD1 == eflp) {
}
#endif
}
}
/**
* @brief Gets the flash descriptor structure.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @return A flash device descriptor.
*
* @notapi
*/
const flash_descriptor_t *efl_lld_get_descriptor(void *instance) {
(void)instance;
return &efl_lld_descriptor;
}
/**
* @brief Read operation.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @param[in] offset flash offset
* @param[in] n number of bytes to be read
* @param[out] rp pointer to the data buffer
* @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_READ if the read operation failed.
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
*
* @notapi
*/
flash_error_t efl_lld_read(void *instance, flash_offset_t offset,
size_t n, uint8_t *rp) {
EFlashDriver *devp = (EFlashDriver *)instance;
flash_error_t err = FLASH_NO_ERROR;
osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
osalDbgCheck(((size_t)offset + n) <= (size_t)efl_lld_descriptor.size);
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
"invalid state");
/* No reading while erasing.*/
if (devp->state == FLASH_ERASE) {
return FLASH_BUSY_ERASING;
}
/* FLASH_READY state while the operation is performed.*/
devp->state = FLASH_READ;
/* IMPLEMENT */
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
/**
* @brief Program operation.
* @note The device supports ECC, it is only possible to write erased
* pages once except when writing all zeroes.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @param[in] offset flash offset
* @param[in] n number of bytes to be programmed
* @param[in] pp pointer to the data buffer
* @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_PROGRAM if the program operation failed.
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
*
* @notapi
*/
flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
size_t n, const uint8_t *pp) {
EFlashDriver *devp = (EFlashDriver *)instance;
flash_error_t err = FLASH_NO_ERROR;
osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
osalDbgCheck(((size_t)offset + n) <= (size_t)efl_lld_descriptor.size);
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
"invalid state");
/* No programming while erasing.*/
if (devp->state == FLASH_ERASE) {
return FLASH_BUSY_ERASING;
}
/* FLASH_PGM state while the operation is performed.*/
devp->state = FLASH_PGM;
/* IMPLEMENT */
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
/**
* @brief Starts a whole-device erase operation.
* @note This function only erases bank 2 if it is present. Bank 1 is not
* touched because it is where the program is running on.
* Pages on bank 1 can be individually erased.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @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.
*
* @notapi
*/
flash_error_t efl_lld_start_erase_all(void *instance) {
EFlashDriver *devp = (EFlashDriver *)instance;
osalDbgCheck(instance != NULL);
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
"invalid state");
/* No erasing while erasing.*/
if (devp->state == FLASH_ERASE) {
return FLASH_BUSY_ERASING;
}
/* FLASH_PGM state while the operation is performed.*/
devp->state = FLASH_ERASE;
/* IMPLEMENT */
return FLASH_NO_ERROR;
}
/**
* @brief Starts an sector erase operation.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @param[in] sector sector to be erased
* @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.
*
* @notapi
*/
flash_error_t efl_lld_start_erase_sector(void *instance,
flash_sector_t sector) {
EFlashDriver *devp = (EFlashDriver *)instance;
osalDbgCheck(instance != NULL);
osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
"invalid state");
/* No erasing while erasing.*/
if (devp->state == FLASH_ERASE) {
return FLASH_BUSY_ERASING;
}
/* FLASH_PGM state while the operation is performed.*/
devp->state = FLASH_ERASE;
/* IMPLEMENT */
return FLASH_NO_ERROR;
}
/**
* @brief Queries the driver for erase operation progress.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @param[out] msec recommended time, in milliseconds, that
* should be spent before calling this
* function again, can be @p NULL
* @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_ERASE if the erase operation failed.
* @retval FLASH_ERROR_HW_FAILURE if access to the memory failed.
*
* @api
*/
flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec) {
EFlashDriver *devp = (EFlashDriver *)instance;
flash_error_t err = FLASH_NO_ERROR;
(void)msec;
/* If there is an erase in progress then the device must be checked.*/
if (devp->state == FLASH_ERASE) {
/* IMPLEMENT */
}
return err;
}
/**
* @brief Returns the erase state of a sector.
*
* @param[in] instance pointer to a @p EFlashDriver instance
* @param[in] sector sector to be verified
* @return An error code.
* @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.
*
* @notapi
*/
flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector) {
EFlashDriver *devp = (EFlashDriver *)instance;
flash_error_t err = FLASH_NO_ERROR;
osalDbgCheck(instance != NULL);
osalDbgCheck(sector < efl_lld_descriptor.sectors_count);
osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE),
"invalid state");
/* No verifying while erasing.*/
if (devp->state == FLASH_ERASE) {
return FLASH_BUSY_ERASING;
}
/* IMPLEMENT */
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
#endif /* HAL_USE_EFL == TRUE */
/** @} */