diff --git a/ADIS_tinyK22_SplitFlap/.cproject b/ADIS_tinyK22_SplitFlap/.cproject index fed5235..2e180dc 100644 --- a/ADIS_tinyK22_SplitFlap/.cproject +++ b/ADIS_tinyK22_SplitFlap/.cproject @@ -116,6 +116,14 @@ + + + + + + + + @@ -362,7 +370,7 @@ - + @@ -483,6 +491,14 @@ + + + + + + + + @@ -729,7 +745,7 @@ - + @@ -765,7 +781,7 @@ SDK_2.x_MK22FN512xxx12 2.12.0 - middleware.baremetal.MK22F51212;platform.drivers.smc.MK22F51212;platform.drivers.port.MK22F51212;platform.drivers.dspi.MK22F51212;platform.drivers.adc16.MK22F51212;platform.drivers.uart.MK22F51212;platform.drivers.clock.MK22F51212;platform.drivers.rtc.MK22F51212;platform.drivers.common.MK22F51212;platform.drivers.i2c.MK22F51212;platform.drivers.gpio.MK22F51212;device.MK22F51212_system.MK22F51212;device.MK22F51212_CMSIS.MK22F51212;CMSIS_Include_core_cm.MK22F51212;platform.utilities.assert.MK22F51212;component.serial_manager_uart.MK22F51212;utility.debug_console.MK22F51212;component.serial_manager.MK22F51212;component.uart_adapter.MK22F51212;component.lists.MK22F51212;project_template.MK22F51212.MK22F51212;device.MK22F51212_startup.MK22F51212;platform.drivers.sim.MK22F51212; + middleware.baremetal.MK22F51212;platform.drivers.smc.MK22F51212;platform.drivers.port.MK22F51212;platform.drivers.dspi.MK22F51212;platform.drivers.adc16.MK22F51212;platform.drivers.uart.MK22F51212;platform.drivers.clock.MK22F51212;platform.drivers.rtc.MK22F51212;platform.drivers.common.MK22F51212;platform.drivers.i2c.MK22F51212;platform.drivers.gpio.MK22F51212;device.MK22F51212_system.MK22F51212;device.MK22F51212_CMSIS.MK22F51212;CMSIS_Include_core_cm.MK22F51212;platform.utilities.assert.MK22F51212;component.serial_manager_uart.MK22F51212;utility.debug_console.MK22F51212;component.serial_manager.MK22F51212;component.uart_adapter.MK22F51212;component.lists.MK22F51212;project_template.MK22F51212.MK22F51212;device.MK22F51212_startup.MK22F51212;platform.drivers.sim.MK22F51212;platform.drivers.flash.MK22F51212; MK22FN512VLH12 cm4 core0_MK22FN512xxx12 diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_flash.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_flash.h new file mode 100644 index 0000000..429d33b --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_flash.h @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FLASH_H +#define FSL_FLASH_H + +#include "fsl_ftfx_cache.h" +#include "fsl_ftfx_flash.h" +#if FSL_FEATURE_FLASH_HAS_FLEX_NVM +#include "fsl_ftfx_flexnvm.h" +#endif + +/*! + * @addtogroup flash_driver + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* FSL_FLASH_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_adapter.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_adapter.h new file mode 100644 index 0000000..780dbea --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_adapter.h @@ -0,0 +1,396 @@ +/* + * Copyright 2017-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_ADAPTER_H +#define FSL_FTFX_ADAPTER_H + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#define INVALID_REG_MASK (0) +#define INVALID_REG_SHIFT (0) +#define INVALID_REG_ADDRESS (NULL) +#define INVALID_REG_VALUE (0x00U) + +/* @brief Flash register access type defines */ +#define FTFx_REG8_ACCESS_TYPE volatile uint8_t * +#define FTFx_REG32_ACCESS_TYPE volatile uint32_t * + +/*! + * @name Common flash register info defines + * @{ + */ +#if defined(FTFA) +#define FTFx FTFA +#define FTFx_BASE FTFA_BASE +#define FTFx_FSTAT_CCIF_MASK FTFA_FSTAT_CCIF_MASK +#define FTFx_FSTAT_CCIF_SHIFT FTFA_FSTAT_CCIF_SHIFT +#define FTFx_FSTAT_RDCOLERR_MASK FTFA_FSTAT_RDCOLERR_MASK +#define FTFx_FSTAT_ACCERR_MASK FTFA_FSTAT_ACCERR_MASK +#define FTFx_FSTAT_FPVIOL_MASK FTFA_FSTAT_FPVIOL_MASK +#define FTFx_FSTAT_MGSTAT0_MASK FTFA_FSTAT_MGSTAT0_MASK +#define FTFx_FSEC_SEC_MASK FTFA_FSEC_SEC_MASK +#define FTFx_FSEC_KEYEN_MASK FTFA_FSEC_KEYEN_MASK +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM +#define FTFx_FCNFG_RAMRDY_MASK FTFA_FCNFG_RAMRDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */ +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM +#define FTFx_FCNFG_EEERDY_MASK FTFA_FCNFG_EEERDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ +#elif defined(FTFE) +#define FTFx FTFE +#define FTFx_BASE FTFE_BASE +#define FTFx_FSTAT_CCIF_MASK FTFE_FSTAT_CCIF_MASK +#define FTFx_FSTAT_CCIF_SHIFT FTFE_FSTAT_CCIF_SHIFT +#define FTFx_FSTAT_RDCOLERR_MASK FTFE_FSTAT_RDCOLERR_MASK +#define FTFx_FSTAT_ACCERR_MASK FTFE_FSTAT_ACCERR_MASK +#define FTFx_FSTAT_FPVIOL_MASK FTFE_FSTAT_FPVIOL_MASK +#define FTFx_FSTAT_MGSTAT0_MASK FTFE_FSTAT_MGSTAT0_MASK +#define FTFx_FSEC_SEC_MASK FTFE_FSEC_SEC_MASK +#define FTFx_FSEC_KEYEN_MASK FTFE_FSEC_KEYEN_MASK +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM +#define FTFx_FCNFG_RAMRDY_MASK FTFE_FCNFG_RAMRDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */ +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM +#define FTFx_FCNFG_EEERDY_MASK FTFE_FCNFG_EEERDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ +#elif defined(FTFL) +#define FTFx FTFL +#define FTFx_BASE FTFL_BASE +#define FTFx_FSTAT_CCIF_MASK FTFL_FSTAT_CCIF_MASK +#define FTFx_FSTAT_CCIF_SHIFT FTFL_FSTAT_CCIF_SHIFT +#define FTFx_FSTAT_RDCOLERR_MASK FTFL_FSTAT_RDCOLERR_MASK +#define FTFx_FSTAT_ACCERR_MASK FTFL_FSTAT_ACCERR_MASK +#define FTFx_FSTAT_FPVIOL_MASK FTFL_FSTAT_FPVIOL_MASK +#define FTFx_FSTAT_MGSTAT0_MASK FTFL_FSTAT_MGSTAT0_MASK +#define FTFx_FSEC_SEC_MASK FTFL_FSEC_SEC_MASK +#define FTFx_FSEC_KEYEN_MASK FTFL_FSEC_KEYEN_MASK +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_RAM) && FSL_FEATURE_FLASH_HAS_FLEX_RAM +#define FTFx_FCNFG_RAMRDY_MASK FTFL_FCNFG_RAMRDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_RAM */ +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM +#define FTFx_FCNFG_EEERDY_MASK FTFL_FCNFG_EEERDY_MASK +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ +#else +#error "Unknown flash controller" +#endif +/*@}*/ + +/*! + * @name Common flash register access info defines + * @{ + */ +#define FTFx_FCCOB3_REG (FTFx->FCCOB3) +#define FTFx_FCCOB5_REG (FTFx->FCCOB5) +#define FTFx_FCCOB6_REG (FTFx->FCCOB6) +#define FTFx_FCCOB7_REG (FTFx->FCCOB7) + +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#if defined(FTFA_FPROTSL_PROTS_MASK) || defined(FTFE_FPROTSL_PROTS_MASK) || defined(FTFL_FPROTSL_PROTS_MASK) +#define FTFx_FLASH1_HAS_INT_PROT_REG (1) +#define FTFx_FPROTSH_REG (FTFx->FPROTSH) +#define FTFx_FPROTSL_REG (FTFx->FPROTSL) +#else +#define FTFx_FLASH1_HAS_INT_PROT_REG (0) +#endif +#endif + +#if defined(FTFA_FPROTH0_PROT_MASK) || defined(FTFE_FPROTH0_PROT_MASK) || defined(FTFL_FPROTH0_PROT_MASK) +#define FTFx_FLASH0_HAS_HIGH_PROT_REG (1) +#define FTFx_FPROT_HIGH_REG (FTFx->FPROTH3) +#define FTFx_FPROTH3_REG (FTFx->FPROTH3) +#define FTFx_FPROTH2_REG (FTFx->FPROTH2) +#define FTFx_FPROTH1_REG (FTFx->FPROTH1) +#define FTFx_FPROTH0_REG (FTFx->FPROTH0) +#else +#define FTFx_FLASH0_HAS_HIGH_PROT_REG (0) +#endif + +#if defined(FTFA_FPROTL0_PROT_MASK) || defined(FTFE_FPROTL0_PROT_MASK) || defined(FTFL_FPROTL0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROTL3) +#define FTFx_FPROTL3_REG (FTFx->FPROTL3) +#define FTFx_FPROTL2_REG (FTFx->FPROTL2) +#define FTFx_FPROTL1_REG (FTFx->FPROTL1) +#define FTFx_FPROTL0_REG (FTFx->FPROTL0) +#elif defined(FTFA_FPROT0_PROT_MASK) || defined(FTFE_FPROT0_PROT_MASK) || defined(FTFL_FPROT0_PROT_MASK) +#define FTFx_FPROT_LOW_REG (FTFx->FPROT3) +#define FTFx_FPROTL3_REG (FTFx->FPROT3) +#define FTFx_FPROTL2_REG (FTFx->FPROT2) +#define FTFx_FPROTL1_REG (FTFx->FPROT1) +#define FTFx_FPROTL0_REG (FTFx->FPROT0) +#endif + +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#if defined(FTFA_FACSSS_SGSIZE_S_MASK) || defined(FTFE_FACSSS_SGSIZE_S_MASK) || defined(FTFL_FACSSS_SGSIZE_S_MASK) +#define FTFx_FLASH1_HAS_INT_XACC_REG (1) +#define FTFx_XACCSH_REG (FTFx->XACCSH) +#define FTFx_XACCSL_REG (FTFx->XACCSL) +#define FTFx_FACSSS_REG (FTFx->FACSSS) +#define FTFx_FACSNS_REG (FTFx->FACSNS) +#else +#define FTFx_FLASH1_HAS_INT_XACC_REG (0) +#endif +#endif + +#if (defined(FTFA_FACSS_SGSIZE_MASK) || defined(FTFE_FACSS_SGSIZE_MASK) || defined(FTFL_FACSS_SGSIZE_MASK) || \ + defined(FTFA_FACSS_SGSIZE_S_MASK) || defined(FTFE_FACSS_SGSIZE_S_MASK) || defined(FTFL_FACSS_SGSIZE_S_MASK)) +#define FTFx_FLASH0_HAS_INT_XACC_REG (1) +#define FTFx_XACCH3_REG (FTFx->XACCH3) +#define FTFx_XACCL3_REG (FTFx->XACCL3) +#define FTFx_FACSS_REG (FTFx->FACSS) +#define FTFx_FACSN_REG (FTFx->FACSN) +#else +#define FTFx_FLASH0_HAS_INT_XACC_REG (0) +#endif +/*@}*/ + +/*! + * @brief MCM cache register access info defines. + */ +#if defined(MCM_PLACR_CFCC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_PLACR_CFCC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_PLACR_CFCC_SHIFT +#if defined(MCM0) +#define MCM0_CACHE_REG MCM0->PLACR +#elif defined(MCM) && (!defined(MCM1)) +#define MCM0_CACHE_REG MCM->PLACR +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->PLACR +#elif defined(MCM) && (!defined(MCM0)) +#define MCM1_CACHE_REG MCM->PLACR +#endif +#else +#define MCM_CACHE_CLEAR_MASK INVALID_REG_MASK +#define MCM_CACHE_CLEAR_SHIFT INVALID_REG_SHIFT +#define MCM0_CACHE_REG (INVALID_REG_ADDRESS) +#define MCM1_CACHE_REG (INVALID_REG_ADDRESS) +#endif + +/*! + * @brief FMC cache register access info defines. + */ +#if defined(FMC_PFB01CR_S_INV_MASK) +#define FMC_SPECULATION_INVALIDATE_MASK FMC_PFB01CR_S_INV_MASK +#define FMC_SPECULATION_INVALIDATE_SHIFT FMC_PFB01CR_S_INV_SHIFT +#define FMC_SPECULATION_INVALIDATE_REG FMC->PFB01CR +#elif defined(FMC_PFB01CR_S_B_INV_MASK) +#define FMC_SPECULATION_INVALIDATE_MASK FMC_PFB01CR_S_B_INV_MASK +#define FMC_SPECULATION_INVALIDATE_SHIFT FMC_PFB01CR_S_B_INV_SHIFT +#define FMC_SPECULATION_INVALIDATE_REG FMC->PFB01CR +#elif defined(FMC_PFB0CR_S_INV_MASK) +#define FMC_SPECULATION_INVALIDATE_MASK FMC_PFB0CR_S_INV_MASK +#define FMC_SPECULATION_INVALIDATE_SHIFT FMC_PFB0CR_S_INV_SHIFT +#define FMC_SPECULATION_INVALIDATE_REG FMC->PFB0CR +#elif defined(FMC_PFB0CR_S_B_INV_MASK) +#define FMC_SPECULATION_INVALIDATE_MASK FMC_PFB0CR_S_B_INV_MASK +#define FMC_SPECULATION_INVALIDATE_SHIFT FMC_PFB0CR_S_B_INV_SHIFT +#define FMC_SPECULATION_INVALIDATE_REG FMC->PFB0CR +#else +#define FMC_SPECULATION_INVALIDATE_MASK INVALID_REG_MASK +#define FMC_SPECULATION_INVALIDATE_SHIFT INVALID_REG_SHIFT +#define FMC_SPECULATION_INVALIDATE(x) (((uint32_t)(((uint32_t)(x)) << INVALID_REG_SHIFT)) & INVALID_REG_MASK) +#define FMC_SPECULATION_INVALIDATE_REG (INVALID_REG_ADDRESS) +#endif + +#if defined(FMC_PFB01CR_CINV_WAY_MASK) +#define FMC_CACHE_CLEAR_MASK FMC_PFB01CR_CINV_WAY_MASK +#define FMC_CACHE_CLEAR_SHIFT FMC_PFB01CR_CINV_WAY_SHIFT +#define FMC_CACHE_CLEAR(x) FMC_PFB01CR_CINV_WAY(x) +#elif defined(FMC_PFB0CR_CINV_WAY_MASK) +#define FMC_CACHE_CLEAR_MASK FMC_PFB0CR_CINV_WAY_MASK +#define FMC_CACHE_CLEAR_SHIFT FMC_PFB0CR_CINV_WAY_SHIFT +#define FMC_CACHE_CLEAR(x) FMC_PFB0CR_CINV_WAY(x) +#else +#define FMC_CACHE_CLEAR_MASK INVALID_REG_MASK +#define FMC_CACHE_CLEAR_SHIFT INVALID_REG_SHIFT +#define FMC_CACHE_CLEAR(x) (((uint32_t)(((uint32_t)(x)) << INVALID_REG_SHIFT)) & INVALID_REG_MASK) +#endif + +#if defined(FMC_PFB01CR_B0DPE_MASK) +#define FMC_CACHE_B0DPE_MASK FMC_PFB01CR_B0DPE_MASK +#define FMC_CACHE_B0IPE_MASK FMC_PFB01CR_B0IPE_MASK +#define FMC_CACHE_REG FMC->PFB01CR +#elif defined(FMC_PFB0CR_B0DPE_MASK) +#define FMC_CACHE_B0DPE_MASK FMC_PFB0CR_B0DPE_MASK +#define FMC_CACHE_B0IPE_MASK FMC_PFB0CR_B0IPE_MASK +#define FMC_CACHE_REG FMC->PFB0CR +#else +#define FMC_CACHE_B0DPE_MASK INVALID_REG_MASK +#define FMC_CACHE_B0IPE_MASK INVALID_REG_MASK +#define FMC_CACHE_REG (INVALID_REG_ADDRESS) +#endif + +/*! + * @brief MSCM cache register access info defines. + */ +#if defined(MSCM_OCMDR_OCM1_MASK) +#define MSCM_SPECULATION_SET_MASK MSCM_OCMDR_OCM1_MASK +#define MSCM_SPECULATION_SET_SHIFT MSCM_OCMDR_OCM1_SHIFT +#define MSCM_SPECULATION_SET(x) MSCM_OCMDR_OCM1(x) +#elif defined(MSCM_OCMDR0_OCM1_MASK) || defined(MSCM_OCMDR1_OCM1_MASK) +#define MSCM_SPECULATION_SET_MASK MSCM_OCMDR0_OCM1_MASK +#define MSCM_SPECULATION_SET_SHIFT MSCM_OCMDR0_OCM1_SHIFT +#define MSCM_SPECULATION_SET(x) MSCM_OCMDR0_OCM1(x) +#elif defined(MSCM_OCMDR_OCMC1_MASK) +#define MSCM_SPECULATION_SET_MASK MSCM_OCMDR_OCMC1_MASK +#define MSCM_SPECULATION_SET_SHIFT MSCM_OCMDR_OCMC1_SHIFT +#define MSCM_SPECULATION_SET(x) MSCM_OCMDR_OCMC1(x) +#else +#define MSCM_SPECULATION_SET_MASK INVALID_REG_MASK +#define MSCM_SPECULATION_SET_SHIFT INVALID_REG_SHIFT +#define MSCM_SPECULATION_SET(x) (((uint32_t)(((uint32_t)(x)) << INVALID_REG_SHIFT)) & INVALID_REG_MASK) +#endif + +#if defined(MSCM_OCMDR_OCM2_MASK) +#define MSCM_CACHE_CLEAR_MASK MSCM_OCMDR_OCM2_MASK +#define MSCM_CACHE_CLEAR_SHIFT MSCM_OCMDR_OCM2_SHIFT +#define MSCM_CACHE_CLEAR(x) MSCM_OCMDR_OCM2(x) +#else +#define MSCM_CACHE_CLEAR_MASK INVALID_REG_MASK +#define MSCM_CACHE_CLEAR_SHIFT INVALID_REG_SHIFT +#define MSCM_CACHE_CLEAR(x) (((uint32_t)(((uint32_t)(x)) << INVALID_REG_SHIFT)) & INVALID_REG_MASK) +#endif + +#if defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR_OCMC1_MASK) +#define MSCM_OCMDR0_REG MSCM->OCMDR[0] +#define MSCM_OCMDR1_REG MSCM->OCMDR[1] +#elif defined(MSCM_OCMDR0_OCM1_MASK) || defined(MSCM_OCMDR1_OCM1_MASK) +#define MSCM_OCMDR0_REG MSCM->OCMDR0 +#define MSCM_OCMDR1_REG MSCM->OCMDR1 +#else +#define MSCM_OCMDR0_REG (INVALID_REG_ADDRESS) +#define MSCM_OCMDR1_REG (INVALID_REG_ADDRESS) +#endif + +/*! + * @brief MSCM prefetch speculation defines. + */ +#define MSCM_OCMDR_OCMC1_DFDS_MASK (0x10U) +#define MSCM_OCMDR_OCMC1_DFCS_MASK (0x20U) +#define MSCM_OCMDR_OCMC1_DFDS_SHIFT (4U) +#define MSCM_OCMDR_OCMC1_DFCS_SHIFT (5U) + +/*! + * @brief SIM PFSIZE register access info defines. + */ +#if defined(SIM_FCFG1_CORE0_PFSIZE_MASK) +#define SIM_FLASH0_PFSIZE_MASK SIM_FCFG1_CORE0_PFSIZE_MASK +#define SIM_FLASH0_PFSIZE_SHIFT SIM_FCFG1_CORE0_PFSIZE_SHIFT +#define SIM_FCFG1_REG SIM->FCFG1 +#elif defined(SIM_FCFG1_PFSIZE_MASK) +#define SIM_FLASH0_PFSIZE_MASK SIM_FCFG1_PFSIZE_MASK +#define SIM_FLASH0_PFSIZE_SHIFT SIM_FCFG1_PFSIZE_SHIFT +#define SIM_FCFG1_REG SIM->FCFG1 +#else +#define SIM_FLASH0_PFSIZE_MASK INVALID_REG_MASK +#define SIM_FLASH0_PFSIZE_SHIFT INVALID_REG_SHIFT +#define SIM_FCFG1_REG INVALID_REG_VALUE +#endif + +#if defined(SIM_FCFG1_CORE1_PFSIZE_MASK) +#define SIM_FLASH1_PFSIZE_MASK SIM_FCFG1_CORE1_PFSIZE_MASK +#define SIM_FLASH1_PFSIZE_SHIFT SIM_FCFG1_CORE1_PFSIZE_SHIFT +#else +#define SIM_FLASH1_PFSIZE_MASK INVALID_REG_MASK +#define SIM_FLASH1_PFSIZE_SHIFT INVALID_REG_SHIFT +#endif + +/*! + * @name Dual core/flash configuration + * @{ + */ +/*! @brief Redefines some flash features. */ +#if defined(FSL_FEATURE_FLASH_CURRENT_CORE_ID) +#if (FSL_FEATURE_FLASH_CURRENT_CORE_ID == 0u) +#define FLASH0_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS +#define FLASH0_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT +#define FLASH0_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE +#define FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT +#define FLASH1_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS +#define FLASH1_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT +#define FLASH1_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE +#if defined(FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT) && \ + defined(FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT) +#define FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT +#else +#define FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#endif +#define FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT +#elif (FSL_FEATURE_FLASH_CURRENT_CORE_ID == 1u) +#define FLASH0_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS +#define FLASH0_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT +#define FLASH0_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE +#if defined(FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT) && \ + defined(FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT) +#define FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_1_SECTION_CMD_ADDRESS_ALIGMENT +#else +#define FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#endif +#define FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT +#define FLASH1_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS +#define FLASH1_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT +#define FLASH1_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE +#define FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT +#endif +#else /* undfine FSL_FEATURE_FLASH_CURRENT_CORE_ID */ +#define FLASH0_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_START_ADDRESS +#define FLASH0_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT +#define FLASH0_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE +#define FLASH0_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE +#define FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#define FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#define FLASH1_FEATURE_PFLASH_START_ADDRESS FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS +#define FLASH1_FEATURE_PFLASH_BLOCK_COUNT FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT +#define FLASH1_FEATURE_PFLASH_BLOCK_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE +#define FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE +#define FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT +#define FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT +#else /* undfine FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH or FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS */ +#define FLASH1_FEATURE_PFLASH_START_ADDRESS 0 +#define FLASH1_FEATURE_PFLASH_BLOCK_COUNT 0 +#define FLASH1_FEATURE_PFLASH_BLOCK_SIZE 0 +#define FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE 0 +#define FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE 0 +#define FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT 0 +#define FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT 0 +#define FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT 0 +#endif +#endif + +#if FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT > FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT +#define MAX_FLASH_PROT_REGION_COUNT FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT +#else +#define MAX_FLASH_PROT_REGION_COUNT FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT +#endif + +/*@}*/ + +#endif /* FSL_FTFX_ADAPTER_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.c b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.c new file mode 100644 index 0000000..6eb0474 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.c @@ -0,0 +1,549 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "fsl_ftfx_cache.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.flash" +#endif + +/*! + * @name Flash cache and speculation control defines + * @{ + */ +#if defined(MCM_PLACR_CFCC_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1u) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0u) +#endif + +#define FLASH_CACHE_IS_CONTROLLED_BY_MSCM (0u) + +#if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1u) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0u) +#endif + +#if defined(MCM_PLACR_DFCS_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1u) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0u) +#endif + +#if defined(MSCM_OCMDR_OCMC1_MASK) || defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR0_OCM1_MASK) || \ + defined(MSCM_OCMDR1_OCM1_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1u) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0u) +#endif + +#if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB0CR_S_B_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) || \ + defined(FMC_PFB01CR_S_B_INV_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (1u) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0u) +#endif + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM || FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC || \ + FLASH_CACHE_IS_CONTROLLED_BY_MCM || FLASH_CACHE_IS_CONTROLLED_BY_FMC || FLASH_CACHE_IS_CONTROLLED_BY_MSCM +#define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (1) +#else +#define FLASH_IS_CACHE_INVALIDATION_AVAILABLE (0u) +#endif +/*@}*/ + +/*! @brief A function pointer used to point to relocated ftfx_common_bit_operation() */ +typedef void (*callftfxCommonBitOperation_t)(FTFx_REG32_ACCESS_TYPE base, + uint32_t bitMask, + uint32_t bitShift, + uint32_t bitValue); + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(ftfx_cache_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MSCM +/*! @brief Performs the cache clear to the flash by MSCM.*/ +void mscm_flash_cache_clear(ftfx_cache_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(ftfx_cache_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Sets the prefetch speculation buffer to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(ftfx_cache_config_t *config, bool enable); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(ftfx_cache_config_t *config); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ + +#if FTFx_DRIVER_IS_FLASH_RESIDENT +static void ftfx_common_bit_operation_command_sequence( + ftfx_cache_config_t *config, FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + +#if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE +/*! @brief Copy flash_cache_clear_command() to RAM*/ +static void ftfx_copy_common_bit_operation_to_ram(uint32_t *ftfxCommonBitOperation); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +#if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE +/*! + * @brief Position independent code of ftfx_common_bit_operation() + * + * Note1: The prototype of C function is shown as below: + * @code + * void ftfx_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t + * bitValue) + * { + * if (bitMask) + * { + * uint32_t value = (((uint32_t)(((uint32_t)(bitValue)) << bitShift)) & bitMask); + * *base = (*base & (~bitMask)) | value; + * } + * + * __ISB(); + * __DSB(); + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +static const uint32_t s_ftfxCommonBitOperationFunctionCode[] = { + 0x2900b510u, 0x6804d005u, 0x4093438cu, 0x43214019u, 0xf3bf6001u, 0xf3bf8f6fu, 0xbd108f4fu, +}; + +#if (!FTFx_DRIVER_IS_EXPORTED) +/*! @brief A static buffer used to hold ftfx_common_bit_operation() */ +static uint32_t s_ftfxCommonBitOperation[kFTFx_CACHE_RamFuncMaxSizeInWords]; +#endif /* (!FTFx_DRIVER_IS_EXPORTED) */ +#endif /* FLASH_IS_CACHE_INVALIDATION_AVAILABLE && FTFx_DRIVER_IS_FLASH_RESIDENT */ + +/******************************************************************************* + * Code + ******************************************************************************/ + +status_t FTFx_CACHE_Init(ftfx_cache_config_t *config) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + +/* copy required flash commands to RAM */ +#if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE + if (NULL == config->bitOperFuncAddr.callFlashCommand) + { +#if FTFx_DRIVER_IS_EXPORTED + return kStatus_FTFx_ExecuteInRamFunctionNotReady; +#else + config->bitOperFuncAddr.commadAddr = (uint32_t)s_ftfxCommonBitOperation; +#endif /* FTFx_DRIVER_IS_EXPORTED */ + } + + ftfx_copy_common_bit_operation_to_ram((uint32_t *)config->bitOperFuncAddr.commadAddr); +#endif /* FLASH_IS_CACHE_INVALIDATION_AVAILABLE && FTFx_DRIVER_IS_FLASH_RESIDENT */ + + return kStatus_FTFx_Success; +} + +/*! + * @brief Flash Cache/Prefetch/Speculation Clear Process + * + * This function is used to perform the cache and prefetch speculation clear process to the flash. + */ +status_t FTFx_CACHE_ClearCachePrefetchSpeculation(ftfx_cache_config_t *config, bool isPreProcess) +{ + /* We pass the ftfx register address as a parameter to ftfx_common_bit_operation() instead of using + * pre-processed MACROs or a global variable in ftfx_common_bit_operation() + * to make sure that ftfx_common_bit_operation() will be compiled into position-independent code (PIC). */ + if (!isPreProcess) + { +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM + mcm_flash_cache_clear(config); +#endif +#if FLASH_CACHE_IS_CONTROLLED_BY_MSCM + mscm_flash_cache_clear(config); +#endif +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC + fmc_flash_cache_clear(config); +#endif +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(config, true); +#endif +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + fmc_flash_prefetch_speculation_clear(config); +#endif + } + if (isPreProcess) + { +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(config, false); +#endif + } + + return kStatus_FTFx_Success; +} + +status_t FTFx_CACHE_PflashSetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus) +{ +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + if (true == speculationStatus->instructionOff) + { + if (false == speculationStatus->dataOff) + { + return kStatus_FTFx_InvalidSpeculationOption; + } + else + { + MCM0_CACHE_REG |= MCM_PLACR_DFCS_MASK; + } + } + else + { + MCM0_CACHE_REG &= ~MCM_PLACR_DFCS_MASK; + if (false == speculationStatus->dataOff) + { + MCM0_CACHE_REG |= MCM_PLACR_EFDS_MASK; + } + else + { + MCM0_CACHE_REG &= ~MCM_PLACR_EFDS_MASK; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + if (false == speculationStatus->instructionOff) + { + FMC_CACHE_REG |= FMC_CACHE_B0IPE_MASK; + } + else + { + FMC_CACHE_REG &= ~FMC_CACHE_B0IPE_MASK; + } + if (false == speculationStatus->dataOff) + { + FMC_CACHE_REG |= FMC_CACHE_B0DPE_MASK; + } + else + { + FMC_CACHE_REG &= ~FMC_CACHE_B0DPE_MASK; + } + + /* Invalidate Prefetch Speculation Buffer */ + FMC_SPECULATION_INVALIDATE_REG |= FMC_SPECULATION_INVALIDATE_MASK; + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + if (true == speculationStatus->instructionOff) + { + if (false == speculationStatus->dataOff) + { + return kStatus_FTFx_InvalidSpeculationOption; + } + else + { + MSCM_OCMDR0_REG |= MSCM_OCMDR_OCMC1_DFCS_MASK; + } + } + else + { + MSCM_OCMDR0_REG &= ~MSCM_OCMDR_OCMC1_DFCS_MASK; + if (false == speculationStatus->dataOff) + { + MSCM_OCMDR0_REG &= ~MSCM_OCMDR_OCMC1_DFDS_MASK; + } + else + { + MSCM_OCMDR0_REG |= MSCM_OCMDR_OCMC1_DFDS_MASK; + } + } + } +#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ + + return kStatus_FTFx_Success; +} + +status_t FTFx_CACHE_PflashGetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus) +{ + (void)memset(speculationStatus, 0, sizeof(ftfx_prefetch_speculation_status_t)); + + /* Assuming that all speculation options are enabled. */ + speculationStatus->instructionOff = false; + speculationStatus->dataOff = false; + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + uint32_t value = MCM0_CACHE_REG; + if (0U != (value & MCM_PLACR_DFCS_MASK)) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOff = true; + speculationStatus->dataOff = true; + } + else + { + /* Speculation buffer is on for instruction. */ + if (0U == (value & MCM_PLACR_EFDS_MASK)) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOff = true; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + uint32_t value = FMC_CACHE_REG; + if (0U == (value & FMC_CACHE_B0DPE_MASK)) + { + /* Do not prefetch in response to data references. */ + speculationStatus->dataOff = true; + } + if (0U == (value & FMC_CACHE_B0IPE_MASK)) + { + /* Do not prefetch in response to instruction fetches. */ + speculationStatus->instructionOff = true; + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + uint32_t value = MSCM_OCMDR0_REG; + if (0U != (value & MSCM_OCMDR_OCMC1_DFCS_MASK)) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOff = true; + speculationStatus->dataOff = true; + } + else + { + /* Speculation buffer is on for instruction. */ + if (0U != (value & MSCM_OCMDR_OCMC1_DFDS_MASK)) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOff = true; + } + } + } +#endif + + return kStatus_FTFx_Success; +} + +#if FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE +/*! @brief Copy PIC of ftfx_common_bit_operation() to RAM */ +static void ftfx_copy_common_bit_operation_to_ram(uint32_t *ftfxCommonBitOperation) +{ + assert(sizeof(s_ftfxCommonBitOperationFunctionCode) <= ((uint32_t)kFTFx_CACHE_RamFuncMaxSizeInWords * 4U)); + + (void)memcpy(ftfxCommonBitOperation, s_ftfxCommonBitOperationFunctionCode, + sizeof(s_ftfxCommonBitOperationFunctionCode)); +} +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT && FLASH_IS_CACHE_INVALIDATION_AVAILABLE */ + +#if FTFx_DRIVER_IS_FLASH_RESIDENT +static void ftfx_common_bit_operation_command_sequence( + ftfx_cache_config_t *config, FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue) +{ + uint32_t *ftfxCommonBitOperationAddr; + ftfxCommonBitOperationAddr = &config->bitOperFuncAddr.commadAddr; + /* Since the value of ARM function pointer is always odd, but the real start + * address + * of function memory should be even, that's why +1 operation exist. */ + *ftfxCommonBitOperationAddr += 1UL; + callftfxCommonBitOperation_t ftfxCommonBitOperationCommand = config->bitOperFuncAddr.callFlashCommand; + /* Workround for some devices which doesn't need this function */ + ftfxCommonBitOperationCommand((FTFx_REG32_ACCESS_TYPE)base, bitMask, bitShift, bitValue); + *ftfxCommonBitOperationAddr -= 1UL; +} +#endif /*FTFx_DRIVER_IS_FLASH_RESIDENT*/ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(ftfx_cache_config_t *config) +{ + FTFx_REG32_ACCESS_TYPE regBase; + +#if defined(MCM0_CACHE_REG) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG; +#elif defined(MCM1_CACHE_REG) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG; +#endif + +#if FTFx_DRIVER_IS_FLASH_RESIDENT + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1UL); + +#else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ + *regBase |= MCM_CACHE_CLEAR_MASK; + + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MSCM +/*! @brief Performs the cache clear to the flash by MSCM.*/ +void mscm_flash_cache_clear(ftfx_cache_config_t *config) +{ + uint8_t setValue = 0x1U; + +/* The OCMDR[0] is always used to cache main Pflash*/ +/* For device with FlexNVM support, the OCMDR[1] is used to cache Dflash. + * For device with secondary flash support, the OCMDR[1] is used to cache secondary Pflash. */ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + switch (config->flashMemoryIndex) + { + case kFLASH_MemoryIndexSecondaryFlash: + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR1_REG, + MSCM_CACHE_CLEAR_MASK, MSCM_CACHE_CLEAR_SHIFT, setValue); + break; + case kFLASH_MemoryIndexPrimaryFlash: + default: + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG, + MSCM_CACHE_CLEAR_MASK, MSCM_CACHE_CLEAR_SHIFT, setValue); + break; + } +#else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ + switch (config->flashMemoryIndex) + { + case kFLASH_MemoryIndexSecondaryFlash: + MSCM_OCMDR1_REG = (MSCM_OCMDR1_REG & (~MSCM_CACHE_CLEAR_MASK)) | MSCM_CACHE_CLEAR(setValue); + /* Each cache clear instruction should be followed by below code*/ + __ISB(); + __DSB(); + break; + case kFLASH_MemoryIndexPrimaryFlash: + default: + MSCM_OCMDR0_REG = (MSCM_OCMDR0_REG & (~MSCM_CACHE_CLEAR_MASK)) | MSCM_CACHE_CLEAR(setValue); + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); + break; + } +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(ftfx_cache_config_t *config) +{ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&FMC_CACHE_REG, FMC_CACHE_CLEAR_MASK, + FMC_CACHE_CLEAR_SHIFT, 0xFUL); +#else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ + FMC_CACHE_REG = (FMC_CACHE_REG & (~FMC_CACHE_CLEAR_MASK)) | FMC_CACHE_CLEAR(~0); + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM +/*! @brief Performs the prefetch speculation buffer clear to the flash by MSCM.*/ +void mscm_flash_prefetch_speculation_enable(ftfx_cache_config_t *config, bool enable) +{ + uint8_t setValue; + if (enable) + { + setValue = 0x0U; + } + else + { + setValue = 0x3U; + } + +/* The OCMDR[0] is always used to prefetch main Pflash*/ +/* For device with FlexNVM support, the OCMDR[1] is used to prefetch Dflash. + * For device with secondary flash support, the OCMDR[1] is used to prefetch secondary Pflash. */ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + + switch (config->flashMemoryIndex) + { + case 1: + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR1_REG, + MSCM_SPECULATION_SET_MASK, MSCM_SPECULATION_SET_SHIFT, setValue); + break; + case 0: + default: + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&MSCM_OCMDR0_REG, + MSCM_SPECULATION_SET_MASK, MSCM_SPECULATION_SET_SHIFT, setValue); + break; + } +#else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ + switch (config->flashMemoryIndex) + { + case kFLASH_MemoryIndexSecondaryFlash: + MSCM_OCMDR1_REG = (MSCM_OCMDR1_REG & (~MSCM_SPECULATION_SET_MASK)) | MSCM_SPECULATION_SET(setValue); + /* Each cache clear instruction should be followed by below code*/ + __ISB(); + __DSB(); + break; + case kFLASH_MemoryIndexPrimaryFlash: + default: + MSCM_OCMDR0_REG = (MSCM_OCMDR0_REG & (~MSCM_SPECULATION_SET_MASK)) | MSCM_SPECULATION_SET(setValue); + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); + break; + } +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM */ + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC +/*! @brief Performs the prefetch speculation buffer clear to the flash by FMC.*/ +void fmc_flash_prefetch_speculation_clear(ftfx_cache_config_t *config) +{ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + /* calling flash command sequence function to execute the command */ + ftfx_common_bit_operation_command_sequence(config, (FTFx_REG32_ACCESS_TYPE)&FMC_SPECULATION_INVALIDATE_REG, + FMC_SPECULATION_INVALIDATE_MASK, FMC_SPECULATION_INVALIDATE_SHIFT, 1UL); +#else /* !FTFx_DRIVER_IS_FLASH_RESIDENT */ + FMC_SPECULATION_INVALIDATE_REG |= FMC_SPECULATION_INVALIDATE_MASK; + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.h new file mode 100644 index 0000000..0bba177 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_cache.h @@ -0,0 +1,113 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_CACHE_H +#define FSL_FTFX_CACHE_H + +#include "fsl_ftfx_controller.h" + +/*! + * @addtogroup ftfx_cache_driver + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @brief FTFx prefetch speculation status. + */ +typedef struct _flash_prefetch_speculation_status +{ + bool instructionOff; /*!< Instruction speculation.*/ + bool dataOff; /*!< Data speculation.*/ +} ftfx_prefetch_speculation_status_t; + +/*! + * @brief Constants for execute-in-RAM flash function. + */ +enum _ftfx_cache_ram_func_constants +{ + kFTFx_CACHE_RamFuncMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/ +}; + +typedef union +{ + uint32_t commadAddr; + void (*callFlashCommand)(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t bitValue); +} function_bit_operation_ptr_t; + +/*! @brief FTFx cache driver state information. + * + * An instance of this structure is allocated by the user of the flash driver and + * passed into each of the driver APIs. + */ +typedef struct _ftfx_cache_config +{ + uint8_t flashMemoryIndex; /*!< 0 - primary flash; 1 - secondary flash*/ + uint8_t reserved[3]; + function_bit_operation_ptr_t bitOperFuncAddr; /*!< An buffer point to the flash execute-in-RAM function. */ +} ftfx_cache_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Initializes the global FTFx cache structure members. + * + * This function checks and initializes the Flash module for the other FTFx cache APIs. + * + * @param config Pointer to the storage for the driver runtime state. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + */ +status_t FTFx_CACHE_Init(ftfx_cache_config_t *config); + +/*! + * @brief Process the cache/prefetch/speculation to the flash. + * + * @param config A pointer to the storage for the driver runtime state. + * @param isPreProcess The possible option used to control flash cache/prefetch/speculation + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + */ +status_t FTFx_CACHE_ClearCachePrefetchSpeculation(ftfx_cache_config_t *config, bool isPreProcess); + +/*! + * @brief Sets the PFlash prefetch speculation to the intended speculation status. + * + * @param speculationStatus The expected protect status to set to the PFlash protection register. Each bit is + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidSpeculationOption An invalid speculation option argument is provided. + */ +status_t FTFx_CACHE_PflashSetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus); + +/*! + * @brief Gets the PFlash prefetch speculation status. + * + * @param speculationStatus Speculation status returned by the PFlash IP. + * @retval #kStatus_FTFx_Success API was executed successfully. + */ +status_t FTFx_CACHE_PflashGetPrefetchSpeculation(ftfx_prefetch_speculation_status_t *speculationStatus); + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* FSL_FTFX_CACHE_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.c b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.c new file mode 100644 index 0000000..42a322a --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.c @@ -0,0 +1,1510 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "fsl_ftfx_controller.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.flash" +#endif + +/*! + * @name Flash controller command numbers + * @{ + */ +#define FTFx_VERIFY_BLOCK 0x00U /*!< RD1BLK*/ +#define FTFx_VERIFY_SECTION 0x01U /*!< RD1SEC*/ +#define FTFx_PROGRAM_CHECK 0x02U /*!< PGMCHK*/ +#define FTFx_READ_RESOURCE 0x03U /*!< RDRSRC*/ +#define FTFx_PROGRAM_LONGWORD 0x06U /*!< PGM4*/ +#define FTFx_PROGRAM_PHRASE 0x07U /*!< PGM8*/ +#define FTFx_ERASE_BLOCK 0x08U /*!< ERSBLK*/ +#define FTFx_ERASE_SECTOR 0x09U /*!< ERSSCR*/ +#define FTFx_PROGRAM_SECTION 0x0BU /*!< PGMSEC*/ +#define FTFx_GENERATE_CRC 0x0CU /*!< CRCGEN*/ +#define FTFx_VERIFY_ALL_BLOCK 0x40U /*!< RD1ALL*/ +#define FTFx_READ_ONCE 0x41U /*!< RDONCE or RDINDEX*/ +#define FTFx_PROGRAM_ONCE 0x43U /*!< PGMONCE or PGMINDEX*/ +#define FTFx_ERASE_ALL_BLOCK 0x44U /*!< ERSALL*/ +#define FTFx_SECURITY_BY_PASS 0x45U /*!< VFYKEY*/ +#define FTFx_SWAP_CONTROL 0x46U /*!< SWAP*/ +#define FTFx_ERASE_ALL_BLOCK_UNSECURE 0x49U /*!< ERSALLU*/ +#define FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT 0x4AU /*!< RD1XA*/ +#define FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT 0x4BU /*!< ERSXA*/ +#define FTFx_PROGRAM_PARTITION 0x80U /*!< PGMPART*/ +#define FTFx_SET_FLEXRAM_FUNCTION 0x81U /*!< SETRAM*/ +/*@}*/ + +/*! + * @brief Constants for execute-in-RAM flash function. + */ +enum _ftfx_ram_func_constants +{ + kFTFx_RamFuncMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/ +}; + +/*! @brief A function pointer used to point to relocated flash_run_command() */ +typedef void (*callFtfxRunCommand_t)(FTFx_REG8_ACCESS_TYPE ftfx_fstat); + +/*! + * @name Enumeration for Flash security register code + * @{ + */ +enum _ftfx_fsec_register_code +{ + kFTFx_FsecRegCode_KEYEN_Enabled = 0x80U, + kFTFx_FsecRegCode_SEC_Unsecured = 0x02U +}; +/*@}*/ + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! + * @brief Enumeration for flash config area. + */ +enum _ftfx_pflash_config_area_range +{ + kFTFx_PflashConfigAreaStart = 0x400U, + kFTFx_PflashConfigAreaEnd = 0x40FU +}; +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! @brief Init IFR memory related info */ +static void ftfx_init_ifr(ftfx_config_t *config); + +#if FTFx_DRIVER_IS_FLASH_RESIDENT +/*! @brief Copy flash_run_command() to RAM*/ +static void ftfx_copy_run_command_to_ram(uint32_t *ftfxRunCommand); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + +/*! @brief Internal function Flash command sequence. Called by driver APIs only*/ +static status_t ftfx_command_sequence(ftfx_config_t *config); + +/*! @brief Internal function Flash asynchronous command sequence. Called by driver APIs only*/ +static void ftfx_command_sequence_non_blocking(ftfx_config_t *config); + +/*! @brief Validates the range and alignment of the given address range.*/ +static status_t ftfx_check_mem_range(ftfx_config_t *config, + uint32_t startAddress, + uint32_t lengthInBytes, + uint8_t alignmentBaseline); + +/*! @brief Validates the given user key for flash erase APIs.*/ +static status_t ftfx_check_user_key(uint32_t key); + +/*! @brief Reads word from byte address.*/ +static uint32_t ftfx_read_word_from_byte_address(const uint8_t *src); + +/*! @brief Writes word to byte address.*/ +static void ftfx_write_word_to_byte_address(uint8_t *dst, uint32_t word); + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! @brief Validates the range of the given resource address.*/ +static status_t ftfx_check_resource_range(ftfx_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + uint32_t alignmentBaseline, + ftfx_read_resource_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! @brief Validates the given flexram function option.*/ +static inline status_t ftfx_check_flexram_function_option(ftfx_flexram_func_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! @brief Validates the given swap control option.*/ +static status_t ftfx_check_swap_control_option(ftfx_swap_control_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +#if FTFx_DRIVER_IS_FLASH_RESIDENT +/*! + * @brief Position independent code of flash_run_command + * + * Note1: The prototype of C function is shown as below: + * @code + * void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat) + * { + * *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; + * + * while (!((*ftfx_fstat) & FTFx_FSTAT_CCIF_MASK)) + * { + * } + * } + * @endcode + * Note2: The binary code is generated by IAR 7.70.1 + */ +static const uint32_t s_ftfxRunCommandFunctionCode[] = { + 0x70012180u, + 0x420a7802u, + 0x4770d0fcu, +}; +#if (!FTFx_DRIVER_IS_EXPORTED) +/*! @brief A static buffer used to hold flash_run_command() */ +static uint32_t s_ftfxRunCommand[kFTFx_RamFuncMaxSizeInWords]; +#endif /* (!FTFx_DRIVER_IS_EXPORTED) */ +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + +/*! @brief Access to FTFx Registers */ +static volatile uint32_t *const kFCCOBx = (volatile uint32_t *)(uint32_t)&FTFx_FCCOB3_REG; + +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM +/*! @brief Table of eeprom sizes. */ +static const uint16_t kEepromDensities[16] = { + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0000, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0001, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0010, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0011, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0100, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0101, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0110, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_0111, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1000, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1001, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1010, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1011, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1100, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1101, + FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1110, FSL_FEATURE_FLASH_FLEX_NVM_EEPROM_SIZE_FOR_EEESIZE_1111}; +/*! @brief Table of dflash sizes. */ +static const uint32_t kDflashDensities[16] = { + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0000, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0001, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0010, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0011, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0100, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0101, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0110, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_0111, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1000, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1001, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1010, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1011, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1100, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1101, + FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1110, FSL_FEATURE_FLASH_FLEX_NVM_DFLASH_SIZE_FOR_DEPART_1111}; +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * @brief Initializes the global flash properties structure members. + */ +void FTFx_API_Init(ftfx_config_t *config) +{ + if (config == NULL) + { + return; + } + config->runCmdFuncAddr.callFlashCommand = NULL; + config->flexramBlockBase = FSL_FEATURE_FLASH_FLEX_RAM_START_ADDRESS; + config->flexramTotalSize = FSL_FEATURE_FLASH_FLEX_RAM_SIZE; + + /* copy required flash command to RAM */ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + config->runCmdFuncAddr.commadAddr = (uint32_t)s_ftfxRunCommand; + ftfx_copy_run_command_to_ram((uint32_t *)config->runCmdFuncAddr.commadAddr); +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + + ftfx_init_ifr(config); +} + +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM +/*! + * @brief Updates FlexNVM memory partition status according to data flash 0 IFR. + */ +status_t FTFx_API_UpdateFlexnvmPartitionStatus(ftfx_config_t *config) +{ + struct _dflash_ifr_field_config + { + uint32_t reserved0; + uint8_t FlexNVMPartitionCode; + uint8_t EEPROMDataSetSize; + uint16_t reserved1; + } dataIFRReadOut; + uint32_t flexnvmInfoIfrAddr; + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + flexnvmInfoIfrAddr = + config->ifrDesc.resRange.dflashIfrStart + config->ifrDesc.resRange.ifrMemSize - sizeof(dataIFRReadOut); + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD + /* Get FlexNVM memory partition info from data flash IFR */ + returnCode = FTFx_CMD_ReadResource(config, flexnvmInfoIfrAddr, (uint8_t *)&dataIFRReadOut, sizeof(dataIFRReadOut), + kFTFx_ResourceOptionFlashIfr); + if (returnCode != kStatus_FTFx_Success) + { + return kStatus_FTFx_PartitionStatusUpdateFailure; + } +#else +#error "Cannot get FlexNVM memory partition info" +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + + /* Fill out partitioned EEPROM size */ + dataIFRReadOut.EEPROMDataSetSize &= 0x0FU; + config->eepromTotalSize = kEepromDensities[dataIFRReadOut.EEPROMDataSetSize]; + + /* Fill out partitioned DFlash size */ + dataIFRReadOut.FlexNVMPartitionCode &= 0x0FU; + config->flashDesc.totalSize = kDflashDensities[dataIFRReadOut.FlexNVMPartitionCode]; + + return kStatus_FTFx_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ + +/*! + * @brief Erases the flash sectors encompassed by parameters passed into function. + */ +status_t FTFx_CMD_Erase(ftfx_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) +{ + uint32_t sectorSize; + uint32_t endAddress; /* storing end address */ + uint32_t numberOfSectors; /* number of sectors calculated by endAddress */ + status_t returnCode; + uint32_t eraseStart; + + /* Check the supplied address range. */ + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, config->opsConfig.addrAligment.sectorCmd); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* Validate the user key */ + returnCode = ftfx_check_user_key(key); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + eraseStart = config->opsConfig.convertedAddress; + sectorSize = config->flashDesc.sectorSize; + + /* Calculate Flash end address */ + endAddress = eraseStart + lengthInBytes - 1U; + + /* re-calculate the endAddress and align it to the start of the next sector + * which will be used in the comparison below */ + if (0U != (endAddress % sectorSize)) + { + numberOfSectors = endAddress / sectorSize + 1U; + endAddress = numberOfSectors * sectorSize - 1U; + } + + /* the start address will increment to the next sector address + * until it reaches the endAdddress */ + while (eraseStart <= endAddress) + { + /* preparing passing parameter to erase a flash block */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_SECTOR, eraseStart); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + /* checking the success of command execution */ + if (kStatus_FTFx_Success != returnCode) + { + break; + } + else + { + /* Increment to the next sector */ + eraseStart += sectorSize; + } + } + + return returnCode; +} + +/*! + * @brief erases one flash sector size based on the start address. + */ +status_t FTFx_CMD_EraseSectorNonBlocking(ftfx_config_t *config, uint32_t start, uint32_t key) +{ + uint32_t eraseStart; + uint8_t aligmentInBytes; + status_t returnCode = kStatus_FTFx_AddressError; + aligmentInBytes = config->opsConfig.addrAligment.sectorCmd; + uint32_t lengthInBytes = config->flashDesc.sectorSize; + + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + /* Validate the user key */ + returnCode = ftfx_check_user_key(key); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + eraseStart = config->opsConfig.convertedAddress; + + /* preparing passing parameter to erase a flash block */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_SECTOR, eraseStart); + /* calling flash command sequence function to execute the command */ + ftfx_command_sequence_non_blocking(config); + + return returnCode; +} + +/*! + * @brief Erases entire flash + */ +status_t FTFx_CMD_EraseAll(ftfx_config_t *config, uint32_t key) +{ + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* preparing passing parameter to erase all flash blocks */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_BLOCK, 0xFFFFFFU); + + /* Validate the user key */ + returnCode = ftfx_check_user_key(key); + if (kStatus_FTFx_Success != returnCode) + { + return returnCode; + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM + /* Data flash IFR will be erased by erase all command, so we need to + * update FlexNVM memory partition status synchronously */ + if (returnCode == kStatus_FTFx_Success) + { + if (config->ifrDesc.resRange.dflashIfrStart != config->ifrDesc.resRange.pflashIfrStart) + { + returnCode = FTFx_API_UpdateFlexnvmPartitionStatus(config); + } + } +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ + + return returnCode; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD +/*! + * @brief Erases the entire flash, including protected sectors. + */ +status_t FTFx_CMD_EraseAllUnsecure(ftfx_config_t *config, uint32_t key) +{ + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Prepare passing parameter to erase all flash blocks (unsecure). */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_BLOCK_UNSECURE, 0xFFFFFFU); + + /* Validate the user key */ + returnCode = ftfx_check_user_key(key); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM + /* Data flash IFR will be erased by erase all unsecure command, so we need to + * update FlexNVM memory partition status synchronously */ + if (returnCode == kStatus_FTFx_Success) + { + if (config->ifrDesc.resRange.dflashIfrStart != config->ifrDesc.resRange.pflashIfrStart) + { + returnCode = FTFx_API_UpdateFlexnvmPartitionStatus(config); + } + } +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ + + return returnCode; +} +#endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */ + +/*! + * @brief Erases all program flash execute-only segments defined by the FXACC registers. + */ +status_t FTFx_CMD_EraseAllExecuteOnlySegments(ftfx_config_t *config, uint32_t key) +{ + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* preparing passing parameter to erase all execute-only segments + * 1st element for the FCCOB register */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_ERASE_ALL_EXECUTE_ONLY_SEGMENT, 0xFFFFFFU); + + /* Validate the user key */ + returnCode = ftfx_check_user_key(key); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + return returnCode; +} + +/*! + * @brief Programs flash with data at locations passed in through parameters. + */ +status_t FTFx_CMD_Program(ftfx_config_t *config, uint32_t start, const uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + uint8_t blockWriteUnitSize = config->opsConfig.addrAligment.blockWriteUnitSize; + uint32_t programStart; + uint32_t remainingLength; + if (src == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Check the supplied address range. */ + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, blockWriteUnitSize); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + programStart = config->opsConfig.convertedAddress; + remainingLength = lengthInBytes; + + while (remainingLength > 0U) + { + /* preparing passing parameter to program the flash block */ + kFCCOBx[1] = ftfx_read_word_from_byte_address((const uint8_t *)src); + src = &src[4]; + + if (4U == blockWriteUnitSize) + { + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_LONGWORD, programStart); + } + else if (8U == blockWriteUnitSize) + { + kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t *)src); + src = &src[4]; + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_PHRASE, programStart); + } + else + { + return kStatus_FTFx_InvalidArgument; + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + /* checking for the success of command execution */ + if (kStatus_FTFx_Success != returnCode) + { + break; + } + else + { + /* update programStart address for next iteration */ + programStart += blockWriteUnitSize; + + /* update remainingLength for next iteration */ + remainingLength -= blockWriteUnitSize; + } + } + + return returnCode; +} + +/*! + * @brief Programs Program Once Field through parameters. + */ +status_t FTFx_CMD_ProgramOnce(ftfx_config_t *config, uint32_t index, const uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + + if ((config == NULL) || (src == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + /* pass parameters to FTFx */ + kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_PROGRAM_ONCE, index, 0xFFFFU); + + kFCCOBx[1] = ftfx_read_word_from_byte_address((const uint8_t *)src); + + /* Note: Have to separate the first index from the rest if it equals 0 + * to avoid a pointless comparison of unsigned int to 0 compiler warning */ + if (config->ifrDesc.feature.has8ByteIdxSupport != 0U) + { + if (config->ifrDesc.feature.has4ByteIdxSupport != 0U) + { + if (((index == config->ifrDesc.idxInfo.mix8byteIdxStart) || + ((index >= ((uint32_t)config->ifrDesc.idxInfo.mix8byteIdxStart + 1U)) && + (index <= config->ifrDesc.idxInfo.mix8byteIdxEnd))) && + (lengthInBytes == 8U)) + { + kFCCOBx[2] = ftfx_read_word_from_byte_address(&src[4]); + } + } + else + { + kFCCOBx[2] = ftfx_read_word_from_byte_address(&src[4]); + } + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + return returnCode; +} + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD +/*! + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. + */ +status_t FTFx_CMD_ProgramSection(ftfx_config_t *config, uint32_t start, const uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + uint32_t sectorSize; + uint32_t programaddress; + uint8_t aligmentInBytes = config->opsConfig.addrAligment.sectionCmd; + const uint8_t *srcaddress = src; +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD + bool needSwitchFlexRamMode = false; +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + + if (srcaddress == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Check the supplied address range. */ + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + programaddress = config->opsConfig.convertedAddress; + sectorSize = config->flashDesc.sectorSize; + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD + /* Switch function of FlexRAM if needed */ + if ((FTFx->FCNFG & FTFx_FCNFG_RAMRDY_MASK) == 0U) + { + needSwitchFlexRamMode = true; + + returnCode = FTFx_CMD_SetFlexramFunction(config, kFTFx_FlexramFuncOptAvailableAsRam); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + } +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + + while (lengthInBytes > 0U) + { + /* Make sure the write operation doesn't span two sectors */ + uint32_t endAddressOfCurrentSector = ALIGN_UP(programaddress, sectorSize); + uint32_t lengthTobeProgrammedOfCurrentSector; + uint32_t currentOffset = 0U; + + if (endAddressOfCurrentSector == programaddress) + { + endAddressOfCurrentSector += sectorSize; + } + + if ((lengthInBytes + programaddress) > endAddressOfCurrentSector) + { + lengthTobeProgrammedOfCurrentSector = endAddressOfCurrentSector - programaddress; + } + else + { + lengthTobeProgrammedOfCurrentSector = lengthInBytes; + } + + /* Program Current Sector */ + while (lengthTobeProgrammedOfCurrentSector > 0U) + { + /* Make sure the program size doesn't exceeds Acceleration RAM size */ + uint32_t programSizeOfCurrentPass; + uint32_t numberOfPhases; + + if (lengthTobeProgrammedOfCurrentSector > (uint32_t)kFLASH_AccelerationRamSize) + { + programSizeOfCurrentPass = (uint32_t)kFLASH_AccelerationRamSize; + } + else + { + programSizeOfCurrentPass = lengthTobeProgrammedOfCurrentSector; + } + + /* Copy data to FlexRAM */ + (void)memcpy((uint8_t *)config->flexramBlockBase, &srcaddress[currentOffset], programSizeOfCurrentPass); + /* Set programaddress address of the data to be programmed */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_SECTION, programaddress + currentOffset); + /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */ + numberOfPhases = programSizeOfCurrentPass / aligmentInBytes; + + kFCCOBx[1] = BYTE2WORD_2_2(numberOfPhases, 0xFFFFU); + + /* Peform command sequence */ + returnCode = ftfx_command_sequence(config); + + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + lengthTobeProgrammedOfCurrentSector -= programSizeOfCurrentPass; + currentOffset += programSizeOfCurrentPass; + } + + srcaddress = &srcaddress[currentOffset]; + programaddress += currentOffset; + lengthInBytes -= currentOffset; + } + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD + /* Restore function of FlexRAM if needed. */ + if (needSwitchFlexRamMode) + { + returnCode = FTFx_CMD_SetFlexramFunction(config, kFTFx_FlexramFuncOptAvailableForEeprom); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + } +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + + return returnCode; +} +#endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD +/*! + * @brief Prepares the FlexNVM block for use as data flash, EEPROM backup, or a combination of both and initializes the + * FlexRAM. + */ +status_t FTFx_CMD_ProgramPartition(ftfx_config_t *config, + ftfx_partition_flexram_load_opt_t option, + uint32_t eepromDataSizeCode, + uint32_t flexnvmPartitionCode) +{ + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* eepromDataSizeCode[7:6], flexnvmPartitionCode[7:4] should be all 1'b0 + * or it will cause access error. */ + /* eepromDataSizeCode bit with 0x3FU; */ + /* flexnvmPartitionCode bit with 0x0FU; */ + + /* preparing passing parameter to program the flash block */ + kFCCOBx[0] = BYTE2WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option); + kFCCOBx[1] = BYTE2WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM + /* Data flash IFR will be updated by program partition command during reset sequence, + * so we just set reserved values for partitioned FlexNVM size here */ + config->eepromTotalSize = 0xFFFFU; + config->flashDesc.totalSize = 0xFFFFFFFFU; +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ + + return (returnCode); +} +#endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */ + +/*! + * @brief Reads the Program Once Field through parameters. + */ +status_t FTFx_CMD_ReadOnce(ftfx_config_t *config, uint32_t index, uint8_t *dst, uint32_t lengthInBytes) +{ + status_t returnCode; + + if ((config == NULL) || (dst == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + /* pass parameters to FTFx */ + kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_READ_ONCE, index, 0xFFFFU); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + if (returnCode == kStatus_FTFx_Success) + { + ftfx_write_word_to_byte_address(dst, kFCCOBx[1]); + /* Note: Have to separate the first index from the rest if it equals 0 + * to avoid a pointless comparison of unsigned int to 0 compiler warning */ + if (config->ifrDesc.feature.has8ByteIdxSupport != 0U) + { + if (config->ifrDesc.feature.has4ByteIdxSupport != 0U) + { + if (((index == config->ifrDesc.idxInfo.mix8byteIdxStart) || + ((index >= ((uint32_t)config->ifrDesc.idxInfo.mix8byteIdxStart + 1U)) && + (index <= config->ifrDesc.idxInfo.mix8byteIdxEnd))) && + (lengthInBytes == 8U)) + { + ftfx_write_word_to_byte_address(&dst[4], kFCCOBx[2]); + } + } + else + { + ftfx_write_word_to_byte_address(&dst[4], kFCCOBx[2]); + } + } + } + + return returnCode; +} + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! + * @brief Reads the resource with data at locations passed in through parameters. + * + * this function can read date from program flash IFR, data flash IFR space, + * and the Version ID field. + */ +status_t FTFx_CMD_ReadResource( + ftfx_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option) +{ + status_t returnCode; + uint32_t readstart; + uint8_t *destaddress; + uint32_t readlengthBytes; + readstart = start; + destaddress = dst; + readlengthBytes = lengthInBytes; + if ((config == NULL) || (dst == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + uint8_t aligmentInBytes = config->opsConfig.addrAligment.resourceCmd; + + /* Check the supplied address range. */ + returnCode = ftfx_check_resource_range(config, readstart, readlengthBytes, aligmentInBytes, option); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + while (readlengthBytes > 0U) + { + /* preparing passing parameter */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_READ_RESOURCE, readstart); + if (aligmentInBytes == 4U) + { + kFCCOBx[2] = BYTE2WORD_1_3(option, 0xFFFFFFU); + } + else if (aligmentInBytes == 8U) + { + kFCCOBx[1] = BYTE2WORD_1_3(option, 0xFFFFFFU); + } + else + { + return kStatus_FTFx_InvalidArgument; + } + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + if (kStatus_FTFx_Success != returnCode) + { + break; + } + + /* fetch data */ + ftfx_write_word_to_byte_address(destaddress, kFCCOBx[1]); + destaddress = &destaddress[4]; + if (aligmentInBytes == 8U) + { + ftfx_write_word_to_byte_address(destaddress, kFCCOBx[2]); + destaddress = &destaddress[4]; + } + /* update readstart address for next iteration */ + readstart += aligmentInBytes; + /* update readlengthBytes for next iteration */ + readlengthBytes -= aligmentInBytes; + } + + return (returnCode); +} +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +/*! + * @brief Verifies an erasure of the desired flash area at a specified margin level. + * + * This function checks the appropriate number of flash sectors based on + * the desired start address and length to check whether the flash is erased + * to the specified read margin level. + */ +status_t FTFx_CMD_VerifyErase(ftfx_config_t *config, uint32_t start, uint32_t lengthInBytes, ftfx_margin_value_t margin) +{ + /* Check arguments. */ + uint32_t blockSize; + uint32_t nextBlockStartAddress; + uint32_t remainingBytes; + uint8_t aligmentInBytes = config->opsConfig.addrAligment.sectionCmd; + status_t returnCode; + uint32_t erasestart; + + /* Validates the range and alignment of the given address range.*/ + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes); + if (kStatus_FTFx_Success != returnCode) + { + return returnCode; + } + + erasestart = config->opsConfig.convertedAddress; + blockSize = config->flashDesc.totalSize / config->flashDesc.blockCount; + + /* Calculate the next block start address */ + nextBlockStartAddress = ALIGN_UP(erasestart, blockSize); + + if (nextBlockStartAddress == erasestart) + { + nextBlockStartAddress += blockSize; + } + + remainingBytes = lengthInBytes; + + while (0U != remainingBytes) + { + uint32_t numberOfPhrases; + + uint32_t verifyLength = nextBlockStartAddress - erasestart; + /* Calculate the size to be verified, this flash does not support erase and program across block. */ + if (verifyLength > remainingBytes) + { + verifyLength = remainingBytes; + } + + /* Calculate the number of phrases to be verified */ + numberOfPhrases = verifyLength / aligmentInBytes; + + /* Fill in verify section command parameters. */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_VERIFY_SECTION, erasestart); + kFCCOBx[1] = BYTE2WORD_2_1_1(numberOfPhrases, margin, 0xFFU); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + if (kStatus_FTFx_Success != returnCode) + { + return returnCode; + } + + remainingBytes -= verifyLength; + erasestart += verifyLength; + nextBlockStartAddress += blockSize; + } + + return kStatus_FTFx_Success; +} + +/*! + * @brief Verifies erasure of the entire flash at a specified margin level. + */ +status_t FTFx_CMD_VerifyEraseAll(ftfx_config_t *config, ftfx_margin_value_t margin) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* preparing passing parameter to verify all block command */ + kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_VERIFY_ALL_BLOCK, margin, 0xFFFFU); + + /* calling flash command sequence function to execute the command */ + return ftfx_command_sequence(config); +} + +/*! + * @brief Verifies whether the program flash execute-only segments have been erased to + * the specified read margin level. + */ +status_t FTFx_CMD_VerifyEraseAllExecuteOnlySegments(ftfx_config_t *config, ftfx_margin_value_t margin) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* preparing passing parameter to verify erase all execute-only segments command */ + kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_VERIFY_ALL_EXECUTE_ONLY_SEGMENT, margin, 0xFFFFU); + + /* calling flash command sequence function to execute the command */ + return ftfx_command_sequence(config); +} + +/*! + * @brief Verifies programming of the desired flash area at a specified margin level. + * + * This function verifies the data programed in the flash memory using the + * Flash Program Check Command and compares it to the expected data for a given + * flash area as determined by the start address and length. + */ +status_t FTFx_CMD_VerifyProgram(ftfx_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + const uint8_t *expectedData, + ftfx_margin_value_t margin, + uint32_t *failedAddress, + uint32_t *failedData) +{ + status_t returnCode; + uint8_t aligmentInBytes = config->opsConfig.addrAligment.checkCmd; + uint32_t programstart; + uint32_t programlength; + programlength = lengthInBytes; + if (expectedData == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Validates the range and alignment of the given address range */ + returnCode = ftfx_check_mem_range(config, start, lengthInBytes, aligmentInBytes); + if (kStatus_FTFx_Success != returnCode) + { + return returnCode; + } + + programstart = config->opsConfig.convertedAddress; + + while (0U != programlength) + { + /* preparing passing parameter to program check the flash block */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_PROGRAM_CHECK, programstart); + kFCCOBx[1] = BYTE2WORD_1_3(margin, 0xFFFFFFU); + kFCCOBx[2] = ftfx_read_word_from_byte_address((const uint8_t *)expectedData); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + + /* checking for the success of command execution */ + if (kStatus_FTFx_Success != returnCode) + { + if (failedAddress != NULL) + { + *failedAddress = programstart; + } + if (failedData != NULL) + { + *failedData = 0U; + } + break; + } + + programlength -= aligmentInBytes; + expectedData = &expectedData[aligmentInBytes]; + programstart += aligmentInBytes; + } + + return (returnCode); +} + +/*! + * @brief Allows users to bypass security with a backdoor key. + */ +status_t FTFx_CMD_SecurityBypass(ftfx_config_t *config, const uint8_t *backdoorKey) +{ + uint8_t registerValue; /* registerValue */ + status_t returnCode; /* return code variable */ + + if ((config == NULL) || (backdoorKey == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + /* set the default return code as kStatus_Success */ + returnCode = kStatus_FTFx_Success; + + /* Get flash security register value */ + registerValue = FTFx->FSEC; + + /* Check to see if flash is in secure state (any state other than 0x2) + * If not, then skip this since flash is not secure */ + if (0x02U != (registerValue & 0x03U)) + { + /* preparing passing parameter to erase a flash block */ + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_SECURITY_BY_PASS, 0xFFFFFFU); + kFCCOBx[1] = BYTE2WORD_1_1_1_1(backdoorKey[0], backdoorKey[1], backdoorKey[2], backdoorKey[3]); + kFCCOBx[2] = BYTE2WORD_1_1_1_1(backdoorKey[4], backdoorKey[5], backdoorKey[6], backdoorKey[7]); + + /* calling flash command sequence function to execute the command */ + returnCode = ftfx_command_sequence(config); + } + + return (returnCode); +} + +/*! + * @brief Returns the security state via the pointer passed into the function. + */ +status_t FTFx_REG_GetSecurityState(ftfx_config_t *config, ftfx_security_state_t *state) +{ + /* store data read from flash register */ + uint8_t registerValue; + if ((config == NULL) || (state == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Get flash security register value */ + registerValue = FTFx->FSEC; + + /* check the status of the flash security bits in the security register */ + if ((uint8_t)kFTFx_FsecRegCode_SEC_Unsecured == (registerValue & FTFx_FSEC_SEC_MASK)) + { + /* Flash in unsecured state */ + *state = kFTFx_SecurityStateNotSecure; + } + else + { + /* Flash in secured state + * check for backdoor key security enable bit */ + if ((uint8_t)kFTFx_FsecRegCode_KEYEN_Enabled == (registerValue & FTFx_FSEC_KEYEN_MASK)) + { + /* Backdoor key security enabled */ + *state = kFTFx_SecurityStateBackdoorEnabled; + } + else + { + /* Backdoor key security disabled */ + *state = kFTFx_SecurityStateBackdoorDisabled; + } + } + + return kStatus_FTFx_Success; +} + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! + * @brief Sets the FlexRAM function command. + */ +status_t FTFx_CMD_SetFlexramFunction(ftfx_config_t *config, ftfx_flexram_func_opt_t option) +{ + status_t status; + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + status = ftfx_check_flexram_function_option(option); + if (kStatus_FTFx_Success != status) + { + return status; + } + + /* preparing passing parameter to verify all block command */ + kFCCOBx[0] = BYTE2WORD_1_1_2(FTFx_SET_FLEXRAM_FUNCTION, option, 0xFFFFU); + + /* calling flash command sequence function to execute the command */ + return ftfx_command_sequence(config); +} +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! + * @brief Configures the Swap function or checks the swap state of the Flash module. + */ +status_t FTFx_CMD_SwapControl(ftfx_config_t *config, + uint32_t address, + ftfx_swap_control_opt_t option, + ftfx_swap_state_config_t *returnInfo) +{ + status_t returnCode; + + if ((config == NULL) || (returnInfo == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + if ((address & ((uint32_t)FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT - 1u)) != 0U) + { + return kStatus_FTFx_AlignmentError; + } + + /* Make sure address provided is in the lower half of Program flash but not in the Flash Configuration Field */ + if ((address >= (config->flashDesc.totalSize / 2u)) || + ((address >= (uint32_t)kFTFx_PflashConfigAreaStart) && (address <= (uint32_t)kFTFx_PflashConfigAreaEnd))) + { + return kStatus_FTFx_SwapIndicatorAddressError; + } + + /* Checking the option. */ + returnCode = ftfx_check_swap_control_option(option); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + kFCCOBx[0] = BYTE2WORD_1_3(FTFx_SWAP_CONTROL, address); + kFCCOBx[1] = BYTE2WORD_1_3(option, 0xFFFFFFU); + + returnCode = ftfx_command_sequence(config); + + returnInfo->flashSwapState = (ftfx_swap_state_t)FTFx_FCCOB5_REG; + returnInfo->currentSwapBlockStatus = (ftfx_swap_block_status_t)FTFx_FCCOB6_REG; + returnInfo->nextSwapBlockStatus = (ftfx_swap_block_status_t)FTFx_FCCOB7_REG; + + return returnCode; +} +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + +static void ftfx_init_ifr(ftfx_config_t *config) +{ +#if FSL_FEATURE_FLASH_IS_FTFA + /* FTFA parts(eg. K80, KL80, L5K) support both 4-bytes and 8-bytes unit size */ + config->ifrDesc.feature.has4ByteIdxSupport = 1U; + config->ifrDesc.feature.has8ByteIdxSupport = 1U; + config->ifrDesc.idxInfo.mix8byteIdxStart = 0x10U; + config->ifrDesc.idxInfo.mix8byteIdxEnd = 0x13U; +#elif FSL_FEATURE_FLASH_IS_FTFE + /* FTFE parts(eg. K65, KE18) only support 8-bytes unit size */ + config->ifrDesc.feature.has4ByteIdxSupport = 0U; + config->ifrDesc.feature.has8ByteIdxSupport = 1U; +#elif FSL_FEATURE_FLASH_IS_FTFL + /* FTFL parts(eg. K20) only support 4-bytes unit size */ + config->ifrDesc.feature.has4ByteIdxSupport = 1U; + config->ifrDesc.feature.has8ByteIdxSupport = 0U; +#endif + + config->ifrDesc.resRange.pflashIfrStart = 0x0000U; + config->ifrDesc.resRange.versionIdSize = 0x08U; +#if FSL_FEATURE_FLASH_IS_FTFE + config->ifrDesc.resRange.versionIdStart = 0x08U; + config->ifrDesc.resRange.ifrMemSize = 0x0400U; +#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA = =1 */ + config->ifrDesc.resRange.versionIdStart = 0x00U; + config->ifrDesc.resRange.ifrMemSize = 0x0100U; +#endif + +#if FSL_FEATURE_FLASH_HAS_FLEX_NVM + config->ifrDesc.resRange.dflashIfrStart = 0x800000U; +#endif + +#if FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +#if FSL_FEATURE_FLASH_IS_FTFE + config->ifrDesc.resRange.pflashSwapIfrStart = 0x40000U; +#else /* FSL_FEATURE_FLASH_IS_FTFL == 1 or FSL_FEATURE_FLASH_IS_FTFA == 1 */ + config->ifrDesc.resRange.pflashSwapIfrStart = config->flashDesc.totalSize / 4; +#endif +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ +} + +#if FTFx_DRIVER_IS_FLASH_RESIDENT +/*! + * @brief Copy PIC of flash_run_command() to RAM + */ +static void ftfx_copy_run_command_to_ram(uint32_t *ftfxRunCommand) +{ + assert(sizeof(s_ftfxRunCommandFunctionCode) <= ((uint32_t)kFTFx_RamFuncMaxSizeInWords * 4U)); + + /* Since the value of ARM function pointer is always odd, but the real start address + * of function memory should be even, that's why +1 operation exist. */ + (void)memcpy(ftfxRunCommand, s_ftfxRunCommandFunctionCode, sizeof(s_ftfxRunCommandFunctionCode)); +} +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + +/*! + * @brief FTFx Command Sequence + * + * This function is used to perform the command write sequence to the flash. + * + * @param driver Pointer to storage for the driver runtime state. + * @return An error code or kStatus_FTFx_Success + */ +static status_t ftfx_command_sequence(ftfx_config_t *config) +{ + uint8_t registerValue; + +#if FTFx_DRIVER_IS_FLASH_RESIDENT + /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ + FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; + + /* Since the value of ARM function pointer is always odd, but the real start address + * of function memory should be even, that's why +1 operation exist. */ + config->runCmdFuncAddr.commadAddr += 1UL; + callFtfxRunCommand_t callFtfxRunCommand = config->runCmdFuncAddr.callFlashCommand; + + /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using + * pre-processed MICRO sentences or operating global variable in flash_run_comamnd() + * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */ + callFtfxRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); + config->runCmdFuncAddr.commadAddr -= 1UL; +#else + /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ + FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; + + /* clear CCIF bit */ + FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK; + + /* Check CCIF bit of the flash status register, wait till it is set. + * IP team indicates that this loop will always complete. */ + while (!(FTFx->FSTAT & FTFx_FSTAT_CCIF_MASK)) + { + } +#endif /* FTFx_DRIVER_IS_FLASH_RESIDENT */ + + /* Check error bits */ + /* Get flash status register value */ + registerValue = FTFx->FSTAT; + + /* checking access error */ + if (0U != (registerValue & FTFx_FSTAT_ACCERR_MASK)) + { + return kStatus_FTFx_AccessError; + } + /* checking protection error */ + else if (0U != (registerValue & FTFx_FSTAT_FPVIOL_MASK)) + { + return kStatus_FTFx_ProtectionViolation; + } + /* checking MGSTAT0 non-correctable error */ + else if (0U != (registerValue & FTFx_FSTAT_MGSTAT0_MASK)) + { + return kStatus_FTFx_CommandFailure; + } + else + { + return kStatus_FTFx_Success; + } +} + +static void ftfx_command_sequence_non_blocking(ftfx_config_t *config) +{ +#if FTFx_DRIVER_IS_FLASH_RESIDENT + /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ + FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; + + /* Since the value of ARM function pointer is always odd, but the real start address + * of function memory should be even, that's why +1 operation exist. */ + config->runCmdFuncAddr.commadAddr += 1UL; + callFtfxRunCommand_t callFtfxRunCommand = config->runCmdFuncAddr.callFlashCommand; + + /* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using + * pre-processed MICRO sentences or operating global variable in flash_run_comamnd() + * to make sure that flash_run_command() will be compiled into position-independent code (PIC). */ + callFtfxRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); + config->runCmdFuncAddr.commadAddr -= 1UL; +#else + /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ + FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; + + /* clear CCIF bit */ + FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK; +#endif +} + +/*! @brief Validates the range and alignment of the given address range.*/ +static status_t ftfx_check_mem_range(ftfx_config_t *config, + uint32_t startAddress, + uint32_t lengthInBytes, + uint8_t alignmentBaseline) +{ + status_t status = kStatus_FTFx_AddressError; + + /* Verify the start and length are alignmentBaseline aligned. */ + if ((0U != (startAddress & (uint8_t)(alignmentBaseline - 1U))) || + (0U != (lengthInBytes & (uint8_t)(alignmentBaseline - 1U)))) + { + return kStatus_FTFx_AlignmentError; + } + + /* check for valid range of the target addresses */ + if ((startAddress >= config->flashDesc.blockBase) && + ((startAddress + lengthInBytes) <= (config->flashDesc.blockBase + config->flashDesc.totalSize))) + { + status = kStatus_FTFx_Success; + } +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS) && FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS + else if ((startAddress >= config->flashDesc.aliasBlockBase) && + ((startAddress + lengthInBytes) <= (config->flashDesc.aliasBlockBase + config->flashDesc.totalSize))) + { + status = kStatus_FTFx_Success; + } + else + { + status = kStatus_FTFx_AddressError; + } +#endif + + return status; +} + +/*! @brief Validates the given user key for flash erase APIs.*/ +static status_t ftfx_check_user_key(uint32_t key) +{ + /* Validate the user key */ + if (key != (uint32_t)kFTFx_ApiEraseKey) + { + return kStatus_FTFx_EraseKeyError; + } + + return kStatus_FTFx_Success; +} + +/*! @brief Reads word from byte address.*/ +static uint32_t ftfx_read_word_from_byte_address(const uint8_t *src) +{ + uint32_t word = 0U; + const uint8_t *readsrc = src; + /* If the source address is aligned with 4 bytes */ + if (0U == ((uint32_t)readsrc % 4U)) + { + word = *(const uint32_t *)(uint32_t)readsrc; + } + /* Read 4 bytes from a non-4-byte aligned address, 1 byte one time */ + else + { + for (uint32_t i = 0U; i < 4U; i++) + { + word |= (uint32_t)(*readsrc) << (i * 8U); + readsrc++; + } + } + + return word; +} + +/*! @brief Writes word to byte address.*/ +static void ftfx_write_word_to_byte_address(uint8_t *dst, uint32_t word) +{ + uint8_t *writedst = dst; + /* If the source address is aligned with 4 bytes */ + if (0U == ((uint32_t)writedst % 4U)) + { + *(uint32_t *)(uint32_t)writedst = word; + } + else + { + /* Write 4 bytes into a non-4-byte aligned address memory, 1 byte one time */ + for (uint32_t i = 0U; i < 4U; i++) + { + *writedst = (uint8_t)((word >> (i * 8U)) & 0xFFU); + writedst++; + } + } +} + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! @brief Validates the range of the given resource address.*/ +static status_t ftfx_check_resource_range(ftfx_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + uint32_t alignmentBaseline, + ftfx_read_resource_opt_t option) +{ + status_t status; + uint32_t maxReadbleAddress; + + if ((0U != (start & (alignmentBaseline - 1u))) || (0U != (lengthInBytes & (alignmentBaseline - 1u)))) + { + return kStatus_FTFx_AlignmentError; + } + + status = kStatus_FTFx_Success; + + maxReadbleAddress = start + lengthInBytes - 1u; + /* read resource code from the version ID field */ + if (option == kFTFx_ResourceOptionVersionId) + { + if ((start != config->ifrDesc.resRange.versionIdStart) || + (lengthInBytes != config->ifrDesc.resRange.versionIdSize)) + { + status = kStatus_FTFx_InvalidArgument; + } + } + else if (option == kFTFx_ResourceOptionFlashIfr) + { + /* read resource code from the program flash IFR space */ + if ((start >= config->ifrDesc.resRange.pflashIfrStart) && + (maxReadbleAddress < (config->ifrDesc.resRange.pflashIfrStart + config->ifrDesc.resRange.ifrMemSize))) + { + } +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM) && FSL_FEATURE_FLASH_HAS_FLEX_NVM + /* read resource code from the date flash IFR space */ + else if ((start >= config->ifrDesc.resRange.dflashIfrStart) && + (maxReadbleAddress < (config->ifrDesc.resRange.dflashIfrStart + config->ifrDesc.resRange.ifrMemSize))) + { + } +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD + /* read resource code from the Program Flash Swap IFR space */ + else if ((start >= config->ifrDesc.resRange.pflashSwapIfrStart) && + (maxReadbleAddress < + (config->ifrDesc.resRange.pflashSwapIfrStart + config->ifrDesc.resRange.ifrMemSize))) + { + } +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + else + { + status = kStatus_FTFx_InvalidArgument; + } + } + else + { + status = kStatus_FTFx_InvalidArgument; + } + + return status; +} +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! @brief Validates the given flexram function option.*/ +static inline status_t ftfx_check_flexram_function_option(ftfx_flexram_func_opt_t option) +{ + if ((option != kFTFx_FlexramFuncOptAvailableAsRam) && (option != kFTFx_FlexramFuncOptAvailableForEeprom)) + { + return kStatus_FTFx_InvalidArgument; + } + + return kStatus_FTFx_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! @brief Validates the given swap control option.*/ +static status_t ftfx_check_swap_control_option(ftfx_swap_control_opt_t option) +{ + if ((option == kFTFx_SwapControlOptionIntializeSystem) || (option == kFTFx_SwapControlOptionSetInUpdateState) || + (option == kFTFx_SwapControlOptionSetInCompleteState) || (option == kFTFx_SwapControlOptionReportStatus) || + (option == kFTFx_SwapControlOptionDisableSystem)) + { + return kStatus_FTFx_Success; + } + + return kStatus_FTFx_InvalidArgument; +} +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.h new file mode 100644 index 0000000..de5d651 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_controller.h @@ -0,0 +1,846 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_CONTROLLER_H +#define FSL_FTFX_CONTROLLER_H + +#include "fsl_ftfx_features.h" +#include "fsl_ftfx_utilities.h" + +/*! + * @addtogroup ftfx_controller + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @name FTFx status + * @{ + */ +/*! @brief FTFx driver status group. */ +#if defined(kStatusGroup_FlashDriver) +#define kStatusGroupGeneric kStatusGroup_Generic +#define kStatusGroupFtfxDriver kStatusGroup_FlashDriver +#elif defined(kStatusGroup_FLASH) +#define kStatusGroupGeneric kStatusGroup_Generic +#define kStatusGroupFtfxDriver kStatusGroup_FLASH +#else +#define kStatusGroupGeneric 0 +#define kStatusGroupFtfxDriver 1 +#endif + +/*! + * @brief FTFx driver status codes. + */ +enum +{ + kStatus_FTFx_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< API is executed successfully*/ + kStatus_FTFx_InvalidArgument = MAKE_STATUS(kStatusGroupGeneric, 4), /*!< Invalid argument*/ + kStatus_FTFx_SizeError = MAKE_STATUS(kStatusGroupFtfxDriver, 0), /*!< Error size*/ + kStatus_FTFx_AlignmentError = + MAKE_STATUS(kStatusGroupFtfxDriver, 1), /*!< Parameter is not aligned with the specified baseline*/ + kStatus_FTFx_AddressError = MAKE_STATUS(kStatusGroupFtfxDriver, 2), /*!< Address is out of range */ + kStatus_FTFx_AccessError = + MAKE_STATUS(kStatusGroupFtfxDriver, 3), /*!< Invalid instruction codes and out-of bound addresses */ + kStatus_FTFx_ProtectionViolation = MAKE_STATUS( + kStatusGroupFtfxDriver, 4), /*!< The program/erase operation is requested to execute on protected areas */ + kStatus_FTFx_CommandFailure = + MAKE_STATUS(kStatusGroupFtfxDriver, 5), /*!< Run-time error during command execution. */ + kStatus_FTFx_UnknownProperty = MAKE_STATUS(kStatusGroupFtfxDriver, 6), /*!< Unknown property.*/ + kStatus_FTFx_EraseKeyError = MAKE_STATUS(kStatusGroupFtfxDriver, 7), /*!< API erase key is invalid.*/ + kStatus_FTFx_RegionExecuteOnly = MAKE_STATUS(kStatusGroupFtfxDriver, 8), /*!< The current region is execute-only.*/ + kStatus_FTFx_ExecuteInRamFunctionNotReady = + MAKE_STATUS(kStatusGroupFtfxDriver, 9), /*!< Execute-in-RAM function is not available.*/ + kStatus_FTFx_PartitionStatusUpdateFailure = + MAKE_STATUS(kStatusGroupFtfxDriver, 10), /*!< Failed to update partition status.*/ + kStatus_FTFx_SetFlexramAsEepromError = + MAKE_STATUS(kStatusGroupFtfxDriver, 11), /*!< Failed to set FlexRAM as EEPROM.*/ + kStatus_FTFx_RecoverFlexramAsRamError = + MAKE_STATUS(kStatusGroupFtfxDriver, 12), /*!< Failed to recover FlexRAM as RAM.*/ + kStatus_FTFx_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFtfxDriver, 13), /*!< Failed to set FlexRAM as RAM.*/ + kStatus_FTFx_RecoverFlexramAsEepromError = + MAKE_STATUS(kStatusGroupFtfxDriver, 14), /*!< Failed to recover FlexRAM as EEPROM.*/ + kStatus_FTFx_CommandNotSupported = MAKE_STATUS(kStatusGroupFtfxDriver, 15), /*!< Flash API is not supported.*/ + kStatus_FTFx_SwapSystemNotInUninitialized = + MAKE_STATUS(kStatusGroupFtfxDriver, 16), /*!< Swap system is not in an uninitialzed state.*/ + kStatus_FTFx_SwapIndicatorAddressError = + MAKE_STATUS(kStatusGroupFtfxDriver, 17), /*!< The swap indicator address is invalid.*/ + kStatus_FTFx_ReadOnlyProperty = MAKE_STATUS(kStatusGroupFtfxDriver, 18), /*!< The flash property is read-only.*/ + kStatus_FTFx_InvalidPropertyValue = + MAKE_STATUS(kStatusGroupFtfxDriver, 19), /*!< The flash property value is out of range.*/ + kStatus_FTFx_InvalidSpeculationOption = + MAKE_STATUS(kStatusGroupFtfxDriver, 20), /*!< The option of flash prefetch speculation is invalid.*/ + kStatus_FTFx_CommandOperationInProgress = + MAKE_STATUS(kStatusGroupFtfxDriver, 21), /*!< The option of flash command is processing.*/ +}; +/*@}*/ + +/*! + * @name FTFx API key + * @{ + */ +/*! + * @brief Enumeration for FTFx driver API keys. + * + * @note The resulting value is built with a byte order such that the string + * being readable in expected order when viewed in a hex editor, if the value + * is treated as a 32-bit little endian value. + */ +enum _ftfx_driver_api_keys +{ + kFTFx_ApiEraseKey = FOUR_CHAR_CODE('k', 'f', 'e', 'k') /*!< Key value used to validate all FTFx erase APIs.*/ +}; +/*@}*/ + +/*! + * @brief Enumeration for the FlexRAM load during reset option. + */ +typedef enum _ftfx_partition_flexram_load_option +{ + kFTFx_PartitionFlexramLoadOptLoadedWithValidEepromData = + 0x00U, /*!< FlexRAM is loaded with valid EEPROM data during reset sequence.*/ + kFTFx_PartitionFlexramLoadOptNotLoaded = 0x01U /*!< FlexRAM is not loaded during reset sequence.*/ +} ftfx_partition_flexram_load_opt_t; + +/*! + * @brief Enumeration for the two possible options of flash read resource command. + */ +typedef enum _ftfx_read_resource_opt +{ + kFTFx_ResourceOptionFlashIfr = + 0x00U, /*!< Select code for Program flash 0 IFR, Program flash swap 0 IFR, Data flash 0 IFR */ + kFTFx_ResourceOptionVersionId = 0x01U /*!< Select code for the version ID*/ +} ftfx_read_resource_opt_t; + +/*! + * @brief Enumeration for supported FTFx margin levels. + */ +typedef enum _ftfx_margin_value +{ + kFTFx_MarginValueNormal, /*!< Use the 'normal' read level for 1s.*/ + kFTFx_MarginValueUser, /*!< Apply the 'User' margin to the normal read-1 level.*/ + kFTFx_MarginValueFactory, /*!< Apply the 'Factory' margin to the normal read-1 level.*/ + kFTFx_MarginValueInvalid /*!< Not real margin level, Used to determine the range of valid margin level. */ +} ftfx_margin_value_t; + +/*! + * @brief Enumeration for the three possible FTFx security states. + */ +typedef enum _ftfx_security_state +{ + kFTFx_SecurityStateNotSecure = (int)0xc33cc33cu, /*!< Flash is not secure.*/ + kFTFx_SecurityStateBackdoorEnabled = (int)0x5aa55aa5u, /*!< Flash backdoor is enabled.*/ + kFTFx_SecurityStateBackdoorDisabled = (int)0x5ac33ca5u /*!< Flash backdoor is disabled.*/ +} ftfx_security_state_t; + +/*! + * @brief Enumeration for the two possilbe options of set FlexRAM function command. + */ +typedef enum _ftfx_flexram_function_option +{ + kFTFx_FlexramFuncOptAvailableAsRam = 0xFFU, /*!< An option used to make FlexRAM available as RAM */ + kFTFx_FlexramFuncOptAvailableForEeprom = 0x00U /*!< An option used to make FlexRAM available for EEPROM */ +} ftfx_flexram_func_opt_t; + +/*! + * @brief Enumeration for acceleration ram property. + */ +enum _flash_acceleration_ram_property +{ + kFLASH_AccelerationRamSize = 0x400U +}; + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! + * @brief Enumeration for the possible options of Swap control commands + */ +typedef enum _ftfx_swap_control_option +{ + kFTFx_SwapControlOptionIntializeSystem = 0x01U, /*!< An option used to initialize the Swap system */ + kFTFx_SwapControlOptionSetInUpdateState = 0x02U, /*!< An option used to set the Swap in an update state */ + kFTFx_SwapControlOptionSetInCompleteState = 0x04U, /*!< An option used to set the Swap in a complete state */ + kFTFx_SwapControlOptionReportStatus = 0x08U, /*!< An option used to report the Swap status */ + kFTFx_SwapControlOptionDisableSystem = 0x10U /*!< An option used to disable the Swap status */ +} ftfx_swap_control_opt_t; +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + +/*! + * @brief Enumeration for the possible flash Swap status. + */ +typedef enum _ftfx_swap_state +{ + kFTFx_SwapStateUninitialized = 0x00U, /*!< Flash Swap system is in an uninitialized state.*/ + kFTFx_SwapStateReady = 0x01U, /*!< Flash Swap system is in a ready state.*/ + kFTFx_SwapStateUpdate = 0x02U, /*!< Flash Swap system is in an update state.*/ + kFTFx_SwapStateUpdateErased = 0x03U, /*!< Flash Swap system is in an updateErased state.*/ + kFTFx_SwapStateComplete = 0x04U, /*!< Flash Swap system is in a complete state.*/ + kFTFx_SwapStateDisabled = 0x05U /*!< Flash Swap system is in a disabled state.*/ +} ftfx_swap_state_t; + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! + * @brief Enumeration for the possible flash Swap block status + */ +typedef enum _ftfx_swap_block_status +{ + kFTFx_SwapBlockStatusLowerHalfProgramBlocksAtZero = + 0x00U, /*!< Swap block status is that lower half program block at zero.*/ + kFTFx_SwapBlockStatusUpperHalfProgramBlocksAtZero = + 0x01U, /*!< Swap block status is that upper half program block at zero.*/ +} ftfx_swap_block_status_t; + +/*! + * @brief Flash Swap information + */ +typedef struct _ftfx_swap_state_config +{ + ftfx_swap_state_t flashSwapState; /*! +#include +#include "fsl_device_registers.h" +#include "bootloader_common.h" +#else +#include "fsl_common.h" +#endif + +#include "fsl_ftfx_adapter.h" + +/*! + * @addtogroup ftfx_feature + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @name FTFx configuration + * @{ + */ +/*! @brief Flash driver location. */ +#if !defined(FTFx_DRIVER_IS_FLASH_RESIDENT) +#if (!defined(BL_TARGET_ROM) && !defined(BL_TARGET_RAM)) +#define FTFx_DRIVER_IS_FLASH_RESIDENT 1U /*!< Used for the flash resident application. */ +#else +#define FTFx_DRIVER_IS_FLASH_RESIDENT 0U /*!< Used for the non-flash resident application. */ +#endif +#endif + +/*! @brief Flash Driver Export option */ +#if !defined(FTFx_DRIVER_IS_EXPORTED) +#if defined(BL_TARGET_ROM) +#define FTFx_DRIVER_IS_EXPORTED 1U /*!< Used for the ROM bootloader. */ +#else +#define FTFx_DRIVER_IS_EXPORTED 0U /*!< Used for the MCUXpresso SDK application. */ +#endif +#endif +/*@}*/ + +/*! @brief Indicates whether the secondary flash is supported in the Flash driver */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) || defined(FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS) +#define FTFx_DRIVER_HAS_FLASH1_SUPPORT (1U) +#define FTFx_FLASH_COUNT (2U) +#else +#define FTFx_DRIVER_HAS_FLASH1_SUPPORT (0U) +#define FTFx_FLASH_COUNT (1U) +#endif + +/*! + * @name Secondary flash configuration + * @{ + */ +/*! @brief Indicates whether the secondary flash has its own protection register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FPROTS_PROTS_MASK) +#define FTFx_FLASH1_HAS_PROT_CONTROL (1U) +#else +#define FTFx_FLASH1_HAS_PROT_CONTROL (0U) +#endif + +/*! @brief Indicates whether the secondary flash has its own Execute-Only access register in flash module. */ +#if defined(FSL_FEATURE_FLASH_HAS_MULTIPLE_FLASH) && defined(FTFE_FACSSS_SGSIZE_S_MASK) +#define FTFx_FLASH1_HAS_XACC_CONTROL (1U) +#else +#define FTFx_FLASH1_HAS_XACC_CONTROL (0U) +#endif +/*@}*/ + +#if FTFx_FLASH1_HAS_XACC_CONTROL || FTFx_FLASH1_HAS_PROT_CONTROL +#define FTFx_FLASH1_IS_INDEPENDENT_BLOCK (1U) +#else +#define FTFx_FLASH1_IS_INDEPENDENT_BLOCK (0U) +#endif + +/*! @}*/ + +#endif /* FSL_FTFX_FEATURES_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.c b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.c new file mode 100644 index 0000000..4b19c10 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.c @@ -0,0 +1,1544 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "fsl_ftfx_flash.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.flash" +#endif + +/*! + * @brief Enumeration for special memory property. + */ +enum _ftfx_special_mem_property +{ + kFTFx_AccessSegmentUnitSize = 256UL, + kFTFx_MinProtectBlockSize = 1024UL, +}; + +#if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD +/*! + * @brief Enumeration for the index of read/program once record + */ +enum _k3_flash_read_once_index +{ + kFLASH_RecordIndexSwapAddr = 0xA1U, /*!< Index of Swap indicator address.*/ + kFLASH_RecordIndexSwapEnable = 0xA2U, /*!< Index of Swap system enable.*/ + kFLASH_RecordIndexSwapDisable = 0xA3U, /*!< Index of Swap system disable.*/ +}; +#endif /* FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD */ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! @brief init flash features */ +static void flash_init_features(ftfx_config_t *config); + +/*! @brief init protection feature */ +static void flash_protection_init(flash_config_t *config, uint8_t flashIndex); + +/*! @brief init access segment feature */ +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +static void flash_access_init(flash_config_t *config, uint8_t flashIndex); +#endif + +/*! @brief init flash operation config */ +static void flash_opsonfig_Init(flash_config_t *config, uint8_t flashIndex); + +/*! @brief Calculate flash memory size based on given parameter */ +static uint32_t flash_calculate_mem_size(uint32_t pflashBlockCount, + uint32_t pflashBlockSize, + uint32_t pfsizeMask, + uint32_t pfsizeShift); + +static uint32_t flash_calculate_prot_segment_size(uint32_t flashSize, uint32_t segmentCount); + +/*! @brief Validates the given address to get current flash index */ +static status_t flash_check_range_to_get_index(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + uint8_t *flashIndex); + +/*! @brief Decide whether to convert the start address from primary flash to secondary flash based on the current start + * address*/ +static void flash_convert_start_address(ftfx_config_t *config, uint32_t start); + +#if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP +/*! @brief Validates the given address to see if it is equal to swap indicator address in pflash swap IFR.*/ +static status_t flash_validate_swap_indicator_address(ftfx_config_t *config, uint32_t address); +#endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +static volatile uint32_t *const kFPROTL = (volatile uint32_t *)(uint32_t)&FTFx_FPROT_LOW_REG; +#if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG +static volatile uint32_t *const kFPROTH = (volatile uint32_t *)(uint32_t)&FTFx_FPROT_HIGH_REG; +#endif /* FTFx_FLASH0_HAS_HIGH_PROT_REG */ +#if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG +volatile uint8_t *const kFPROTSL = (volatile uint8_t *)(uint32_t)&FTFx_FPROTSL_REG; +volatile uint8_t *const kFPROTSH = (volatile uint8_t *)(uint32_t)&FTFx_FPROTSH_REG; +#endif /* FTFx_FLASH1_HAS_INT_PROT_REG */ + +/*! + * @brief Table of pflash sizes. + * + * The index into this table is the value of the SIM_FCFG1.PFSIZE bitfield. + * + * The values in this table have been right shifted 10 bits so that they will all fit within + * an 16-bit integer. To get the actual flash density, you must left shift the looked up value + * by 10 bits. + * + * Elements of this table have a value of 0 in cases where the PFSIZE bitfield value is + * reserved. + * + * Code to use the table: + * @code + * uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; + * flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + * @endcode + */ +#if defined(FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION) && (FSL_FEATURE_FLASH_SIZE_ENCODING_RULE_VERSION == 1) +static const uint16_t kPFlashDensities[] = { + 0u, /* 0x0 - undefined */ + 0u, /* 0x1 - undefined */ + 0u, /* 0x2 - undefined */ + 0u, /* 0x3 - undefined */ + 0u, /* 0x4 - undefined */ + 0u, /* 0x5 - undefined */ + 0u, /* 0x6 - undefined */ + 0u, /* 0x7 - undefined */ + 0u, /* 0x8 - undefined */ + 0u, /* 0x9 - undefined */ + 256u, /* 0xa - 262144, 256KB */ + 0u, /* 0xb - undefined */ + 1024u, /* 0xc - 1048576, 1MB */ + 0u, /* 0xd - undefined */ + 0u, /* 0xe - undefined */ + 0u, /* 0xf - undefined */ +}; +#else +static const uint16_t kPFlashDensities[] = { + 8u, /* 0x0 - 8192, 8KB */ + 16u, /* 0x1 - 16384, 16KB */ + 24u, /* 0x2 - 24576, 24KB */ + 32u, /* 0x3 - 32768, 32KB */ + 48u, /* 0x4 - 49152, 48KB */ + 64u, /* 0x5 - 65536, 64KB */ + 96u, /* 0x6 - 98304, 96KB */ + 128u, /* 0x7 - 131072, 128KB */ + 192u, /* 0x8 - 196608, 192KB */ + 256u, /* 0x9 - 262144, 256KB */ + 384u, /* 0xa - 393216, 384KB */ + 512u, /* 0xb - 524288, 512KB */ + 768u, /* 0xc - 786432, 768KB */ + 1024u, /* 0xd - 1048576, 1MB */ + 1536u, /* 0xe - 1572864, 1.5MB */ + /* 2048u, 0xf - 2097152, 2MB */ +}; +#endif + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * @brief Initializes the global flash properties structure members. + * + * This function checks and initializes the Flash module for the other Flash APIs. + * + * @param config Pointer to the storage for the driver runtime state. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLASH_Init(flash_config_t *config) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + for (uint8_t flashIndex = 0U; flashIndex < FTFx_FLASH_COUNT; flashIndex++) + { + /* init flash type, kinetis has Pflash and flxnvm, pflash is often used to store executable code + * and flexnvm can be used as date flash to store user data, and can also be configured as eeprom backup space + * with flexram. + */ + config->ftfxConfig[flashIndex].flashDesc.type = (uint8_t)kFTFx_MemTypePflash; + /* init the current flash index */ + config->ftfxConfig[flashIndex].flashDesc.index = flashIndex; + /* init flash features */ + flash_init_features(&config->ftfxConfig[flashIndex]); + /* init flash Operation Config */ + flash_opsonfig_Init(config, flashIndex); + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasXaccControl)) + { + /* init access segment feature */ + flash_access_init(config, flashIndex); + } +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ +#if (FTFx_FLASH_COUNT > 1U) + if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasProtControl)) +#endif + { + /* init protection feature */ + flash_protection_init(config, flashIndex); + } + + /* Init FTFx Kernel */ + FTFx_API_Init(&config->ftfxConfig[flashIndex]); + } + + return kStatus_FTFx_Success; +} + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + * + * This function erases the appropriate number of flash sectors based on the + * desired start address and length. + * + * @param config The pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be erased. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words) + * to be erased. Must be word-aligned. + * @param key The value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the appropriate number of flash sectors based on the + * desired start address and length was erased successfully. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + * @retval #kStatus_FTFx_EraseKeyError The API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) +{ + status_t returnCode; + uint8_t flashIndex; + + /* check the supplied address range to get flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* Decide whether to convert the start address from primary flash to secondary flash based on the current address */ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + return FTFx_CMD_Erase(&config->ftfxConfig[flashIndex], start, lengthInBytes, key); +} + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + * + * This function erases one flash sector size based on the start address, and it is + * executed asynchronously. + */ +status_t FLASH_EraseSectorNonBlocking(flash_config_t *config, uint32_t start, uint32_t key) +{ + status_t returnCode; + uint8_t flashIndex; + uint32_t lengthInBytes = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + + /* check the supplied address range to get flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* Decide whether to convert the start address from primary flash to secondary flash based on the current address */ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + return FTFx_CMD_EraseSectorNonBlocking(&config->ftfxConfig[flashIndex], start, key); +} + +/*! + * @brief Erases entire flexnvm + */ +status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) +{ + return FTFx_CMD_EraseAll(&config->ftfxConfig[0], key); +} + +#if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD +/*! + * @brief Erases the entire flexnvm, including protected sectors. + */ +status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key) +{ + return FTFx_CMD_EraseAllUnsecure(&config->ftfxConfig[0], key); +} +#endif + +/*! + * @brief Programs flash with data at locations passed in through parameters. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and the length. + */ +status_t FLASH_Program(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + uint8_t flashIndex; + + /* check range to get flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + /* convert the start address from primary flash to secondary flash based on the current address */ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + /* Programs flash */ + return FTFx_CMD_Program(&config->ftfxConfig[flashIndex], start, src, lengthInBytes); +} + +/*! + * @brief Reads the Program Once Field through parameters. + */ +status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint8_t *src, uint32_t lengthInBytes) +{ + return FTFx_CMD_ProgramOnce(&config->ftfxConfig[0], index, src, lengthInBytes); +} + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD +/*! + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and length. + * + */ +status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + uint8_t flashIndex; + + /* Validates the range of the given address range and get flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* convert the start address from primary flash to secondary flash based on the current address */ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + return FTFx_CMD_ProgramSection(&config->ftfxConfig[flashIndex], start, src, lengthInBytes); +} +#endif + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! + * @brief Reads the resource with data at locations passed in through parameters. + */ +status_t FLASH_ReadResource( + flash_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option) +{ + return FTFx_CMD_ReadResource(&config->ftfxConfig[0], start, dst, lengthInBytes, option); +} +#endif + +/*! + * @brief Reads the Program Once Field through parameters. + */ +status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint8_t *dst, uint32_t lengthInBytes) +{ + return FTFx_CMD_ReadOnce(&config->ftfxConfig[0], index, dst, lengthInBytes); +} + +/*! + * @brief Verifies an erasure of the desired flash area at a specified margin level. + * + * This function checks the appropriate number of flash sectors based on + * the desired start address and length to check whether the flash is erased + * to the specified read margin level. + */ +status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, ftfx_margin_value_t margin) +{ + status_t returnCode; + uint8_t flashIndex; + + /* check range to get flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* convert the start address from primary flash to secondary flash based on the current start address*/ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + return FTFx_CMD_VerifyErase(&config->ftfxConfig[flashIndex], start, lengthInBytes, margin); +} + +/*! + * @brief Verifies erasure of the entire flash at a specified margin level. + */ +status_t FLASH_VerifyEraseAll(flash_config_t *config, ftfx_margin_value_t margin) +{ + return FTFx_CMD_VerifyEraseAll(&config->ftfxConfig[0], margin); +} + +/*! + * @brief Verifies programming of the desired flash area at a specified margin level. + * + * This function verifies the data programmed in the flash memory using the + * Flash Program Check Command and compares it to the expected data for a given + * flash area as determined by the start address and length. + */ +status_t FLASH_VerifyProgram(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + const uint8_t *expectedData, + ftfx_margin_value_t margin, + uint32_t *failedAddress, + uint32_t *failedData) +{ + status_t returnCode; + uint8_t flashIndex; + + /* Validates the given address to get current flash index */ + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + /* convert the start address from primary flash to secondary flash based on the current start address */ + flash_convert_start_address(&config->ftfxConfig[flashIndex], start); + + return FTFx_CMD_VerifyProgram(&config->ftfxConfig[flashIndex], start, lengthInBytes, expectedData, margin, + failedAddress, failedData); +} + +/*! + * @brief Returns the security state via the pointer passed into the function. + */ +status_t FLASH_GetSecurityState(flash_config_t *config, ftfx_security_state_t *state) +{ + return FTFx_REG_GetSecurityState(&config->ftfxConfig[0], state); +} + +/*! + * @brief Allows users to bypass security with a backdoor key. + */ +status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey) +{ + return FTFx_CMD_SecurityBypass(&config->ftfxConfig[0], backdoorKey); +} + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! + * @brief Sets the FlexRAM function command. + */ +status_t FLASH_SetFlexramFunction(flash_config_t *config, ftfx_flexram_func_opt_t option) +{ + return FTFx_CMD_SetFlexramFunction(&config->ftfxConfig[0], option); +} +#endif + +#if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP +/*! + * @brief Swaps the lower half flash with the higher half flash. + */ +status_t FLASH_Swap(flash_config_t *config, uint32_t address, bool isSetEnable) +{ + status_t returnCode; + ftfx_swap_state_config_t returnInfo; + ftfx_config_t *ftfxConfig; + uint8_t flashIndex; + + returnCode = flash_check_range_to_get_index(config, address, 1U, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + ftfxConfig = &config->ftfxConfig[flashIndex]; + + (void)memset(&returnInfo, 0xFF, sizeof(returnInfo)); + + do + { + returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionReportStatus, &returnInfo); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + if (!isSetEnable) + { + if (returnInfo.flashSwapState == kFTFx_SwapStateDisabled) + { + return kStatus_FTFx_Success; + } + else if (returnInfo.flashSwapState == kFTFx_SwapStateUninitialized) + { + /* The swap system changed to the DISABLED state with Program flash block 0 + * located at relative flash address 0x0_0000 */ + returnCode = + FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionDisableSystem, &returnInfo); + } + else + { + /* Swap disable should be requested only when swap system is in the uninitialized state */ + return kStatus_FTFx_SwapSystemNotInUninitialized; + } + } + else + { + /* When first swap: the initial swap state is Uninitialized, flash swap indicator address is unset, + * the swap procedure should be Uninitialized -> Update-Erased -> Complete. + * After the first swap has been completed, the flash swap inidicator address cannot be modified + * unless EraseAllBlocks command is issued, the swap procedure is changed to Update -> Update-Erased -> + * Complete. */ + switch (returnInfo.flashSwapState) + { + case kFTFx_SwapStateUninitialized: + /* If current swap mode is Uninitialized, Initialize Swap to Initialized/READY state. */ + returnCode = + FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionIntializeSystem, &returnInfo); + break; + case kFTFx_SwapStateReady: + /* Validate whether the address provided to the swap system is matched to + * swap indicator address in the IFR */ + returnCode = flash_validate_swap_indicator_address(ftfxConfig, address); + if (returnCode == kStatus_FTFx_Success) + { + /* If current swap mode is Initialized/Ready, Initialize Swap to UPDATE state. */ + returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionSetInUpdateState, + &returnInfo); + } + break; + case kFTFx_SwapStateUpdate: + /* If current swap mode is Update, Erase indicator sector in non active block + * to proceed swap system to update-erased state */ + returnCode = FLASH_Erase(config, address + (ftfxConfig->flashDesc.totalSize >> 1u), + ftfxConfig->opsConfig.addrAligment.sectorCmd, (uint32_t)kFTFx_ApiEraseKey); + break; + case kFTFx_SwapStateUpdateErased: + /* If current swap mode is Update or Update-Erased, progress Swap to COMPLETE State */ + returnCode = FTFx_CMD_SwapControl(ftfxConfig, address, kFTFx_SwapControlOptionSetInCompleteState, + &returnInfo); + break; + case kFTFx_SwapStateComplete: + break; + case kFTFx_SwapStateDisabled: + /* When swap system is in disabled state, We need to clear swap system back to uninitialized + * by issuing EraseAllBlocks command */ + returnCode = kStatus_FTFx_SwapSystemNotInUninitialized; + break; + default: + returnCode = kStatus_FTFx_InvalidArgument; + break; + } + } + if (returnCode != kStatus_FTFx_Success) + { + break; + } + } while (!((kFTFx_SwapStateComplete == returnInfo.flashSwapState) && isSetEnable)); + + return returnCode; +} +#endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ + +/*! + * @brief Returns the protection state of the desired flash area via the pointer passed into the function. + */ +status_t FLASH_IsProtected(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + flash_prot_state_t *protection_state) +{ + status_t returnCode; + ftfx_config_t *ftfxConfig; + uint8_t flashIndex; + + if (protection_state == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + ftfxConfig = &config->ftfxConfig[flashIndex]; + +#if (FTFx_FLASH_COUNT > 1U) + if (0U != (ftfxConfig->flashDesc.feature.hasProtControl)) +#endif + { + uint32_t endAddress; /* end address for protection check */ + uint32_t regionCheckedCounter; /* increments each time the flash address was checked for + * protection status */ + uint32_t regionCounter; /* incrementing variable used to increment through the flash + * protection regions */ + uint32_t protectStatusCounter; /* increments each time a flash region was detected as protected */ + uint8_t flashRegionProtectStatus[MAX_FLASH_PROT_REGION_COUNT]; /* array of the protection + * status for each + * protection region */ + for (uint32_t i = 0U; i < (uint32_t)MAX_FLASH_PROT_REGION_COUNT; + i++) /* The protection register is initialized to the */ + { /* unprotected state by default. */ + flashRegionProtectStatus[i] = (uint8_t)0xFF; /* The array is initialized to all 1 */ + } + + uint32_t + flashRegionAddress[MAX_FLASH_PROT_REGION_COUNT + 1U]; /* array of the start addresses for each flash + * protection region. Note this is REGION_COUNT+1 + * due to requiring the next start address after + * the end of flash for loop-check purposes below */ + bool isBreakNeeded = false; + /* Calculate Flash end address */ + endAddress = start + lengthInBytes; + + /* populate the flashRegionAddress array with the start address of each flash region */ + regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */ + /* populate up to 33rd element of array, this is the next address after end of flash array */ + while (regionCounter <= ftfxConfig->flashDesc.protectRegionMem.count) + { + flashRegionAddress[regionCounter] = ftfxConfig->flashDesc.protectRegionMem.base + + ftfxConfig->flashDesc.protectRegionMem.size * regionCounter; + regionCounter++; + } + + /* populate flashRegionProtectStatus array with status information + * Protection status for each region is stored in the FPROT[3:0] registers + * Each bit represents one region of flash + * 4 registers * 8-bits-per-register = 32-bits (32-regions) + * The convention is: + * FPROT3[bit 0] is the first protection region (start of flash memory) + * FPROT0[bit 7] is the last protection region (end of flash memory) + * regionCounter is used to determine which FPROT[3:0] register to check for protection status + * Note: FPROT=1 means NOT protected, FPROT=0 means protected */ + regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */ + static volatile uint32_t *const kFPROTLx = (volatile uint32_t *)(uint32_t)&FTFx_FPROTL3_REG; + +#if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG + static volatile uint32_t *const kFPROTHx = (volatile uint32_t *)(uint32_t)&FTFx_FPROTH3_REG; +#endif + +#if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG + static volatile uint16_t *const kFPROTSx = (volatile uint16_t *)(uint32_t)&FTFx_FPROTSL_REG; +#endif + while (regionCounter < ftfxConfig->flashDesc.protectRegionMem.count) + { +#if (FTFx_FLASH_COUNT > 1U) + if ((0U == ftfxConfig->flashDesc.index) || (0U != ftfxConfig->flashDesc.feature.hasIndProtReg)) +#endif + { +#if defined(MAX_FLASH_PROT_REGION_COUNT) && (MAX_FLASH_PROT_REGION_COUNT <= 32U) + if (regionCounter < (uint32_t)MAX_FLASH_PROT_REGION_COUNT) + { + flashRegionProtectStatus[regionCounter] = (uint8_t)(((kFPROTLx[0]) >> regionCounter) & 0x1U); + } +#else + if (regionCounter < 32u) + { + flashRegionProtectStatus[regionCounter] = (uint8_t)(((kFPROTLx[0]) >> regionCounter) & 0x1U); + } +#endif +#if defined(MAX_FLASH_PROT_REGION_COUNT) && (MAX_FLASH_PROT_REGION_COUNT == 64u) + else if (regionCounter < 64U) + { + flashRegionProtectStatus[regionCounter] = + (uint8_t)(((kFPROTHx[0]) >> (regionCounter - 32U)) & 0x1U); + } +#endif + else + { + isBreakNeeded = true; + } + regionCounter++; + } +#if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG + else if ((1U == ftfxConfig->flashDesc.index) && (0U != ftfxConfig->flashDesc.feature.hasIndProtReg)) + { + /* Note: So far protection region count may be 8/16 */ + if (regionCounter < 16U) + { + flashRegionProtectStatus[regionCounter] = (uint8_t)((kFPROTSx[0] >> regionCounter) & (0x01u)); + } + else + { + isBreakNeeded = true; + } + regionCounter++; + } +#endif /* FTFx_FLASH1_HAS_INT_PROT_REG */ +#if (FTFx_FLASH_COUNT > 1U) + else + { + return kStatus_FTFx_InvalidArgument; + } +#endif + if (isBreakNeeded) + { + break; + } + } + + /* loop through the flash regions and check + * desired flash address range for protection status + * loop stops when it is detected that start has exceeded the endAddress */ + regionCounter = 0U; /* make sure regionCounter is initialized to 0 first */ + regionCheckedCounter = 0U; + protectStatusCounter = 0U; /* make sure protectStatusCounter is initialized to 0 first */ + while (start < endAddress) + { + /* check to see if the address falls within this protection region + * Note that if the entire flash is to be checked, the last protection + * region checked would consist of the last protection start address and + * the start address following the end of flash */ + if ((start >= flashRegionAddress[regionCounter]) && (start < flashRegionAddress[regionCounter + 1U])) + { + /* increment regionCheckedCounter to indicate this region was checked */ + regionCheckedCounter++; + + /* check the protection status of this region + * Note: FPROT=1 means NOT protected, FPROT=0 means protected */ + if (0U == flashRegionProtectStatus[regionCounter]) + { + /* increment protectStatusCounter to indicate this region is protected */ + protectStatusCounter++; + } + start += + ftfxConfig->flashDesc.protectRegionMem.size; /* increment to an address within the next region */ + } + regionCounter++; /* increment regionCounter to check for the next flash protection region */ + } + + /* if protectStatusCounter == 0, then no region of the desired flash region is protected */ + if (protectStatusCounter == 0U) + { + *protection_state = kFLASH_ProtectionStateUnprotected; + } + /* if protectStatusCounter == regionCheckedCounter, then each region checked was protected */ + else if (protectStatusCounter == regionCheckedCounter) + { + *protection_state = kFLASH_ProtectionStateProtected; + } + /* if protectStatusCounter != regionCheckedCounter, then protection status is mixed + * In other words, some regions are protected while others are unprotected */ + else + { + *protection_state = kFLASH_ProtectionStateMixed; + } + } +#if (FTFx_FLASH_COUNT > 1U) + else + { + *protection_state = kFLASH_ProtectionStateUnprotected; + } +#endif + + return kStatus_FTFx_Success; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! + * @brief Returns the access state of the desired flash area via the pointer passed into the function. + * + * This function retrieves the current flash access status for a given + * flash area as determined by the start address and length. + */ +status_t FLASH_IsExecuteOnly(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + flash_xacc_state_t *access_state) +{ + status_t returnCode; + ftfx_config_t *ftfxConfig; + uint8_t flashIndex; + + if (access_state == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + returnCode = flash_check_range_to_get_index(config, start, lengthInBytes, &flashIndex); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + ftfxConfig = &config->ftfxConfig[flashIndex]; + + /* store the execute only segment count */ + uint32_t executeOnlySegmentCounter = 0U; + + /* Calculate end address */ + uint32_t endAddress = start + lengthInBytes; + + /* Aligning start address and end address */ + uint32_t alignedStartAddress = ALIGN_DOWN(start, ftfxConfig->flashDesc.accessSegmentMem.size); + uint32_t alignedEndAddress = ALIGN_UP(endAddress, ftfxConfig->flashDesc.accessSegmentMem.size); + + uint32_t u32flag = 1U; + uint32_t segmentIndex = 0U; + + /* Calculate the execute only segment Count */ + uint32_t maxSupportedExecuteOnlySegmentCount = + (alignedEndAddress - alignedStartAddress) / ftfxConfig->flashDesc.accessSegmentMem.size; + + while (start < endAddress) + { + uint32_t xacc = 0U; + bool isInvalidSegmentIndex = false; + + /* Calculate which segmentIndex the address is in */ + segmentIndex = + (start - ftfxConfig->flashDesc.accessSegmentMem.base) / ftfxConfig->flashDesc.accessSegmentMem.size; + + if ((0U == ftfxConfig->flashDesc.index) || (0U != ftfxConfig->flashDesc.feature.hasIndXaccReg)) + { + /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size. + */ + if (segmentIndex < 32U) + { + xacc = *(const volatile uint32_t *)(uint32_t)&FTFx_XACCL3_REG; + } + else if (segmentIndex < ftfxConfig->flashDesc.accessSegmentMem.count) + { + xacc = *(const volatile uint32_t *)(uint32_t)&FTFx_XACCH3_REG; + segmentIndex -= 32U; + } + else + { + isInvalidSegmentIndex = true; + } + } +#if defined(FTFx_FLASH1_HAS_INT_XACC_REG) && FTFx_FLASH1_HAS_INT_XACC_REG + else if ((ftfxConfig->flashDesc.index == 1U) && (0u != ftfxConfig->flashDesc.feature.hasIndXaccReg)) + { + /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size. + */ + if (segmentIndex < 8U) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG; + } + else if (segmentIndex < ftfxConfig->flashDesc.accessSegmentMem.count) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG; + segmentIndex -= 8U; + } + else + { + isInvalidSegmentIndex = true; + } + } +#endif + else + { + return kStatus_FTFx_InvalidArgument; + } + + if (isInvalidSegmentIndex) + { + break; + } + + /* Determine if this address range is in a execute-only protection flash segment. */ + if (0U != ((~xacc) & (u32flag << segmentIndex))) + { + executeOnlySegmentCounter++; + } + /* Calculate tne next start address */ + start += ftfxConfig->flashDesc.accessSegmentMem.size; + } + + if (executeOnlySegmentCounter < 1u) + { + *access_state = kFLASH_AccessStateUnLimited; + } + else if (executeOnlySegmentCounter < maxSupportedExecuteOnlySegmentCount) + { + *access_state = kFLASH_AccessStateMixed; + } + else + { + *access_state = kFLASH_AccessStateExecuteOnly; + } + + return kStatus_FTFx_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +/*! + * @brief Sets the PFlash Protection to the intended protection status. + * + * @param config A pointer to storage for the driver runtime state. + * @param protectStatus The expected protect status to set to the PFlash protection register. Each bit is + * corresponding to protection of 1/32(64) of the total PFlash. The least significant bit is corresponding to the lowest + * address area of PFlash. The most significant bit is corresponding to the highest address area of PFlash. There are + * two possible cases as shown below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + */ +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus) +{ + if ((config == NULL) || (protectStatus == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Most boards support program flash protect feature, The FPROT registers + * define which program flash regions are protected from program and erase operations. + * Protected flash regions cannot have their content changed; + * that is, these regions cannot be programmed and cannot be erased by any flash command + */ +#if (FTFx_FLASH_COUNT > 1U) + if (0U != (config->ftfxConfig[0].flashDesc.feature.hasProtControl)) +#endif + { + if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits >= 32U) + { + /* set PFlash protection register, unprotected regions are marked with a 1 and + * setting PFlash protection register, unprotected regions are marked with a 1 and + * protected regions use a 0; each bit of FPROT register can only be changed from 1s to 0s + * while all bits with 0s to 1s transitions are ignored. + */ + *kFPROTL = protectStatus->protl; + if (protectStatus->protl != *kFPROTL) + { + return kStatus_FTFx_CommandFailure; + } + } +#if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG + /* For primary flash with eight PROT registers allow up to 64 protected segments of equal memory size. */ + if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 64U) + { + *kFPROTH = protectStatus->proth; + if (protectStatus->proth != *kFPROTH) + { + return kStatus_FTFx_CommandFailure; + } + } +#endif + } +#if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG + else if ((0U != config->ftfxConfig[1].flashDesc.feature.hasProtControl) && + (0U != config->ftfxConfig[1].flashDesc.feature.hasIndProtReg)) + { + /* For secondary flash with two FPROT registers allow up to 16 protected segments of equal memory size. */ + if (config->ftfxConfig[1].flashDesc.feature.ProtRegBits == 16U) + { + *kFPROTSL = protectStatus->protsl; + if (protectStatus->protsl != *kFPROTSL) + { + return kStatus_FTFx_CommandFailure; + } + *kFPROTSH = protectStatus->protsh; + if (protectStatus->protsh != *kFPROTSH) + { + return kStatus_FTFx_CommandFailure; + } + } + } +#endif +#if (FTFx_FLASH_COUNT > 1U) + else + { + /*do nothing*/ + } +#endif + + return kStatus_FTFx_Success; +} + +/*! + * @brief Gets the PFlash protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus Protect status returned by the PFlash IP. Each bit is corresponding to the protection of + * 1/32(64) + * of the total PFlash. The least significant bit corresponds to the lowest address area of the PFlash. + * The most significant bit corresponds to the highest address area of PFlash. There are two possible cases as shown + * below: 0: this area is protected. 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + */ +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus) +{ + if ((config == NULL) || (protectStatus == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + +#if (FTFx_FLASH_COUNT > 1U) + if (0U != (config->ftfxConfig[0].flashDesc.feature.hasProtControl)) +#endif + { + /* get the flash protect status */ + if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits >= 32U) + { + protectStatus->protl = *kFPROTL; + } +#if defined(FTFx_FLASH0_HAS_HIGH_PROT_REG) && FTFx_FLASH0_HAS_HIGH_PROT_REG + /* For primary flash with eight PROT registers allow up to 64 protected segments of equal memory size. */ + if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 64U) + { + protectStatus->proth = *kFPROTH; + } +#endif + } +#if defined(FTFx_FLASH1_HAS_INT_PROT_REG) && FTFx_FLASH1_HAS_INT_PROT_REG + /* For secondary flash with two FPROT registers allow up to 16 protected segments of equal memory size. */ + else if ((0U != config->ftfxConfig[1].flashDesc.feature.hasProtControl) && + (0U != config->ftfxConfig[1].flashDesc.feature.hasIndProtReg)) + { + if (config->ftfxConfig[0].flashDesc.feature.ProtRegBits == 16U) + { + protectStatus->protsl = *kFPROTSL; + protectStatus->protsh = *kFPROTSH; + } + } +#endif +#if (FTFx_FLASH_COUNT > 1U) + else + { + /*do nothing*/ + } +#endif + return kStatus_FTFx_Success; +} + +/*! + * @brief Returns the desired flash property. + * + * @param config A pointer to the storage for the driver runtime state. + * @param whichProperty The desired property from the list of properties in + * enum flash_property_tag_t + * @param value A pointer to the value returned for the desired flash property. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_UnknownProperty An unknown property tag. + */ +status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value) +{ + if ((config == NULL) || (value == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + status_t status = kStatus_FTFx_Success; + + switch (whichProperty) + { + /* gat Pflash0 sector size */ + case kFLASH_PropertyPflash0SectorSize: + *value = config->ftfxConfig[0].flashDesc.sectorSize; + break; + /* gat Pflash0 total size */ + case kFLASH_PropertyPflash0TotalSize: + *value = config->ftfxConfig[0].flashDesc.totalSize; + break; + /* gat Pflash0 block size */ + case kFLASH_PropertyPflash0BlockSize: + *value = config->ftfxConfig[0].flashDesc.totalSize / config->ftfxConfig[0].flashDesc.blockCount; + break; + /* gat Pflash0 block cont */ + case kFLASH_PropertyPflash0BlockCount: + *value = config->ftfxConfig[0].flashDesc.blockCount; + break; + /* gat Pflash0 block base address */ + case kFLASH_PropertyPflash0BlockBaseAddr: + *value = config->ftfxConfig[0].flashDesc.blockBase; + break; + /* gat Pflash0 fac support feature */ + case kFLASH_PropertyPflash0FacSupport: + *value = (uint32_t)config->ftfxConfig[0].flashDesc.feature.hasXaccControl; + break; + /* gat Pflash0 access segment size feature */ + case kFLASH_PropertyPflash0AccessSegmentSize: + *value = config->ftfxConfig[0].flashDesc.accessSegmentMem.size; + break; + /* gat Pflash0 access segment count feature */ + case kFLASH_PropertyPflash0AccessSegmentCount: + *value = config->ftfxConfig[0].flashDesc.accessSegmentMem.count; + break; + +#if defined(FTFx_DRIVER_HAS_FLASH1_SUPPORT) && FTFx_DRIVER_HAS_FLASH1_SUPPORT + case kFLASH_PropertyPflash1SectorSize: + *value = config->ftfxConfig[1].flashDesc.sectorSize; + break; + case kFLASH_PropertyPflash1TotalSize: + *value = config->ftfxConfig[1].flashDesc.totalSize; + break; + case kFLASH_PropertyPflash1BlockSize: + *value = config->ftfxConfig[1].flashDesc.totalSize / config->ftfxConfig[1].flashDesc.blockCount; + break; + case kFLASH_PropertyPflash1BlockCount: + *value = config->ftfxConfig[1].flashDesc.blockCount; + break; + case kFLASH_PropertyPflash1BlockBaseAddr: + *value = config->ftfxConfig[1].flashDesc.blockBase; + break; + case kFLASH_PropertyPflash1FacSupport: + *value = (uint32_t)config->ftfxConfig[1].flashDesc.feature.hasXaccControl; + break; + case kFLASH_PropertyPflash1AccessSegmentSize: + *value = config->ftfxConfig[1].flashDesc.accessSegmentMem.size; + break; + case kFLASH_PropertyPflash1AccessSegmentCount: + *value = config->ftfxConfig[1].flashDesc.accessSegmentMem.count; + break; +#endif + /* gat FlexRam block base addrese */ + case kFLASH_PropertyFlexRamBlockBaseAddr: + *value = config->ftfxConfig[0].flexramBlockBase; + break; + /* gat FlexRam total size */ + case kFLASH_PropertyFlexRamTotalSize: + *value = config->ftfxConfig[0].flexramTotalSize; + break; + + default: /* catch inputs that are not recognized */ + status = kStatus_FTFx_UnknownProperty; + break; + } + + return status; +} + +/*! + * @brief init flash FPROT, XACC registers and Independent flash block + */ +static void flash_init_features(ftfx_config_t *config) +{ + /* Initialize whether flash0 has independent block, protection registers and + * execute only access registers */ +#if (FTFx_FLASH_COUNT > 1U) + if (config->flashDesc.index == 0U) +#endif + { + config->flashDesc.feature.isIndBlock = 1U; + config->flashDesc.feature.hasIndPfsizeReg = 1U; + config->flashDesc.feature.hasIndProtReg = 1U; + config->flashDesc.feature.hasIndXaccReg = 1U; + } + /* if another flash exists */ +#if defined(FTFx_DRIVER_HAS_FLASH1_SUPPORT) && FTFx_DRIVER_HAS_FLASH1_SUPPORT + else if (config->flashDesc.index == 1U) + { + config->flashDesc.feature.isIndBlock = FTFx_FLASH1_IS_INDEPENDENT_BLOCK; + config->flashDesc.feature.hasIndPfsizeReg = config->flashDesc.feature.isIndBlock; + config->flashDesc.feature.hasIndProtReg = FTFx_FLASH1_HAS_INT_PROT_REG; + config->flashDesc.feature.hasIndXaccReg = FTFx_FLASH1_HAS_INT_XACC_REG; + } +#endif +#if (FTFx_FLASH_COUNT > 1U) + else + { + /*do nothing*/ + } +#endif + /* init protection Registers feature*/ + config->flashDesc.feature.hasProtControl = 1U; + /* init Execute-only Access Registers feature*/ + config->flashDesc.feature.hasXaccControl = FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL; +} + +/*! + * @brief Initializes the flash operation config. + */ +static void flash_opsonfig_Init(flash_config_t *config, uint8_t flashIndex) +{ + uint32_t pflashStartAddress; + uint32_t pflashBlockSize; + uint32_t pflashBlockCount; + uint32_t pflashBlockSectorSize; + uint32_t pfsizeMask; + uint32_t pfsizeShift; + uint32_t pflashBlockWriteUnitSize; /* store P-Flash write unit size */ + uint32_t pflashSectorCmdAlignment; /* store P-Flash Erase sector command address alignment */ + uint32_t pflashSectionCmdAlignment; /* store Rrogram/Verify section command address alignment */ + +#if (FTFx_FLASH_COUNT > 1U) + if (flashIndex == 1U) + { + pflashStartAddress = FLASH1_FEATURE_PFLASH_START_ADDRESS; + pflashBlockSize = FLASH1_FEATURE_PFLASH_BLOCK_SIZE; + pflashBlockCount = FLASH1_FEATURE_PFLASH_BLOCK_COUNT; + pflashBlockSectorSize = FLASH1_FEATURE_PFLASH_BLOCK_SECTOR_SIZE; + pflashBlockWriteUnitSize = FLASH1_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE; + pflashSectorCmdAlignment = FLASH1_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT; + pflashSectionCmdAlignment = FLASH1_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; + pfsizeMask = SIM_FLASH1_PFSIZE_MASK; + pfsizeShift = SIM_FLASH1_PFSIZE_SHIFT; + } + else +#endif + { + pflashStartAddress = FLASH0_FEATURE_PFLASH_START_ADDRESS; /* get P-Flash start address */ + pflashBlockSize = FLASH0_FEATURE_PFLASH_BLOCK_SIZE; + pflashBlockCount = FLASH0_FEATURE_PFLASH_BLOCK_COUNT; + pflashBlockSectorSize = FLASH0_FEATURE_PFLASH_BLOCK_SECTOR_SIZE; + pflashBlockWriteUnitSize = FLASH0_FEATURE_PFLASH_BLOCK_WRITE_UNIT_SIZE; + pflashSectorCmdAlignment = FLASH0_FEATURE_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT; + pflashSectionCmdAlignment = FLASH0_FEATURE_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; + pfsizeMask = SIM_FLASH0_PFSIZE_MASK; + pfsizeShift = SIM_FLASH0_PFSIZE_SHIFT; + } + /* init current flash start address */ + config->ftfxConfig[flashIndex].flashDesc.blockBase = pflashStartAddress; + /* init current flash block count */ + config->ftfxConfig[flashIndex].flashDesc.blockCount = pflashBlockCount; + /* init current flash block sector size */ + config->ftfxConfig[flashIndex].flashDesc.sectorSize = pflashBlockSectorSize; + +#if (FTFx_FLASH_COUNT > 1U) + if ((0U != config->ftfxConfig[flashIndex].flashDesc.feature.isIndBlock) && + (0U != config->ftfxConfig[flashIndex].flashDesc.feature.hasIndPfsizeReg)) +#endif + { + /* Calculate flash memory size based on given parameter */ + config->ftfxConfig[flashIndex].flashDesc.totalSize = + flash_calculate_mem_size(pflashBlockCount, pflashBlockSize, pfsizeMask, pfsizeShift); + } +#if (FTFx_FLASH_COUNT > 1U) + else + { + config->ftfxConfig[flashIndex].flashDesc.totalSize = pflashBlockCount * pflashBlockSize; + } +#endif + + /* init P-Flash write unit size */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.blockWriteUnitSize = (uint8_t)pflashBlockWriteUnitSize; + /* init P-Flash Erase sector command address alignment */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.sectorCmd = (uint8_t)pflashSectorCmdAlignment; + /* init P-Flash Rrogram/Verify section command address alignment */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.sectionCmd = (uint8_t)pflashSectionCmdAlignment; + /* init P-Flash Read resource command address alignment. */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.resourceCmd = + (uint8_t)FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT; + /* init P-Flash Program check command address alignment. */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.checkCmd = + (uint8_t)FSL_FEATURE_FLASH_PFLASH_CHECK_CMD_ADDRESS_ALIGMENT; + /* init P-Flash swap command address alignment */ + config->ftfxConfig[flashIndex].opsConfig.addrAligment.swapCtrlCmd = + (uint8_t)FSL_FEATURE_FLASH_PFLASH_SWAP_CONTROL_CMD_ADDRESS_ALIGMENT; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief init access segment feature */ +static void flash_access_init(flash_config_t *config, uint8_t flashIndex) +{ + ftfx_spec_mem_t *specMem; + + /* start to initialize the structure of access segment */ +#if defined(FTFx_FLASH1_HAS_INT_XACC_REG) && FTFx_FLASH1_HAS_INT_XACC_REG + specMem = &config->ftfxConfig[flashIndex].flashDesc.accessSegmentMem; + if (flashIndex == 1U) + { + specMem->base = config->ftfxConfig[flashIndex].flashDesc.blockBase; + specMem->size = (uint32_t)kFTFx_AccessSegmentUnitSize << FTFx_FACSSS_REG; + specMem->count = FTFx_FACSNS_REG; + } + else +#else + specMem = &config->ftfxConfig[0].flashDesc.accessSegmentMem; +#endif /* FTFx_FLASH1_HAS_INT_XACC_REG */ + { + specMem->base = config->ftfxConfig[0].flashDesc.blockBase; + specMem->size = (uint32_t)kFTFx_AccessSegmentUnitSize << FTFx_FACSS_REG; + specMem->count = FTFx_FACSN_REG; + } +} +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +/*! @brief init protection feature */ +static void flash_protection_init(flash_config_t *config, uint8_t flashIndex) +{ + uint32_t pflashProtectionRegionCount; +#if (FTFx_FLASH_COUNT > 1U) + uint8_t i; + + if (flashIndex == 1U) + { + /* store flash0 Protection region count */ + pflashProtectionRegionCount = FLASH1_FEATURE_PFLASH_PROTECTION_REGION_COUNT; + } + else +#endif // #if (FTFx_FLASH_COUNT > 1U) + { + /* store flash0 Protection region count */ + pflashProtectionRegionCount = FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT; + } + + /* Start to initialize the structure of protection features */ + ftfx_spec_mem_t *specMem; + specMem = &config->ftfxConfig[flashIndex].flashDesc.protectRegionMem; +#if (FTFx_FLASH_COUNT > 1U) + if (0U != (config->ftfxConfig[flashIndex].flashDesc.feature.hasIndProtReg)) +#endif // #if (FTFx_FLASH_COUNT > 1U) + { + specMem->base = config->ftfxConfig[flashIndex].flashDesc.blockBase; + specMem->count = pflashProtectionRegionCount; + /* Calculate flash prot segment size */ + specMem->size = + flash_calculate_prot_segment_size(config->ftfxConfig[flashIndex].flashDesc.totalSize, specMem->count); + } +#if (FTFx_FLASH_COUNT > 1U) + else + { + uint32_t pflashTotalSize = 0U; + specMem->base = config->ftfxConfig[0].flashDesc.blockBase; + specMem->count = FLASH0_FEATURE_PFLASH_PROTECTION_REGION_COUNT; + if (flashIndex == FTFx_FLASH_COUNT - 1U) + { + uint32_t segmentSize; /* store the flash protection region count */ + for (i = 0U; i < FTFx_FLASH_COUNT; i++) + { + /* get pflash total size*/ + pflashTotalSize += config->ftfxConfig[flashIndex].flashDesc.totalSize; + } + /* get pflash port segment size based on parameters */ + segmentSize = flash_calculate_prot_segment_size(pflashTotalSize, specMem->count); + for (i = 0U; i < FTFx_FLASH_COUNT; i++) + { + /* init flash0 and flash1 port segment size */ + config->ftfxConfig[i].flashDesc.protectRegionMem.size = segmentSize; + } + } + } +#endif // #if (FTFx_FLASH_COUNT > 1U) +} + +/*! + * @brief Calculate flash memory size based on given parameter + */ +static uint32_t flash_calculate_mem_size(uint32_t pflashBlockCount, + uint32_t pflashBlockSize, + uint32_t pfsizeMask, + uint32_t pfsizeShift) +{ + uint8_t pfsize; + uint32_t flashDensity; + + /* PFSIZE=0xf means that on customer parts the IFR was not correctly programmed. + * We just use the pre-defined flash size in feature file here to support pre-production parts */ + pfsize = (uint8_t)((SIM_FCFG1_REG & pfsizeMask) >> pfsizeShift); + if (pfsize == 0xfU) + { + flashDensity = pflashBlockCount * pflashBlockSize; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10U; + } + + return flashDensity; +} + +/*! + * @brief Calculate flash prot segment size + */ +static uint32_t flash_calculate_prot_segment_size(uint32_t flashSize, uint32_t segmentCount) +{ + uint32_t segmentSize; + + /* Calculate the size of the flash protection region + * If the flash density is > 32KB, then protection region is 1/32 of total flash density + * Else if flash density is < 32KB, then flash protection region is set to 1KB */ + if (flashSize > segmentCount * (uint32_t)kFTFx_MinProtectBlockSize) + { + segmentSize = flashSize / segmentCount; + } + else + { + segmentSize = (uint32_t)kFTFx_MinProtectBlockSize; + } + + return segmentSize; +} + +/*! + * @brief Validates the given start address and length to get flash index + */ +static status_t flash_check_range_to_get_index(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + uint8_t *flashIndex) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Validates the range of the given address */ + for (uint8_t index = 0U; index < FTFx_FLASH_COUNT; index++) + { + if ((start >= config->ftfxConfig[index].flashDesc.blockBase) && + ((start + lengthInBytes) <= + (config->ftfxConfig[index].flashDesc.blockBase + config->ftfxConfig[index].flashDesc.totalSize))) + { + *flashIndex = config->ftfxConfig[index].flashDesc.index; + return kStatus_FTFx_Success; + } + } + + return kStatus_FTFx_AddressError; +} + +/*! + * @brief Decide whether to convert the start address from primary flash to secondary flash based on the current start + * address + */ +static void flash_convert_start_address(ftfx_config_t *config, uint32_t start) +{ + // The caller will guarantee that the config is valid +#if (FTFx_FLASH_COUNT > 1U) + if ((0U != config->flashDesc.index) && (0U != config->flashDesc.feature.isIndBlock)) + { + /* When required by the command, address bit 23 selects between main flash memory + * (=0) and secondary flash memory (=1).*/ + config->opsConfig.convertedAddress = start - config->flashDesc.blockBase + 0x800000U; + } + else +#endif + { + config->opsConfig.convertedAddress = start; + } +} + +#if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP +/*! + * @brief Validates the given address to see if it is equal to swap indicator address in pflash swap IFR. + */ +static status_t flash_validate_swap_indicator_address(ftfx_config_t *config, uint32_t address) +{ + status_t returnCode; + struct _flash_swap_ifr_field_config + { + uint16_t swapIndicatorAddress; /*!< A Swap indicator address field.*/ + uint16_t swapEnableWord; /*!< A Swap enable word field.*/ + uint8_t reserved0[4]; /*!< A reserved field.*/ + uint8_t reserved1[2]; /*!< A reserved field.*/ + uint16_t swapDisableWord; /*!< A Swap disable word field.*/ + uint8_t reserved2[4]; /*!< A reserved field.*/ + } flashSwapIfrFieldData; + uint32_t swapIndicatorAddress; + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD + returnCode = + FTFx_CMD_ReadResource(config, config->ifrDesc.resRange.pflashSwapIfrStart, (uint8_t *)&flashSwapIfrFieldData, + sizeof(flashSwapIfrFieldData), kFTFx_ResourceOptionFlashIfr); + + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } +#else + { + /* From RM, the actual info are stored in FCCOB6,7 */ + uint32_t returnValue[2]; + returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapAddr, (uint8_t *)returnValue, 4U); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + flashSwapIfrFieldData.swapIndicatorAddress = (uint16_t)returnValue[0]; + returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapEnable, (uint8_t *)returnValue, 4U); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + returnCode = FTFx_CMD_ReadOnce(config, (uint32_t)kFLASH_RecordIndexSwapDisable, (uint8_t *)returnValue, 4U); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + } +#endif + + /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field, + * the low several bit value of Swap Indicator Address is always 1'b0 */ + swapIndicatorAddress = + (uint32_t)flashSwapIfrFieldData.swapIndicatorAddress * config->opsConfig.addrAligment.swapCtrlCmd; + if (address != swapIndicatorAddress) + { + return kStatus_FTFx_SwapIndicatorAddressError; + } + + return returnCode; +} +#endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ + +status_t FLASH_GetCommandState(void) +{ + uint8_t registerValue; + uint32_t idleFlag; + + /* Get flash status register value */ + registerValue = FTFx->FSTAT; + + /* Check DONE bit of the flash status register */ + idleFlag = ((uint32_t)registerValue & FTFx_FSTAT_CCIF_MASK) >> FTFx_FSTAT_CCIF_SHIFT; + if (idleFlag == 0U) + { + return kStatus_FTFx_CommandOperationInProgress; + } + else + { + /* Check error bits */ + /* checking access error */ + if (0U != (registerValue & FTFx_FSTAT_ACCERR_MASK)) + { + return kStatus_FTFx_AccessError; + } + /* checking protection error */ + else if (0U != (registerValue & FTFx_FSTAT_FPVIOL_MASK)) + { + return kStatus_FTFx_ProtectionViolation; + } + /* checking MGSTAT0 non-correctable error */ + else if (0U != (registerValue & FTFx_FSTAT_MGSTAT0_MASK)) + { + return kStatus_FTFx_CommandFailure; + } + else + { + return kStatus_FTFx_Success; + } + } +} diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.h new file mode 100644 index 0000000..c014ab5 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flash.h @@ -0,0 +1,705 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_FLASH_H +#define FSL_FTFX_FLASH_H + +#include "fsl_ftfx_controller.h" + +/*! + * @addtogroup ftfx_flash_driver + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define kStatus_FLASH_Success kStatus_FTFx_Success +#define kFLASH_ApiEraseKey kFTFx_ApiEraseKey + +/*! + * @name Flash version + * @{ + */ +/*! @brief Flash driver version for SDK*/ +#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(3U, 1U, 2U)) /*!< Version 3.1.2. */ + +/*! @brief Flash driver version for ROM*/ +#define FSL_FLASH_DRIVER_VERSION_ROM (MAKE_VERSION(3U, 0U, 0U)) /*!< Version 3.0.0. */ + +/*@}*/ + +/*! + * @brief Enumeration for the three possible flash protection levels. + */ +typedef enum _flash_protection_state +{ + kFLASH_ProtectionStateUnprotected, /*!< Flash region is not protected.*/ + kFLASH_ProtectionStateProtected, /*!< Flash region is protected.*/ + kFLASH_ProtectionStateMixed /*!< Flash is mixed with protected and unprotected region.*/ +} flash_prot_state_t; + +/*! + * @brief PFlash protection status + */ +typedef union _pflash_protection_status +{ + uint32_t protl; /*!< PROT[31:0] .*/ + uint32_t proth; /*!< PROT[63:32].*/ + uint8_t protsl; /*!< PROTS[7:0] .*/ + uint8_t protsh; /*!< PROTS[15:8] .*/ + uint8_t reserved[2]; +} pflash_prot_status_t; + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! + * @brief Enumeration for the three possible flash execute access levels. + */ +typedef enum _flash_execute_only_access_state +{ + kFLASH_AccessStateUnLimited, /*!< Flash region is unlimited.*/ + kFLASH_AccessStateExecuteOnly, /*!< Flash region is execute only.*/ + kFLASH_AccessStateMixed /*!< Flash is mixed with unlimited and execute only region.*/ +} flash_xacc_state_t; +#endif /* not define FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +/*! + * @brief Enumeration for various flash properties. + */ +typedef enum _flash_property_tag +{ + kFLASH_PropertyPflash0SectorSize = 0x00U, /*!< Pflash sector size property.*/ + kFLASH_PropertyPflash0TotalSize = 0x01U, /*!< Pflash total size property.*/ + kFLASH_PropertyPflash0BlockSize = 0x02U, /*!< Pflash block size property.*/ + kFLASH_PropertyPflash0BlockCount = 0x03U, /*!< Pflash block count property.*/ + kFLASH_PropertyPflash0BlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/ + kFLASH_PropertyPflash0FacSupport = 0x05U, /*!< Pflash fac support property.*/ + kFLASH_PropertyPflash0AccessSegmentSize = 0x06U, /*!< Pflash access segment size property.*/ + kFLASH_PropertyPflash0AccessSegmentCount = 0x07U, /*!< Pflash access segment count property.*/ + + kFLASH_PropertyPflash1SectorSize = 0x10U, /*!< Pflash sector size property.*/ + kFLASH_PropertyPflash1TotalSize = 0x11U, /*!< Pflash total size property.*/ + kFLASH_PropertyPflash1BlockSize = 0x12U, /*!< Pflash block size property.*/ + kFLASH_PropertyPflash1BlockCount = 0x13U, /*!< Pflash block count property.*/ + kFLASH_PropertyPflash1BlockBaseAddr = 0x14U, /*!< Pflash block base address property.*/ + kFLASH_PropertyPflash1FacSupport = 0x15U, /*!< Pflash fac support property.*/ + kFLASH_PropertyPflash1AccessSegmentSize = 0x16U, /*!< Pflash access segment size property.*/ + kFLASH_PropertyPflash1AccessSegmentCount = 0x17U, /*!< Pflash access segment count property.*/ + + kFLASH_PropertyFlexRamBlockBaseAddr = 0x20U, /*!< FlexRam block base address property.*/ + kFLASH_PropertyFlexRamTotalSize = 0x21U, /*!< FlexRam total size property.*/ +} flash_property_tag_t; + +/*! @brief Flash driver state information. + * + * An instance of this structure is allocated by the user of the flash driver and + * passed into each of the driver APIs. + */ +typedef struct _flash_config +{ + ftfx_config_t ftfxConfig[FTFx_FLASH_COUNT]; +} flash_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name Initialization + * @{ + */ + +/*! + * @brief Initializes the global flash properties structure members. + * + * This function checks and initializes the Flash module for the other Flash APIs. + * + * @param config Pointer to the storage for the driver runtime state. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLASH_Init(flash_config_t *config); + +/*@}*/ + +/*! + * @name Erasing + * @{ + */ + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + * + * This function erases the appropriate number of flash sectors based on the + * desired start address and length. + * + * @param config The pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be erased. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words) + * to be erased. Must be word-aligned. + * @param key The value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the appropriate number of flash sectors based on the + * desired start address and length were erased successfully. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + * @retval #kStatus_FTFx_EraseKeyError The API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key); + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + * + * This function erases one flash sector size based on the start address, and it is + * executed asynchronously. + * + * NOTE: This function can only erase one flash sector at a time, and the other commands + * can be executed after the previous command has been completed. + * + * @param config The pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be erased. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param key The value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + * @retval #kStatus_FTFx_EraseKeyError The API erase key is invalid. + */ +status_t FLASH_EraseSectorNonBlocking(flash_config_t *config, uint32_t start, uint32_t key); + +/*! + * @brief Erases entire flexnvm + * + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the all pflash and flexnvm were erased successfully, + * the swap and eeprom have been reset to unconfigured state. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_EraseKeyError API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLASH_EraseAll(flash_config_t *config, uint32_t key); + +#if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD +/*! + * @brief Erases the entire flexnvm, including protected sectors. + * + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; + * the protected sectors of flash were reset to unprotected status. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_EraseKeyError API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key); +#endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */ + +/*@}*/ + +/*! + * @name Programming + * @{ + */ + +/*! + * @brief Programs flash with data at locations passed in through parameters. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and the length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param src A pointer to the source buffer of data that is to be programmed + * into the flash. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired data were programed successfully + * into flash based on desired start address and length. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_Program(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); + +/*! + * @brief Program the Program-Once-Field through parameters. + * + * This function Program the Program-once-feild with given index and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param index The index indicating the area of program once field to be read. + * @param src A pointer to the source buffer of data that is used to store + * data to be write. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; The index indicating the area + * of program once field was programed successfully. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint8_t *src, uint32_t lengthInBytes); + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD +/*! + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param src A pointer to the source buffer of data that is to be programmed + * into the flash. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired data have been programed successfully into + * flash based on start address and length. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_SetFlexramAsRamError Failed to set flexram as RAM. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_RecoverFlexramAsEepromError Failed to recover FlexRAM as EEPROM. + */ +status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); +#endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */ + +/*@}*/ + +/*! + * @name Reading + * @{ + */ + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! + * @brief Reads the resource with data at locations passed in through parameters. + * + * This function reads the flash memory with the desired location for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param dst A pointer to the destination buffer of data that is used to store + * data to be read. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be read. Must be word-aligned. + * @param option The resource option which indicates which area should be read back. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the data have been read successfully from + * program flash IFR, data flash IFR space, and the Version ID field. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_ReadResource( + flash_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +/*! + * @brief Reads the Program Once Field through parameters. + * + * This function reads the read once feild with given index and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param index The index indicating the area of program once field to be read. + * @param dst A pointer to the destination buffer of data that is used to store + * data to be read. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the data have been successfuly + * read form Program flash0 IFR map and Program Once field based on index and length. + + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint8_t *dst, uint32_t lengthInBytes); + +/*@}*/ + +/*! + * @name Verification + * @{ + */ + +/*! + * @brief Verifies an erasure of the desired flash area at a specified margin level. + * + * This function checks the appropriate number of flash sectors based on + * the desired start address and length to check whether the flash is erased + * to the specified read margin level. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be verified. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be verified. Must be word-aligned. + * @param margin Read margin choice. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the specified FLASH region has been erased. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, ftfx_margin_value_t margin); + +/*! + * @brief Verifies erasure of the entire flash at a specified margin level. + * + * This function checks whether the flash is erased to the + * specified read margin level. + * + * @param config A pointer to the storage for the driver runtime state. + * @param margin Read margin choice. + * + * @retval #kStatus_FTFx_Success API was executed successfully; all program flash and flexnvm were in erased state. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_VerifyEraseAll(flash_config_t *config, ftfx_margin_value_t margin); + +/*! + * @brief Verifies programming of the desired flash area at a specified margin level. + * + * This function verifies the data programmed in the flash memory using the + * Flash Program Check Command and compares it to the expected data for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be verified. Must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be verified. Must be word-aligned. + * @param expectedData A pointer to the expected data that is to be + * verified against. + * @param margin Read margin choice. + * @param failedAddress A pointer to the returned failing address. + * @param failedData A pointer to the returned failing data. Some derivatives do + * not include failed data as part of the FCCOBx registers. In this + * case, zeros are returned upon failure. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired data have been successfully programed into + * specified FLASH region. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_VerifyProgram(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + const uint8_t *expectedData, + ftfx_margin_value_t margin, + uint32_t *failedAddress, + uint32_t *failedData); + +/*@}*/ + +/*! + * @name Security + * @{ + */ + +/*! + * @brief Returns the security state via the pointer passed into the function. + * + * This function retrieves the current flash security status, including the + * security enabling state and the backdoor key enabling state. + * + * @param config A pointer to storage for the driver runtime state. + * @param state A pointer to the value returned for the current security status code: + * + * @retval #kStatus_FTFx_Success API was executed successfully; the security state of flash was stored to state. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + */ +status_t FLASH_GetSecurityState(flash_config_t *config, ftfx_security_state_t *state); + +/*! + * @brief Allows users to bypass security with a backdoor key. + * + * If the MCU is in secured state, this function unsecures the MCU by + * comparing the provided backdoor key with ones in the flash configuration + * field. + * + * @param config A pointer to the storage for the driver runtime state. + * @param backdoorKey A pointer to the user buffer containing the backdoor key. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey); + +/*@}*/ + +/*! + * @name FlexRAM + * @{ + */ + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! + * @brief Sets the FlexRAM function command. + * + * @param config A pointer to the storage for the driver runtime state. + * @param option The option used to set the work mode of FlexRAM. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the FlexRAM has been successfully configured as RAM or + * EEPROM. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_SetFlexramFunction(flash_config_t *config, ftfx_flexram_func_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*@}*/ + +/*! + * @name Swap + * @{ + */ + +#if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP +/*! + * @brief Swaps the lower half flash with the higher half flash. + * + * @param config A pointer to the storage for the driver runtime state. + * @param address Address used to configure the flash swap function + * @param isSetEnable The possible option used to configure the Flash Swap function or check the flash Swap status. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the lower half flash and higher half flash have been + * swaped. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_SwapIndicatorAddressError Swap indicator address is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_SwapSystemNotInUninitialized Swap system is not in an uninitialized state. + */ +status_t FLASH_Swap(flash_config_t *config, uint32_t address, bool isSetEnable); +#endif /* FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP */ + +/*@}*/ + +/*! + * @name Protection + * @{ + */ + +/*! + * @brief Returns the protection state of the desired flash area via the pointer passed into the function. + * + * This function retrieves the current flash protect status for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be checked. Must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words) + * to be checked. Must be word-aligned. + * @param protection_state A pointer to the value returned for the current + * protection status code for the desired flash area. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the protection state of specified FLASH region was + * stored to protection_state. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + */ +status_t FLASH_IsProtected(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + flash_prot_state_t *protection_state); + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! + * @brief Returns the access state of the desired flash area via the pointer passed into the function. + * + * This function retrieves the current flash access status for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be checked. Must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be checked. Must be word-aligned. + * @param access_state A pointer to the value returned for the current + * access status code for the desired flash area. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the executeOnly state of specified FLASH region was + * stored to access_state. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned to the specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + */ +status_t FLASH_IsExecuteOnly(flash_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + flash_xacc_state_t *access_state); +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +/*! + * @brief Sets the PFlash Protection to the intended protection status. + * + * @param config A pointer to storage for the driver runtime state. + * @param protectStatus The expected protect status to set to the PFlash protection register. Each bit is + * corresponding to protection of 1/32(64) of the total PFlash. The least significant bit is corresponding to the lowest + * address area of PFlash. The most significant bit is corresponding to the highest address area of PFlash. There are + * two possible cases as shown below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the specified FLASH region is protected. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + */ +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus); + +/*! + * @brief Gets the PFlash protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus Protect status returned by the PFlash IP. Each bit is corresponding to the protection of + * 1/32(64) + * of the + * total PFlash. The least significant bit corresponds to the lowest address area of the PFlash. The most significant + * bit corresponds to the highest address area of PFlash. There are two possible cases as shown below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the Protection state was stored to protectStatus; + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + */ +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_prot_status_t *protectStatus); + +/*@}*/ + +/*! + * @name Properties + * @{ + */ + +/*! + * @brief Returns the desired flash property. + * + * @param config A pointer to the storage for the driver runtime state. + * @param whichProperty The desired property from the list of properties in + * enum flash_property_tag_t + * @param value A pointer to the value returned for the desired flash property. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the flash property was stored to value. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_UnknownProperty An unknown property tag. + */ +status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value); + +/*@}*/ + +/*! + * @name commantStatus + * @{ + */ + +/*! + * @brief Get previous command status. + * + * This function is used to obtain the execution status of the previous command. + * + * @retval #kStatus_FTFx_Success The previous command is executed successfully. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLASH_GetCommandState(void); + +/*@}*/ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* FSL_FTFX_FLASH_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.c b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.c new file mode 100644 index 0000000..d8b2743 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.c @@ -0,0 +1,511 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "fsl_ftfx_flexnvm.h" + +#if FSL_FEATURE_FLASH_HAS_FLEX_NVM + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.flash" +#endif + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! @brief Convert address for Flexnvm dflash.*/ +static status_t flexnvm_convert_start_address(flexnvm_config_t *config, uint32_t start); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +status_t FLEXNVM_Init(flexnvm_config_t *config) +{ + status_t returnCode; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + config->ftfxConfig.flashDesc.type = (uint8_t)kFTFx_MemTypeFlexnvm; + config->ftfxConfig.flashDesc.index = 0U; + + /* Set Flexnvm memory operation parameters */ + config->ftfxConfig.opsConfig.addrAligment.blockWriteUnitSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_WRITE_UNIT_SIZE; + config->ftfxConfig.opsConfig.addrAligment.sectorCmd = FSL_FEATURE_FLASH_FLEX_NVM_SECTOR_CMD_ADDRESS_ALIGMENT; + config->ftfxConfig.opsConfig.addrAligment.sectionCmd = FSL_FEATURE_FLASH_FLEX_NVM_SECTION_CMD_ADDRESS_ALIGMENT; + config->ftfxConfig.opsConfig.addrAligment.resourceCmd = FSL_FEATURE_FLASH_FLEX_NVM_RESOURCE_CMD_ADDRESS_ALIGMENT; + config->ftfxConfig.opsConfig.addrAligment.checkCmd = FSL_FEATURE_FLASH_FLEX_NVM_CHECK_CMD_ADDRESS_ALIGMENT; + + /* Set Flexnvm memory properties */ + config->ftfxConfig.flashDesc.blockBase = FSL_FEATURE_FLASH_FLEX_NVM_START_ADDRESS; +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS) && FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS + config->ftfxConfig.flashDesc.aliasBlockBase = FSL_FEATURE_FLASH_FLEX_NVM_ALIAS_START_ADDRESS; +#endif + config->ftfxConfig.flashDesc.sectorSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; + config->ftfxConfig.flashDesc.blockCount = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; + + /* Init FTFx Kernel */ + FTFx_API_Init(&config->ftfxConfig); + + returnCode = FTFx_API_UpdateFlexnvmPartitionStatus(&config->ftfxConfig); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return kStatus_FTFx_Success; +} + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + */ +status_t FLEXNVM_DflashErase(flexnvm_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) +{ + status_t returnCode; + returnCode = flexnvm_convert_start_address(config, start); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return FTFx_CMD_Erase(&config->ftfxConfig, start, lengthInBytes, key); +} + +/*! + * @brief Erases entire flexnvm + */ +status_t FLEXNVM_EraseAll(flexnvm_config_t *config, uint32_t key) +{ + return FTFx_CMD_EraseAll(&config->ftfxConfig, key); +} + +#if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD +/*! + * @brief Erases the entire flexnvm, including protected sectors. + */ +status_t FLEXNVM_EraseAllUnsecure(flexnvm_config_t *config, uint32_t key) +{ + return FTFx_CMD_EraseAllUnsecure(&config->ftfxConfig, key); +} +#endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */ + +/*! + * @brief Programs flash with data at locations passed in through parameters. + */ +status_t FLEXNVM_DflashProgram(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + returnCode = flexnvm_convert_start_address(config, start); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return FTFx_CMD_Program(&config->ftfxConfig, start, src, lengthInBytes); +} + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD +/*! + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. + */ +status_t FLEXNVM_DflashProgramSection(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + /* Convert address for Flexnvm dflash */ + returnCode = flexnvm_convert_start_address(config, start); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return FTFx_CMD_ProgramSection(&config->ftfxConfig, start, src, lengthInBytes); +} +#endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */ + +/*! + * @brief Prepares the FlexNVM block for use as data flash, EEPROM backup, or a combination + * of both and initializes the FlexRAM. + */ +status_t FLEXNVM_ProgramPartition(flexnvm_config_t *config, + ftfx_partition_flexram_load_opt_t option, + uint32_t eepromDataSizeCode, + uint32_t flexnvmPartitionCode) +{ + return FTFx_CMD_ProgramPartition(&config->ftfxConfig, option, eepromDataSizeCode, flexnvmPartitionCode); +} + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! + * @brief Reads the resource with data at locations passed in through parameters. + */ +status_t FLEXNVM_ReadResource( + flexnvm_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option) +{ + return FTFx_CMD_ReadResource(&config->ftfxConfig, start, dst, lengthInBytes, option); +} +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +/*! + * @brief Verifies an erasure of the desired flash area at a specified margin level. + */ +status_t FLEXNVM_DflashVerifyErase(flexnvm_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + ftfx_margin_value_t margin) +{ + status_t returnCode; + returnCode = flexnvm_convert_start_address(config, start); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return FTFx_CMD_VerifyErase(&config->ftfxConfig, start, lengthInBytes, margin); +} + +/*! + * @brief Verifies erasure of the entire flash at a specified margin level. + */ +status_t FLEXNVM_VerifyEraseAll(flexnvm_config_t *config, ftfx_margin_value_t margin) +{ + return FTFx_CMD_VerifyEraseAll(&config->ftfxConfig, margin); +} + +/*! + * @brief Verifies programming of the desired flash area at a specified margin level. + */ +status_t FLEXNVM_DflashVerifyProgram(flexnvm_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + const uint8_t *expectedData, + ftfx_margin_value_t margin, + uint32_t *failedAddress, + uint32_t *failedData) +{ + status_t returnCode; + returnCode = flexnvm_convert_start_address(config, start); + if (returnCode != kStatus_FTFx_Success) + { + return returnCode; + } + + return FTFx_CMD_VerifyProgram(&config->ftfxConfig, start, lengthInBytes, expectedData, margin, failedAddress, + failedData); +} + +/*! + * @brief Returns the security state via the pointer passed into the function. + */ +status_t FLEXNVM_GetSecurityState(flexnvm_config_t *config, ftfx_security_state_t *state) +{ + return FTFx_REG_GetSecurityState(&config->ftfxConfig, state); +} + +/*! + * @brief Allows users to bypass security with a backdoor key. + */ +status_t FLEXNVM_SecurityBypass(flexnvm_config_t *config, const uint8_t *backdoorKey) +{ + return FTFx_CMD_SecurityBypass(&config->ftfxConfig, backdoorKey); +} + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! + * @brief Sets the FlexRAM function command. + */ +status_t FLEXNVM_SetFlexramFunction(flexnvm_config_t *config, ftfx_flexram_func_opt_t option) +{ + return FTFx_CMD_SetFlexramFunction(&config->ftfxConfig, option); +} +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*! + * @brief Programs the EEPROM with data at locations passed in through parameters. + */ +status_t FLEXNVM_EepromWrite(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes) +{ + status_t returnCode; + bool needSwitchFlexRamMode = false; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* Validates the range of the given address */ + if ((start < config->ftfxConfig.flexramBlockBase) || + ((start + lengthInBytes) > (config->ftfxConfig.flexramBlockBase + config->ftfxConfig.eepromTotalSize))) + { + return kStatus_FTFx_AddressError; + } + + returnCode = kStatus_FTFx_Success; + + /* Switch function of FlexRAM if needed */ + if (0U == (FTFx->FCNFG & FTFx_FCNFG_EEERDY_MASK)) + { + needSwitchFlexRamMode = true; + + returnCode = FTFx_CMD_SetFlexramFunction(&config->ftfxConfig, kFTFx_FlexramFuncOptAvailableForEeprom); + if (returnCode != kStatus_FTFx_Success) + { + return kStatus_FTFx_SetFlexramAsEepromError; + } + } + + /* Write data to FlexRAM when it is used as EEPROM emulator */ + while (lengthInBytes > 0U) + { + if ((0U == (start & 0x3U)) && (0U == ((uint32_t)src & 0x3U)) && (lengthInBytes >= 4U)) + { + *(uint32_t *)start = *(uint32_t *)(uint32_t)src; + start += 4U; + src = &src[4]; + lengthInBytes -= 4U; + } + else if ((0U == (start & 0x1U)) && (0U == ((uint32_t)src & 0x1U)) && (lengthInBytes >= 2U)) + { + *(uint16_t *)start = *(uint16_t *)(uint32_t)src; + start += 2U; + src = &src[2]; + lengthInBytes -= 2U; + } + else + { + *(uint8_t *)start = *src; + start += 1U; + src = &src[1]; + lengthInBytes -= 1U; + } + /* Wait till EEERDY bit is set */ + while (0U == (FTFx->FCNFG & FTFx_FCNFG_EEERDY_MASK)) + { + } + + /* Check for protection violation error */ + if (0U != (FTFx->FSTAT & FTFx_FSTAT_FPVIOL_MASK)) + { + return kStatus_FTFx_ProtectionViolation; + } + } + + /* Switch function of FlexRAM if needed */ + if (needSwitchFlexRamMode) + { + returnCode = FTFx_CMD_SetFlexramFunction(&config->ftfxConfig, kFTFx_FlexramFuncOptAvailableAsRam); + if (returnCode != kStatus_FTFx_Success) + { + return kStatus_FTFx_RecoverFlexramAsRamError; + } + } + + return returnCode; +} + +/*! + * @brief Sets the DFlash protection to the intended protection status. + */ +status_t FLEXNVM_DflashSetProtection(flexnvm_config_t *config, uint8_t protectStatus) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + if ((config->ftfxConfig.flashDesc.totalSize == 0U) || (config->ftfxConfig.flashDesc.totalSize == 0xFFFFFFFFU)) + { + return kStatus_FTFx_CommandNotSupported; + } + + /* Individual data flash regions will be protected from program and erase operations by setting the + * associated DPROT bit to the protected state. Each FDPROT bit only be changed from 1s to 0s, + * meaning the protection can only be increased */ + FTFx->FDPROT = protectStatus; + + if (FTFx->FDPROT != protectStatus) + { + return kStatus_FTFx_CommandFailure; + } + + return kStatus_FTFx_Success; +} + +/*! + * @brief Gets the DFlash protection status. + */ +status_t FLEXNVM_DflashGetProtection(flexnvm_config_t *config, uint8_t *protectStatus) +{ + if ((config == NULL) || (protectStatus == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + if ((config->ftfxConfig.flashDesc.totalSize == 0U) || (config->ftfxConfig.flashDesc.totalSize == 0xFFFFFFFFU)) + { + return kStatus_FTFx_CommandNotSupported; + } + + /* return the flexnvm DFlash protection status */ + *protectStatus = FTFx->FDPROT; + + return kStatus_FTFx_Success; +} + +/*! + * @brief Sets the EEPROM protection to the intended protection status. + */ +status_t FLEXNVM_EepromSetProtection(flexnvm_config_t *config, uint8_t protectStatus) +{ + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + if ((config->ftfxConfig.eepromTotalSize == 0U) || (config->ftfxConfig.eepromTotalSize == 0xFFFFU)) + { + return kStatus_FTFx_CommandNotSupported; + } + /* Individual data flash regions will be protected from program and erase operations by setting the + * associated FEPROT bit to the protected state; Each FEPROT bit only be changed from 1s to 0s, + * meaning the protection can only be increased. */ + FTFx->FEPROT = protectStatus; + + if (FTFx->FEPROT != protectStatus) + { + return kStatus_FTFx_CommandFailure; + } + + return kStatus_FTFx_Success; +} + +/*! + * @brief Gets the EEPROM protection status. + */ +status_t FLEXNVM_EepromGetProtection(flexnvm_config_t *config, uint8_t *protectStatus) +{ + if ((config == NULL) || (protectStatus == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + if ((config->ftfxConfig.eepromTotalSize == 0U) || (config->ftfxConfig.eepromTotalSize == 0xFFFFU)) + { + return kStatus_FTFx_CommandNotSupported; + } + + /* return EEPROM protection status */ + *protectStatus = FTFx->FEPROT; + + return kStatus_FTFx_Success; +} + +/*! + * @brief Returns the desired flexnvm property. + */ +status_t FLEXNVM_GetProperty(flexnvm_config_t *config, flexnvm_property_tag_t whichProperty, uint32_t *value) +{ + if ((config == NULL) || (value == NULL)) + { + return kStatus_FTFx_InvalidArgument; + } + + status_t status = kStatus_FTFx_Success; + + switch (whichProperty) + { + /* get flexnvm date flash sector size */ + case kFLEXNVM_PropertyDflashSectorSize: + *value = config->ftfxConfig.flashDesc.sectorSize; + break; + /* get flexnvm date flash total size */ + case kFLEXNVM_PropertyDflashTotalSize: + *value = config->ftfxConfig.flashDesc.totalSize; + break; + /* get flexnvm date flash block size */ + case kFLEXNVM_PropertyDflashBlockSize: + *value = config->ftfxConfig.flashDesc.totalSize / config->ftfxConfig.flashDesc.blockCount; + break; + /* get flexnvm date flash block cont */ + case kFLEXNVM_PropertyDflashBlockCount: + *value = config->ftfxConfig.flashDesc.blockCount; + break; + /* get flexnvm date flash block base address */ + case kFLEXNVM_PropertyDflashBlockBaseAddr: + *value = config->ftfxConfig.flashDesc.blockBase; + break; +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS) && FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS + case kFLEXNVM_PropertyAliasDflashBlockBaseAddr: + *value = config->ftfxConfig.flashDesc.aliasBlockBase; + break; +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS */ + case kFLEXNVM_PropertyFlexRamBlockBaseAddr: + *value = config->ftfxConfig.flexramBlockBase; + break; + /* get flexram total size */ + case kFLEXNVM_PropertyFlexRamTotalSize: + *value = config->ftfxConfig.flexramTotalSize; + break; + /* get flexnvm eeprom total size */ + case kFLEXNVM_PropertyEepromTotalSize: + *value = config->ftfxConfig.eepromTotalSize; + break; + /* catch inputs that are not recognized */ + default: + status = kStatus_FTFx_UnknownProperty; + break; + } + return status; +} + +/*! @brief Convert address for Flexnvm dflash.*/ +static status_t flexnvm_convert_start_address(flexnvm_config_t *config, uint32_t start) +{ + status_t status = kStatus_FTFx_AddressError; + + if (config == NULL) + { + return kStatus_FTFx_InvalidArgument; + } + + /* From Spec: When required by the command, address bit 23 selects between program flash memory + * (=0) and data flash memory (=1).*/ + if (start >= config->ftfxConfig.flashDesc.blockBase) + { + config->ftfxConfig.opsConfig.convertedAddress = start - config->ftfxConfig.flashDesc.blockBase + 0x800000U; + status = kStatus_FTFx_Success; + } +#if defined(FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS) && FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS + /* for MKW39/38/37 which have alias blockBase */ + else if (start >= config->ftfxConfig.flashDesc.aliasBlockBase) + { + config->ftfxConfig.opsConfig.convertedAddress = start - config->ftfxConfig.flashDesc.aliasBlockBase + 0x800000U; + status = kStatus_FTFx_Success; + } + else + { + status = kStatus_FTFx_Success; + } +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM_ALIAS */ + + return status; +} + +#endif /* FSL_FEATURE_FLASH_HAS_FLEX_NVM */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.h new file mode 100644 index 0000000..9abd29c --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_flexnvm.h @@ -0,0 +1,564 @@ +/* + * Copyright 2013-2016 Freescale Semiconductor, Inc. + * Copyright 2016-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_FLEXNVM_H +#define FSL_FTFX_FLEXNVM_H + +#include "fsl_ftfx_controller.h" + +/*! + * @addtogroup ftfx_flexnvm_driver + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @brief Enumeration for various flexnvm properties. + */ +typedef enum _flexnvm_property_tag +{ + kFLEXNVM_PropertyDflashSectorSize = 0x00U, /*!< Dflash sector size property.*/ + kFLEXNVM_PropertyDflashTotalSize = 0x01U, /*!< Dflash total size property.*/ + kFLEXNVM_PropertyDflashBlockSize = 0x02U, /*!< Dflash block size property.*/ + kFLEXNVM_PropertyDflashBlockCount = 0x03U, /*!< Dflash block count property.*/ + kFLEXNVM_PropertyDflashBlockBaseAddr = 0x04U, /*!< Dflash block base address property.*/ + kFLEXNVM_PropertyAliasDflashBlockBaseAddr = 0x05U, /*!< Dflash block base address Alias property.*/ + kFLEXNVM_PropertyFlexRamBlockBaseAddr = 0x06U, /*!< FlexRam block base address property.*/ + kFLEXNVM_PropertyFlexRamTotalSize = 0x07U, /*!< FlexRam total size property.*/ + kFLEXNVM_PropertyEepromTotalSize = 0x08U, /*!< EEPROM total size property.*/ +} flexnvm_property_tag_t; + +/*! @brief Flexnvm driver state information. + * + * An instance of this structure is allocated by the user of the Flexnvm driver and + * passed into each of the driver APIs. + */ +typedef struct _flexnvm_config +{ + ftfx_config_t ftfxConfig; +} flexnvm_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name Initialization + * @{ + */ + +/*! + * @brief Initializes the global flash properties structure members. + * + * This function checks and initializes the Flash module for the other Flash APIs. + * + * @param config Pointer to the storage for the driver runtime state. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLEXNVM_Init(flexnvm_config_t *config); + +/*@}*/ + +/*! + * @name Erasing + * @{ + */ + +/*! + * @brief Erases the Dflash sectors encompassed by parameters passed into function. + * + * This function erases the appropriate number of flash sectors based on the + * desired start address and length. + * + * @param config The pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be erased. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words) + * to be erased. Must be word-aligned. + * @param key The value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the appropriate number of date flash sectors based on + * the desired start address and length were erased successfully. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError The parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError The address is out of range. + * @retval #kStatus_FTFx_EraseKeyError The API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_DflashErase(flexnvm_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key); + +/*! + * @brief Erases entire flexnvm + * + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the entire flexnvm has been erased successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_EraseKeyError API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLEXNVM_EraseAll(flexnvm_config_t *config, uint32_t key); + +#if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD +/*! + * @brief Erases the entire flexnvm, including protected sectors. + * + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the flexnvm is not in securityi state. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_EraseKeyError API erase key is invalid. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_PartitionStatusUpdateFailure Failed to update the partition status. + */ +status_t FLEXNVM_EraseAllUnsecure(flexnvm_config_t *config, uint32_t key); +#endif /* FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD */ + +/*@}*/ + +/*! + * @name Programming + * @{ + */ + +/*! + * @brief Programs flash with data at locations passed in through parameters. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and the length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param src A pointer to the source buffer of data that is to be programmed + * into the flash. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired date have been successfully + * programed into specified date flash region. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_DflashProgram(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); + +#if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD +/*! + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. + * + * This function programs the flash memory with the desired data for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param src A pointer to the source buffer of data that is to be programmed + * into the flash. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired date have been successfully + * programed into specified date flash area. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_SetFlexramAsRamError Failed to set flexram as RAM. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + * @retval #kStatus_FTFx_RecoverFlexramAsEepromError Failed to recover FlexRAM as EEPROM. + */ +status_t FLEXNVM_DflashProgramSection(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); +#endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD */ + +/*! + * @brief Prepares the FlexNVM block for use as data flash, EEPROM backup, or a combination of both and initializes the + * FlexRAM. + * + * @param config Pointer to storage for the driver runtime state. + * @param option The option used to set FlexRAM load behavior during reset. + * @param eepromDataSizeCode Determines the amount of FlexRAM used in each of the available EEPROM subsystems. + * @param flexnvmPartitionCode Specifies how to split the FlexNVM block between data flash memory and EEPROM backup + * memory supporting EEPROM functions. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the FlexNVM block for use as data flash, EEPROM backup, + * or a combination of both have been Prepared. + * + * @retval #kStatus_FTFx_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + */ +status_t FLEXNVM_ProgramPartition(flexnvm_config_t *config, + ftfx_partition_flexram_load_opt_t option, + uint32_t eepromDataSizeCode, + uint32_t flexnvmPartitionCode); + +/*@}*/ + +/*! + * @name Reading + * @{ + */ + +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD +/*! + * @brief Reads the resource with data at locations passed in through parameters. + * + * This function reads the flash memory with the desired location for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param dst A pointer to the destination buffer of data that is used to store + * data to be read. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be read. Must be word-aligned. + * @param option The resource option which indicates which area should be read back. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the data have been read successfully from + * program flash IFR, data flash IFR space, and the Version ID field + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with the specified baseline. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_ReadResource( + flexnvm_config_t *config, uint32_t start, uint8_t *dst, uint32_t lengthInBytes, ftfx_read_resource_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD */ + +/*@}*/ + +/*! + * @name Verification + * @{ + */ + +/*! + * @brief Verifies an erasure of the desired flash area at a specified margin level. + * + * This function checks the appropriate number of flash sectors based on + * the desired start address and length to check whether the flash is erased + * to the specified read margin level. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be verified. + * The start address does not need to be sector-aligned but must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be verified. Must be word-aligned. + * @param margin Read margin choice. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the specified data flash region is in erased state. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_DflashVerifyErase(flexnvm_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + ftfx_margin_value_t margin); + +/*! + * @brief Verifies erasure of the entire flash at a specified margin level. + * + * This function checks whether the flash is erased to the + * specified read margin level. + * + * @param config A pointer to the storage for the driver runtime state. + * @param margin Read margin choice. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the entire flexnvm region is in erased state. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_VerifyEraseAll(flexnvm_config_t *config, ftfx_margin_value_t margin); + +/*! + * @brief Verifies programming of the desired flash area at a specified margin level. + * + * This function verifies the data programmed in the flash memory using the + * Flash Program Check Command and compares it to the expected data for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be verified. Must be word-aligned. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be verified. Must be word-aligned. + * @param expectedData A pointer to the expected data that is to be + * verified against. + * @param margin Read margin choice. + * @param failedAddress A pointer to the returned failing address. + * @param failedData A pointer to the returned failing data. Some derivatives do + * not include failed data as part of the FCCOBx registers. In this + * case, zeros are returned upon failure. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desired data hve been programed successfully into + * specified data flash region. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_DflashVerifyProgram(flexnvm_config_t *config, + uint32_t start, + uint32_t lengthInBytes, + const uint8_t *expectedData, + ftfx_margin_value_t margin, + uint32_t *failedAddress, + uint32_t *failedData); + +/*@}*/ + +/*! + * @name Security + * @{ + */ + +/*! + * @brief Returns the security state via the pointer passed into the function. + * + * This function retrieves the current flash security status, including the + * security enabling state and the backdoor key enabling state. + * + * @param config A pointer to storage for the driver runtime state. + * @param state A pointer to the value returned for the current security status code: + * + * @retval #kStatus_FTFx_Success API was executed successfully; + * the security state of flexnvm was stored to state. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + */ +status_t FLEXNVM_GetSecurityState(flexnvm_config_t *config, ftfx_security_state_t *state); + +/*! + * @brief Allows users to bypass security with a backdoor key. + * + * If the MCU is in secured state, this function unsecures the MCU by + * comparing the provided backdoor key with ones in the flash configuration + * field. + * + * @param config A pointer to the storage for the driver runtime state. + * @param backdoorKey A pointer to the user buffer containing the backdoor key. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_SecurityBypass(flexnvm_config_t *config, const uint8_t *backdoorKey); + +/*@}*/ + +/*! + * @name FlexRAM + * @{ + */ + +#if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD +/*! + * @brief Sets the FlexRAM function command. + * + * @param config A pointer to the storage for the driver runtime state. + * @param option The option used to set the work mode of FlexRAM. + * + * @retval #kStatus_FTFx_Success API was executed successfully; + * the FlexRAM has been successfully configured as RAM or EEPROM + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. + * @retval #kStatus_FTFx_AccessError Invalid instruction codes and out-of bounds addresses. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_CommandFailure Run-time error during the command execution. + */ +status_t FLEXNVM_SetFlexramFunction(flexnvm_config_t *config, ftfx_flexram_func_opt_t option); +#endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*@}*/ + +/*! + * @brief Programs the EEPROM with data at locations passed in through parameters. + * + * This function programs the emulated EEPROM with the desired data for a given + * flash area as determined by the start address and length. + * + * @param config A pointer to the storage for the driver runtime state. + * @param start The start address of the desired flash memory to be programmed. Must be + * word-aligned. + * @param src A pointer to the source buffer of data that is to be programmed + * into the flash. + * @param lengthInBytes The length, given in bytes (not words or long-words), + * to be programmed. Must be word-aligned. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the desires data have been successfully programed + * into specified eeprom region. + * + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_AddressError Address is out of range. + * @retval #kStatus_FTFx_SetFlexramAsEepromError Failed to set flexram as eeprom. + * @retval #kStatus_FTFx_ProtectionViolation The program/erase operation is requested to execute on protected areas. + * @retval #kStatus_FTFx_RecoverFlexramAsRamError Failed to recover the FlexRAM as RAM. + */ +status_t FLEXNVM_EepromWrite(flexnvm_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); + +/*! + * @name Flash Protection Utilities + * @{ + */ + +/*! + * @brief Sets the DFlash protection to the intended protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus The expected protect status to set to the DFlash protection register. Each bit + * corresponds to the protection of the 1/8 of the total DFlash. The least significant bit corresponds to the lowest + * address area of the DFlash. The most significant bit corresponds to the highest address area of the DFlash. There + * are + * two possible cases as shown below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully; the specified DFlash region is protected. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandNotSupported Flash API is not supported. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + */ +status_t FLEXNVM_DflashSetProtection(flexnvm_config_t *config, uint8_t protectStatus); + +/*! + * @brief Gets the DFlash protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus DFlash Protect status returned by the PFlash IP. Each bit corresponds to the protection of the + * 1/8 of + * the total DFlash. The least significant bit corresponds to the lowest address area of the DFlash. The most + * significant bit corresponds to the highest address area of the DFlash, and so on. There are two possible cases as + * below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandNotSupported Flash API is not supported. + */ +status_t FLEXNVM_DflashGetProtection(flexnvm_config_t *config, uint8_t *protectStatus); + +/*! + * @brief Sets the EEPROM protection to the intended protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus The expected protect status to set to the EEPROM protection register. Each bit + * corresponds to the protection of the 1/8 of the total EEPROM. The least significant bit corresponds to the lowest + * address area of the EEPROM. The most significant bit corresponds to the highest address area of EEPROM, and so on. + * There are two possible cases as shown below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandNotSupported Flash API is not supported. + * @retval #kStatus_FTFx_CommandFailure Run-time error during command execution. + */ +status_t FLEXNVM_EepromSetProtection(flexnvm_config_t *config, uint8_t protectStatus); + +/*! + * @brief Gets the EEPROM protection status. + * + * @param config A pointer to the storage for the driver runtime state. + * @param protectStatus DFlash Protect status returned by the PFlash IP. Each bit corresponds to the protection of the + * 1/8 of + * the total EEPROM. The least significant bit corresponds to the lowest address area of the EEPROM. The most + * significant bit corresponds to the highest address area of the EEPROM. There are two possible cases as below: + * 0: this area is protected. + * 1: this area is unprotected. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_CommandNotSupported Flash API is not supported. + */ +status_t FLEXNVM_EepromGetProtection(flexnvm_config_t *config, uint8_t *protectStatus); + +/*@}*/ + +/*! + * @name Properties + * @{ + */ + +/*! + * @brief Returns the desired flexnvm property. + * + * @param config A pointer to the storage for the driver runtime state. + * @param whichProperty The desired property from the list of properties in + * enum flexnvm_property_tag_t + * @param value A pointer to the value returned for the desired flexnvm property. + * + * @retval #kStatus_FTFx_Success API was executed successfully. + * @retval #kStatus_FTFx_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FTFx_UnknownProperty An unknown property tag. + */ +status_t FLEXNVM_GetProperty(flexnvm_config_t *config, flexnvm_property_tag_t whichProperty, uint32_t *value); + +/*@}*/ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* FSL_FTFX_FLEXNVM_H */ diff --git a/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_utilities.h b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_utilities.h new file mode 100644 index 0000000..e8540f3 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/drivers/fsl_ftfx_utilities.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_FTFX_UTILITIES_H +#define FSL_FTFX_UTILITIES_H + +/*! + * @addtogroup ftfx_utilities + * @{ + */ +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief Constructs the version number for drivers. */ +#if !defined(MAKE_VERSION) +#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) +#endif + +/*! @brief Constructs a status code value from a group and a code number. */ +#if !defined(MAKE_STATUS) +#define MAKE_STATUS(group, code) ((((group)*100) + (code))) +#endif + +/*! @brief Constructs the four character code for the Flash driver API key. */ +#if !defined(FOUR_CHAR_CODE) +#define FOUR_CHAR_CODE(a, b, c, d) \ + (((uint32_t)(d) << 24u) | ((uint32_t)(c) << 16u) | ((uint32_t)(b) << 8u) | ((uint32_t)(a))) +#endif + +//! @name Alignment macros +//@{ +/*! @brief Alignment(down) utility. */ +#if !defined(ALIGN_DOWN) +#define ALIGN_DOWN(x, a) (((uint32_t)(x)) & ~((uint32_t)(a)-1u)) +#endif + +/*! @brief Alignment(up) utility. */ +#if !defined(ALIGN_UP) +#define ALIGN_UP(x, a) ALIGN_DOWN((uint32_t)(x) + (uint32_t)(a)-1u, a) +#endif +//@} + +/*! @brief bytes2word utility. */ +#define B1P4(b) (((uint32_t)(b)&0xFFU) << 24U) +#define B1P3(b) (((uint32_t)(b)&0xFFU) << 16U) +#define B1P2(b) (((uint32_t)(b)&0xFFU) << 8U) +#define B1P1(b) ((uint32_t)(b)&0xFFU) +#define B2P3(b) (((uint32_t)(b)&0xFFFFU) << 16U) +#define B2P2(b) (((uint32_t)(b)&0xFFFFU) << 8U) +#define B2P1(b) ((uint32_t)(b)&0xFFFFU) +#define B3P2(b) (((uint32_t)(b)&0xFFFFFFU) << 8U) +#define B3P1(b) ((uint32_t)(b)&0xFFFFFFU) + +#define BYTE2WORD_1_3(x, y) (B1P4(x) | B3P1(y)) +#define BYTE2WORD_2_2(x, y) (B2P3(x) | B2P1(y)) +#define BYTE2WORD_3_1(x, y) (B3P2(x) | B1P1(y)) +#define BYTE2WORD_1_1_2(x, y, z) (B1P4(x) | B1P3(y) | B2P1(z)) +#define BYTE2WORD_1_2_1(x, y, z) (B1P4(x) | B2P2(y) | B1P1(z)) +#define BYTE2WORD_2_1_1(x, y, z) (B2P3(x) | B1P2(y) | B1P1(z)) +#define BYTE2WORD_1_1_1_1(x, y, z, w) (B1P4(x) | B1P3(y) | B1P2(z) | B1P1(w)) + +/*! @}*/ + +#endif /* FSL_FTFX_UTILITIES_H */ diff --git a/ADIS_tinyK22_SplitFlap/source/IncludeMcuLibConfig.h b/ADIS_tinyK22_SplitFlap/source/IncludeMcuLibConfig.h index 292bde7..dbfd7fd 100644 --- a/ADIS_tinyK22_SplitFlap/source/IncludeMcuLibConfig.h +++ b/ADIS_tinyK22_SplitFlap/source/IncludeMcuLibConfig.h @@ -120,5 +120,15 @@ add_compile_options(-include "../config/IncludeMcuLibConfig.h") /* #define configHEAP_SECTION_NAME_STRING ".bss.$SRAM_LOWER.FreeRTOS" */ /* ------------------- FatFS ---------------------------*/ #define McuLib_CONFIG_USE_FAT_FS (0) +/* ---------------------------------------------------------------------------------------*/ +/* McuFlash */ +#define McuFlash_CONFIG_IS_ENABLED (1) +/* ---------------------------------------------------------------------------------------*/ +/* MinINI */ +#define McuMinINI_CONFIG_FS (McuMinINI_CONFIG_FS_TYPE_FLASH_FS) +#define McuMinINI_CONFIG_FLASH_NVM_ADDR_START ((0+512*1024)-McuMinINI_CONFIG_FLASH_NVM_BLOCK_SIZE) +#define McuMinINI_CONFIG_FLASH_NVM_BLOCK_SIZE (0x800) +#define McuMinINI_CONFIG_FLASH_NVM_MAX_DATA_SIZE (0x800) /* must be 64, 128, 256, ... */ + #endif /* INCLUDEMCULIBCONFIG_H_ */ diff --git a/ADIS_tinyK22_SplitFlap/source/nvmc.c b/ADIS_tinyK22_SplitFlap/source/nvmc.c new file mode 100644 index 0000000..5298bab --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/source/nvmc.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2019-2022, Erich Styger + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "platform.h" +#if PL_CONFIG_USE_NVMC +#include "nvmc.h" +#include +#if PL_CONFIG_USE_MININI + #include "MinIni/McuMinINI.h" +#endif +#include "McuLib.h" +#include "McuUtility.h" +#include "Shell.h" +#include "McuLog.h" + +#define NVMC_MININI_FILE_NAME "settings.ini" /* 'file' name used */ + +/* RS-485 bus settings */ +#define NVMC_MININI_SECTION_RS485 "rs485" +#define NVMC_MININI_KEY_RS485_ADDR "addr" /* long value: RS-485 address */ + +/* application settings */ +#define NVMC_MININI_SECTION_APP "app" +#define NVMC_MININI_KEY_APP_FLAGS "flags" /* long value: application flags */ + +/* motor settings */ +#define NVMC_MININI_SECTION_MOTOR "motor" /* motor0, motor1, ... */ +#define NVMC_MININI_KEY_MOTOR_ID "id" /* long value: stepper motor id/label */ +#define NVMC_MININI_KEY_MOTOR_OFFSET "offs" /* long value: stepper motor offset */ +#define NVMC_MININI_KEY_MOTOR_X "x" /* long value: x position of split-flap */ +#define NVMC_MININI_KEY_MOTOR_Y "y" /* long value: y position of split-flap */ + +uint8_t NVMC_GetRS485Addr(uint8_t *addr) { +#if PL_CONFIG_USE_MININI + *addr = McuMinINI_ini_getl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, 0x1, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + *addr = 0x1; + return ERR_OK; +#endif +} + +uint8_t NVMC_SetRS485Addr(uint8_t addr) { +#if PL_CONFIG_USE_MININI && McuMinINI_CONFIG_READ_ONLY + return ERR_FAILED; +#elif PL_CONFIG_USE_MININI + McuMinINI_ini_putl(NVMC_MININI_SECTION_RS485, NVMC_MININI_KEY_RS485_ADDR, addr, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + return ERR_FAILED; +#endif +} + +uint8_t NVMC_GetFlags(uint32_t *flags) { +#if PL_CONFIG_USE_MININI + *flags = McuMinINI_ini_getl(NVMC_MININI_SECTION_APP, NVMC_MININI_KEY_APP_FLAGS, 0x0, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + *flags = 0; + return ERR_OK; +#endif +} + +uint8_t NVMC_SetFlags(uint32_t flags) { +#if PL_CONFIG_USE_MININI && McuMinINI_CONFIG_READ_ONLY + return ERR_FAILED; +#elif PL_CONFIG_USE_MININI + McuMinINI_ini_putl(NVMC_MININI_SECTION_APP, NVMC_MININI_KEY_APP_FLAGS, flags, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + return ERR_FAILED; +#endif +} + +#if PL_CONFIG_USE_MININI +static void BuildStepperSectionName(unsigned char *sectionName, size_t nameSize, uint8_t motorIdx) { + McuUtility_strcpy(sectionName, nameSize, (unsigned char*)NVMC_MININI_SECTION_MOTOR); + McuUtility_strcatNum8u(sectionName, nameSize, motorIdx); /* append motor index to section name */ +} +#endif + +uint8_t NVMC_GetStepperID(uint8_t motorIdx, int16_t *id) { +#if PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + *id = McuMinINI_ini_getl((char*)sectionName, NVMC_MININI_KEY_MOTOR_ID, -1, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + *id = -1; + return ERR_OK; +#endif +} + +uint8_t NVMC_SetStepperID(uint8_t motorIdx, uint16_t id) { +#if PL_CONFIG_USE_MININI && McuMinINI_CONFIG_READ_ONLY + return ERR_FAILED; +#elif PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + McuMinINI_ini_putl((char*)sectionName, NVMC_MININI_KEY_MOTOR_ID, id, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + return ERR_FAILED; +#endif +} + +uint8_t NVMC_GetStepperPosition(uint8_t motorIdx, int16_t *xp, int16_t *yp) { +#if PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + *xp = McuMinINI_ini_getl((char*)sectionName, NVMC_MININI_KEY_MOTOR_X, -1, NVMC_MININI_FILE_NAME); + *yp = McuMinINI_ini_getl((char*)sectionName, NVMC_MININI_KEY_MOTOR_Y, -1, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + *xp = 0; + *yp = 0; + return ERR_OK; +#endif +} + +uint8_t NVMC_SetStepperPosition(uint8_t motorIdx, int16_t xPos, int16_t yPos) { +#if PL_CONFIG_USE_MININI && McuMinINI_CONFIG_READ_ONLY + return ERR_FAILED; +#elif PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + McuMinINI_ini_putl((char*)sectionName, NVMC_MININI_KEY_MOTOR_X, xPos, NVMC_MININI_FILE_NAME); + McuMinINI_ini_putl((char*)sectionName, NVMC_MININI_KEY_MOTOR_Y, yPos, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + return ERR_FAILED; +#endif +} + +int16_t NVMC_GetStepperZeroOffset(uint8_t motorIdx) { +#if PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + return McuMinINI_ini_getl((char*)sectionName, NVMC_MININI_KEY_MOTOR_OFFSET, 0, NVMC_MININI_FILE_NAME); +#else + return 0; +#endif +} + +uint8_t NVMC_SetStepperZeroOffset(uint8_t motorIdx, int16_t offset) { +#if PL_CONFIG_USE_MININI && McuMinINI_CONFIG_READ_ONLY + return ERR_FAILED; +#elif PL_CONFIG_USE_MININI + unsigned char sectionName[16]; + + BuildStepperSectionName(sectionName, sizeof(sectionName), motorIdx); + McuMinINI_ini_putl((char*)sectionName, NVMC_MININI_KEY_MOTOR_OFFSET, offset, NVMC_MININI_FILE_NAME); + return ERR_OK; +#else + return ERR_FAILED; +#endif +} + +static uint8_t PrintStatus(const McuShell_StdIOType *io) { + uint8_t buf[64]; + uint8_t res, addr; + uint32_t flags; + + McuShell_SendStatusStr((unsigned char*)"nvmc", (unsigned char*)"Non-volatile memory configuration area\r\n", io->stdOut); + + res = NVMC_GetRS485Addr(&addr); + if (res==ERR_OK) { + McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"0x"); + McuUtility_strcatNum8Hex(buf, sizeof(buf), addr); + McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n"); + } else { + McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"ERROR\r\n"); + } + McuShell_SendStatusStr((unsigned char*)" RS-485 addr", buf, io->stdOut); + + res = NVMC_GetFlags(&flags); + if (res==ERR_OK) { + McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"0x"); + McuUtility_strcatNum32Hex(buf, sizeof(buf), flags); + McuUtility_strcat(buf, sizeof(buf), (unsigned char*)" mag: "); + if (flags&NVMC_FLAGS_MAGNET_ENABLED) { + McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"1"); + } else { + McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"0"); + } + McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n"); + } else { + McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"ERROR\r\n"); + } + McuShell_SendStatusStr((unsigned char*)" flags", buf, io->stdOut); + return ERR_OK; +} + +static uint8_t PrintHelp(const McuShell_StdIOType *io) { + McuShell_SendHelpStr((unsigned char*)"nvmc", (unsigned char*)"Group of NVMC commands\r\n", io->stdOut); + McuShell_SendHelpStr((unsigned char*)" help|status", (unsigned char*)"Print help or status information\r\n", io->stdOut); + McuShell_SendHelpStr((unsigned char*)" flags ", (unsigned char*)"Set flags\r\n", io->stdOut); + return ERR_OK; +} + +uint8_t NVMC_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io) { + if (McuUtility_strcmp((char*)cmd, McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, "nvmc help")==0) { + *handled = true; + return PrintHelp(io); + } else if ((McuUtility_strcmp((char*)cmd, McuShell_CMD_STATUS)==0) || (McuUtility_strcmp((char*)cmd, "nvmc status")==0)) { + *handled = true; + return PrintStatus(io); + } else if (McuUtility_strncmp((char*)cmd, "nvmc flags", sizeof("nvmc flags")-1)==0) { + *handled = true; + const unsigned char *p; + int32_t val; + + p = cmd + sizeof("nvmc flags ")-1; + if (McuUtility_xatoi(&p, &val)==ERR_OK) { + return NVMC_SetFlags((uint32_t)val); + } else { + return ERR_FAILED; + } + } + return ERR_OK; +} + +void NVMC_Deinit(void) { + /* nothing needed */ +} + +void NVMC_Init(void){ + /* nothing needed */ +} +#endif /* PL_CONFIG_USE_NVMC */ diff --git a/ADIS_tinyK22_SplitFlap/source/nvmc.h b/ADIS_tinyK22_SplitFlap/source/nvmc.h new file mode 100644 index 0000000..af31218 --- /dev/null +++ b/ADIS_tinyK22_SplitFlap/source/nvmc.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2019-2022, Erich Styger + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NVMC_H_ +#define NVMC_H_ + +#include "platform.h" +#include +#include +#include "McuShell.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NVMC_FLAGS_MAGNET_ENABLED (1<<0) /* if magnets are enabled or not */ + +/*! + * \brief Provide the id/label of the stepper motor + * \param motorIdx Motor index + * \param id Where the id gets stored + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_GetStepperID(uint8_t motorIdx, int16_t *id); +/*! + * \brief Set the id/label of the stepper motor + * \param motorIdx Motor index + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_SetStepperID(uint8_t motorIdx, uint16_t id); + +/*! + * \brief Provide the offset from the magnet position for a stepper motor + * \param motorIdx Motor index + * \return Stored offset + */ +int16_t NVMC_GetStepperZeroOffset(uint8_t motorIdx); + +/*! + * \brief Store the offset from the magnet position for a stepper motor + * \param motorIdx Motor index + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_SetStepperZeroOffset(uint8_t motorIdx, int16_t offset); + +/*! + * \brief Getter to get the RS-485 address + * \param addr Where to store the address + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_GetRS485Addr(uint8_t *addr); + +/*! + * \brief Setter to set the RS-485 address. + * \param addr Address to store + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_SetRS485Addr(uint8_t addr); + +/*! + * \brief Return for a given motor the character it is responsible for. + * \param motorIdx Motor index number + * \param xp Where to store the x coordinate, returns -1 for not attached motor + * \param yp Where to store the y coordinate, returns -1 for not attached motor + */ +uint8_t NVMC_GetStepperPosition(uint8_t motorIdx, int16_t *xp, int16_t *yp); + +/*! + * \brief Set position for a given motor the character it is responsible for. + * \param motorIdx Motor index number + * \param xp Where to store the x coordinate, returns -1 for not attached motor + * \param yp Where to store the y coordinate, returns -1 for not attached motor + */ +uint8_t NVMC_SetStepperPosition(uint8_t motorIdx, int16_t xPos, int16_t yPos); + +/*! + * \brief Getter to get the flags stored + * \flags Where to store the flags + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_GetFlags(uint32_t *flags); + +/*! + * \brief Setter to set the flags in the configuration + * \param flags The flags to be set + * \return Error code, ERR_OK for everything ok + */ +uint8_t NVMC_SetFlags(uint32_t flags); + +/*! \brief Command line shell parser interface */ +uint8_t NVMC_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io); + +/*! \brief Module de-initialization */ +void NVMC_Deinit(void); + +/*! \brief Module initialization */ +void NVMC_Init(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* NVMC_H_ */ diff --git a/ADIS_tinyK22_SplitFlap/source/platform.c b/ADIS_tinyK22_SplitFlap/source/platform.c index 6aff52b..b29a668 100644 --- a/ADIS_tinyK22_SplitFlap/source/platform.c +++ b/ADIS_tinyK22_SplitFlap/source/platform.c @@ -18,6 +18,13 @@ #include "shell.h" #include "McuShellUart.h" #include "McuLog.h" +#if PL_CONFIG_USE_NVMC + #include "nvmc.h" +#endif +#if PL_CONFIG_USE_MININI + #include "MinIni/McuMinINI.h" + #include "minIni/McuFlash.h" +#endif void PL_Init(void){ @@ -26,6 +33,16 @@ void PL_Init(void){ CLOCK_EnableClock(kCLOCK_PortB); CLOCK_EnableClock(kCLOCK_PortC); + /* NVMC init */ +#if PL_CONFIG_USE_NVMC + NVMC_Init(); +#endif +#if PL_CONFIG_USE_MININI + McuMinINI_Init(); + McuFlash_Init(); + McuFlash_RegisterMemory((const void*)McuMinINI_CONFIG_FLASH_NVM_ADDR_START, 1*McuMinINI_CONFIG_FLASH_NVM_BLOCK_SIZE); +#endif + McuLib_Init(); McuRTOS_Init(); McuWait_Init(); @@ -55,4 +72,13 @@ void PL_Deinit(void){ McuWait_Deinit(); McuRTOS_Deinit(); McuLib_Deinit(); + + /* NVMC deinit */ +#if PL_CONFIG_USE_MININI + McuMinINI_Deinit(); + McuFlash_Deinit(); +#endif +#if PL_CONFIG_USE_NVMC + NVMC_Deinit(); +#endif } diff --git a/ADIS_tinyK22_SplitFlap/source/platform.h b/ADIS_tinyK22_SplitFlap/source/platform.h index f67cd9b..d668bf0 100644 --- a/ADIS_tinyK22_SplitFlap/source/platform.h +++ b/ADIS_tinyK22_SplitFlap/source/platform.h @@ -10,6 +10,8 @@ /* SETTINGS */ //#define APP_DEBUG +#define PL_CONFIG_USE_NVMC (1) +#define PL_CONFIG_USE_MININI (1 && PL_CONFIG_USE_NVMC) /* Platform initialization */ void PL_Init(void); diff --git a/ADIS_tinyK22_SplitFlap/source/shell.c b/ADIS_tinyK22_SplitFlap/source/shell.c index 693c320..d757bbd 100644 --- a/ADIS_tinyK22_SplitFlap/source/shell.c +++ b/ADIS_tinyK22_SplitFlap/source/shell.c @@ -13,6 +13,9 @@ #include "McuLog.h" #include "McuUtility.h" #include "MotOffsetTable.h" +#include "minIni/McuMinINI.h" +#include "minIni/McuFlash.h" +#include "nvmc.h" #define SHELL_CMD_ELEM_SIZE (sizeof(Shell_cmd_s)) @@ -138,6 +141,10 @@ static const McuShell_ParseCommandCallback CmdParserTable[] = ParseCommand, McuShell_ParseCommand, McuRTOS_ParseCommand, + McuFlash_ParseCommand, + ini_ParseCommand, + McuMinINI_ParseCommand, + NVMC_ParseCommand, NULL /* Sentinel */ };