NUC123: EFL driver

This commit is contained in:
Alex Lewontin 2021-01-10 12:49:16 -05:00
parent 09394a1b1a
commit 4cbc3250c0
No known key found for this signature in database
GPG Key ID: 52A3855FC3BB8CD7
5 changed files with 834 additions and 1 deletions

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_EFL TRUE,$(HALCONF)),)
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/FLASHv1/hal_efl_lld.c
endif
else
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/FLASHv1/hal_efl_lld.c
endif
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/FLASHv1

View File

@ -0,0 +1,648 @@
/*
ChibiOS - Copyright (C) 2020 Alex Lewontin
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 NUC123 Embedded Flash subsystem low level driver source.
*
* @addtogroup HAL_EFL
* @{
*/
#include "hal.h"
#if HAL_USE_EFL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#define NUC123_LFOM_UPPERBOUND 25000000UL
#define NUC123_MFOM_UPPERBOUND 50000000UL
#define FMC_FATCON_LFOM_Pos FMC_FATCON_FOMSEL0_Pos
#define FMC_FATCON_LFOM_Msk FMC_FATCON_FOMSEL0_Msk
#define FMC_FATCON_MFOM_Pos FMC_FATCON_FOMSEL1_Pos
#define FMC_FATCON_MFOM_Msk FMC_FATCON_FOMSEL1_Msk
#define NUC123_PAGE_SIZE 4UL
#define NUC123_SECTOR_SIZE 0x200UL
#define NUC123_LDROM_SIZE 0x1000UL
#define NUC123_APROM_SIZE (NUC123_FLASH_SIZE - NUC123_DATAFLASH_SIZE)
#define NUC123_EFL_CMD_ERASE 0x22UL
#define NUC123_EFL_CMD_PROG 0x21UL
#define NUC123_EFL_CMD_READ 0UL
#define NUC123_EFL_CMD_CHIPERASE 0x26UL /* Undocumented */
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief EFL1 driver identifier.
*/
#if (NUC123_EFL_USE_EFL1 == TRUE) || defined(__DOXYGEN__)
EFlashDriver EFLD1;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
static const flash_descriptor_t efl_lld_descriptors[] = {
#if (NUC123_EFL_ACCESS_APROM == TRUE) || defined(__DOXYGEN__)
{.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_MEMORY_MAPPED |
FLASH_ATTR_REWRITABLE,
.page_size = NUC123_PAGE_SIZE,
.sectors_count = NUC123_APROM_SIZE / NUC123_SECTOR_SIZE,
.sectors = NULL,
.sectors_size = NUC123_SECTOR_SIZE,
.address = (uint8_t *)0,
.size = NUC123_APROM_SIZE},
#endif
#if (NUC123_EFL_ACCESS_DATAFLASH == TRUE) || defined(__DOXYGEN__)
{.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_MEMORY_MAPPED |
FLASH_ATTR_REWRITABLE,
.page_size = NUC123_PAGE_SIZE,
.sectors_count = NUC123_DATAFLASH_SIZE / NUC123_SECTOR_SIZE,
.sectors = NULL,
.sectors_size = NUC123_SECTOR_SIZE,
.address = (uint8_t *)NUC123_DFBADDR,
.size = NUC123_DATAFLASH_SIZE},
#endif
#if (NUC123_EFL_ACCESS_LDROM == TRUE) || defined(__DOXYGEN__)
{.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_MEMORY_MAPPED |
FLASH_ATTR_REWRITABLE,
.page_size = NUC123_PAGE_SIZE,
.sectors_count = NUC123_LDROM_SIZE / NUC123_SECTOR_SIZE,
.sectors = NULL,
.sectors_size = NUC123_SECTOR_SIZE,
.address = (uint8_t *)0x100000,
.size = NUC123_LDROM_SIZE},
#endif
#if (NUC123_EFL_ACCESS_CONFIG == TRUE) || defined(__DOXYGEN__)
{.attributes = FLASH_ATTR_ERASED_IS_ONE | FLASH_ATTR_MEMORY_MAPPED |
FLASH_ATTR_REWRITABLE,
.page_size = NUC123_PAGE_SIZE,
.sectors_count = 1,
.sectors = NULL,
.sectors_size = NUC123_SECTOR_SIZE,
.address = (uint8_t *)0x300000,
.size = 8},
#endif
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/* Starts the ISP function, does not block */
static inline void start_ISP(void)
{
SystemUnlockReg();
FMC->ISPTRG |= FMC_ISPTRG_ISPGO_Msk;
__ISB();
LOCKREG();
}
/* Starts the ISP function and blocks til conclusion */
static inline flash_error_t do_ISP(void)
{
start_ISP();
while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk)
;
if (FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
return FLASH_ERROR_HW_FAILURE;
}
return FLASH_NO_ERROR;
}
/**
* @brief Returns the minimum of two unsigned values. A safer implementation
* of the classic macro
*
* @param[in] x An unsigned value
* @param[in] y An unsigned value
*
* @return The smaller of x and y
*
* @notapi
*/
static inline unsigned min(unsigned x, unsigned y)
{
return ((x > y) ? y : x);
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level Embedded Flash driver initialization.
*
* @notapi
*/
void efl_lld_init(void)
{
#if (NUC123_EFL_USE_EFL1 == TRUE)
eflObjectInit(&EFLD1);
EFLD1.bank = 0;
#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)
{
uint32_t ispcon;
if (eflp->state == FLASH_STOP) {
SystemUnlockReg();
ispcon = FMC->ISPCON;
ispcon |= (FMC_ISPCON_ISPEN_Msk);
/* Enables the peripheral.*/
CLK->APBCLK |= CLK_AHBCLK_ISP_EN_Msk;
#if NUC123_HCLK < NUC123_LFOM_UPPERBOUND
FMC->FATCON |= FMC_FATCON_LFOM_Msk;
#elif NUC123_HCLK < NUC123_MFOM_UPPERBOUND
FMC->FATCON |= FMC_FATCON_MFOM_Msk;
#endif
#if (NUC123_EFL_ACCESS_APROM == TRUE) || (NUC123_EFL_ACCESS_DATAFLASH == TRUE)
ispcon |= FMC_ISPCON_APUEN_Msk;
#endif
#if (NUC123_EFL_ACCESS_LDROM == TRUE)
ispcon |= FMC_ISPCON_LDUEN_Msk;
#endif
#if (NUC123_EFL_ACCESS_CONFIG == TRUE)
ispcon |= FMC_ISPCON_CFGUEN_Msk;
#endif
FMC->ISPCON = ispcon;
LOCKREG();
}
}
/**
* @brief Deactivates the Embedded Flash peripheral.
*
* @param[in] eflp pointer to a @p EFlashDriver structure
*
* @notapi
*/
void efl_lld_stop(EFlashDriver* eflp)
{
uint32_t ispcon;
if (eflp->state == FLASH_READY) {
SystemUnlockReg();
ispcon = FMC->ISPCON;
ispcon &= ~FMC_ISPCON_ISPEN_Msk;
/* Disables the peripheral.*/
#if (NUC123_EFL_ACCESS_APROM == TRUE) || (NUC123_EFL_ACCESS_DATAFLASH == TRUE)
ispcon &= ~FMC_ISPCON_APUEN_Msk;
#endif
#if (NUC123_EFL_ACCESS_LDROM == TRUE)
ispcon &= ~FMC_ISPCON_LDUEN_Msk;
#endif
#if (NUC123_EFL_ACCESS_CONFIG == TRUE)
ispcon &= ~FMC_ISPCON_CFGUEN_Msk;
#endif
FMC->ISPCON = ispcon;
CLK->APBCLK &= ~CLK_AHBCLK_ISP_EN_Msk;
LOCKREG();
}
}
/**
* @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)
{
return efl_lld_descriptors + ((EFlashDriver *)instance)->bank;
}
/**
* @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;
const flash_descriptor_t *desc = efl_lld_get_descriptor(instance);
flash_error_t err = FLASH_NO_ERROR;
uint32_t data;
osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
osalDbgCheck(((size_t)offset + n) <= (size_t)desc->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_READ state while the operation is performed.*/
devp->state = FLASH_READ;
FMC->ISPCMD = NUC123_EFL_CMD_READ;
while (n) {
FMC->ISPADR = (uint32_t)desc->address + (offset & ~3);
err = do_ISP();
if (err) {
break;
}
data = FMC->ISPDAT;
/* For most iterations, the switch doesn't do anything, but it doesn't
hurt, and it allows us to consolidate the leading partial word
with the rest, which compiles smaller. The compiler is pretty good
at pulling things out of the loop, if speed is more important. */
switch (offset % 4) {
case 0:
*(rp++) = (uint8_t)((data >> 0) & 0xFF);
if (!(--n)) { break; }
/* fallthrough */
case 1:
*(rp++) = (uint8_t)((data >> 8) & 0xFF);
if (!(--n)) { break; }
/* fallthrough */
case 2:
*(rp++) = (uint8_t)((data >> 16) & 0xFF);
if (!(--n)) { break; }
/* fallthrough */
case 3:
*(rp++) = (uint8_t)((data >> 24) & 0xFF);
if (!(--n)) { break; }
}
offset += (4 - (offset % 4));
}
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
/**
* @brief Program operation.
*
* @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;
const flash_descriptor_t *desc = efl_lld_get_descriptor(instance);
flash_error_t err = FLASH_NO_ERROR;
uint32_t data;
osalDbgCheck((instance != NULL) && (pp != NULL) && (n > 0U));
osalDbgCheck(((size_t)offset + n) <= (size_t)desc->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;
if (offset % 4) {
FMC->ISPCMD = NUC123_EFL_CMD_READ;
FMC->ISPADR = (uint32_t)desc->address + (offset & ~3);
err = do_ISP();
if (err) {
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
data = FMC->ISPDAT;
switch (offset % 4) {
case 1:
data &= 0xFFFF00FF;
data |= (*(pp++) << 8);
if (!(--n)) {
break;
}
/* fallthrough */
case 2:
data &= 0xFF00FFFF;
data |= (*(pp++) << 16);
if (!(--n)) {
break;
}
/* fallthrough */
case 3:
data &= 0x00FFFFFF;
data |= (*(pp++) << 24);
if (!(--n)) {
break;
}
}
FMC->ISPDAT = data;
FMC->ISPCMD = NUC123_EFL_CMD_PROG;
err = do_ISP();
if (err) {
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
offset += 4 - (offset % 4);
}
FMC->ISPCMD = NUC123_EFL_CMD_PROG;
while (n >= 4) {
FMC->ISPADR = (uint32_t)desc->address + offset;
FMC->ISPDAT = (*(pp + 0)) | (*(pp + 1) << 8) |
(*(pp + 2) << 16) | (*(pp + 3) << 24);
err = do_ISP();
if (err) {
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
n -= 4;
pp += 4;
offset += 4;
}
if (n) {
FMC->ISPCMD = NUC123_EFL_CMD_READ;
FMC->ISPADR = (uint32_t)desc->address + offset;
err = do_ISP();
if (err) {
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
data = FMC->ISPDAT;
switch (n) {
case 3:
data &= 0xFF00FFFF;
data |= (pp[2] << 16);
/* fallthrough */
case 2:
data &= 0xFFFF00FF;
data |= (pp[1] << 8);
/* fallthrough */
case 1:
data &= 0xFFFFFF00;
data |= (pp[0] << 0);
}
FMC->ISPDAT = data;
FMC->ISPCMD = NUC123_EFL_CMD_PROG;
err = do_ISP();
}
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
/**
* @brief Starts a whole-device erase operation.
* @note This operation erases the entirety of the bank associated with
* the driver indicated by @p instance. Calling this function on
* the bank that contains the code that is currently executing
* will result in undefined behavior.
* @note This operation is not supported asynchronously, so this will
* not return until all erases have been completed.
*
* @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;
const flash_descriptor_t *desc = efl_lld_get_descriptor(instance);
flash_error_t err = FLASH_NO_ERROR;
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;
FMC->ISPCMD = NUC123_EFL_CMD_ERASE;
for (uint8_t i = 0; i < desc->sectors_count; ++i)
{
FMC->ISPADR = (uint32_t)((i * (desc->sectors_size)) +
desc->address);
err = do_ISP();
if (err) {
break;
}
}
devp->state = FLASH_READY;
return err;
}
/**
* @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;
const flash_descriptor_t *desc = efl_lld_get_descriptor(instance);
osalDbgCheck(instance != NULL);
osalDbgCheck(sector < desc->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_ERASE state while the operation is performed.*/
devp->state = FLASH_ERASE;
FMC->ISPCMD = NUC123_EFL_CMD_ERASE;
FMC->ISPADR = (uint32_t)((sector * (desc->sectors_size)) +
desc->address);
start_ISP();
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;
/* TODO: figure out an actual amount of time */
*msec = 0UL;
/* If there is an erase in progress then the device must be checked.*/
if (devp->state == FLASH_ERASE) {
if (FMC->ISPSTA & FMC_ISPSTA_ISPGO_Msk) {
return FLASH_BUSY_ERASING;
}
if (FMC->ISPCON & FMC_ISPCON_ISPFF_Msk) {
return FLASH_ERROR_HW_FAILURE;
}
devp->state = FLASH_READY;
}
return FLASH_NO_ERROR;
}
/**
* @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;
const flash_descriptor_t *desc = efl_lld_get_descriptor(instance);
flash_error_t err = FLASH_NO_ERROR;
osalDbgCheck(instance != NULL);
osalDbgCheck(sector < desc->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;
}
devp->state = FLASH_READ;
FMC->ISPCMD = NUC123_EFL_CMD_READ;
for (size_t i = 0; i < desc->sectors_size; i = i + 4) {
FMC->ISPADR = (uint32_t)desc->address + (desc->sectors_size * sector) + i;
err = do_ISP();
if (err) {
break;
}
if (FMC->ISPDAT != 0xFFFFFFFF) {
err = FLASH_ERROR_VERIFY;
break;
}
}
/* Ready state again.*/
devp->state = FLASH_READY;
return err;
}
#endif /* HAL_USE_EFL == TRUE */
/** @} */

View File

@ -0,0 +1,167 @@
/*
ChibiOS - Copyright (C) 2020 Alex Lewontin
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.h
* @brief NUC123 Embedded Flash subsystem low level driver header.
* @note This driver only supports management of APROM. LDROM, config
* registers, and data flash (not yet supported by the platform driver)
* are not supported.
* @addtogroup HAL_EFL
* @{
*/
#ifndef HAL_EFL_LLD_H
#define HAL_EFL_LLD_H
#if HAL_USE_EFL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name NUC123 configuration options
* @{
*/
/**
* @brief EFL1 driver enable switch.
* @details If set to @p TRUE the support for EFL1 is included.
*
* @note The default is @p TRUE.
*/
#if !defined(NUC123_EFL_USE_EFL1) || defined(__DOXYGEN__)
#define NUC123_EFL_USE_EFL1 TRUE
#endif
/**
* @brief APROM access enable switch.
* @details If set to @p TRUE the support for APROM access is included.
*
* @note The default is @p FALSE.
*/
#if !defined(NUC123_EFL_ACCESS_APROM) || defined(__DOXYGEN__)
#define NUC123_EFL_ACCESS_APROM FALSE
#endif
/**
* @brief Data flash access enable switch.
* @details If set to @p TRUE the support for data flash access is included.
*
* @note The default is @p FALSE.
*/
#if !defined(NUC123_EFL_ACCESS_DATAFLASH) || defined(__DOXYGEN__)
#define NUC123_EFL_ACCESS_DATAFLASH FALSE
#endif
/**
* @brief LDROM access enable switch.
* @details If set to @p FALSE the support for LDROM access is included.
*
* @note The default is @p FALSE.
*/
#if !defined(NUC123_EFL_ACCESS_LDROM) || defined(__DOXYGEN__)
#define NUC123_EFL_ACCESS_LDROM FALSE
#endif
/**
* @brief CONFIG0/1 access enable switch.
* @details If set to @p FALSE the support for CONFIG0/1 access is included.
*
* @note The default is @p FALSE.
*/
#if !defined(NUC123_EFL_ACCESS_CONFIG) || defined(__DOXYGEN__)
#define NUC123_EFL_ACCESS_CONFIG FALSE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
typedef enum {
#if (NUC123_EFL_ACCESS_APROM == TRUE) || defined(__DOXYGEN__)
NUC123_EFL_BANK_APROM,
#endif
#if (NUC123_EFL_ACCESS_DATAFLASH == TRUE) || defined(__DOXYGEN__)
NUC123_EFL_BANK_DATAFLASH,
#endif
#if (NUC123_EFL_ACCESS_LDROM == TRUE) || defined(__DOXYGEN__)
NUC123_EFL_BANK_LDROM,
#endif
#if (NUC123_EFL_ACCESS_CONFIG == TRUE) || defined(__DOXYGEN__)
NUC123_EFL_BANK_CONFIG,
#endif
NUC123_EFL_BANK_NONE
} nuc123_eflbank_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Low level fields of the embedded flash driver structure.
*/
#define efl_lld_driver_fields \
/* The currently used bank.*/ \
nuc123_eflbank_t bank
/**
* @brief Low level fields of the embedded flash configuration structure.
*/
#define efl_lld_config_fields \
/* Dummy configuration, it is not needed.*/ \
uint32_t dummy
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if (NUC123_EFL_USE_EFL1 == TRUE) && !defined(__DOXYGEN__)
extern EFlashDriver EFLD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void efl_lld_init(void);
void efl_lld_start(EFlashDriver *eflp);
void efl_lld_stop(EFlashDriver *eflp);
const flash_descriptor_t *efl_lld_get_descriptor(void *instance);
flash_error_t efl_lld_read(void *instance, flash_offset_t offset, size_t n,
uint8_t *rp);
flash_error_t efl_lld_program(void *instance, flash_offset_t offset,
size_t n, const uint8_t *pp);
flash_error_t efl_lld_start_erase_all(void *instance);
flash_error_t efl_lld_start_erase_sector(void *instance, flash_sector_t sector);
flash_error_t efl_lld_query_erase(void *instance, uint32_t *msec);
flash_error_t efl_lld_verify_erase(void *instance, flash_sector_t sector);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_EFL == TRUE */
#endif /* HAL_EFL_LLD_H */
/** @} */

View File

@ -43,6 +43,7 @@
#define PLATFORM_NAME "NUC123SD4AN0 NUC123 Cortex M0 USB Micro"
#define NUC123xxxANx
#undef NUC123xxxAEx
#define NUC123_FLASH_SIZE 0x11000
#else
#error "NUC123 device unsupported or not specified"
#endif
@ -184,6 +185,13 @@
/**
* @brief Enables or disables data flash
* @warning If data this is set to @p TRUE, the data flash
* is subtracted from the APROM. The linker script is not aware
* of this, so therefore it is the responsiblity of the user to ensure
* that the combination of the data flash & the text section still fit
* into ROM.
* @note The default is @p FALSE.
*/
#if !defined(NUC123_DATAFLASH_ENABLED) || defined(__DOXYGEN__)
#define NUC123_DATAFLASH_ENABLED FALSE
@ -229,7 +237,7 @@
/*
* Persistant configuration settings.
*/
#if NUC123_DATAFLASH_ENABLE
#if (NUC123_DATAFLASH_ENABLED == TRUE)
#if (NUC123_DATAFLASH_SIZE == 4096)
/* DFVSEN = 1, nothing else matters */

View File

@ -17,6 +17,7 @@ include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/SERIALv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/I2Cv1/driver.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/FLASHv1/driver.mk
# Shared variables
ALLCSRC += $(PLATFORMSRC)