diff options
Diffstat (limited to 'drivers')
75 files changed, 7541 insertions, 3260 deletions
diff --git a/drivers/fsl_adc16.c b/drivers/fsl_adc16.c index 800d1dc..0af6a44 100644 --- a/drivers/fsl_adc16.c +++ b/drivers/fsl_adc16.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,10 @@ static uint32_t ADC16_GetInstance(ADC_Type *base); /*! @brief Pointers to ADC16 bases for each instance. */ static ADC_Type *const s_adc16Bases[] = ADC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to ADC16 clocks for each instance. */ static const clock_ip_name_t s_adc16Clocks[] = ADC16_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -57,7 +59,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ADC16_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_adc16Bases); instance++) { if (s_adc16Bases[instance] == base) { @@ -65,7 +67,7 @@ static uint32_t ADC16_GetInstance(ADC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ADC16_COUNT); + assert(instance < ARRAY_SIZE(s_adc16Bases)); return instance; } @@ -76,8 +78,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* ADCx_CFG1. */ tmp32 = ADC_CFG1_ADICLK(config->clockSource) | ADC_CFG1_MODE(config->resolution); @@ -126,8 +130,10 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config) void ADC16_Deinit(ADC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_adc16Clocks[ADC16_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void ADC16_GetDefaultConfig(adc16_config_t *config) @@ -152,7 +158,7 @@ status_t ADC16_DoAutoCalibration(ADC_Type *base) volatile uint32_t tmp32; /* 'volatile' here is for the dummy read of ADCx_R[0] register. */ status_t status = kStatus_Success; - /* The calibration would be failed when in hardware mode. + /* The calibration would be failed when in hardwar mode. * Remember the hardware trigger state here and restore it later if the hardware trigger is enabled.*/ if (0U != (ADC_SC2_ADTRG_MASK & base->SC2)) { diff --git a/drivers/fsl_adc16.h b/drivers/fsl_adc16.h index 7f5169a..ea62c55 100644 --- a/drivers/fsl_adc16.h +++ b/drivers/fsl_adc16.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -73,7 +73,7 @@ enum _adc16_status_flags * @brief Channel multiplexer mode for each channel. * * For some ADC16 channels, there are two pin selections in channel multiplexer. For example, ADC0_SE4a and ADC0_SE4b - * are the different channels but share the same channel number. + * are the different channels that share the same channel number. */ typedef enum _adc_channel_mux_mode { @@ -103,7 +103,7 @@ typedef enum _adc16_resolution kADC16_Resolution12or13Bit = 1U, /*!< Single End 12-bit or Differential Sample 13-bit. */ kADC16_Resolution10or11Bit = 2U, /*!< Single End 10-bit or Differential Sample 11-bit. */ - /* This group of enumeration is for public user. */ + /* This group of enumeration is for a public user. */ kADC16_ResolutionSE8Bit = kADC16_Resolution8or9Bit, /*!< Single End 8-bit. */ kADC16_ResolutionSE12Bit = kADC16_Resolution12or13Bit, /*!< Single End 12-bit. */ kADC16_ResolutionSE10Bit = kADC16_Resolution10or11Bit, /*!< Single End 10-bit. */ @@ -202,7 +202,7 @@ typedef enum _adc16_pga_gain #endif /* FSL_FEATURE_ADC16_HAS_PGA */ /*! - * @brief ADC16 converter configuration . + * @brief ADC16 converter configuration. */ typedef struct _adc16_config { @@ -218,7 +218,7 @@ typedef struct _adc16_config } adc16_config_t; /*! - * @brief ADC16 Hardware compare configuration. + * @brief ADC16 Hardware comparison configuration. */ typedef struct _adc16_hardware_compare_config { @@ -295,9 +295,9 @@ void ADC16_Init(ADC_Type *base, const adc16_config_t *config); void ADC16_Deinit(ADC_Type *base); /*! - * @brief Gets an available pre-defined settings for converter's configuration. + * @brief Gets an available pre-defined settings for the converter's configuration. * - * This function initializes the converter configuration structure with an available settings. The default values are: + * This function initializes the converter configuration structure with available settings. The default values are as follows. * @code * config->referenceVoltageSource = kADC16_ReferenceVoltageSourceVref; * config->clockSource = kADC16_ClockSourceAsynchronousClock; @@ -309,7 +309,7 @@ void ADC16_Deinit(ADC_Type *base); * config->enableLowPower = false; * config->enableContinuousConversion = false; * @endcode - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void ADC16_GetDefaultConfig(adc16_config_t *config); @@ -317,15 +317,15 @@ void ADC16_GetDefaultConfig(adc16_config_t *config); /*! * @brief Automates the hardware calibration. * - * This auto calibration helps to adjust the plus/minus side gain automatically on the converter's working situation. + * This auto calibration helps to adjust the plus/minus side gain automatically. * Execute the calibration before using the converter. Note that the hardware trigger should be used - * during calibration. + * during the calibration. * * @param base ADC16 peripheral base address. * * @return Execution status. * @retval kStatus_Success Calibration is done successfully. - * @retval kStatus_Fail Calibration is failed. + * @retval kStatus_Fail Calibration has failed. */ status_t ADC16_DoAutoCalibration(ADC_Type *base); #endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */ @@ -349,16 +349,16 @@ static inline void ADC16_SetOffsetValue(ADC_Type *base, int16_t value) /* @} */ /*! - * @name Advanced Feature + * @name Advanced Features * @{ */ #if defined(FSL_FEATURE_ADC16_HAS_DMA) && FSL_FEATURE_ADC16_HAS_DMA /*! - * @brief Enables generating the DMA trigger when conversion is completed. + * @brief Enables generating the DMA trigger when the conversion is complete. * * @param base ADC16 peripheral base address. - * @param enable Switcher of DMA feature. "true" means to enable, "false" means not. + * @param enable Switcher of the DMA feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) { @@ -377,7 +377,7 @@ static inline void ADC16_EnableDMA(ADC_Type *base, bool enable) * @brief Enables the hardware trigger mode. * * @param base ADC16 peripheral base address. - * @param enable Switcher of hardware trigger feature. "true" means to enable, "false" means not. + * @param enable Switcher of the hardware trigger feature. "true" means enabled, "false" means not enabled. */ static inline void ADC16_EnableHardwareTrigger(ADC_Type *base, bool enable) { @@ -407,13 +407,12 @@ void ADC16_SetChannelMuxMode(ADC_Type *base, adc16_channel_mux_mode_t mode); /*! * @brief Configures the hardware compare mode. * - * The hardware compare mode provides a way to process the conversion result automatically by hardware. Only the result - * in - * compare range is available. To compare the range, see "adc16_hardware_compare_mode_t", or the reference - * manual document for more detailed information. + * The hardware compare mode provides a way to process the conversion result automatically by using hardware. Only the result + * in the compare range is available. To compare the range, see "adc16_hardware_compare_mode_t" or the appopriate reference + * manual for more information. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_hardware_compare_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_hardware_compare_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare_config_t *config); @@ -421,21 +420,21 @@ void ADC16_SetHardwareCompareConfig(ADC_Type *base, const adc16_hardware_compare /*! * @brief Sets the hardware average mode. * - * Hardware average mode provides a way to process the conversion result automatically by hardware. The multiple - * conversion results are accumulated and averaged internally. This aids reading results. + * The hardware average mode provides a way to process the conversion result automatically by using hardware. The multiple + * conversion results are accumulated and averaged internally making them easier to read. * * @param base ADC16 peripheral base address. - * @param mode Setting hardware average mode. See "adc16_hardware_average_mode_t". + * @param mode Setting the hardware average mode. See "adc16_hardware_average_mode_t". */ void ADC16_SetHardwareAverage(ADC_Type *base, adc16_hardware_average_mode_t mode); #endif /* FSL_FEATURE_ADC16_HAS_HW_AVERAGE */ #if defined(FSL_FEATURE_ADC16_HAS_PGA) && FSL_FEATURE_ADC16_HAS_PGA /*! - * @brief Configures the PGA for converter's front end. + * @brief Configures the PGA for the converter's front end. * * @param base ADC16 peripheral base address. - * @param config Pointer to "adc16_pga_config_t" structure. Passing "NULL" is to disable the feature. + * @param config Pointer to the "adc16_pga_config_t" structure. Passing "NULL" disables the feature. */ void ADC16_SetPGAConfig(ADC_Type *base, const adc16_pga_config_t *config); #endif /* FSL_FEATURE_ADC16_HAS_PGA */ @@ -467,26 +466,26 @@ void ADC16_ClearStatusFlags(ADC_Type *base, uint32_t mask); /*! * @brief Configures the conversion channel. * - * This operation triggers the conversion if in software trigger mode. When in hardware trigger mode, this API + * This operation triggers the conversion when in software trigger mode. When in hardware trigger mode, this API * configures the channel while the external trigger source helps to trigger the conversion. * * Note that the "Channel Group" has a detailed description. - * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC can have more than one - * group of status and control register, one for each conversion. The channel group parameter indicates which group of - * registers are used channel group 0 is for Group A registers and channel group 1 is for Group B registers. The + * To allow sequential conversions of the ADC to be triggered by internal peripherals, the ADC has more than one + * group of status and control registers, one for each conversion. The channel group parameter indicates which group of + * registers are used, for example, channel group 0 is for Group A registers and channel group 1 is for Group B registers. The * channel groups are used in a "ping-pong" approach to control the ADC operation. At any point, only one of - * the channel groups is actively controlling ADC conversions. Channel group 0 is used for both software and hardware - * trigger modes of operation. Channel groups 1 and greater indicate potentially multiple channel group registers for - * use only in hardware trigger mode. See the chip configuration information in the MCU reference manual about the - * number of SC1n registers (channel groups) specific to this device. None of the channel groups 1 or greater are used - * for software trigger operation and therefore writes to these channel groups do not initiate a new conversion. - * Updating channel group 0 while a different channel group is actively controlling a conversion is allowed and + * the channel groups is actively controlling ADC conversions. The channel group 0 is used for both software and hardware + * trigger modes. Channel group 1 and greater indicates multiple channel group registers for + * use only in hardware trigger mode. See the chip configuration information in the appropriate MCU reference manual for the + * number of SC1n registers (channel groups) specific to this device. Channel group 1 or greater are not used + * for software trigger operation. Therefore, writing to these channel groups does not initiate a new conversion. + * Updating the channel group 0 while a different channel group is actively controlling a conversion is allowed and * vice versa. Writing any of the channel group registers while that specific channel group is actively controlling a * conversion aborts the current conversion. * * @param base ADC16 peripheral base address. * @param channelGroup Channel group index. - * @param config Pointer to "adc16_channel_config_t" structure for conversion channel. + * @param config Pointer to the "adc16_channel_config_t" structure for the conversion channel. */ void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config); diff --git a/drivers/fsl_clock.c b/drivers/fsl_clock.c index b5549aa..210c080 100644 --- a/drivers/fsl_clock.c +++ b/drivers/fsl_clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -28,7 +29,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fsl_common.h" #include "fsl_clock.h" /******************************************************************************* @@ -190,17 +190,36 @@ static uint32_t CLOCK_GetPll0RefFreq(void); */ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq); +/******************************************************************************* + * Code + ******************************************************************************/ + +#ifndef MCG_USER_CONFIG_FLL_STABLE_DELAY_EN /*! * @brief Delay function to wait FLL stable. * * Delay function to wait FLL stable in FEI mode or FEE mode, should wait at least * 1ms. Every time changes FLL setting, should wait this time for FLL stable. */ -static void CLOCK_FllStableDelay(void); - -/******************************************************************************* - * Code - ******************************************************************************/ +void CLOCK_FllStableDelay(void) +{ + /* + Should wait at least 1ms. Because in these modes, the core clock is 100MHz + at most, so this function could obtain the 1ms delay. + */ + volatile uint32_t i = 30000U; + while (i--) + { + __NOP(); + } +} +#else /* With MCG_USER_CONFIG_FLL_STABLE_DELAY_EN defined. */ +/* Once user defines the MCG_USER_CONFIG_FLL_STABLE_DELAY_EN to use their own delay function, he has to + * create his own CLOCK_FllStableDelay() function in application code. Since the clock functions in this + * file would call the CLOCK_FllStableDelay() regardness how it is defined. + */ +extern void CLOCK_FllStableDelay(void); +#endif /* MCG_USER_CONFIG_FLL_STABLE_DELAY_EN */ static uint32_t CLOCK_GetMcgExtClkFreq(void) { @@ -334,19 +353,6 @@ static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq) return range; } -static void CLOCK_FllStableDelay(void) -{ - /* - Should wait at least 1ms. Because in these modes, the core clock is 100MHz - at most, so this function could obtain the 1ms delay. - */ - volatile uint32_t i = 30000U; - while (i--) - { - __NOP(); - } -} - uint32_t CLOCK_GetOsc0ErClkFreq(void) { if (OSC0->CR & OSC_CR_ERCLKEN_MASK) @@ -653,16 +659,6 @@ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel) } MCG->C7 = (MCG->C7 & ~MCG_C7_OSCSEL_MASK) | MCG_C7_OSCSEL(oscsel); - if (kMCG_OscselOsc == oscsel) - { - if (MCG->C2 & MCG_C2_EREFS_MASK) - { - while (!(MCG->S & MCG_S_OSCINIT0_MASK)) - { - } - } - } - if (needDelay) { /* ERR009878 Delay at least 50 micro-seconds for external clock change valid. */ @@ -1251,6 +1247,17 @@ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait and check status. */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1393,6 +1400,17 @@ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void | MCG_C1_FRDIV(frdiv) /* FRDIV = frdiv */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for Reference clock Status bit to clear */ while (kMCG_FllSrcExternal != MCG_S_IREFST_VAL) { @@ -1453,6 +1471,8 @@ status_t CLOCK_SetBlpeMode(void) status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config) { + assert(config); + /* This function is designed to change MCG to PBE mode from PEE/BLPE/FBE, but with this workflow, the source mode could be all modes except PEI/PBI. @@ -1481,6 +1501,8 @@ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *co /* Change to PLL mode. */ MCG->C6 |= MCG_C6_PLLS_MASK; + + /* Wait for PLL mode changed. */ while (!(MCG->S & MCG_S_PLLST_MASK)) { } @@ -1594,6 +1616,17 @@ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel) ((MCG->C1 & ~(MCG_C1_CLKS_MASK | MCG_C1_IREFS_MASK)) | (MCG_C1_CLKS(kMCG_ClkOutSrcExternal) /* CLKS = 2 */ | MCG_C1_IREFS(kMCG_FllSrcExternal))); /* IREFS = 0 */ + /* If use external crystal as clock source, wait for it stable. */ + if (MCG_C7_OSCSEL(kMCG_OscselOsc) == (MCG->C7 & MCG_C7_OSCSEL_MASK)) + { + if (MCG->C2 & MCG_C2_EREFS_MASK) + { + while (!(MCG->S & MCG_S_OSCINIT0_MASK)) + { + } + } + } + /* Wait for MCG_S[CLKST] and MCG_S[IREFST]. */ while ((MCG->S & (MCG_S_IREFST_MASK | MCG_S_CLKST_MASK)) != (MCG_S_IREFST(kMCG_FllSrcExternal) | MCG_S_CLKST(kMCG_ClkOutStatExt))) diff --git a/drivers/fsl_clock.h b/drivers/fsl_clock.h index 4c4fb59..8f5a577 100644 --- a/drivers/fsl_clock.h +++ b/drivers/fsl_clock.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright (c) 2016 - 2017 , NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -12,7 +13,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -31,10 +32,7 @@ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include <stdint.h> -#include <stdbool.h> -#include <assert.h> +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ @@ -42,39 +40,75 @@ /*! @file */ /******************************************************************************* + * Configurations + ******************************************************************************/ + +/*! @brief Configures whether to check a parameter in a function. + * + * Some MCG settings must be changed with conditions, for example: + * 1. MCGIRCLK settings, such as the source, divider, and the trim value should not change when + * MCGIRCLK is used as a system clock source. + * 2. MCG_C7[OSCSEL] should not be changed when the external reference clock is used + * as a system clock source. For example, in FBE/BLPE/PBE modes. + * 3. The users should only switch between the supported clock modes. + * + * MCG functions check the parameter and MCG status before setting, if not allowed + * to change, the functions return error. The parameter checking increases code size, + * if code size is a critical requirement, change #MCG_CONFIG_CHECK_PARAM to 0 to + * disable parameter checking. + */ +#ifndef MCG_CONFIG_CHECK_PARAM +#define MCG_CONFIG_CHECK_PARAM 0U +#endif + +/*! @brief Configure whether driver controls clock + * + * When set to 0, peripheral drivers will enable clock in initialize function + * and disable clock in de-initialize function. When set to 1, peripheral + * driver will not control the clock, application could contol the clock out of + * the driver. + * + * @note All drivers share this feature switcher. If it is set to 1, application + * should handle clock enable and disable for all drivers. + */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) +#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0 +#endif + +/******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief CLOCK driver version 2.2.0. */ -#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*! @brief CLOCK driver version 2.2.1. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 1)) /*@}*/ /*! @brief External XTAL0 (OSC0) clock frequency. * - * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal0Freq to set the value in to clock driver. For example, - * if XTAL0 is 8MHz, + * The XTAL0/EXTAL0 (OSC0) clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal0Freq to set the value in the clock driver. For example, + * if XTAL0 is 8 MHz: * @code - * CLOCK_InitOsc0(...); // Setup the OSC0 - * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to clock driver. + * CLOCK_InitOsc0(...); // Set up the OSC0 + * CLOCK_SetXtal0Freq(80000000); // Set the XTAL0 value to the clock driver. * @endcode * - * This is important for the multicore platforms, only one core needs to setup - * OSC0 using CLOCK_InitOsc0, all other cores need to call CLOCK_SetXtal0Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up the + * OSC0 using the CLOCK_InitOsc0. All other cores need to call the CLOCK_SetXtal0Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal0Freq; /*! @brief External XTAL32/EXTAL32/RTC_CLKIN clock frequency. * - * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz, when the clock is setup, use the - * function CLOCK_SetXtal32Freq to set the value in to clock driver. + * The XTAL32/EXTAL32/RTC_CLKIN clock frequency in Hz. When the clock is set up, use the + * function CLOCK_SetXtal32Freq to set the value in the clock driver. * - * This is important for the multicore platforms, only one core needs to setup - * the clock, all other cores need to call CLOCK_SetXtal32Freq - * to get valid clock frequency. + * This is important for the multicore platforms where only one core needs to set up + * the clock. All other cores need to call the CLOCK_SetXtal32Freq + * to get a valid clock frequency. */ extern uint32_t g_xtal32Freq; @@ -185,9 +219,9 @@ extern uint32_t g_xtal32Freq; } /*! @brief Clock ip name array for MPU. */ -#define MPU_CLOCKS \ - { \ - kCLOCK_Mpu0 \ +#define SYSMPU_CLOCKS \ + { \ + kCLOCK_Sysmpu0 \ } /*! @brief Clock ip name array for VREF. */ @@ -384,7 +418,7 @@ typedef enum _clock_ip_name kCLOCK_Flexbus0 = CLK_GATE_DEFINE(0x1040U, 0U), kCLOCK_Dma0 = CLK_GATE_DEFINE(0x1040U, 1U), - kCLOCK_Mpu0 = CLK_GATE_DEFINE(0x1040U, 2U), + kCLOCK_Sysmpu0 = CLK_GATE_DEFINE(0x1040U, 2U), } clock_ip_name_t; /*!@brief SIM configuration structure for clock setting. */ @@ -398,7 +432,7 @@ typedef struct _sim_clock_config /*! @brief OSC work mode. */ typedef enum _osc_mode { - kOSC_ModeExt = 0U, /*!< Use external clock. */ + kOSC_ModeExt = 0U, /*!< Use an external clock. */ #if (defined(MCG_C2_EREFS_MASK) && !(defined(MCG_C2_EREFS0_MASK))) kOSC_ModeOscLowPower = MCG_C2_EREFS_MASK, /*!< Oscillator low power. */ #else @@ -448,8 +482,8 @@ typedef struct _oscer_config * @brief OSC Initialization Configuration Structure * * Defines the configuration data structure to initialize the OSC. - * When porting to a new board, please set the following members - * according to board setting: + * When porting to a new board, set the following members + * according to the board setting: * 1. freq: The external frequency. * 2. workMode: The OSC module mode. */ @@ -545,8 +579,8 @@ enum _mcg_status kStatus_MCG_AtmDesiredFreqInvalid = MAKE_STATUS(kStatusGroup_MCG, 3), /*!< Invalid desired frequency for ATM. */ kStatus_MCG_AtmIrcUsed = MAKE_STATUS(kStatusGroup_MCG, 4), /*!< IRC is used when using ATM. */ kStatus_MCG_AtmHardwareFail = MAKE_STATUS(kStatusGroup_MCG, 5), /*!< Hardware fail occurs during ATM. */ - kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Could not change clock source because - it is used currently. */ + kStatus_MCG_SourceUsed = MAKE_STATUS(kStatusGroup_MCG, 6) /*!< Can't change the clock source because + it is in use. */ }; /*! @brief MCG status flags. */ @@ -569,11 +603,11 @@ enum _mcg_irclk_enable_mode /*! @brief MCG PLL clock enable mode definition. */ enum _mcg_pll_enable_mode { - kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable indepencent of - MCG clock mode. Generally, PLL + kMCG_PllEnableIndependent = MCG_C5_PLLCLKEN0_MASK, /*!< MCGPLLCLK enable independent of the + MCG clock mode. Generally, the PLL is disabled in FLL modes - (FEI/FBI/FEE/FBE), set PLL clock - enable independent will enable + (FEI/FBI/FEE/FBE). Setting the PLL clock + enable independent, enables the PLL in the FLL modes. */ kMCG_PllEnableInStop = MCG_C5_PLLSTEN0_MASK /*!< MCGPLLCLK enable in STOP mode. */ }; @@ -600,16 +634,16 @@ typedef struct _mcg_pll_config uint8_t vdiv; /*!< VCO divider VDIV. */ } mcg_pll_config_t; -/*! @brief MCG configure structure for mode change. +/*! @brief MCG mode change configuration structure * - * When porting to a new board, please set the following members - * according to board setting: - * 1. frdiv: If FLL uses the external reference clock, please set this - * value to make sure external reference clock divided by frdiv is - * in the range 31.25kHz to 39.0625kHz. + * When porting to a new board, set the following members + * according to the board setting: + * 1. frdiv: If the FLL uses the external reference clock, set this + * value to ensure that the external reference clock divided by frdiv is + * in the 31.25 kHz to 39.0625 kHz range. * 2. The PLL reference clock divider PRDIV: PLL reference clock frequency after - * PRDIV should be in the range of FSL_FEATURE_MCG_PLL_REF_MIN to - * FSL_FEATURE_MCG_PLL_REF_MAX. + * PRDIV should be in the FSL_FEATURE_MCG_PLL_REF_MIN to + * FSL_FEATURE_MCG_PLL_REF_MAX range. */ typedef struct _mcg_config { @@ -854,9 +888,9 @@ static inline void CLOCK_SetSimSafeDivs(void) /*@{*/ /*! - * @brief Get the MCG output clock(MCGOUTCLK) frequency. + * @brief Gets the MCG output clock (MCGOUTCLK) frequency. * - * This function gets the MCG output clock frequency (Hz) based on current MCG + * This function gets the MCG output clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGOUTCLK. @@ -864,40 +898,40 @@ static inline void CLOCK_SetSimSafeDivs(void) uint32_t CLOCK_GetOutClkFreq(void); /*! - * @brief Get the MCG FLL clock(MCGFLLCLK) frequency. + * @brief Gets the MCG FLL clock (MCGFLLCLK) frequency. * - * This function gets the MCG FLL clock frequency (Hz) based on current MCG - * register value. The FLL is only enabled in FEI/FBI/FEE/FBE mode, in other - * modes, FLL is disabled in low power state. + * This function gets the MCG FLL clock frequency in Hz based on the current MCG + * register value. The FLL is enabled in FEI/FBI/FEE/FBE mode and + * disabled in low power state in other modes. * * @return The frequency of MCGFLLCLK. */ uint32_t CLOCK_GetFllFreq(void); /*! - * @brief Get the MCG internal reference clock(MCGIRCLK) frequency. + * @brief Gets the MCG internal reference clock (MCGIRCLK) frequency. * - * This function gets the MCG internal reference clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG internal reference clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGIRCLK. */ uint32_t CLOCK_GetInternalRefClkFreq(void); /*! - * @brief Get the MCG fixed frequency clock(MCGFFCLK) frequency. + * @brief Gets the MCG fixed frequency clock (MCGFFCLK) frequency. * - * This function gets the MCG fixed frequency clock frequency (Hz) based - * on current MCG register value. + * This function gets the MCG fixed frequency clock frequency in Hz based + * on the current MCG register value. * * @return The frequency of MCGFFCLK. */ uint32_t CLOCK_GetFixedFreqClkFreq(void); /*! - * @brief Get the MCG PLL0 clock(MCGPLL0CLK) frequency. + * @brief Gets the MCG PLL0 clock (MCGPLL0CLK) frequency. * - * This function gets the MCG PLL0 clock frequency (Hz) based on current MCG + * This function gets the MCG PLL0 clock frequency in Hz based on the current MCG * register value. * * @return The frequency of MCGPLL0CLK. @@ -910,12 +944,12 @@ uint32_t CLOCK_GetPll0Freq(void); /*@{*/ /*! - * @brief Enable or disable MCG low power. + * @brief Enables or disables the MCG low power. * - * Enable MCG low power will disable the PLL and FLL in bypass modes. That is, - * in FBE and PBE modes, enable low power will set MCG to BLPE mode, in FBI and - * PBI mode, enable low power will set MCG to BLPI mode. - * When disable MCG low power, the PLL or FLL will be enabled based on MCG setting. + * Enabling the MCG low power disables the PLL and FLL in bypass modes. In other words, + * in FBE and PBE modes, enabling low power sets the MCG to BLPE mode. In FBI and + * PBI modes, enabling low power sets the MCG to BLPI mode. + * When disabling the MCG low power, the PLL or FLL are enabled based on MCG settings. * * @param enable True to enable MCG low power, false to disable MCG low power. */ @@ -932,42 +966,56 @@ static inline void CLOCK_SetLowPowerEnable(bool enable) } /*! - * @brief Configure the Internal Reference clock (MCGIRCLK) + * @brief Configures the Internal Reference clock (MCGIRCLK). * - * This function setups the \c MCGIRCLK base on parameters. It selects the IRC - * source, if fast IRC is used, this function also sets the fast IRC divider. - * This function also sets whether enable \c MCGIRCLK in stop mode. - * Calling this function in FBI/PBI/BLPI modes may change the system clock, so - * it is not allowed to use this in these modes. + * This function sets the \c MCGIRCLK base on parameters. It also selects the IRC + * source. If the fast IRC is used, this function sets the fast IRC divider. + * This function also sets whether the \c MCGIRCLK is enabled in stop mode. + * Calling this function in FBI/PBI/BLPI modes may change the system clock. As a result, + * using the function in these modes it is not allowed. * * @param enableMode MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * @param ircs MCGIRCLK clock source, choose fast or slow. * @param fcrdiv Fast IRC divider setting (\c FCRDIV). - * @retval kStatus_MCG_SourceUsed MCGIRCLK is used as system clock, should not configure MCGIRCLK. + * @retval kStatus_MCG_SourceUsed Because the internall reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success MCGIRCLK configuration finished successfully. */ status_t CLOCK_SetInternalRefClkConfig(uint8_t enableMode, mcg_irc_mode_t ircs, uint8_t fcrdiv); /*! - * @brief Select the MCG external reference clock. + * @brief Selects the MCG external reference clock. * - * Select the MCG external reference clock source, it changes the MCG_C7[OSCSEL] - * and wait for the clock source stable. Should not change external reference - * clock in FEE/FBE/BLPE/PBE/PEE mdes, so don't call this function in these modes. + * Selects the MCG external reference clock source, changes the MCG_C7[OSCSEL], + * and waits for the clock source to be stable. Because the external reference + * clock should not be changed in FEE/FBE/BLPE/PBE/PEE modes, do not call this function in these modes. * * @param oscsel MCG external reference clock source, MCG_C7[OSCSEL]. - * @retval kStatus_MCG_SourceUsed External reference clock is used, should not change. + * @retval kStatus_MCG_SourceUsed Because the external reference clock is used as a clock source, + * the confuration should not be changed. Otherwise, a glitch occurs. * @retval kStatus_Success External reference clock set successfully. */ status_t CLOCK_SetExternalRefClkConfig(mcg_oscsel_t oscsel); /*! + * @brief Set the FLL external reference clock divider value. + * + * Sets the FLL external reference clock divider value, the register MCG_C1[FRDIV]. + * + * @param frdiv The FLL external reference clock divider value, MCG_C1[FRDIV]. + */ +static inline void CLOCK_SetFllExtRefDiv(uint8_t frdiv) +{ + MCG->C1 = (MCG->C1 & ~MCG_C1_FRDIV_MASK) | MCG_C1_FRDIV(frdiv); +} + +/*! * @brief Enables the PLL0 in FLL mode. * - * This function setups the PLL0 in FLL mode, make sure the PLL reference - * clock is enabled before calling this function. This function reconfigures - * the PLL0, make sure the PLL0 is not used as a clock source while calling - * this function. The function CLOCK_CalcPllDiv can help to get the proper PLL + * This function sets us the PLL0 in FLL mode and reconfigures + * the PLL0. Ensure that the PLL reference + * clock is enabled before calling this function and that the PLL0 is not used as a clock source. + * The function CLOCK_CalcPllDiv gets the correct PLL * divider values. * * @param config Pointer to the configuration structure. @@ -977,7 +1025,7 @@ void CLOCK_EnablePll0(mcg_pll_config_t const *config); /*! * @brief Disables the PLL0 in FLL mode. * - * This function disables the PLL0 in FLL mode, it should be used together with + * This function disables the PLL0 in FLL mode. It should be used together with the * @ref CLOCK_EnablePll0. */ static inline void CLOCK_DisablePll0(void) @@ -986,19 +1034,19 @@ static inline void CLOCK_DisablePll0(void) } /*! - * @brief Calculates the PLL divider setting for desired output frequency. + * @brief Calculates the PLL divider setting for a desired output frequency. * - * This function calculates the proper reference clock divider (\c PRDIV) and - * VCO divider (\c VDIV) to generate desired PLL output frequency. It returns the - * closest frequency PLL could generate, the corresponding \c PRDIV/VDIV are - * returned from parameters. If desired frequency is not valid, this function + * This function calculates the correct reference clock divider (\c PRDIV) and + * VCO divider (\c VDIV) to generate a desired PLL output frequency. It returns the + * closest frequency match with the corresponding \c PRDIV/VDIV + * returned from parameters. If a desired frequency is not valid, this function * returns 0. * * @param refFreq PLL reference clock frequency. * @param desireFreq Desired PLL output frequency. * @param prdiv PRDIV value to generate desired PLL frequency. * @param vdiv VDIV value to generate desired PLL frequency. - * @return Closest frequency PLL could generate. + * @return Closest frequency match that the PLL was able generate. */ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, uint8_t *vdiv); @@ -1008,38 +1056,38 @@ uint32_t CLOCK_CalcPllDiv(uint32_t refFreq, uint32_t desireFreq, uint8_t *prdiv, /*@{*/ /*! - * @brief Set the OSC0 clock monitor mode. + * @brief Sets the OSC0 clock monitor mode. * - * Set the OSC0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the OSC0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetOsc0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the RTC OSC clock monitor mode. + * @brief Sets the RTC OSC clock monitor mode. * - * Set the RTC OSC clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the RTC OSC clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetRtcOscMonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Set the PLL0 clock monitor mode. + * @brief Sets the PLL0 clock monitor mode. * - * Set the PLL0 clock monitor mode, see @ref mcg_monitor_mode_t for details. + * This function sets the PLL0 clock monitor mode. See @ref mcg_monitor_mode_t for details. * - * @param mode The monitor mode to set. + * @param mode Monitor mode to set. */ void CLOCK_SetPll0MonitorMode(mcg_monitor_mode_t mode); /*! - * @brief Get the MCG status flags. + * @brief Gets the MCG status flags. * - * This function gets the MCG clock status flags, all the status flags are + * This function gets the MCG clock status flags. All status flags are * returned as a logical OR of the enumeration @ref _mcg_status_flags_t. To - * check specific flags, compare the return value with the flags. + * check a specific flag, compare the return value with the flag. * * Example: * @code @@ -1065,8 +1113,8 @@ uint32_t CLOCK_GetStatusFlags(void); /*! * @brief Clears the MCG status flags. * - * This function clears the MCG clock lock lost status. The parameter is logical - * OR value of the flags to clear, see @ref _mcg_status_flags_t. + * This function clears the MCG clock lock lost status. The parameter is a logical + * OR value of the flags to clear. See @ref _mcg_status_flags_t. * * Example: * @code @@ -1091,8 +1139,8 @@ void CLOCK_ClearStatusFlags(uint32_t mask); * @brief Configures the OSC external reference clock (OSCERCLK). * * This function configures the OSC external reference clock (OSCERCLK). - * For example, to enable the OSCERCLK in normal mode and stop mode, and also set - * the output divider to 1, as follows: + * This is an example to enable the OSCERCLK in normal and stop modes and also set + * the output divider to 1: * @code oscer_config_t config = @@ -1144,18 +1192,18 @@ static inline void OSC_SetCapLoad(OSC_Type *base, uint8_t capLoad) } /*! - * @brief Initialize OSC0. + * @brief Initializes the OSC0. * - * This function initializes OSC0 according to board configuration. + * This function initializes the OSC0 according to the board configuration. * * @param config Pointer to the OSC0 configuration structure. */ void CLOCK_InitOsc0(osc_config_t const *config); /*! - * @brief Deinitialize OSC0. + * @brief Deinitializes the OSC0. * - * This function deinitializes OSC0. + * This function deinitializes the OSC0. */ void CLOCK_DeinitOsc0(void); @@ -1167,7 +1215,7 @@ void CLOCK_DeinitOsc0(void); */ /*! - * @brief Set the XTAL0 frequency based on board setting. + * @brief Sets the XTAL0 frequency based on board settings. * * @param freq The XTAL0/EXTAL0 input clock frequency in Hz. */ @@ -1177,7 +1225,7 @@ static inline void CLOCK_SetXtal0Freq(uint32_t freq) } /*! - * @brief Set the XTAL32/RTC_CLKIN frequency based on board setting. + * @brief Sets the XTAL32/RTC_CLKIN frequency based on board settings. * * @param freq The XTAL32/EXTAL32/RTC_CLKIN input clock frequency in Hz. */ @@ -1193,22 +1241,22 @@ static inline void CLOCK_SetXtal32Freq(uint32_t freq) */ /*! - * @brief Auto trim the internal reference clock. + * @brief Auto trims the internal reference clock. * - * This function trims the internal reference clock using external clock. If + * This function trims the internal reference clock by using the external clock. If * successful, it returns the kStatus_Success and the frequency after * trimming is received in the parameter @p actualFreq. If an error occurs, * the error code is returned. * - * @param extFreq External clock frequency, should be bus clock. - * @param desireFreq Frequency want to trim to. - * @param actualFreq Actual frequency after trim. + * @param extFreq External clock frequency, which should be a bus clock. + * @param desireFreq Frequency to trim to. + * @param actualFreq Actual frequency after trimming. * @param atms Trim fast or slow internal reference clock. * @retval kStatus_Success ATM success. - * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for ATM. + * @retval kStatus_MCG_AtmBusClockInvalid The bus clock is not in allowed range for the ATM. * @retval kStatus_MCG_AtmDesiredFreqInvalid MCGIRCLK could not be trimmed to the desired frequency. - * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as bus clock source. - * @retval kStatus_MCG_AtmHardwareFail Hardware fails during trim. + * @retval kStatus_MCG_AtmIrcUsed Could not trim because MCGIRCLK is used as a bus clock source. + * @retval kStatus_MCG_AtmHardwareFail Hardware fails while trimming. */ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_t *actualFreq, mcg_atm_select_t atms); /* @} */ @@ -1219,265 +1267,265 @@ status_t CLOCK_TrimInternalRefClk(uint32_t extFreq, uint32_t desireFreq, uint32_ /*! * @brief Gets the current MCG mode. * - * This function checks the MCG registers and determine current MCG mode. + * This function checks the MCG registers and determines the current MCG mode. * - * @return Current MCG mode or error code, see @ref mcg_mode_t. + * @return Current MCG mode or error code; See @ref mcg_mode_t. */ mcg_mode_t CLOCK_GetMode(void); /*! - * @brief Set MCG to FEI mode. + * @brief Sets the MCG to FEI mode. * - * This function sets MCG to FEI mode. If could not set to FEI mode directly - * from current mode, this function returns error. + * This function sets the MCG to FEI mode. If setting to FEI mode fails + * from the current mode, this function returns an error. * * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to ensure that the FLL is stable. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed - * to frequency above 32768Hz. + * to a frequency above 32768 Hz. */ status_t CLOCK_SetFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode. + * @brief Sets the MCG to FEE mode. * - * This function sets MCG to FEE mode. If could not set to FEE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FEE mode. If setting to FEE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable, if pass - * in NULL, then does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. Passing + * NULL does not cause a delay. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFeeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBI mode. + * @brief Sets the MCG to FBI mode. * - * This function sets MCG to FBI mode. If could not set to FBI mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBI mode. If setting to FBI mode fails + * from the current mode, this function returns an error. * * @param dmx32 DMX32 in FBI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBI mode, this parameter could be NULL. Pass in - * NULL does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBI mode, this parameter can be NULL. Passing + * NULL does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed - * to frequency above 32768Hz. + * to frequency above 32768 Hz. */ status_t CLOCK_SetFbiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FBE mode. + * @brief Sets the MCG to FBE mode. * - * This function sets MCG to FBE mode. If could not set to FBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to FBE mode. If setting to FBE mode fails + * from the current mode, this function returns an error. * * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FBE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. If FLL - * is not used in FBE mode, this parameter could be NULL. Pass in NULL - * does not delay. + * @param fllStableDelay Delay function to make sure FLL is stable. If the FLL + * is not used in FBE mode, this parameter can be NULL. Passing NULL + * does not cause a delay. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetFbeMode(uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode. + * @brief Sets the MCG to BLPI mode. * - * This function sets MCG to BLPI mode. If could not set to BLPI mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPI mode. If setting to BLPI mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpiMode(void); /*! - * @brief Set MCG to BLPE mode. + * @brief Sets the MCG to BLPE mode. * - * This function sets MCG to BLPE mode. If could not set to BLPE mode directly - * from current mode, this function returns error. + * This function sets the MCG to BLPE mode. If setting to BLPE mode fails + * from the current mode, this function returns an error. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_SetBlpeMode(void); /*! - * @brief Set MCG to PBE mode. + * @brief Sets the MCG to PBE mode. * - * This function sets MCG to PBE mode. If could not set to PBE mode directly - * from current mode, this function returns error. + * This function sets the MCG to PBE mode. If setting to PBE mode fails + * from the current mode, this function returns an error. * * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * * @note - * 1. The parameter \c pllcs selects the PLL, for some platforms, there is - * only one PLL, the parameter pllcs is kept for interface compatible. - * 2. The parameter \c config is the PLL configuration structure, on some - * platforms, could choose the external PLL directly. This means that the - * configuration structure is not necessary, pass in NULL for this case. + * 1. The parameter \c pllcs selects the PLL. For platforms with + * only one PLL, the parameter pllcs is kept for interface compatibility. + * 2. The parameter \c config is the PLL configuration structure. On some + * platforms, it is possible to choose the external PLL directly, which renders the + * configuration structure not necessary. In this case, pass in NULL. * For example: CLOCK_SetPbeMode(kMCG_OscselOsc, kMCG_PllClkSelExtPll, NULL); */ status_t CLOCK_SetPbeMode(mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to PEE mode. + * @brief Sets the MCG to PEE mode. * - * This function sets MCG to PEE mode. + * This function sets the MCG to PEE mode. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * - * @note This function only change CLKS to use PLL/FLL output. If the - * PRDIV/VDIV are different from PBE mode, please setup these - * settings in PBE mode and wait for stable then switch to PEE mode. + * @note This function only changes the CLKS to use the PLL/FLL output. If the + * PRDIV/VDIV are different than in the PBE mode, set them up + * in PBE mode and wait. When the clock is stable, switch to PEE mode. */ status_t CLOCK_SetPeeMode(void); /*! - * @brief Switch MCG to FBE mode quickly from external mode. + * @brief Switches the MCG to FBE mode from the external mode. * - * This function changes MCG from external modes (PEE/PBE/BLPE/FEE) to FBE mode quickly. - * It only changes to use external clock as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEE mode to FEI mode: + * This function switches the MCG from external modes (PEE/PBE/BLPE/FEE) to the FBE mode quickly. + * The external clock is used as the system clock souce and PLL is disabled. However, + * the FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEE mode to FEI mode: * * @code * CLOCK_ExternalModeToFbeModeQuick(); * CLOCK_SetFeiMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not external modes, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an external mode, do not call this function. */ status_t CLOCK_ExternalModeToFbeModeQuick(void); /*! - * @brief Switch MCG to FBI mode quickly from internal modes. + * @brief Switches the MCG to FBI mode from internal modes. * - * This function changes MCG from internal modes (PEI/PBI/BLPI/FEI) to FBI mode quickly. - * It only changes to use MCGIRCLK as the system clock souce and disable PLL, but does not - * configure FLL settings. This is a lite function with small code size, it is useful - * during mode switch. For example, to switch from PEI mode to FEE mode: + * This function switches the MCG from internal modes (PEI/PBI/BLPI/FEI) to the FBI mode quickly. + * The MCGIRCLK is used as the system clock souce and PLL is disabled. However, + * FLL settings are not configured. This is a lite function with a small code size, which is useful + * during the mode switch. For example, to switch from PEI mode to FEE mode: * * @code * CLOCK_InternalModeToFbiModeQuick(); * CLOCK_SetFeeMode(...); * @endcode * - * @retval kStatus_Success Change successfully. - * @retval kStatus_MCG_ModeInvalid Current mode is not internal mode, should not call this function. + * @retval kStatus_Success Switched successfully. + * @retval kStatus_MCG_ModeInvalid If the current mode is not an internal mode, do not call this function. */ status_t CLOCK_InternalModeToFbiModeQuick(void); /*! - * @brief Set MCG to FEI mode during system boot up. + * @brief Sets the MCG to FEI mode during system boot up. * - * This function sets MCG to FEI mode from reset mode, it could be used to + * This function sets the MCG to FEI mode from the reset mode. It can also be used to * set up MCG during system boot up. * * @param dmx32 DMX32 in FEI mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. * @note If @p dmx32 is set to kMCG_Dmx32Fine, the slow IRC must not be trimmed - * to frequency above 32768Hz. + * to frequency above 32768 Hz. */ status_t CLOCK_BootToFeiMode(mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to FEE mode during system bootup. + * @brief Sets the MCG to FEE mode during system bootup. * - * This function sets MCG to FEE mode from reset mode, it could be used to - * set up MCG during system boot up. + * This function sets MCG to FEE mode from the reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, OSCSEL. * @param frdiv FLL reference clock divider setting, FRDIV. * @param dmx32 DMX32 in FEE mode. * @param drs The DCO range selection. - * @param fllStableDelay Delay function to make sure FLL is stable. + * @param fllStableDelay Delay function to ensure that the FLL is stable. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToFeeMode( mcg_oscsel_t oscsel, uint8_t frdiv, mcg_dmx32_t dmx32, mcg_drs_t drs, void (*fllStableDelay)(void)); /*! - * @brief Set MCG to BLPI mode during system boot up. + * @brief Sets the MCG to BLPI mode during system boot up. * - * This function sets MCG to BLPI mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPI mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param fcrdiv Fast IRC divider, FCRDIV. * @param ircs The internal reference clock to select, IRCS. * @param ircEnableMode The MCGIRCLK enable mode, OR'ed value of @ref _mcg_irclk_enable_mode. * * @retval kStatus_MCG_SourceUsed Could not change MCGIRCLK setting. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpiMode(uint8_t fcrdiv, mcg_irc_mode_t ircs, uint8_t ircEnableMode); /*! - * @brief Set MCG to BLPE mode during sytem boot up. + * @brief Sets the MCG to BLPE mode during sytem boot up. * - * This function sets MCG to BLPE mode from reset mode, it could be used to - * setup MCG during sytem boot up. + * This function sets the MCG to BLPE mode from the reset mode. It can also be used to + * set up the MCG during sytem boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToBlpeMode(mcg_oscsel_t oscsel); /*! - * @brief Set MCG to PEE mode during system boot up. + * @brief Sets the MCG to PEE mode during system boot up. * - * This function sets MCG to PEE mode from reset mode, it could be used to - * setup MCG during system boot up. + * This function sets the MCG to PEE mode from reset mode. It can also be used to + * set up the MCG during system boot up. * * @param oscsel OSC clock select, MCG_C7[OSCSEL]. * @param pllcs The PLL selection, PLLCS. * @param config Pointer to the PLL configuration. * * @retval kStatus_MCG_ModeUnreachable Could not switch to the target mode. - * @retval kStatus_Success Switch to target mode successfully. + * @retval kStatus_Success Switched to the target mode successfully. */ status_t CLOCK_BootToPeeMode(mcg_oscsel_t oscsel, mcg_pll_clk_select_t pllcs, mcg_pll_config_t const *config); /*! - * @brief Set MCG to some target mode. + * @brief Sets the MCG to a target mode. * - * This function sets MCG to some target mode defined by the configure - * structure, if cannot switch to target mode directly, this function will - * choose the proper path. + * This function sets MCG to a target mode defined by the configuration + * structure. If switching to the target mode fails, this function + * chooses the correct path. * * @param config Pointer to the target MCG mode configuration structure. - * @return Return kStatus_Success if switch successfully, otherwise return error code #_mcg_status. + * @return Return kStatus_Success if switched successfully; Otherwise, it returns an error code #_mcg_status. * - * @note If external clock is used in the target mode, please make sure it is - * enabled, for example, if the OSC0 is used, please setup OSC0 correctly before - * this funciton. + * @note If the external clock is used in the target mode, ensure that it is + * enabled. For example, if the OSC0 is used, set up OSC0 correctly before calling this + * function. */ status_t CLOCK_SetMcgConfig(mcg_config_t const *config); diff --git a/drivers/fsl_cmp.c b/drivers/fsl_cmp.c index 557a0c5..6a5f15a 100644 --- a/drivers/fsl_cmp.c +++ b/drivers/fsl_cmp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t CMP_GetInstance(CMP_Type *base); ******************************************************************************/ /*! @brief Pointers to CMP bases for each instance. */ static CMP_Type *const s_cmpBases[] = CMP_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to CMP clocks for each instance. */ static const clock_ip_name_t s_cmpClocks[] = CMP_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMP_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmpBases); instance++) { if (s_cmpBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t CMP_GetInstance(CMP_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMP_COUNT); + assert(instance < ARRAY_SIZE(s_cmpBases)); return instance; } @@ -75,8 +77,10 @@ void CMP_Init(CMP_Type *base, const cmp_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ CMP_Enable(base, false); /* Disable the CMP module during configuring. */ @@ -123,8 +127,10 @@ void CMP_Deinit(CMP_Type *base) /* Disable the CMP module. */ CMP_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_cmpClocks[CMP_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMP_GetDefaultConfig(cmp_config_t *config) diff --git a/drivers/fsl_cmp.h b/drivers/fsl_cmp.h index 4c85bba..5d16bf0 100644 --- a/drivers/fsl_cmp.h +++ b/drivers/fsl_cmp.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -63,8 +63,8 @@ enum _cmp_interrupt_enable */ enum _cmp_status_flags { - kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on compare output has occurred. */ - kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on compare output has occurred. */ + kCMP_OutputRisingEventFlag = CMP_SCR_CFR_MASK, /*!< Rising-edge on the comparison output has occurred. */ + kCMP_OutputFallingEventFlag = CMP_SCR_CFF_MASK, /*!< Falling-edge on the comparison output has occurred. */ kCMP_OutputAssertEventFlag = CMP_SCR_COUT_MASK, /*!< Return the current value of the analog comparator output. */ }; @@ -84,20 +84,20 @@ typedef enum _cmp_hysteresis_mode */ typedef enum _cmp_reference_voltage_source { - kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as resistor ladder network supply reference Vin. */ - kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin1 = 0U, /*!< Vin1 is selected as a resistor ladder network supply reference Vin. */ + kCMP_VrefSourceVin2 = 1U, /*!< Vin2 is selected as a resistor ladder network supply reference Vin. */ } cmp_reference_voltage_source_t; /*! - * @brief Configuration for the comparator. + * @brief Configures the comparator. */ typedef struct _cmp_config { bool enableCmp; /*!< Enable the CMP module. */ cmp_hysteresis_mode_t hysteresisMode; /*!< CMP Hysteresis mode. */ - bool enableHighSpeed; /*!< Enable High-speed comparison mode. */ - bool enableInvertOutput; /*!< Enable inverted comparator output. */ - bool useUnfilteredOutput; /*!< Set compare output(COUT) to equal COUTA(true) or COUT(false). */ + bool enableHighSpeed; /*!< Enable High-speed (HS) comparison mode. */ + bool enableInvertOutput; /*!< Enable the inverted comparator output. */ + bool useUnfilteredOutput; /*!< Set the compare output(COUT) to equal COUTA(true) or COUT(false). */ bool enablePinOut; /*!< The comparator output is available on the associated pin. */ #if defined(FSL_FEATURE_CMP_HAS_TRIGGER_MODE) && FSL_FEATURE_CMP_HAS_TRIGGER_MODE bool enableTriggerMode; /*!< Enable the trigger mode. */ @@ -105,24 +105,24 @@ typedef struct _cmp_config } cmp_config_t; /*! - * @brief Configuration for the filter. + * @brief Configures the filter. */ typedef struct _cmp_filter_config { #if defined(FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT) && FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT - bool enableSample; /*!< Using external SAMPLE as sampling clock input, or using divided bus clock. */ + bool enableSample; /*!< Using the external SAMPLE as a sampling clock input or using a divided bus clock. */ #endif /* FSL_FEATURE_CMP_HAS_EXTERNAL_SAMPLE_SUPPORT */ - uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7, 0 would cause the filter disabled.*/ - uint8_t filterPeriod; /*!< Filter Sample Period. The divider to bus clock. Available range is 0-255. */ + uint8_t filterCount; /*!< Filter Sample Count. Available range is 1-7; 0 disables the filter.*/ + uint8_t filterPeriod; /*!< Filter Sample Period. The divider to the bus clock. Available range is 0-255. */ } cmp_filter_config_t; /*! - * @brief Configuration for the internal DAC. + * @brief Configures the internal DAC. */ typedef struct _cmp_dac_config { cmp_reference_voltage_source_t referenceVoltageSource; /*!< Supply voltage reference source. */ - uint8_t DACValue; /*!< Value for DAC Output Voltage. Available range is 0-63.*/ + uint8_t DACValue; /*!< Value for the DAC Output Voltage. Available range is 0-63.*/ } cmp_dac_config_t; #if defined(__cplusplus) @@ -141,28 +141,28 @@ extern "C" { /*! * @brief Initializes the CMP. * - * This function initializes the CMP module. The operations included are: + * This function initializes the CMP module. The operations included are as follows. * - Enabling the clock for CMP module. * - Configuring the comparator. * - Enabling the CMP module. - * Note: For some devices, multiple CMP instance share the same clock gate. In this case, to enable the clock for - * any instance enables all the CMPs. Check the chip reference manual for the clock assignment of the CMP. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, to enable the clock for + * any instance enables all CMPs. See the appropriate MCU reference manual for the clock assignment of the CMP. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_Init(CMP_Type *base, const cmp_config_t *config); /*! * @brief De-initializes the CMP module. * - * This function de-initializes the CMP module. The operations included are: + * This function de-initializes the CMP module. The operations included are as follows. * - Disabling the CMP module. * - Disabling the clock for CMP module. * * This function disables the clock for the CMP. - * Note: For some devices, multiple CMP instance shares the same clock gate. In this case, before disabling the - * clock for the CMP, ensure that all the CMP instances are not used. + * Note that for some devices, multiple CMP instances share the same clock gate. In this case, before disabling the + * clock for the CMP, ensure that all the CMP instances are not used. * * @param base CMP peripheral base address. */ @@ -172,7 +172,7 @@ void CMP_Deinit(CMP_Type *base); * @brief Enables/disables the CMP module. * * @param base CMP peripheral base address. - * @param enable Enable the module or not. + * @param enable Enables or disables the module. */ static inline void CMP_Enable(CMP_Type *base, bool enable) { @@ -189,7 +189,7 @@ static inline void CMP_Enable(CMP_Type *base, bool enable) /*! * @brief Initializes the CMP user configuration structure. * -* This function initializes the user configuration structure to these default values: +* This function initializes the user configuration structure to these default values. * @code * config->enableCmp = true; * config->hysteresisMode = kCMP_HysteresisLevel0; @@ -207,7 +207,7 @@ void CMP_GetDefaultConfig(cmp_config_t *config); * @brief Sets the input channels for the comparator. * * This function sets the input channels for the comparator. - * Note that two input channels cannot be set as same in the application. When the user selects the same input + * Note that two input channels cannot be set the same way in the application. When the user selects the same input * from the analog mux to the positive and negative port, the comparator is disabled automatically. * * @param base CMP peripheral base address. @@ -228,13 +228,11 @@ void CMP_SetInputChannels(CMP_Type *base, uint8_t positiveChannel, uint8_t negat * @brief Enables/disables the DMA request for rising/falling events. * * This function enables/disables the DMA request for rising/falling events. Either event triggers the generation of - * the DMA - * request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP - * if the - * DMA is disabled. + * the DMA request from CMP if the DMA feature is enabled. Both events are ignored for generating the DMA request from the CMP + * if the DMA is disabled. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ void CMP_EnableDMA(CMP_Type *base, bool enable); #endif /* FSL_FEATURE_CMP_HAS_DMA */ @@ -244,7 +242,7 @@ void CMP_EnableDMA(CMP_Type *base, bool enable); * @brief Enables/disables the window mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) { @@ -264,7 +262,7 @@ static inline void CMP_EnableWindowMode(CMP_Type *base, bool enable) * @brief Enables/disables the pass through mode. * * @param base CMP peripheral base address. - * @param enable Enable the feature or not. + * @param enable Enables or disables the feature. */ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) { @@ -283,7 +281,7 @@ static inline void CMP_EnablePassThroughMode(CMP_Type *base, bool enable) * @brief Configures the filter. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. + * @param config Pointer to the configuration structure. */ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); @@ -291,7 +289,7 @@ void CMP_SetFilterConfig(CMP_Type *base, const cmp_filter_config_t *config); * @brief Configures the internal DAC. * * @param base CMP peripheral base address. - * @param config Pointer to configuration structure. "NULL" is for disabling the feature. + * @param config Pointer to the configuration structure. "NULL" disables the feature. */ void CMP_SetDACConfig(CMP_Type *base, const cmp_dac_config_t *config); diff --git a/drivers/fsl_cmt.c b/drivers/fsl_cmt.c index 43b2d3c..8cf72bc 100644 --- a/drivers/fsl_cmt.c +++ b/drivers/fsl_cmt.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -46,8 +46,6 @@ #define CMT_CMTDIV_FOUR (4) /* CMT diver 8. */ #define CMT_CMTDIV_EIGHT (8) -/* CMT mode bit mask. */ -#define CMT_MODE_BIT_MASK (CMT_MSC_MCGEN_MASK | CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK) /******************************************************************************* * Prototypes @@ -64,8 +62,10 @@ static uint32_t CMT_GetInstance(CMT_Type *base); * Variables ******************************************************************************/ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to cmt clocks for each instance. */ static const clock_ip_name_t s_cmtClock[FSL_FEATURE_SOC_CMT_COUNT] = CMT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to cmt bases for each instance. */ static CMT_Type *const s_cmtBases[] = CMT_BASE_PTRS; @@ -82,7 +82,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_CMT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_cmtBases); instance++) { if (s_cmtBases[instance] == base) { @@ -90,7 +90,7 @@ static uint32_t CMT_GetInstance(CMT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_CMT_COUNT); + assert(instance < ARRAY_SIZE(s_cmtBases)); return instance; } @@ -113,8 +113,10 @@ void CMT_Init(CMT_Type *base, const cmt_config_t *config, uint32_t busClock_Hz) uint8_t divider; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock. */ CLOCK_EnableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Sets clock divider. The divider set in pps should be set to make sycClock_Hz/divder = 8MHz */ @@ -144,15 +146,17 @@ void CMT_Deinit(CMT_Type *base) CMT_DisableInterrupts(base, kCMT_EndOfCycleInterruptEnable); DisableIRQ(s_cmtIrqs[CMT_GetInstance(base)]); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the clock. */ CLOCK_DisableClock(s_cmtClock[CMT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulateConfig) { - uint8_t mscReg; + uint8_t mscReg = base->MSC; - /* Set the mode. */ + /* Judge the mode. */ if (mode != kCMT_DirectIROCtl) { assert(modulateConfig); @@ -166,13 +170,14 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat /* Set carrier modulator. */ CMT_SetModulateMarkSpace(base, modulateConfig->markCount, modulateConfig->spaceCount); + mscReg &= ~ (CMT_MSC_FSK_MASK | CMT_MSC_BASE_MASK); + mscReg |= mode; + } + else + { + mscReg &= ~CMT_MSC_MCGEN_MASK; } - /* Set the CMT mode. */ - mscReg = base->MSC; - mscReg &= ~CMT_MODE_BIT_MASK; - mscReg |= mode; - base->MSC = mscReg; } diff --git a/drivers/fsl_cmt.h b/drivers/fsl_cmt.h index 0d57583..3d81f8a 100644 --- a/drivers/fsl_cmt.h +++ b/drivers/fsl_cmt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -132,10 +132,10 @@ enum _cmt_interrupt_enable */ typedef struct _cmt_modulate_config { - uint8_t highCount1; /*!< The high time for carrier generator first register. */ - uint8_t lowCount1; /*!< The low time for carrier generator first register. */ - uint8_t highCount2; /*!< The high time for carrier generator second register for FSK mode. */ - uint8_t lowCount2; /*!< The low time for carrier generator second register for FSK mode. */ + uint8_t highCount1; /*!< The high-time for carrier generator first register. */ + uint8_t lowCount1; /*!< The low-time for carrier generator first register. */ + uint8_t highCount2; /*!< The high-time for carrier generator second register for FSK mode. */ + uint8_t lowCount2; /*!< The low-time for carrier generator second register for FSK mode. */ uint16_t markCount; /*!< The mark time for the modulator gate. */ uint16_t spaceCount; /*!< The space time for the modulator gate. */ } cmt_modulate_config_t; @@ -163,10 +163,10 @@ extern "C" { */ /*! - * @brief Gets the CMT default configuration structure. The purpose - * of this API is to get the default configuration structure for the CMT_Init(). - * Use the initialized structure unchanged in CMT_Init(), or modify - * some fields of the structure before calling the CMT_Init(). + * @brief Gets the CMT default configuration structure. This API + * gets the default configuration structure for the CMT_Init(). + * Use the initialized structure unchanged in CMT_Init() or modify + * fields of the structure before calling the CMT_Init(). * * @param config The CMT configuration structure pointer. */ @@ -215,7 +215,7 @@ void CMT_SetMode(CMT_Type *base, cmt_mode_t mode, cmt_modulate_config_t *modulat * * @param base CMT peripheral base address. * @return The CMT mode. - * kCMT_DirectIROCtl Carrier modulator is disabled, the IRO signal is directly in software control. + * kCMT_DirectIROCtl Carrier modulator is disabled; the IRO signal is directly in software control. * kCMT_TimeMode Carrier modulator is enabled in time mode. * kCMT_FSKMode Carrier modulator is enabled in FSK mode. * kCMT_BasebandMode Carrier modulator is enabled in baseband mode. @@ -234,11 +234,11 @@ uint32_t CMT_GetCMTFrequency(CMT_Type *base, uint32_t busClock_Hz); /*! * @brief Sets the primary data set for the CMT carrier generator counter. * - * This function sets the high time and low time of the primary data set for the + * This function sets the high-time and low-time of the primary data set for the * CMT carrier generator counter to control the period and the duty cycle of the * output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals - * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals + * (highCount + lowCount) * Tcmt. The duty cycle equals to highCount / (highCount + lowCount). * * @param base CMT peripheral base address. * @param highCount The number of CMT clocks for carrier generator signal high time, @@ -260,10 +260,10 @@ static inline void CMT_SetCarrirGenerateCountOne(CMT_Type *base, uint32_t highCo /*! * @brief Sets the secondary data set for the CMT carrier generator counter. * - * This function is used for FSK mode setting the high time and low time of the secondary + * This function is used for FSK mode setting the high-time and low-time of the secondary * data set CMT carrier generator counter to control the period and the duty cycle * of the output carrier signal. - * If the CMT clock period is Tcmt, The period of the carrier generator signal equals + * If the CMT clock period is Tcmt, the period of the carrier generator signal equals * (highCount + lowCount) * Tcmt. The duty cycle equals highCount / (highCount + lowCount). * * @param base CMT peripheral base address. @@ -324,7 +324,7 @@ static inline void CMT_EnableExtendedSpace(CMT_Type *base, bool enable) } /*! - * @brief Sets IRO - infrared output signal state. + * @brief Sets the IRO (infrared output) signal state. * * Changes the states of the IRO signal when the kCMT_DirectIROMode mode is set * and the IRO signal is enabled. @@ -337,12 +337,12 @@ void CMT_SetIroState(CMT_Type *base, cmt_infrared_output_state_t state); /*! * @brief Enables the CMT interrupt. * - * This function enables the CMT interrupts according to the provided maskIf enabled. + * This function enables the CMT interrupts according to the provided mask if enabled. * The CMT only has the end of the cycle interrupt - an interrupt occurs at the end * of the modulator cycle. This interrupt provides a means for the user * to reload the new mark/space values into the CMT modulator data registers * and verify the modulator mark and space. - * For example, to enable the end of cycle, do the following: + * For example, to enable the end of cycle, do the following. * @code * CMT_EnableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode @@ -359,7 +359,7 @@ static inline void CMT_EnableInterrupts(CMT_Type *base, uint32_t mask) * * This function disables the CMT interrupts according to the provided maskIf enabled. * The CMT only has the end of the cycle interrupt. - * For example, to disable the end of cycle, do the following: + * For example, to disable the end of cycle, do the following. * @code * CMT_DisableInterrupts(CMT, kCMT_EndOfCycleInterruptEnable); * @endcode diff --git a/drivers/fsl_common.c b/drivers/fsl_common.c index de67800..2fe4957 100644 --- a/drivers/fsl_common.c +++ b/drivers/fsl_common.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_common.h" #include "fsl_debug_console.h" @@ -38,22 +38,36 @@ void __aeabi_assert(const char *failedExpr, const char *file, int line) PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" \n", failedExpr, file, line); for (;;) { + __BKPT(0); + } +} +#elif(defined(__REDLIB__)) + +#if SDK_DEBUGCONSOLE +void __assertion_failed(char *_Expr) +{ + PRINTF("%s\n", _Expr); + for (;;) + { __asm("bkpt #0"); } } +#endif + #elif(defined(__GNUC__)) void __assert_func(const char *file, int line, const char *func, const char *failedExpr) { PRINTF("ASSERT ERROR \" %s \": file \"%s\" Line \"%d\" function name \"%s\" \n", failedExpr, file, line, func); for (;;) { - __asm("bkpt #0"); + __BKPT(0); } } #endif /* (defined(__CC_ARM)) || (defined (__ICCARM__)) */ #endif /* NDEBUG */ -void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler) +#ifndef __GIC_PRIO_BITS +uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler) { /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */ #if defined(__CC_ARM) @@ -75,8 +89,10 @@ void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler) uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES); #endif /* defined(__CC_ARM) */ uint32_t n; + uint32_t ret; + uint32_t irqMaskValue; - __disable_irq(); + irqMaskValue = DisableGlobalIRQ(); if (SCB->VTOR != (uint32_t)__VECTOR_RAM) { /* Copy the vector table from ROM to RAM */ @@ -88,8 +104,73 @@ void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler) SCB->VTOR = (uint32_t)__VECTOR_RAM; } + ret = __VECTOR_RAM[irq + 16]; /* make sure the __VECTOR_RAM is noncachable */ __VECTOR_RAM[irq + 16] = irqHandler; - __enable_irq(); + EnableGlobalIRQ(irqMaskValue); + + return ret; +} +#endif + +#ifndef CPU_QN908X +#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) + +void EnableDeepSleepIRQ(IRQn_Type interrupt) +{ + uint32_t index = 0; + uint32_t intNumber = (uint32_t)interrupt; + while (intNumber >= 32u) + { + index++; + intNumber -= 32u; + } + + SYSCON->STARTERSET[index] = 1u << intNumber; + EnableIRQ(interrupt); /* also enable interrupt at NVIC */ +} + +void DisableDeepSleepIRQ(IRQn_Type interrupt) +{ + uint32_t index = 0; + uint32_t intNumber = (uint32_t)interrupt; + while (intNumber >= 32u) + { + index++; + intNumber -= 32u; + } + + DisableIRQ(interrupt); /* also disable interrupt at NVIC */ + SYSCON->STARTERCLR[index] = 1u << intNumber; +} +#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */ +#else +void EnableDeepSleepIRQ(IRQn_Type interrupt) +{ + uint32_t index = 0; + uint32_t intNumber = (uint32_t)interrupt; + while (intNumber >= 32u) + { + index++; + intNumber -= 32u; + } + + /* SYSCON->STARTERSET[index] = 1u << intNumber; */ + EnableIRQ(interrupt); /* also enable interrupt at NVIC */ +} + +void DisableDeepSleepIRQ(IRQn_Type interrupt) +{ + uint32_t index = 0; + uint32_t intNumber = (uint32_t)interrupt; + while (intNumber >= 32u) + { + index++; + intNumber -= 32u; + } + + DisableIRQ(interrupt); /* also disable interrupt at NVIC */ + /* SYSCON->STARTERCLR[index] = 1u << intNumber; */ } +#endif /*CPU_QN908X */ diff --git a/drivers/fsl_common.h b/drivers/fsl_common.h index a843078..f20c090 100644 --- a/drivers/fsl_common.h +++ b/drivers/fsl_common.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,6 +35,11 @@ #include <stdbool.h> #include <stdint.h> #include <string.h> + +#if defined(__ICCARM__) +#include <stddef.h> +#endif + #include "fsl_device_registers.h" /*! @@ -42,7 +47,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -54,11 +58,13 @@ #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) /* Debug console type definition. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ -#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */ +#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */ /*! @brief Status group numbers. */ enum _status_groups @@ -85,6 +91,11 @@ enum _status_groups kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */ kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */ kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */ + kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */ + kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */ + kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */ + kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */ + kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */ kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */ kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */ kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */ @@ -99,6 +110,18 @@ enum _status_groups kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */ kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */ kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */ + kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */ + kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */ + kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */ + kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/ + kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */ + kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */ + kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */ + kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */ + kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */ + kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/ + kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */ + kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */ kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */ kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */ kStatusGroup_ApplicationRangeStart = 100, /*!< Starting number for application groups. */ @@ -125,6 +148,14 @@ typedef int32_t status_t; */ #include "fsl_clock.h" +/* + * Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral + */ +#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \ + (defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0))) +#include "fsl_reset.h" +#endif + /*! @name Min/max macros */ /* @{ */ #if !defined(MIN) @@ -180,11 +211,20 @@ extern "C" { */ static inline void EnableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_EnableIRQ(interrupt); +#else NVIC_EnableIRQ(interrupt); +#endif } } @@ -197,11 +237,20 @@ static inline void EnableIRQ(IRQn_Type interrupt) */ static inline void DisableIRQ(IRQn_Type interrupt) { + if (NotAvail_IRQn == interrupt) + { + return; + } + #if defined(FSL_FEATURE_SOC_INTMUX_COUNT) && (FSL_FEATURE_SOC_INTMUX_COUNT > 0) if (interrupt < FSL_FEATURE_INTMUX_IRQ_START_INDEX) #endif { +#if defined(__GIC_PRIO_BITS) + GIC_DisableIRQ(interrupt); +#else NVIC_DisableIRQ(interrupt); +#endif } } @@ -215,11 +264,19 @@ static inline void DisableIRQ(IRQn_Type interrupt) */ static inline uint32_t DisableGlobalIRQ(void) { +#if defined(CPSR_I_Msk) + uint32_t cpsr = __get_CPSR() & CPSR_I_Msk; + + __disable_irq(); + + return cpsr; +#else uint32_t regPrimask = __get_PRIMASK(); __disable_irq(); return regPrimask; +#endif } /*! @@ -234,7 +291,11 @@ static inline uint32_t DisableGlobalIRQ(void) */ static inline void EnableGlobalIRQ(uint32_t primask) { +#if defined(CPSR_I_Msk) + __set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask); +#else __set_PRIMASK(primask); +#endif } /*! @@ -242,8 +303,41 @@ static inline void EnableGlobalIRQ(uint32_t primask) * * @param irq IRQ number * @param irqHandler IRQ handler address + * @return The old IRQ handler address + */ +uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler); + +#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) +/*! + * @brief Enable specific interrupt for wake-up from deep-sleep mode. + * + * Enable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally). + * + * @param interrupt The IRQ number. + */ +void EnableDeepSleepIRQ(IRQn_Type interrupt); + +/*! + * @brief Disable specific interrupt for wake-up from deep-sleep mode. + * + * Disable the interrupt for wake-up from deep sleep mode. + * Some interrupts are typically used in sleep mode only and will not occur during + * deep-sleep mode because relevant clocks are stopped. However, it is possible to enable + * those clocks (significantly increasing power consumption in the reduced power mode), + * making these wake-ups possible. + * + * @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally). + * + * @param interrupt The IRQ number. */ -void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler); +void DisableDeepSleepIRQ(IRQn_Type interrupt); +#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */ #if defined(__cplusplus) } diff --git a/drivers/fsl_crc.c b/drivers/fsl_crc.c index de86e32..dba1db8 100644 --- a/drivers/fsl_crc.c +++ b/drivers/fsl_crc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -92,7 +92,7 @@ typedef struct _crc_module_config * * @param enable True or false for the selected CRC protocol Reflect In (refin) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes); } @@ -104,7 +104,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectIn(bool enable * * @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter. */ -static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enable) +static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable) { return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone); } @@ -118,7 +118,7 @@ static inline crc_transpose_type_t crc_GetTransposeTypeFromReflectOut(bool enabl * @param base CRC peripheral address. * @param config Pointer to protocol configuration structure. */ -static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) +static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) { uint32_t crcControl; @@ -153,18 +153,18 @@ static void crc_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *con * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for final checksum */ moduleConfig.polynomial = protocolConfig->polynomial; moduleConfig.seed = protocolConfig->seed; - moduleConfig.readTranspose = crc_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = protocolConfig->complementChecksum; moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } /*! @@ -177,7 +177,7 @@ static void crc_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolCo * @param base CRC peripheral address. * @param protocolConfig Pointer to protocol configuration structure. */ -static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) +static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) { crc_module_config_t moduleConfig; /* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */ @@ -185,25 +185,27 @@ static void crc_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protoco moduleConfig.seed = protocolConfig->seed; moduleConfig.readTranspose = kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */ - moduleConfig.writeTranspose = crc_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); + moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */ moduleConfig.crcBits = protocolConfig->crcBits; - crc_ConfigureAndStart(base, &moduleConfig); + CRC_ConfigureAndStart(base, &moduleConfig); } void CRC_Init(CRC_Type *base, const crc_config_t *config) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* ungate clock */ CLOCK_EnableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* configure CRC module and write the seed */ if (config->crcResult == kCrcFinalChecksum) { - crc_SetProtocolConfig(base, config); + CRC_SetProtocolConfig(base, config); } else { - crc_SetRawProtocolConfig(base, config); + CRC_SetRawProtocolConfig(base, config); } } diff --git a/drivers/fsl_crc.h b/drivers/fsl_crc.h index 9d76731..247a9ba 100644 --- a/drivers/fsl_crc.h +++ b/drivers/fsl_crc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,7 +38,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -108,31 +107,33 @@ extern "C" { /*! * @brief Enables and configures the CRC peripheral module. * - * This functions enables the clock gate in the Kinetis SIM module for the CRC peripheral. - * It also configures the CRC module and starts checksum computation by writing the seed. + * This function enables the clock gate in the SIM module for the CRC peripheral. + * It also configures the CRC module and starts a checksum computation by writing the seed. * * @param base CRC peripheral address. - * @param config CRC module configuration structure + * @param config CRC module configuration structure. */ void CRC_Init(CRC_Type *base, const crc_config_t *config); /*! * @brief Disables the CRC peripheral module. * - * This functions disables the clock gate in the Kinetis SIM module for the CRC peripheral. + * This function disables the clock gate in the SIM module for the CRC peripheral. * * @param base CRC peripheral address. */ static inline void CRC_Deinit(CRC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* gate clock */ CLOCK_DisableClock(kCLOCK_Crc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Loads default values to CRC protocol configuration structure. + * @brief Loads default values to the CRC protocol configuration structure. * - * Loads default values to CRC protocol configuration structure. The default values are: + * Loads default values to the CRC protocol configuration structure. The default values are as follows. * @code * config->polynomial = 0x1021; * config->seed = 0xFFFF; @@ -143,14 +144,14 @@ static inline void CRC_Deinit(CRC_Type *base) * config->crcResult = kCrcFinalChecksum; * @endcode * - * @param config CRC protocol configuration structure + * @param config CRC protocol configuration structure. */ void CRC_GetDefaultConfig(crc_config_t *config); /*! * @brief Writes data to the CRC module. * - * Writes input data buffer bytes to CRC data register. + * Writes input data buffer bytes to the CRC data register. * The configured type of transpose is applied. * * @param base CRC peripheral address. @@ -160,24 +161,24 @@ void CRC_GetDefaultConfig(crc_config_t *config); void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize); /*! - * @brief Reads 32-bit checksum from the CRC module. + * @brief Reads the 32-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 32-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 32-bit checksum, after configured transpose and complement operations. */ uint32_t CRC_Get32bitResult(CRC_Type *base); /*! - * @brief Reads 16-bit checksum from the CRC module. + * @brief Reads a 16-bit checksum from the CRC module. * - * Reads CRC data register (intermediate or final checksum). - * The configured type of transpose and complement are applied. + * Reads the CRC data register (either an intermediate or the final checksum). + * The configured type of transpose and complement is applied. * * @param base CRC peripheral address. - * @return intermediate or final 16-bit checksum, after configured transpose and complement operations. + * @return An intermediate or the final 16-bit checksum, after configured transpose and complement operations. */ uint16_t CRC_Get16bitResult(CRC_Type *base); diff --git a/drivers/fsl_dac.c b/drivers/fsl_dac.c index 55e5517..8d13d62 100644 --- a/drivers/fsl_dac.c +++ b/drivers/fsl_dac.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t DAC_GetInstance(DAC_Type *base); ******************************************************************************/ /*! @brief Pointers to DAC bases for each instance. */ static DAC_Type *const s_dacBases[] = DAC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to DAC clocks for each instance. */ static const clock_ip_name_t s_dacClocks[] = DAC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DAC_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dacBases); instance++) { if (s_dacBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t DAC_GetInstance(DAC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DAC_COUNT); + assert(instance < ARRAY_SIZE(s_dacBases)); return instance; } @@ -75,8 +77,10 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config) uint8_t tmp8; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* DACx_C0. */ @@ -99,8 +103,10 @@ void DAC_Deinit(DAC_Type *base) { DAC_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DAC_GetDefaultConfig(dac_config_t *config) diff --git a/drivers/fsl_dac.h b/drivers/fsl_dac.h index 925ca19..b71febf 100644 --- a/drivers/fsl_dac.h +++ b/drivers/fsl_dac.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -149,8 +149,8 @@ typedef struct _dac_buffer_config dac_buffer_watermark_t watermark; /*!< Select the buffer's watermark. */ #endif /* FSL_FEATURE_DAC_HAS_WATERMARK_SELECTION */ dac_buffer_work_mode_t workMode; /*!< Select the buffer's work mode. */ - uint8_t upperLimit; /*!< Set the upper limit for buffer index. - Normally, 0-15 is available for buffer with 16 item. */ + uint8_t upperLimit; /*!< Set the upper limit for the buffer index. + Normally, 0-15 is available for a buffer with 16 items. */ } dac_buffer_config_t; /******************************************************************************* @@ -168,7 +168,7 @@ extern "C" { /*! * @brief Initializes the DAC module. * - * This function initializes the DAC module, including: + * This function initializes the DAC module including the following operations. * - Enabling the clock for DAC module. * - Configuring the DAC converter with a user configuration. * - Enabling the DAC module. @@ -181,7 +181,7 @@ void DAC_Init(DAC_Type *base, const dac_config_t *config); /*! * @brief De-initializes the DAC module. * - * This function de-initializes the DAC module, including: + * This function de-initializes the DAC module including the following operations. * - Disabling the DAC module. * - Disabling the clock for the DAC module. * @@ -192,7 +192,7 @@ void DAC_Deinit(DAC_Type *base); /*! * @brief Initializes the DAC user configuration structure. * - * This function initializes the user configuration structure to a default value. The default values are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->referenceVoltageSource = kDAC_ReferenceVoltageSourceVref2; * config->enableLowPowerMode = false; @@ -205,7 +205,7 @@ void DAC_GetDefaultConfig(dac_config_t *config); * @brief Enables the DAC module. * * @param base DAC peripheral base address. - * @param enable Enables/disables the feature. + * @param enable Enables or disables the feature. */ static inline void DAC_Enable(DAC_Type *base, bool enable) { @@ -230,7 +230,7 @@ static inline void DAC_Enable(DAC_Type *base, bool enable) * @brief Enables the DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables/disables the feature. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBuffer(DAC_Type *base, bool enable) { @@ -255,7 +255,7 @@ void DAC_SetBufferConfig(DAC_Type *base, const dac_buffer_config_t *config); /*! * @brief Initializes the DAC buffer configuration structure. * - * This function initializes the DAC buffer configuration structure to a default value. The default values are: + * This function initializes the DAC buffer configuration structure to default values. The default values are as follows. * @code * config->triggerMode = kDAC_BufferTriggerBySoftwareMode; * config->watermark = kDAC_BufferWatermark1Word; @@ -270,7 +270,7 @@ void DAC_GetDefaultBufferConfig(dac_buffer_config_t *config); * @brief Enables the DMA for DAC buffer. * * @param base DAC peripheral base address. - * @param enable Enables/disables the feature. + * @param enable Enables or disables the feature. */ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) { @@ -288,15 +288,15 @@ static inline void DAC_EnableBufferDMA(DAC_Type *base, bool enable) * @brief Sets the value for items in the buffer. * * @param base DAC peripheral base address. - * @param index Setting index for items in the buffer. The available index should not exceed the size of the DAC buffer. - * @param value Setting value for items in the buffer. 12-bits are available. + * @param index Setting the index for items in the buffer. The available index should not exceed the size of the DAC buffer. + * @param value Setting the value for items in the buffer. 12-bits are available. */ void DAC_SetBufferValue(DAC_Type *base, uint8_t index, uint16_t value); /*! - * @brief Triggers the buffer by software and updates the read pointer of the DAC buffer. + * @brief Triggers the buffer using software and updates the read pointer of the DAC buffer. * - * This function triggers the function by software. The read pointer of the DAC buffer is updated with one step + * This function triggers the function using software. The read pointer of the DAC buffer is updated with one step * after this function is called. Changing the read pointer depends on the buffer's work mode. * * @param base DAC peripheral base address. @@ -310,12 +310,12 @@ static inline void DAC_DoSoftwareTriggerBuffer(DAC_Type *base) * @brief Gets the current read pointer of the DAC buffer. * * This function gets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated - * by software trigger or hardware trigger. + * The current output value depends on the item indexed by the read pointer. It is updated either + * by a software trigger or a hardware trigger. * * @param base DAC peripheral base address. * - * @return Current read pointer of DAC buffer. + * @return The current read pointer of the DAC buffer. */ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) { @@ -326,11 +326,11 @@ static inline uint8_t DAC_GetBufferReadPointer(DAC_Type *base) * @brief Sets the current read pointer of the DAC buffer. * * This function sets the current read pointer of the DAC buffer. - * The current output value depends on the item indexed by the read pointer. It is updated by - * software trigger or hardware trigger. After the read pointer changes, the DAC output value also changes. + * The current output value depends on the item indexed by the read pointer. It is updated either by a + * software trigger or a hardware trigger. After the read pointer changes, the DAC output value also changes. * * @param base DAC peripheral base address. - * @param index Setting index value for the pointer. + * @param index Setting an index value for the pointer. */ void DAC_SetBufferReadPointer(DAC_Type *base, uint8_t index); diff --git a/drivers/fsl_dmamux.c b/drivers/fsl_dmamux.c index a288b9f..39ce9cf 100644 --- a/drivers/fsl_dmamux.c +++ b/drivers/fsl_dmamux.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -52,8 +52,10 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base); /*! @brief Array to map DMAMUX instance number to base pointer. */ static DMAMUX_Type *const s_dmamuxBases[] = DMAMUX_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Array to map DMAMUX instance number to clock name. */ static const clock_ip_name_t s_dmamuxClockName[] = DMAMUX_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -63,7 +65,7 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DMAMUX_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dmamuxBases); instance++) { if (s_dmamuxBases[instance] == base) { @@ -71,17 +73,21 @@ static uint32_t DMAMUX_GetInstance(DMAMUX_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DMAMUX_COUNT); + assert(instance < ARRAY_SIZE(s_dmamuxBases)); return instance; } void DMAMUX_Init(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void DMAMUX_Deinit(DMAMUX_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(s_dmamuxClockName[DMAMUX_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } diff --git a/drivers/fsl_dmamux.h b/drivers/fsl_dmamux.h index 5dce562..071348b 100644 --- a/drivers/fsl_dmamux.h +++ b/drivers/fsl_dmamux.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DMAMUX driver version 2.0.1. */ -#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief DMAMUX driver version 2.0.2. */ +#define FSL_DMAMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ /******************************************************************************* @@ -58,14 +58,14 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name DMAMUX Initialize and De-initialize + * @name DMAMUX Initialization and de-initialization * @{ */ /*! - * @brief Initializes DMAMUX peripheral. + * @brief Initializes the DMAMUX peripheral. * - * This function ungate the DMAMUX clock. + * This function ungates the DMAMUX clock. * * @param base DMAMUX peripheral base address. * @@ -73,9 +73,9 @@ extern "C" { void DMAMUX_Init(DMAMUX_Type *base); /*! - * @brief Deinitializes DMAMUX peripheral. + * @brief Deinitializes the DMAMUX peripheral. * - * This function gate the DMAMUX clock. + * This function gates the DMAMUX clock. * * @param base DMAMUX peripheral base address. */ @@ -88,9 +88,9 @@ void DMAMUX_Deinit(DMAMUX_Type *base); */ /*! - * @brief Enable DMAMUX channel. + * @brief Enables the DMAMUX channel. * - * This function enable DMAMUX channel to work. + * This function enables the DMAMUX channel. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -103,11 +103,11 @@ static inline void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Disable DMAMUX channel. + * @brief Disables the DMAMUX channel. * - * This function disable DMAMUX channel. + * This function disables the DMAMUX channel. * - * @note User must disable DMAMUX channel before configuring it. + * @note The user must disable the DMAMUX channel before configuring it. * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. */ @@ -119,11 +119,11 @@ static inline void DMAMUX_DisableChannel(DMAMUX_Type *base, uint32_t channel) } /*! - * @brief Configure DMAMUX channel source. + * @brief Configures the DMAMUX channel source. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. - * @param source Channel source which is used to trigger DMA transfer. + * @param source Channel source, which is used to trigger the DMA transfer. */ static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source) { @@ -134,9 +134,9 @@ static inline void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_ #if defined(FSL_FEATURE_DMAMUX_HAS_TRIG) && FSL_FEATURE_DMAMUX_HAS_TRIG > 0U /*! - * @brief Enable DMAMUX period trigger. + * @brief Enables the DMAMUX period trigger. * - * This function enable DMAMUX period trigger feature. + * This function enables the DMAMUX period trigger feature. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -149,9 +149,9 @@ static inline void DMAMUX_EnablePeriodTrigger(DMAMUX_Type *base, uint32_t channe } /*! - * @brief Disable DMAMUX period trigger. + * @brief Disables the DMAMUX period trigger. * - * This function disable DMAMUX period trigger. + * This function disables the DMAMUX period trigger. * * @param base DMAMUX peripheral base address. * @param channel DMAMUX channel number. @@ -164,6 +164,31 @@ static inline void DMAMUX_DisablePeriodTrigger(DMAMUX_Type *base, uint32_t chann } #endif /* FSL_FEATURE_DMAMUX_HAS_TRIG */ +#if (defined(FSL_FEATURE_DMAMUX_HAS_A_ON) && FSL_FEATURE_DMAMUX_HAS_A_ON) +/*! + * @brief Enables the DMA channel to be always ON. + * + * This function enables the DMAMUX channel always ON feature. + * + * @param base DMAMUX peripheral base address. + * @param channel DMAMUX channel number. + * @param enable Switcher of the always ON feature. "true" means enabled, "false" means disabled. + */ +static inline void DMAMUX_EnableAlwaysOn(DMAMUX_Type *base, uint32_t channel, bool enable) +{ + assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL); + + if (enable) + { + base->CHCFG[channel] |= DMAMUX_CHCFG_A_ON_MASK; + } + else + { + base->CHCFG[channel] &= ~DMAMUX_CHCFG_A_ON_MASK; + } +} +#endif /* FSL_FEATURE_DMAMUX_HAS_A_ON */ + /* @} */ #if defined(__cplusplus) diff --git a/drivers/fsl_dspi.c b/drivers/fsl_dspi.c index 51da2d8..e2b90ba 100644 --- a/drivers/fsl_dspi.c +++ b/drivers/fsl_dspi.c @@ -1,35 +1,34 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi.h" -#include "com_task.h" /******************************************************************************* * Definitions @@ -66,27 +65,27 @@ static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pc /*! * @brief Master fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Master finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle); /*! * @brief Slave fill up the TX FIFO with data. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle); /*! * @brief Slave finish up a transfer. * It would call back if there is callback function and set the state to idle. - * This is not a public API as it is called from other driver functions. + * This is not a public API. */ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle); @@ -101,7 +100,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param); /*! * @brief Master prepare the transfer. * Basically it set up dspi_master_handle . - * This is not a public API as it is called from other driver functions. fsl_dspi_edma.c also call this function. + * This is not a public API. */ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -124,11 +123,13 @@ static SPI_Type *const s_dspiBases[] = SPI_BASE_PTRS; /*! @brief Pointers to dspi IRQ number for each instance. */ static IRQn_Type const s_dspiIRQ[] = SPI_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to dspi clocks for each instance. */ static clock_ip_name_t const s_dspiClock[] = DSPI_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointers to dspi handles for each instance. */ -static void *g_dspiHandle[FSL_FEATURE_SOC_DSPI_COUNT]; +static void *g_dspiHandle[ARRAY_SIZE(s_dspiBases)]; /*! @brief Pointer to master IRQ handler for each instance. */ static dspi_master_isr_t s_dspiMasterIsr; @@ -144,7 +145,7 @@ uint32_t DSPI_GetInstance(SPI_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_DSPI_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_dspiBases); instance++) { if (s_dspiBases[instance] == base) { @@ -152,16 +153,20 @@ uint32_t DSPI_GetInstance(SPI_Type *base) } } - assert(instance < FSL_FEATURE_SOC_DSPI_COUNT); + assert(instance < ARRAY_SIZE(s_dspiBases)); return instance; } void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz) { + assert(masterConfig); + uint32_t temp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -202,6 +207,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) { + assert(masterConfig); + masterConfig->whichCtar = kDSPI_Ctar0; masterConfig->ctarConfig.baudRate = 500000; masterConfig->ctarConfig.bitsPerFrame = 8; @@ -224,10 +231,14 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig) void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + uint32_t temp = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* enable DSPI clock */ CLOCK_EnableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ DSPI_Enable(base, true); DSPI_StopTransfer(base); @@ -256,6 +267,8 @@ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig) void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig) { + assert(slaveConfig); + slaveConfig->whichCtar = kDSPI_Ctar0; slaveConfig->ctarConfig.bitsPerFrame = 8; slaveConfig->ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; @@ -272,8 +285,10 @@ void DSPI_Deinit(SPI_Type *base) DSPI_StopTransfer(base); DSPI_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* disable DSPI clock */ CLOCK_DisableClock(s_dspiClock[DSPI_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } static void DSPI_SetOnePcsPolarity(SPI_Type *base, dspi_which_pcs_t pcs, dspi_pcs_polarity_config_t activeLowOrHigh) @@ -458,6 +473,8 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) { + assert(command); + command->isPcsContinuous = false; command->whichCtar = kDSPI_Ctar0; command->whichPcs = kDSPI_Pcs0; @@ -467,6 +484,8 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command) void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) { + assert(command); + /* First, clear Transmit Complete Flag (TCF) */ DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag); @@ -628,25 +647,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount == 1) { - while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else - { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -704,20 +704,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while ((remainingReceiveByteCount - remainingSendByteCount) >= fifoSize) { - if (rxData != NULL) - { - *(rxData) = DSPI_ReadData(base); - rxData++; - } - else + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - DSPI_ReadData(base); - } - remainingReceiveByteCount--; + if (rxData != NULL) + { + *(rxData) = DSPI_ReadData(base); + rxData++; + } + else + { + DSPI_ReadData(base); + } + remainingReceiveByteCount--; - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -728,25 +731,6 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) { if (remainingSendByteCount <= 2) { - while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) - { - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) - { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) - { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; - - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); - } - } - while (!(DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)) { DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); @@ -827,20 +811,23 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag); - if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) + while (((remainingReceiveByteCount - remainingSendByteCount) / 2) >= fifoSize) { - wordReceived = DSPI_ReadData(base); - - if (rxData != NULL) + if (DSPI_GetStatusFlags(base) & kDSPI_RxFifoDrainRequestFlag) { - *rxData = wordReceived; - ++rxData; - *rxData = wordReceived >> 8; - ++rxData; - } - remainingReceiveByteCount -= 2; + wordReceived = DSPI_ReadData(base); - DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + if (rxData != NULL) + { + *rxData = wordReceived; + ++rxData; + *rxData = wordReceived >> 8; + ++rxData; + } + remainingReceiveByteCount -= 2; + + DSPI_ClearStatusFlags(base, kDSPI_RxFifoDrainRequestFlag); + } } } } @@ -851,6 +838,9 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer) static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { + assert(handle); + assert(transfer); + dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); @@ -889,7 +879,8 @@ static void DSPI_MasterTransferPrepare(SPI_Type *base, dspi_master_handle_t *han status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -946,6 +937,8 @@ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handl static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* Disable interrupt requests*/ DSPI_DisableInterrupts(base, kDSPI_RxFifoDrainRequestInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable); @@ -959,17 +952,18 @@ static void DSPI_MasterTransferComplete(SPI_Type *base, dspi_master_handle_t *ha status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - /* The transfer is complete.*/ - handle->state = kDSPI_Idle; } static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + uint16_t wordToSend = 0; uint8_t dummyData = DSPI_DUMMY_DATA; @@ -1084,6 +1078,8 @@ static void DSPI_MasterTransferFillUpTxFifo(SPI_Type *base, dspi_master_handle_t void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests*/ @@ -1094,6 +1090,8 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle) void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle) { + assert(handle); + /* RECEIVE IRQ handler: Check read buffer only if there are remaining bytes to read. */ if (handle->remainingReceiveByteCount) { @@ -1215,7 +1213,8 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If receive length is zero */ if (transfer->dataSize == 0) @@ -1303,6 +1302,8 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + uint16_t transmitData = 0; uint8_t dummyPattern = DSPI_DUMMY_DATA; @@ -1389,6 +1390,8 @@ static void DSPI_SlaveTransferFillUpTxFifo(SPI_Type *base, dspi_slave_handle_t * static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + /* Disable interrupt requests */ DSPI_DisableInterrupts(base, kDSPI_TxFifoUnderflowInterruptEnable | kDSPI_TxFifoFillRequestInterruptEnable | kDSPI_RxFifoOverflowInterruptEnable | kDSPI_RxFifoDrainRequestInterruptEnable); @@ -1409,16 +1412,18 @@ static void DSPI_SlaveTransferComplete(SPI_Type *base, dspi_slave_handle_t *hand status = kStatus_Success; } + handle->state = kDSPI_Idle; + if (handle->callback) { handle->callback(base, handle, status, handle->userData); } - - handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); /* Disable interrupt requests */ @@ -1432,10 +1437,11 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle) void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) { + assert(handle); + uint8_t dummyPattern = DSPI_DUMMY_DATA; uint32_t dataReceived; uint32_t dataSend = 0; - //uint32_t dataCount = 0; /* Because SPI protocol is synchronous, the number of bytes that that slave received from the * master is the actual number of bytes that the slave transmitted to the master. So we only @@ -1466,13 +1472,6 @@ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle) /* Descrease remaining receive byte count */ --handle->remainingReceiveByteCount; - /* dataCount = handle->totalByteCount - handle->remainingReceiveByteCount; - - if (dataCount == 2 && (*(handle->rxData - 1) == APALIS_TK1_K20_BULK_WRITE_INST) - && (dataReceived < APALIS_TK1_K20_MAX_BULK)) - handle->totalByteCount += dataReceived; -*/ - if (handle->remainingSendByteCount > 0) { if (handle->txData) @@ -1617,7 +1616,7 @@ static void DSPI_CommonIRQHandler(SPI_Type *base, void *param) } } -#if (FSL_FEATURE_SOC_DSPI_COUNT > 0) +#if defined(SPI0) void SPI0_DriverIRQHandler(void) { assert(g_dspiHandle[0]); @@ -1625,7 +1624,7 @@ void SPI0_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 1) +#if defined(SPI1) void SPI1_DriverIRQHandler(void) { assert(g_dspiHandle[1]); @@ -1633,7 +1632,7 @@ void SPI1_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 2) +#if defined(SPI2) void SPI2_DriverIRQHandler(void) { assert(g_dspiHandle[2]); @@ -1641,7 +1640,7 @@ void SPI2_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 3) +#if defined(SPI3) void SPI3_DriverIRQHandler(void) { assert(g_dspiHandle[3]); @@ -1649,7 +1648,7 @@ void SPI3_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 4) +#if defined(SPI4) void SPI4_DriverIRQHandler(void) { assert(g_dspiHandle[4]); @@ -1657,7 +1656,7 @@ void SPI4_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_DSPI_COUNT > 5) +#if defined(SPI5) void SPI5_DriverIRQHandler(void) { assert(g_dspiHandle[5]); diff --git a/drivers/fsl_dspi.h b/drivers/fsl_dspi.h index dfbeb3e..5dd96af 100644 --- a/drivers/fsl_dspi.h +++ b/drivers/fsl_dspi.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -44,12 +44,14 @@ /*! @name Driver version */ /*@{*/ -/*! @brief DSPI driver version 2.1.1. */ -#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*! @brief DSPI driver version 2.1.4. */ +#define FSL_DSPI_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) /*@}*/ -/*! @brief DSPI dummy data if no Tx data.*/ -#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for tx if there is not txData. */ +#ifndef DSPI_DUMMY_DATA +/*! @brief DSPI dummy data if there is no Tx data.*/ +#define DSPI_DUMMY_DATA (0x00U) /*!< Dummy data used for Tx if there is no txData. */ +#endif /*! @brief Status for the DSPI driver.*/ enum _dspi_status @@ -57,7 +59,7 @@ enum _dspi_status kStatus_DSPI_Busy = MAKE_STATUS(kStatusGroup_DSPI, 0), /*!< DSPI transfer is busy.*/ kStatus_DSPI_Error = MAKE_STATUS(kStatusGroup_DSPI, 1), /*!< DSPI driver error. */ kStatus_DSPI_Idle = MAKE_STATUS(kStatusGroup_DSPI, 2), /*!< DSPI is idle.*/ - kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out Of range. */ + kStatus_DSPI_OutOfRange = MAKE_STATUS(kStatusGroup_DSPI, 3) /*!< DSPI transfer out of range. */ }; /*! @brief DSPI status flags in SPIx_SR register.*/ @@ -71,7 +73,7 @@ enum _dspi_flags kDSPI_RxFifoDrainRequestFlag = SPI_SR_RFDF_MASK, /*!< Receive FIFO Drain Flag.*/ kDSPI_TxAndRxStatusFlag = SPI_SR_TXRXS_MASK, /*!< The module is in Stopped/Running state.*/ kDSPI_AllStatusFlag = SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | - SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All status above.*/ + SPI_SR_RFDF_MASK | SPI_SR_TXRXS_MASK /*!< All statuses above.*/ }; /*! @brief DSPI interrupt source.*/ @@ -105,8 +107,8 @@ typedef enum _dspi_master_slave_mode } dspi_master_slave_mode_t; /*! - * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in Modified Transfer Format. This field is valid - * only when CPHA bit in CTAR register is 0. + * @brief DSPI Sample Point: Controls when the DSPI master samples SIN in the Modified Transfer Format. This field is valid + * only when the CPHA bit in the CTAR register is 0. */ typedef enum _dspi_master_sample_point { @@ -165,36 +167,37 @@ typedef enum _dspi_clock_phase typedef enum _dspi_shift_direction { kDSPI_MsbFirst = 0U, /*!< Data transfers start with most significant bit.*/ - kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit.*/ + kDSPI_LsbFirst = 1U /*!< Data transfers start with least significant bit. + Shifting out of LSB is not supported for slave */ } dspi_shift_direction_t; /*! @brief DSPI delay type selection.*/ typedef enum _dspi_delay_type { kDSPI_PcsToSck = 1U, /*!< Pcs-to-SCK delay. */ - kDSPI_LastSckToPcs, /*!< Last SCK edge to Pcs delay. */ + kDSPI_LastSckToPcs, /*!< The last SCK edge to Pcs delay. */ kDSPI_BetweenTransfer /*!< Delay between transfers. */ } dspi_delay_type_t; /*! @brief DSPI Clock and Transfer Attributes Register (CTAR) selection.*/ typedef enum _dspi_ctar_selection { - kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode, note that CTAR0 and CTAR0_SLAVE are the + kDSPI_Ctar0 = 0U, /*!< CTAR0 selection option for master or slave mode; note that CTAR0 and CTAR0_SLAVE are the same register address. */ kDSPI_Ctar1 = 1U, /*!< CTAR1 selection option for master mode only. */ - kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only , note that some device do not support CTAR2. */ - kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only , note that some device do not support CTAR3. */ - kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only , note that some device do not support CTAR4. */ - kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only , note that some device do not support CTAR5. */ - kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only , note that some device do not support CTAR6. */ - kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only , note that some device do not support CTAR7. */ + kDSPI_Ctar2 = 2U, /*!< CTAR2 selection option for master mode only; note that some devices do not support CTAR2. */ + kDSPI_Ctar3 = 3U, /*!< CTAR3 selection option for master mode only; note that some devices do not support CTAR3. */ + kDSPI_Ctar4 = 4U, /*!< CTAR4 selection option for master mode only; note that some devices do not support CTAR4. */ + kDSPI_Ctar5 = 5U, /*!< CTAR5 selection option for master mode only; note that some devices do not support CTAR5. */ + kDSPI_Ctar6 = 6U, /*!< CTAR6 selection option for master mode only; note that some devices do not support CTAR6. */ + kDSPI_Ctar7 = 7U /*!< CTAR7 selection option for master mode only; note that some devices do not support CTAR7. */ } dspi_ctar_selection_t; -#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro , internal used. */ -#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro , internal used. */ -#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro , internal used. */ -#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro , internal used. */ -/*! @brief Can use this enumeration for DSPI master transfer configFlags. */ +#define DSPI_MASTER_CTAR_SHIFT (0U) /*!< DSPI master CTAR shift macro; used internally. */ +#define DSPI_MASTER_CTAR_MASK (0x0FU) /*!< DSPI master CTAR mask macro; used internally. */ +#define DSPI_MASTER_PCS_SHIFT (4U) /*!< DSPI master PCS shift macro; used internally. */ +#define DSPI_MASTER_PCS_MASK (0xF0U) /*!< DSPI master PCS mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI master transfer configFlags. */ enum _dspi_transfer_config_flag_for_master { kDSPI_MasterCtar0 = 0U << DSPI_MASTER_CTAR_SHIFT, /*!< DSPI master transfer use CTAR0 setting. */ @@ -213,13 +216,13 @@ enum _dspi_transfer_config_flag_for_master kDSPI_MasterPcs4 = 4U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS4 signal. */ kDSPI_MasterPcs5 = 5U << DSPI_MASTER_PCS_SHIFT, /*!< DSPI master transfer use PCS5 signal. */ - kDSPI_MasterPcsContinuous = 1U << 20, /*!< Is PCS signal continuous. */ - kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Is PCS signal active after last frame transfer.*/ + kDSPI_MasterPcsContinuous = 1U << 20, /*!< Indicates whether the PCS signal is continuous. */ + kDSPI_MasterActiveAfterTransfer = 1U << 21, /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ }; -#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro , internal used. */ -#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro , internal used. */ -/*! @brief Can use this enum for DSPI slave transfer configFlags. */ +#define DSPI_SLAVE_CTAR_SHIFT (0U) /*!< DSPI slave CTAR shift macro; used internally. */ +#define DSPI_SLAVE_CTAR_MASK (0x07U) /*!< DSPI slave CTAR mask macro; used internally. */ +/*! @brief Use this enumeration for the DSPI slave transfer configFlags. */ enum _dspi_transfer_config_flag_for_slave { kDSPI_SlaveCtar0 = 0U << DSPI_SLAVE_CTAR_SHIFT, /*!< DSPI slave transfer use CTAR0 setting. */ @@ -234,15 +237,15 @@ enum _dspi_transfer_state kDSPI_Error /*!< Transfer error. */ }; -/*! @brief DSPI master command date configuration used for SPIx_PUSHR.*/ +/*! @brief DSPI master command date configuration used for the SPIx_PUSHR.*/ typedef struct _dspi_command_data_config { - bool isPcsContinuous; /*!< Option to enable the continuous assertion of chip select between transfers.*/ + bool isPcsContinuous; /*!< Option to enable the continuous assertion of the chip select between transfers.*/ dspi_ctar_selection_t whichCtar; /*!< The desired Clock and Transfer Attributes Register (CTAR) to use for CTAS.*/ dspi_which_pcs_t whichPcs; /*!< The desired PCS signal to use for the data transfer.*/ bool isEndOfQueue; /*!< Signals that the current transfer is the last in the queue.*/ - bool clearTransferCount; /*!< Clears SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ + bool clearTransferCount; /*!< Clears the SPI Transfer Counter (SPI_TCNT) before transmission starts.*/ } dspi_command_data_config_t; /*! @brief DSPI master ctar configuration structure.*/ @@ -254,33 +257,33 @@ typedef struct _dspi_master_ctar_config dspi_clock_phase_t cpha; /*!< Clock phase. */ dspi_shift_direction_t direction; /*!< MSB or LSB data shift direction. */ - uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time with nanosecond , set to 0 sets the minimum - delay. It sets the boundary value if out of range that can be set.*/ - uint32_t lastSckToPcsDelayInNanoSec; /*!< Last SCK to PCS delay time with nanosecond , set to 0 sets the - minimum delay.It sets the boundary value if out of range that can be - set.*/ - uint32_t betweenTransferDelayInNanoSec; /*!< After SCK delay time with nanosecond , set to 0 sets the minimum - delay.It sets the boundary value if out of range that can be set.*/ + uint32_t pcsToSckDelayInNanoSec; /*!< PCS to SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ + uint32_t lastSckToPcsDelayInNanoSec; /*!< The last SCK to PCS delay time in nanoseconds; setting to 0 sets the + minimum delay. It also sets the boundary value if out of range.*/ + + uint32_t betweenTransferDelayInNanoSec; /*!< After the SCK delay time in nanoseconds; setting to 0 sets the minimum + delay. It also sets the boundary value if out of range.*/ } dspi_master_ctar_config_t; /*! @brief DSPI master configuration structure.*/ typedef struct _dspi_master_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_master_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - dspi_which_pcs_t whichPcs; /*!< Desired Peripheral Chip Select (pcs). */ - dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< Desired PCS active high or low. */ + dspi_which_pcs_t whichPcs; /*!< The desired Peripheral Chip Select (pcs). */ + dspi_pcs_polarity_config_t pcsActiveHighOrLow; /*!< The desired PCS active high or low. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable . Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_master_config_t; @@ -290,23 +293,23 @@ typedef struct _dspi_slave_ctar_config uint32_t bitsPerFrame; /*!< Bits per frame, minimum 4, maximum 16.*/ dspi_clock_polarity_t cpol; /*!< Clock polarity. */ dspi_clock_phase_t cpha; /*!< Clock phase. */ - /*!< Slave only supports MSB , does not support LSB.*/ + /*!< Slave only supports MSB and does not support LSB.*/ } dspi_slave_ctar_config_t; /*! @brief DSPI slave configuration structure.*/ typedef struct _dspi_slave_config { - dspi_ctar_selection_t whichCtar; /*!< Desired CTAR to use. */ + dspi_ctar_selection_t whichCtar; /*!< The desired CTAR to use. */ dspi_slave_ctar_config_t ctarConfig; /*!< Set the ctarConfig to the desired CTAR. */ - bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that continuous SCK is only + bool enableContinuousSCK; /*!< CONT_SCKE, continuous SCK enable. Note that the continuous SCK is only supported for CPHA = 1.*/ - bool enableRxFifoOverWrite; /*!< ROOE, Receive FIFO overflow overwrite enable. ROOE = 0, the incoming - data is ignored, the data from the transfer that generated the overflow - is either ignored. ROOE = 1, the incoming data is shifted in to the - shift to the shift register. */ - bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if it's true.*/ - dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in Modified Transfer + bool enableRxFifoOverWrite; /*!< ROOE, receive FIFO overflow overwrite enable. If ROOE = 0, the incoming + data is ignored and the data from the transfer that generated the overflow + is also ignored. If ROOE = 1, the incoming data is shifted to the + shift register. */ + bool enableModifiedTimingFormat; /*!< Enables a modified transfer format to be used if true.*/ + dspi_master_sample_point_t samplePoint; /*!< Controls when the module master samples SIN in the Modified Transfer Format. It's valid only when CPHA=0. */ } dspi_slave_config_t; @@ -353,7 +356,7 @@ typedef struct _dspi_transfer volatile size_t dataSize; /*!< Transfer bytes. */ uint32_t - configFlags; /*!< Transfer transfer configuration flags , set from _dspi_transfer_config_flag_for_master if the + configFlags; /*!< Transfer transfer configuration flags; set from _dspi_transfer_config_flag_for_master if the transfer is used for master or _dspi_transfer_config_flag_for_slave enumeration if the transfer is used for slave.*/ } dspi_transfer_t; @@ -361,38 +364,38 @@ typedef struct _dspi_transfer /*! @brief DSPI master transfer handle structure used for transactional API. */ struct _dspi_master_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal is active after the last frame transfer.*/ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ + volatile uint8_t state; /*!< DSPI transfer state, see _dspi_transfer_state.*/ dspi_master_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ }; -/*! @brief DSPI slave transfer handle structure used for transactional API. */ +/*! @brief DSPI slave transfer handle structure used for the transactional API. */ struct _dspi_slave_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile bool isThereExtraByte; /*!< Indicates whether there are extra bytes.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ volatile uint8_t state; /*!< DSPI transfer state.*/ @@ -417,18 +420,18 @@ extern "C" { /*! * @brief Initializes the DSPI master. * - * This function initializes the DSPI master configuration. An example use case is as follows: + * This function initializes the DSPI master configuration. This is an example use case. * @code * dspi_master_config_t masterConfig; * masterConfig.whichCtar = kDSPI_Ctar0; - * masterConfig.ctarConfig.baudRate = 500000000; + * masterConfig.ctarConfig.baudRate = 500000000U; * masterConfig.ctarConfig.bitsPerFrame = 8; * masterConfig.ctarConfig.cpol = kDSPI_ClockPolarityActiveHigh; * masterConfig.ctarConfig.cpha = kDSPI_ClockPhaseFirstEdge; * masterConfig.ctarConfig.direction = kDSPI_MsbFirst; - * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; - * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000 / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; + * masterConfig.ctarConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.ctarConfig.baudRate ; * masterConfig.whichPcs = kDSPI_Pcs0; * masterConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; * masterConfig.enableContinuousSCK = false; @@ -439,8 +442,8 @@ extern "C" { * @endcode * * @param base DSPI peripheral address. - * @param masterConfig Pointer to structure dspi_master_config_t. - * @param srcClock_Hz Module source input clock in Hertz + * @param masterConfig Pointer to the structure dspi_master_config_t. + * @param srcClock_Hz Module source input clock in Hertz. */ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, uint32_t srcClock_Hz); @@ -448,8 +451,8 @@ void DSPI_MasterInit(SPI_Type *base, const dspi_master_config_t *masterConfig, u * @brief Sets the dspi_master_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for the DSPI_MasterInit(). - * User may use the initialized structure unchanged in DSPI_MasterInit() or modify the structure - * before calling DSPI_MasterInit(). + * Users may use the initialized structure unchanged in the DSPI_MasterInit() or modify the structure + * before calling the DSPI_MasterInit(). * Example: * @code * dspi_master_config_t masterConfig; @@ -462,7 +465,7 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); /*! * @brief DSPI slave configuration. * - * This function initializes the DSPI slave configuration. An example use case is as follows: + * This function initializes the DSPI slave configuration. This is an example use case. * @code * dspi_slave_config_t slaveConfig; * slaveConfig->whichCtar = kDSPI_Ctar0; @@ -477,22 +480,22 @@ void DSPI_MasterGetDefaultConfig(dspi_master_config_t *masterConfig); * @endcode * * @param base DSPI peripheral address. - * @param slaveConfig Pointer to structure dspi_master_config_t. + * @param slaveConfig Pointer to the structure dspi_master_config_t. */ void DSPI_SlaveInit(SPI_Type *base, const dspi_slave_config_t *slaveConfig); /*! - * @brief Sets the dspi_slave_config_t structure to default values. + * @brief Sets the dspi_slave_config_t structure to a default value. * * The purpose of this API is to get the configuration structure initialized for the DSPI_SlaveInit(). - * User may use the initialized structure unchanged in DSPI_SlaveInit(), or modify the structure - * before calling DSPI_SlaveInit(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_SlaveInit() or modify the structure + * before calling the DSPI_SlaveInit(). + * This is an example. * @code * dspi_slave_config_t slaveConfig; * DSPI_SlaveGetDefaultConfig(&slaveConfig); * @endcode - * @param slaveConfig pointer to dspi_slave_config_t structure. + * @param slaveConfig Pointer to the dspi_slave_config_t structure. */ void DSPI_SlaveGetDefaultConfig(dspi_slave_config_t *slaveConfig); @@ -506,7 +509,7 @@ void DSPI_Deinit(SPI_Type *base); * @brief Enables the DSPI peripheral and sets the MCR MDIS to 0. * * @param base DSPI peripheral address. - * @param enable pass true to enable module, false to disable module. + * @param enable Pass true to enable module, false to disable module. */ static inline void DSPI_Enable(SPI_Type *base, bool enable) { @@ -532,7 +535,7 @@ static inline void DSPI_Enable(SPI_Type *base, bool enable) /*! * @brief Gets the DSPI status flag state. * @param base DSPI peripheral address. - * @return The DSPI status(in SR register). + * @return DSPI status (in SR register). */ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) { @@ -545,13 +548,13 @@ static inline uint32_t DSPI_GetStatusFlags(SPI_Type *base) * This function clears the desired status bit by using a write-1-to-clear. The user passes in the base and the * desired status bit to clear. The list of status bits is defined in the dspi_status_and_interrupt_request_t. The * function uses these bit positions in its algorithm to clear the desired flag state. - * Example usage: + * This is an example. * @code * DSPI_ClearStatusFlags(base, kDSPI_TxCompleteFlag|kDSPI_EndOfQueueFlag); * @endcode * * @param base DSPI peripheral address. - * @param statusFlags The status flag , used from type dspi_flags. + * @param statusFlags The status flag used from the type dspi_flags. */ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) { @@ -570,7 +573,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) /*! * @brief Enables the DSPI interrupts. * - * This function configures the various interrupt masks of the DSPI. The parameters are base and an interrupt mask. + * This function configures the various interrupt masks of the DSPI. The parameters are a base and an interrupt mask. * Note, for Tx Fill and Rx FIFO drain requests, enable the interrupt request and disable the DMA request. * * @code @@ -578,7 +581,7 @@ static inline void DSPI_ClearStatusFlags(SPI_Type *base, uint32_t statusFlags) * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); @@ -590,7 +593,7 @@ void DSPI_EnableInterrupts(SPI_Type *base, uint32_t mask); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask, can use the enum _dspi_interrupt_enable. + * @param mask The interrupt mask; use the enum _dspi_interrupt_enable. */ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) { @@ -609,13 +612,13 @@ static inline void DSPI_DisableInterrupts(SPI_Type *base, uint32_t mask) /*! * @brief Enables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * DSPI_EnableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) { @@ -625,13 +628,13 @@ static inline void DSPI_EnableDMA(SPI_Type *base, uint32_t mask) /*! * @brief Disables the DSPI DMA request. * - * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are base and a DMA mask. + * This function configures the Rx and Tx DMA mask of the DSPI. The parameters are a base and a DMA mask. * @code * SPI_DisableDMA(base, kDSPI_TxDmaEnable | kDSPI_RxDmaEnable); * @endcode * * @param base DSPI peripheral address. - * @param mask The interrupt mask can use the enum dspi_dma_enable. + * @param mask The interrupt mask; use the enum dspi_dma_enable. */ static inline void DSPI_DisableDMA(SPI_Type *base, uint32_t mask) { @@ -710,7 +713,7 @@ static inline bool DSPI_IsMaster(SPI_Type *base) /*! * @brief Starts the DSPI transfers and clears HALT bit in MCR. * - * This function sets the module to begin data transfer in either master or slave mode. + * This function sets the module to start data transfer in either master or slave mode. * * @param base DSPI peripheral address. */ @@ -719,9 +722,9 @@ static inline void DSPI_StartTransfer(SPI_Type *base) base->MCR &= ~SPI_MCR_HALT_MASK; } /*! - * @brief Stops (halts) DSPI transfers and sets HALT bit in MCR. + * @brief Stops DSPI transfers and sets the HALT bit in MCR. * - * This function stops data transfers in either master or slave mode. + * This function stops data transfers in either master or slave modes. * * @param base DSPI peripheral address. */ @@ -731,15 +734,15 @@ static inline void DSPI_StopTransfer(SPI_Type *base) } /*! - * @brief Enables (or disables) the DSPI FIFOs. + * @brief Enables or disables the DSPI FIFOs. * - * This function allows the caller to disable/enable the Tx and Rx FIFOs (independently). - * Note that to disable, the caller must pass in a logic 0 (false) for the particular FIFO configuration. To enable, - * the caller must pass in a logic 1 (true). + * This function allows the caller to disable/enable the Tx and Rx FIFOs independently. + * Note that to disable, pass in a logic 0 (false) for the particular FIFO configuration. To enable, + * pass in a logic 1 (true). * * @param base DSPI peripheral address. - * @param enableTxFifo Disables (false) the TX FIFO, else enables (true) the TX FIFO - * @param enableRxFifo Disables (false) the RX FIFO, else enables (true) the RX FIFO + * @param enableTxFifo Disables (false) the TX FIFO; Otherwise, enables (true) the TX FIFO + * @param enableRxFifo Disables (false) the RX FIFO; Otherwise, enables (true) the RX FIFO */ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool enableRxFifo) { @@ -751,8 +754,8 @@ static inline void DSPI_SetFifoEnable(SPI_Type *base, bool enableTxFifo, bool en * @brief Flushes the DSPI FIFOs. * * @param base DSPI peripheral address. - * @param flushTxFifo Flushes (true) the Tx FIFO, else do not flush (false) the Tx FIFO - * @param flushRxFifo Flushes (true) the Rx FIFO, else do not flush (false) the Rx FIFO + * @param flushTxFifo Flushes (true) the Tx FIFO; Otherwise, does not flush (false) the Tx FIFO + * @param flushRxFifo Flushes (true) the Rx FIFO; Otherwise, does not flush (false) the Rx FIFO */ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRxFifo) { @@ -762,13 +765,13 @@ static inline void DSPI_FlushFifo(SPI_Type *base, bool flushTxFifo, bool flushRx /*! * @brief Configures the DSPI peripheral chip select polarity simultaneously. - * For example, PCS0 and PCS1 set to active low and other PCS set to active high. Note that the number of + * For example, PCS0 and PCS1 are set to active low and other PCS is set to active high. Note that the number of * PCSs is specific to the device. * @code * DSPI_SetAllPcsPolarity(base, kDSPI_Pcs0ActiveLow | kDSPI_Pcs1ActiveLow); @endcode * @param base DSPI peripheral address. - * @param mask The PCS polarity mask , can use the enum _dspi_pcs_polarity. + * @param mask The PCS polarity mask; use the enum _dspi_pcs_polarity. */ static inline void DSPI_SetAllPcsPolarity(SPI_Type *base, uint32_t mask) { @@ -797,19 +800,19 @@ uint32_t DSPI_MasterSetBaudRate(SPI_Type *base, * @brief Manually configures the delay prescaler and scaler for a particular CTAR. * * This function configures the PCS to SCK delay pre-scalar (PcsSCK) and scalar (CSSCK), after SCK delay pre-scalar - * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT)and scalar (DT). + * (PASC) and scalar (ASC), and the delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes the delay to configure along with the prescaler and scaler value. - * This allows the user to directly set the prescaler/scaler values if they have pre-calculated them or if they simply - * wish to manually increment either value. + * The user passes the delay to the configuration along with the prescaler and scaler value. + * This allows the user to directly set the prescaler/scaler values if pre-calculated or + * to manually increment either value. * * @param base DSPI peripheral address. * @param whichCtar The desired Clock and Transfer Attributes Register (CTAR) of type dspi_ctar_selection_t. * @param prescaler The prescaler delay value (can be an integer 0, 1, 2, or 3). * @param scaler The scaler delay value (can be any integer between 0 to 15). - * @param whichDelay The desired delay to configure, must be of type dspi_delay_type_t + * @param whichDelay The desired delay to configure; must be of type dspi_delay_type_t */ void DSPI_MasterSetDelayScaler( SPI_Type *base, dspi_ctar_selection_t whichCtar, uint32_t prescaler, uint32_t scaler, dspi_delay_type_t whichDelay); @@ -817,15 +820,15 @@ void DSPI_MasterSetDelayScaler( /*! * @brief Calculates the delay prescaler and scaler based on the desired delay input in nanoseconds. * - * This function calculates the values for: + * This function calculates the values for the following. * PCS to SCK delay pre-scalar (PCSSCK) and scalar (CSSCK), or * After SCK delay pre-scalar (PASC) and scalar (ASC), or - * Delay after transfer pre-scalar (PDT)and scalar (DT). + * Delay after transfer pre-scalar (PDT) and scalar (DT). * - * These delay names are available in type dspi_delay_type_t. + * These delay names are available in the type dspi_delay_type_t. * - * The user passes which delay they want to configure along with the desired delay value in nanoseconds. The function - * calculates the values needed for the prescaler and scaler and returning the actual calculated delay as an exact + * The user passes which delay to configure along with the desired delay value in nanoseconds. The function + * calculates the values needed for the prescaler and scaler. Note that returning the calculated delay as an exact * delay match may not be possible. In this case, the closest match is calculated without going below the desired * delay value input. * It is possible to input a very large delay value that exceeds the capability of the part, in which case the maximum @@ -849,11 +852,11 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, * @brief Writes data into the data buffer for master mode. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_data_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -865,7 +868,7 @@ uint32_t DSPI_MasterSetDelayTimes(SPI_Type *base, @endcode * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data) @@ -879,14 +882,14 @@ static inline void DSPI_MasterWriteData(SPI_Type *base, dspi_command_data_config * @brief Sets the dspi_command_data_config_t structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the DSPI_MasterWrite_xx(). - * User may use the initialized structure unchanged in DSPI_MasterWrite_xx() or modify the structure - * before calling DSPI_MasterWrite_xx(). - * Example: + * Users may use the initialized structure unchanged in the DSPI_MasterWrite_xx() or modify the structure + * before calling the DSPI_MasterWrite_xx(). + * This is an example. * @code * dspi_command_data_config_t command; * DSPI_GetDefaultDataCommandConfig(&command); * @endcode - * @param command pointer to dspi_command_data_config_t structure. + * @param command Pointer to the dspi_command_data_config_t structure. */ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); @@ -894,11 +897,11 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * @brief Writes data into the data buffer master mode and waits till complete to return. * * In master mode, the 16-bit data is appended to the 16-bit command info. The command portion - * provides characteristics of the data such as the optional continuous chip select + * provides characteristics of the data, such as the optional continuous chip select * operation between transfers, the desired Clock and Transfer Attributes register to use for the * associated SPI frame, the desired PCS signal to use for the data transfer, whether the current * transfer is the last in the queue, and whether to clear the transfer count (normally needed when - * sending the first frame of a data packet). This is an example: + * sending the first frame of a data packet). This is an example. * @code * dspi_command_config_t commandConfig; * commandConfig.isPcsContinuous = true; @@ -911,10 +914,10 @@ void DSPI_GetDefaultDataCommandConfig(dspi_command_data_config_t *command); * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). Because the SPI is a synchronous protocol, - * receive data is available when transmit completes. + * the received data is available when the transmit completes. * * @param base DSPI peripheral address. - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @param data The data word to be sent. */ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *command, uint16_t data); @@ -929,10 +932,10 @@ void DSPI_MasterWriteDataBlocking(SPI_Type *base, dspi_command_data_config_t *co * improve performance in cases where the command structure is constant. For example, the user calls this function * before starting a transfer to generate the command word. When they are ready to transmit the data, they OR * this formatted command word with the desired data to transmit. This process increases transmit performance when - * compared to calling send functions such as DSPI_HAL_WriteDataMastermode which format the command word each time a + * compared to calling send functions, such as DSPI_HAL_WriteDataMastermode, which format the command word each time a * data word is to be sent. * - * @param command Pointer to command structure. + * @param command Pointer to the command structure. * @return The command word formatted to the PUSHR data register bit field. */ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t *command) @@ -945,24 +948,23 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t /*! * @brief Writes a 32-bit data word (16-bit command appended with 16-bit data) into the data - * buffer, master mode and waits till complete to return. + * buffer master mode and waits till complete to return. * - * In this function, the user must append the 16-bit data to the 16-bit command info then provide the total 32-bit word + * In this function, the user must append the 16-bit data to the 16-bit command information and then provide the total 32-bit word * as the data to send. - * The command portion provides characteristics of the data such as the optional continuous chip select operation -* between - * transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS + * The command portion provides characteristics of the data, such as the optional continuous chip select operation + * between transfers, the desired Clock and Transfer Attributes register to use for the associated SPI frame, the desired PCS * signal to use for the data transfer, whether the current transfer is the last in the queue, and whether to clear the * transfer count (normally needed when sending the first frame of a data packet). The user is responsible for * appending this command with the data to send. This is an example: * @code * dataWord = <16-bit command> | <16-bit data>; - * DSPI_HAL_WriteCommandDataMastermodeBlocking(base, dataWord); + * DSPI_MasterWriteCommandDataBlocking(base, dataWord); * @endcode * * Note that this function does not return until after the transmit is complete. Also note that the DSPI must be * enabled and running to transmit data (MCR[MDIS] & [HALT] = 0). - * Because the SPI is a synchronous protocol, the receive data is available when transmit completes. + * Because the SPI is a synchronous protocol, the received data is available when the transmit completes. * * For a blocking polling transfer, see methods below. * Option 1: @@ -981,7 +983,7 @@ static inline uint32_t DSPI_MasterGetFormattedCommand(dspi_command_data_config_t * DSPI_MasterWriteDataBlocking(base,&command,data_need_to_send_2); * * @param base DSPI peripheral address. - * @param data The data word (command and data combined) to be sent + * @param data The data word (command and data combined) to be sent. */ void DSPI_MasterWriteCommandDataBlocking(SPI_Type *base, uint32_t data); @@ -1033,13 +1035,13 @@ static inline uint32_t DSPI_ReadData(SPI_Type *base) /*! * @brief Initializes the DSPI master handle. * - * This function initializes the DSPI handle which can be used for other DSPI transactional APIs. Usually, for a + * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_handle_t. - * @param callback dspi callback. - * @param userData callback function parameter. + * @param callback DSPI callback. + * @param userData Callback function parameter. */ void DSPI_MasterTransferCreateHandle(SPI_Type *base, dspi_master_handle_t *handle, @@ -1049,12 +1051,11 @@ void DSPI_MasterTransferCreateHandle(SPI_Type *base, /*! * @brief DSPI master transfer data using polling. * - * This function transfers data with polling. This is a blocking function, which does not return until all transfers - * have been - * completed. + * This function transfers data using polling. This is a blocking function, which does not return until all transfers + * have been completed. * * @param base DSPI peripheral base address. - * @param transfer pointer to dspi_transfer_t structure. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); @@ -1063,12 +1064,11 @@ status_t DSPI_MasterTransferBlocking(SPI_Type *base, dspi_transfer_t *transfer); * @brief DSPI master transfer data using interrupts. * * This function transfers data using interrupts. This is a non-blocking function, which returns right away. When all - data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *handle, dspi_transfer_t *transfer); @@ -1079,19 +1079,19 @@ status_t DSPI_MasterTransferNonBlocking(SPI_Type *base, dspi_master_handle_t *ha * This function gets the master transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCount(SPI_Type *base, dspi_master_handle_t *handle, size_t *count); /*! - * @brief DSPI master aborts transfer using an interrupt. + * @brief DSPI master aborts a transfer using an interrupt. * * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); @@ -1101,7 +1101,7 @@ void DSPI_MasterTransferAbort(SPI_Type *base, dspi_master_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); @@ -1111,10 +1111,10 @@ void DSPI_MasterTransferHandleIRQ(SPI_Type *base, dspi_master_handle_t *handle); * This function initializes the DSPI handle, which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * @param handle DSPI handle pointer to dspi_slave_handle_t. + * @param handle DSPI handle pointer to the dspi_slave_handle_t. * @param base DSPI peripheral base address. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData Callback function parameter. */ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, dspi_slave_handle_t *handle, @@ -1125,12 +1125,11 @@ void DSPI_SlaveTransferCreateHandle(SPI_Type *base, * @brief DSPI slave transfers data using an interrupt. * * This function transfers data using an interrupt. This is a non-blocking function, which returns right away. When all - * data - * have been transferred, the callback function is called. + * data is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. + * @param transfer Pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *handle, dspi_transfer_t *transfer); @@ -1141,8 +1140,8 @@ status_t DSPI_SlaveTransferNonBlocking(SPI_Type *base, dspi_slave_handle_t *hand * This function gets the slave transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle Pointer to the dspi_master_handle_t structure which stores the transfer state. + * @param count The number of bytes transferred by using the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, size_t *count); @@ -1150,10 +1149,10 @@ status_t DSPI_SlaveTransferGetCount(SPI_Type *base, dspi_slave_handle_t *handle, /*! * @brief DSPI slave aborts a transfer using an interrupt. * - * This function aborts transfer using an interrupt. + * This function aborts a transfer using an interrupt. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); @@ -1163,7 +1162,7 @@ void DSPI_SlaveTransferAbort(SPI_Type *base, dspi_slave_handle_t *handle); * This function processes the DSPI transmit and receive IRQ. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_handle_t structure which stores the transfer state. + * @param handle Pointer to the dspi_slave_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferHandleIRQ(SPI_Type *base, dspi_slave_handle_t *handle); diff --git a/drivers/fsl_dspi_edma.c b/drivers/fsl_dspi_edma.c index a1c2002..ef0d151 100644 --- a/drivers/fsl_dspi_edma.c +++ b/drivers/fsl_dspi_edma.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_dspi_edma.h" @@ -57,7 +57,7 @@ typedef struct _dspi_slave_edma_private_handle ***********************************************************************************************************************/ /*! * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -66,7 +66,7 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, /*! * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA. -* This is not a public API as it is called from other driver functions. +* This is not a public API. */ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, void *g_dspiEdmaPrivateHandle, @@ -102,6 +102,9 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaIntermediaryToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToIntermediaryHandle); + assert(edmaIntermediaryToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -121,7 +124,8 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If the transfer count is zero, then return immediately.*/ if (transfer->dataSize == 0) @@ -141,6 +145,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand return kStatus_DSPI_Busy; } + handle->state = kDSPI_Busy; + uint32_t instance = DSPI_GetInstance(base); uint16_t wordToSend = 0; uint8_t dummyData = DSPI_DUMMY_DATA; @@ -158,8 +164,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->txBuffIfNull = ((uint32_t)DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - handle->state = kDSPI_Busy; - dspi_command_data_config_t commandStruct; DSPI_StopTransfer(base); DSPI_FlushFifo(base, true, true); @@ -194,39 +198,70 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - /* this limits the amount of data we can transfer due to the linked channel. - * The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame + /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer + * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + if (handle->bitsPerFrame > 8) { - if (transfer->dataSize > 1022) + if (transfer->dataSize > (limited_size << 1u)) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } else { - if (transfer->dataSize > 511) + if (transfer->dataSize > limited_size) { + handle->state = kDSPI_Idle; return kStatus_DSPI_OutOfRange; } } + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) + { + handle->state = kDSPI_Idle; + return kStatus_InvalidArgument; + } + DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback, &s_dspiMasterEdmaPrivateHandle[instance]); - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } + /* + (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. + channel_A minor link to channel_B , channel_B minor link to channel_C. + + Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer. + channel_A:SPI_POPR to rxData, + channel_B:next txData to handle->command (low 16 bits), + channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data + (handle->lastCommand to SPI_PUSHR). + + (2)For DSPI instances with separate RX and TX DMA requests: + Rx DMA request -> channel_A + Tx DMA request -> channel_C -> channel_B . + channel_C major link to channel_B. + So need prepare the first data in "intermediary" before the DMA + transfer and then channel_B is used to prepare the next data to "intermediary" + + channel_A:SPI_POPR to rxData, + channel_C: handle->command (32 bits) to SPI_PUSHR, + channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data + (handle->lastCommand to handle->Command). + */ /*If dspi has separate dma request , prepare the first data in "intermediary" . else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/ @@ -244,22 +279,16 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; /* increment to next data byte */ - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; /* increment to next data byte */ + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; } handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else /* For all words except the last word , frame > 8bits */ { @@ -292,6 +321,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (handle->remainingSendByteCount == 1) { handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + handle->command = handle->lastCommand; } else { @@ -316,21 +346,13 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand { if (handle->txData) { - if (handle->isThereExtraByte) - { - wordToSend = *(handle->txData) | ((uint32_t)dummyData << 8); - } - else - { - wordToSend = *(handle->txData); - ++handle->txData; - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - } + wordToSend = *(handle->txData); + ++handle->txData; + wordToSend |= (unsigned)(*(handle->txData)) << 8U; } else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount = 0; base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend; @@ -348,7 +370,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand else { wordToSend = ((uint32_t)dummyData << 8) | dummyData; - ; } handle->remainingSendByteCount -= 2; base->PUSHR = (handle->command & 0xffff0000U) | wordToSend; @@ -405,7 +426,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } - /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/ + /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/ EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); transferConfigA.srcAddr = (uint32_t)rxAddr; @@ -436,6 +457,10 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -444,9 +469,82 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */ + EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->remainingSendByteCount > 0) + /*Calculate the last data : handle->lastCommand*/ + if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) + { + if (handle->txData) + { + uint32_t bufferIndex = 0; + + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + if (handle->bitsPerFrame <= 8) + { + bufferIndex = handle->remainingSendByteCount - 1; + } + else + { + bufferIndex = handle->remainingSendByteCount - 2; + } + } + else + { + bufferIndex = handle->remainingSendByteCount; + } + + if (handle->bitsPerFrame <= 8) + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; + } + else + { + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | + ((uint32_t)handle->txData[bufferIndex - 1] << 8) | + handle->txData[bufferIndex - 2]; + } + } + else + { + if (handle->bitsPerFrame <= 8) + { + wordToSend = dummyData; + } + else + { + wordToSend = ((uint32_t)dummyData << 8) | dummyData; + } + handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; + } + } + + /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to handle->Command*/ + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand); + transferConfigB.destAddr = (uint32_t) & (handle->command); + transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes; + transferConfigB.srcOffset = 0; + transferConfigB.destOffset = 0; + transferConfigB.minorLoopBytes = 4; + transferConfigB.majorLoopCounts = 1; + + EDMA_TcdReset(softwareTCD); + EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL); + } + + /*User_Send_Buffer(txData) to intermediary(handle->command)*/ + if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) || + ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) && + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || + (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { if (handle->txData) { @@ -471,8 +569,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2; } else { @@ -487,8 +584,7 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigB.minorLoopBytes = 2; if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - /*already prepared the first data in "intermediary" , so minus 1 */ - transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2; } else { @@ -498,74 +594,33 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } } + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD); + EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, false); + } + else + { + EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, + handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); + } + } + else + { EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL); } /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to handle the last data */ - EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - - if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) || - ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) && - (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))) - { - if (handle->txData) - { - uint32_t bufferIndex = 0; - if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) - { - if (handle->bitsPerFrame <= 8) - { - bufferIndex = handle->remainingSendByteCount - 1; - } - else - { - bufferIndex = handle->remainingSendByteCount - 2; - } - } - else - { - bufferIndex = handle->remainingSendByteCount; - } - - if (handle->bitsPerFrame <= 8) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1]; - } - else - { - if (handle->isThereExtraByte) - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 2] | - ((uint32_t)dummyData << 8); - } - else - { - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | - ((uint32_t)handle->txData[bufferIndex - 1] << 8) | - handle->txData[bufferIndex - 2]; - } - } - } - else - { - if (handle->bitsPerFrame <= 8) - { - wordToSend = dummyData; - } - else - { - wordToSend = ((uint32_t)dummyData << 8) | dummyData; - } - handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend; - } - } + EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel); - if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) || - ((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) + /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data + * (handle->lastCommand) to SPI_PUSHR*/ + if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0))) { transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand); transferConfigC.destAddr = (uint32_t)txAddr; @@ -581,7 +636,8 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand } if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) || - ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) + ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) || + (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) { transferConfigC.srcAddr = (uint32_t)(&(handle->command)); transferConfigC.destAddr = (uint32_t)txAddr; @@ -591,18 +647,28 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand transferConfigC.srcOffset = 0; transferConfigC.destOffset = 0; transferConfigC.minorLoopBytes = 4; - - if (handle->bitsPerFrame <= 8) + if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + if (handle->bitsPerFrame <= 8) + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1; + } + else + { + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + } + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); } else { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; + transferConfigC.majorLoopCounts = 1; + + EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, + handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL); } - EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD); EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel, false); } @@ -674,20 +740,15 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand &preemption_config_t); } - /*Set the channel link. - For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C. - For DSPI instances with separate RX and TX DMA requests: - Rx DMA request -> channel_A - Tx DMA request -> channel_C -> channel_B . (so need prepare the first data in "intermediary" before the DMA - transfer and then channel_B is used to prepare the next data to "intermediary" ) */ + /*Set the channel link.*/ if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB - to prepare the next 32bits data (User_send_buffer to handle->command) */ + to prepare the next 32bits data (txData to handle->command) */ if (handle->remainingSendByteCount > 1) { EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base, - handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MinorLink, + handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); } @@ -700,12 +761,6 @@ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *hand EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel); - if (handle->isThereExtraByte) - { - EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, - kEDMA_MajorLink, handle->edmaTxDataToIntermediaryHandle->channel); - } - EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel); @@ -724,37 +779,28 @@ static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -784,7 +830,8 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; @@ -799,6 +846,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, edma_handle_t *edmaTxDataToTxRegHandle) { assert(handle); + assert(edmaRxRegToRxDataHandle); + assert(edmaTxDataToTxRegHandle); /* Zero the handle. */ memset(handle, 0, sizeof(*handle)); @@ -817,7 +866,8 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer) { - assert(handle && transfer); + assert(handle); + assert(transfer); /* If send/receive length is zero */ if (transfer->dataSize == 0) @@ -837,7 +887,7 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle return kStatus_DSPI_Busy; } - edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU)); + handle->state = kDSPI_Busy; uint32_t instance = DSPI_GetInstance(base); uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT; @@ -847,51 +897,48 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame */ - if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) + uint32_t limited_size = 0; + if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) { - if (handle->bitsPerFrame > 8) + limited_size = 32767u; + } + else + { + limited_size = 511u; + } + + if (handle->bitsPerFrame > 8) + { + if (transfer->dataSize > (limited_size << 1u)) { - if (transfer->dataSize > 1022) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } - else + } + else + { + if (transfer->dataSize > limited_size) { - if (transfer->dataSize > 511) - { - return kStatus_DSPI_OutOfRange; - } + handle->state = kDSPI_Idle; + return kStatus_DSPI_OutOfRange; } } - if ((handle->bitsPerFrame > 8) && (transfer->dataSize < 2)) + /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */ + if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1)) { + handle->state = kDSPI_Idle; return kStatus_InvalidArgument; } EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]); - handle->state = kDSPI_Busy; - /* Store transfer information */ handle->txData = transfer->txData; handle->rxData = transfer->rxData; handle->remainingSendByteCount = transfer->dataSize; handle->remainingReceiveByteCount = transfer->dataSize; handle->totalByteCount = transfer->dataSize; - handle->errorCount = 0; - - handle->isThereExtraByte = false; - if (handle->bitsPerFrame > 8) - { - if (handle->remainingSendByteCount % 2 == 1) - { - handle->remainingSendByteCount++; - handle->remainingReceiveByteCount--; - handle->isThereExtraByte = true; - } - } uint16_t wordToSend = 0; uint8_t dummyData = DSPI_DUMMY_DATA; @@ -930,16 +977,9 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle { wordToSend = *(handle->txData); ++handle->txData; /* Increment to next data byte */ - if ((handle->remainingSendByteCount == 2) && (handle->isThereExtraByte)) - { - wordToSend |= (unsigned)(dummyData) << 8U; - ++handle->txData; /* Increment to next data byte */ - } - else - { - wordToSend |= (unsigned)(*(handle->txData)) << 8U; - ++handle->txData; /* Increment to next data byte */ - } + + wordToSend |= (unsigned)(*(handle->txData)) << 8U; + ++handle->txData; /* Increment to next data byte */ } else { @@ -1026,6 +1066,10 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle transferConfigA.minorLoopBytes = 2; transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2; } + + /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */ + handle->nbytes = transferConfigA.minorLoopBytes; + EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, &transferConfigA, NULL); EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel, @@ -1037,98 +1081,47 @@ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/ EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel); - /*If there is extra byte , it would use the */ - if (handle->isThereExtraByte) - { - if (handle->txData) - { - handle->txLastData = - handle->txData[handle->remainingSendByteCount - 2] | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - else - { - handle->txLastData = DSPI_DUMMY_DATA | ((uint32_t)DSPI_DUMMY_DATA << 8); - } - transferConfigC.srcAddr = (uint32_t)(&(handle->txLastData)); - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes; - transferConfigC.srcOffset = 0; - transferConfigC.destOffset = 0; - transferConfigC.minorLoopBytes = 4; - transferConfigC.majorLoopCounts = 1; - - EDMA_TcdReset(softwareTCD); - EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL); - } + transferConfigC.destAddr = (uint32_t)txAddr; + transferConfigC.destOffset = 0; - /*Set another transferConfigC*/ - if ((handle->isThereExtraByte) && (handle->remainingSendByteCount == 2)) + if (handle->txData) { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); + transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); + transferConfigC.srcOffset = 1; } else { - transferConfigC.destAddr = (uint32_t)txAddr; - transferConfigC.destOffset = 0; - - if (handle->txData) - { - transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0])); - transferConfigC.srcOffset = 1; - } - else - { - transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); - transferConfigC.srcOffset = 0; - if (handle->bitsPerFrame <= 8) - { - handle->txBuffIfNull = DSPI_DUMMY_DATA; - } - else - { - handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; - } - } - - transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - + transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull); + transferConfigC.srcOffset = 0; if (handle->bitsPerFrame <= 8) { - transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; - transferConfigC.minorLoopBytes = 1; - transferConfigC.majorLoopCounts = handle->remainingSendByteCount; + handle->txBuffIfNull = DSPI_DUMMY_DATA; } else { - transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; - transferConfigC.minorLoopBytes = 2; - if (handle->isThereExtraByte) - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1; - } - else - { - transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; - } + handle->txBuffIfNull = (DSPI_DUMMY_DATA << 8) | DSPI_DUMMY_DATA; } + } - if (handle->isThereExtraByte) - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, softwareTCD); - EDMA_EnableAutoStopRequest(handle->edmaTxDataToTxRegHandle->base, - handle->edmaTxDataToTxRegHandle->channel, false); - } - else - { - EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, - &transferConfigC, NULL); - } + transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes; - EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); + if (handle->bitsPerFrame <= 8) + { + transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes; + transferConfigC.minorLoopBytes = 1; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount; } + else + { + transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes; + transferConfigC.minorLoopBytes = 2; + transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2; + } + + EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel, + &transferConfigC, NULL); + + EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle); } EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle); @@ -1196,37 +1189,28 @@ static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle, bool transferDone, uint32_t tcds) { + assert(edmaHandle); + assert(g_dspiEdmaPrivateHandle); + dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle; dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle; - uint32_t dataReceived; - DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); - if (dspiEdmaPrivateHandle->handle->isThereExtraByte) - { - while (!((dspiEdmaPrivateHandle->base)->SR & SPI_SR_RFDF_MASK)) - { - } - dataReceived = (dspiEdmaPrivateHandle->base)->POPR; - if (dspiEdmaPrivateHandle->handle->rxData) - { - (dspiEdmaPrivateHandle->handle->rxData[dspiEdmaPrivateHandle->handle->totalByteCount - 1]) = dataReceived; - } - } + dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; if (dspiEdmaPrivateHandle->handle->callback) { dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle, kStatus_Success, dspiEdmaPrivateHandle->handle->userData); } - - dspiEdmaPrivateHandle->handle->state = kDSPI_Idle; } void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle) { + assert(handle); + DSPI_StopTransfer(base); DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable); @@ -1255,7 +1239,8 @@ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t size_t bytes; - bytes = EDMA_GetRemainingBytes(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel); + bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base, + handle->edmaRxRegToRxDataHandle->channel); *count = handle->totalByteCount - bytes; diff --git a/drivers/fsl_dspi_edma.h b/drivers/fsl_dspi_edma.h index 643efad..23e29ce 100644 --- a/drivers/fsl_dspi_edma.h +++ b/drivers/fsl_dspi_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,7 +37,6 @@ * @{ */ - /*********************************************************************************************************************** * Definitions **********************************************************************************************************************/ @@ -56,9 +55,9 @@ typedef struct _dspi_slave_edma_handle dspi_slave_edma_handle_t; * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI master. + * @param handle A pointer to the handle for the DSPI master. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, dspi_master_edma_handle_t *handle, @@ -68,38 +67,39 @@ typedef void (*dspi_master_edma_transfer_callback_t)(SPI_Type *base, * @brief Completion callback function pointer type. * * @param base DSPI peripheral base address. - * @param handle Pointer to the handle for the DSPI slave. + * @param handle A pointer to the handle for the DSPI slave. * @param status Success or error code describing whether the transfer completed. - * @param userData Arbitrary pointer-dataSized value passed from the application. + * @param userData An arbitrary pointer-dataSized value passed from the application. */ typedef void (*dspi_slave_edma_transfer_callback_t)(SPI_Type *base, dspi_slave_edma_handle_t *handle, status_t status, void *userData); -/*! @brief DSPI master eDMA transfer handle structure used for transactional API. */ +/*! @brief DSPI master eDMA transfer handle structure used for the transactional API. */ struct _dspi_master_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile uint32_t command; /*!< Desired data command. */ - volatile uint32_t lastCommand; /*!< Desired last data command. */ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ + volatile uint32_t command; /*!< The desired data command. */ + volatile uint32_t lastCommand; /*!< The desired last data command. */ uint8_t fifoSize; /*!< FIFO dataSize. */ - volatile bool isPcsActiveAfterTransfer; /*!< Is PCS signal keep active after the last frame transfer.*/ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + volatile bool + isPcsActiveAfterTransfer; /*!< Indicates whether the PCS signal keeps active after the last frame transfer.*/ + + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state , _dspi_transfer_state.*/ - dspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ @@ -110,33 +110,30 @@ struct _dspi_master_edma_handle edma_tcd_t dspiSoftwareTCD[2]; /*!<SoftwareTCD , internal used*/ }; -/*! @brief DSPI slave eDMA transfer handle structure used for transactional API.*/ +/*! @brief DSPI slave eDMA transfer handle structure used for the transactional API.*/ struct _dspi_slave_edma_handle { - uint32_t bitsPerFrame; /*!< Desired number of bits per frame. */ - volatile bool isThereExtraByte; /*!< Is there extra byte.*/ + uint32_t bitsPerFrame; /*!< The desired number of bits per frame. */ uint8_t *volatile txData; /*!< Send buffer. */ uint8_t *volatile rxData; /*!< Receive buffer. */ - volatile size_t remainingSendByteCount; /*!< Number of bytes remaining to send.*/ - volatile size_t remainingReceiveByteCount; /*!< Number of bytes remaining to receive.*/ - size_t totalByteCount; /*!< Number of transfer bytes*/ + volatile size_t remainingSendByteCount; /*!< A number of bytes remaining to send.*/ + volatile size_t remainingReceiveByteCount; /*!< A number of bytes remaining to receive.*/ + size_t totalByteCount; /*!< A number of transfer bytes*/ uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/ uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/ uint32_t txLastData; /*!< Used if there is an extra byte when 16bits per frame for DMA purpose.*/ - volatile uint8_t state; /*!< DSPI transfer state.*/ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ - uint32_t errorCount; /*!< Error count for slave transfer.*/ + volatile uint8_t state; /*!< DSPI transfer state.*/ dspi_slave_edma_transfer_callback_t callback; /*!< Completion callback. */ void *userData; /*!< Callback user data. */ edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/ edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg*/ - - edma_tcd_t dspiSoftwareTCD[2]; /*!<SoftwareTCD , internal used*/ }; /*********************************************************************************************************************** @@ -152,17 +149,18 @@ extern "C" { * @brief Initializes the DSPI master eDMA handle. * * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a - * specified DSPI instance, user need only call this API once to get the initialized handle. + * specified DSPI instance, call this API once to get the initialized handle. * - * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request source. - * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and + * Note that DSPI eDMA has separated (RX and TX as two sources) or shared (RX and TX are the same source) DMA request + * source. + * (1) For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and * TX DMAMUX source for edmaIntermediaryToTxRegHandle. - * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. + * (2) For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. * * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_master_edma_handle_t. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData A callback function parameter. * @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. * @param edmaTxDataToIntermediaryHandle edmaTxDataToIntermediaryHandle pointer to edma_handle_t. * @param edmaIntermediaryToTxRegHandle edmaIntermediaryToTxRegHandle pointer to edma_handle_t. @@ -178,34 +176,34 @@ void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base, /*! * @brief DSPI master transfer data using eDMA. * - * This function transfer data using eDMA. This is non-blocking function, which returns right away. When all data - * have been transfer, the callback function is called. + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer); /*! - * @brief DSPI master aborts a transfer which using eDMA. + * @brief DSPI master aborts a transfer which is using eDMA. * - * This function aborts a transfer which using eDMA. + * This function aborts a transfer which is using eDMA. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state. + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. */ void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle); /*! * @brief Gets the master eDMA transfer count. * - * This function get the master eDMA transfer count. + * This function gets the master eDMA transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_master_edma_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle A pointer to the dspi_master_edma_handle_t structure which stores the transfer state. + * @param count A number of bytes transferred by the non-blocking transaction. * @return status of status_t. */ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count); @@ -216,7 +214,8 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle * This function initializes the DSPI eDMA handle which can be used for other DSPI transactional APIs. Usually, for a * specified DSPI instance, call this API once to get the initialized handle. * - * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request source. + * Note that DSPI eDMA has separated (RN and TX in 2 sources) or shared (RX and TX are the same source) DMA request + * source. * (1)For the separated DMA request source, enable and set the RX DMAMUX source for edmaRxRegToRxDataHandle and * TX DMAMUX source for edmaTxDataToTxRegHandle. * (2)For the shared DMA request source, enable and set the RX/RX DMAMUX source for the edmaRxRegToRxDataHandle. @@ -224,7 +223,7 @@ status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle * @param base DSPI peripheral base address. * @param handle DSPI handle pointer to dspi_slave_edma_handle_t. * @param callback DSPI callback. - * @param userData callback function parameter. + * @param userData A callback function parameter. * @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t. * @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t. */ @@ -238,25 +237,25 @@ void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base, /*! * @brief DSPI slave transfer data using eDMA. * - * This function transfer data using eDMA. This is non-blocking function, which returns right away. When all data - * have been transfer, the callback function is called. - * Note that slave EDMA transfer cannot support the situation that transfer_size is 1 when the bitsPerFrame is greater - * than 8 . + * This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data + * is transferred, the callback function is called. + * Note that the slave eDMA transfer doesn't support transfer_size is 1 when the bitsPerFrame is greater + * than eight. * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state. - * @param transfer pointer to dspi_transfer_t structure. + * @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * @param transfer A pointer to the dspi_transfer_t structure. * @return status of status_t. */ status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer); /*! - * @brief DSPI slave aborts a transfer which using eDMA. + * @brief DSPI slave aborts a transfer which is using eDMA. * - * This function aborts a transfer which using eDMA. + * This function aborts a transfer which is using eDMA. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state. + * @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. */ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle); @@ -266,8 +265,8 @@ void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handl * This function gets the slave eDMA transfer count. * * @param base DSPI peripheral base address. - * @param handle pointer to dspi_slave_edma_handle_t structure which stores the transfer state. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle A pointer to the dspi_slave_edma_handle_t structure which stores the transfer state. + * @param count A number of bytes transferred so far by the non-blocking transaction. * @return status of status_t. */ status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count); diff --git a/drivers/fsl_dspi_freertos.c b/drivers/fsl_dspi_freertos.c new file mode 100644 index 0000000..da5eeca --- /dev/null +++ b/drivers/fsl_dspi_freertos.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_dspi_freertos.h" + +static void DSPI_RTOS_Callback(SPI_Type *base, dspi_master_handle_t *drv_handle, status_t status, void *userData) +{ + dspi_rtos_handle_t *handle = (dspi_rtos_handle_t *)userData; + BaseType_t reschedule; + + xSemaphoreGiveFromISR(handle->event, &reschedule); + portYIELD_FROM_ISR(reschedule); +} + +status_t DSPI_RTOS_Init(dspi_rtos_handle_t *handle, + SPI_Type *base, + const dspi_master_config_t *masterConfig, + uint32_t srcClock_Hz) +{ + if (handle == NULL) + { + return kStatus_InvalidArgument; + } + + if (base == NULL) + { + return kStatus_InvalidArgument; + } + + memset(handle, 0, sizeof(dspi_rtos_handle_t)); + +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->mutex = xSemaphoreCreateMutexStatic(&handle->mutexBuffer); +#else + handle->mutex = xSemaphoreCreateMutex(); +#endif + if (handle->mutex == NULL) + { + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->event = xSemaphoreCreateBinaryStatic(&handle->semaphoreBuffer); +#else + handle->event = xSemaphoreCreateBinary(); +#endif + if (handle->event == NULL) + { + vSemaphoreDelete(handle->mutex); + return kStatus_Fail; + } + + handle->base = base; + + DSPI_MasterInit(handle->base, masterConfig, srcClock_Hz); + DSPI_MasterTransferCreateHandle(handle->base, &handle->drv_handle, DSPI_RTOS_Callback, (void *)handle); + + return kStatus_Success; +} + +status_t DSPI_RTOS_Deinit(dspi_rtos_handle_t *handle) +{ + DSPI_Deinit(handle->base); + vSemaphoreDelete(handle->event); + vSemaphoreDelete(handle->mutex); + + return kStatus_Success; +} + +status_t DSPI_RTOS_Transfer(dspi_rtos_handle_t *handle, dspi_transfer_t *transfer) +{ + status_t status; + + /* Lock resource mutex */ + if (xSemaphoreTake(handle->mutex, portMAX_DELAY) != pdTRUE) + { + return kStatus_DSPI_Busy; + } + + status = DSPI_MasterTransferNonBlocking(handle->base, &handle->drv_handle, transfer); + if (status != kStatus_Success) + { + xSemaphoreGive(handle->mutex); + return status; + } + + /* Wait for transfer to finish */ + xSemaphoreTake(handle->event, portMAX_DELAY); + + /* Unlock resource mutex */ + xSemaphoreGive(handle->mutex); + + /* Return status captured by callback function */ + return handle->async_status; +} diff --git a/drivers/fsl_dspi_freertos.h b/drivers/fsl_dspi_freertos.h new file mode 100644 index 0000000..7e7179b --- /dev/null +++ b/drivers/fsl_dspi_freertos.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __FSL_DSPI_FREERTOS_H__ +#define __FSL_DSPI_FREERTOS_H__ + +#include "FreeRTOSConfig.h" +#include "FreeRTOS.h" +#include "portable.h" +#include "semphr.h" + +#include "fsl_dspi.h" + +/*! + * @addtogroup dspi_freertos_driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! +* @cond RTOS_PRIVATE +* @brief DSPI FreeRTOS handle +*/ +typedef struct _dspi_rtos_handle +{ + SPI_Type *base; /*!< DSPI base address */ + dspi_master_handle_t drv_handle; /*!< Handle of the underlying driver, treated as opaque by the RTOS layer */ + status_t async_status; /*!< Transactional state of the underlying driver */ + SemaphoreHandle_t mutex; /*!< Mutex to lock the handle during a transfer */ + SemaphoreHandle_t event; /*!< Semaphore to notify and unblock a task when a transfer ends */ +#if (configSUPPORT_STATIC_ALLOCATION == 1) + StaticSemaphore_t mutexBuffer; /*!< Statically allocated memory for mutex */ + StaticSemaphore_t semaphoreBuffer; /*!< Statically allocated memory for event */ +#endif +} dspi_rtos_handle_t; +/*! \endcond */ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name DSPI RTOS Operation + * @{ + */ + +/*! + * @brief Initializes the DSPI. + * + * This function initializes the DSPI module and the related RTOS context. + * + * @param handle The RTOS DSPI handle, the pointer to an allocated space for RTOS context. + * @param base The pointer base address of the DSPI instance to initialize. + * @param masterConfig A configuration structure to set-up the DSPI in master mode. + * @param srcClock_Hz A frequency of the input clock of the DSPI module. + * @return status of the operation. + */ +status_t DSPI_RTOS_Init(dspi_rtos_handle_t *handle, + SPI_Type *base, + const dspi_master_config_t *masterConfig, + uint32_t srcClock_Hz); + +/*! + * @brief Deinitializes the DSPI. + * + * This function deinitializes the DSPI module and the related RTOS context. + * + * @param handle The RTOS DSPI handle. + */ +status_t DSPI_RTOS_Deinit(dspi_rtos_handle_t *handle); + +/*! + * @brief Performs the SPI transfer. + * + * This function performs the SPI transfer according to the data given in the transfer structure. + * + * @param handle The RTOS DSPI handle. + * @param transfer A structure specifying the transfer parameters. + * @return status of the operation. + */ +status_t DSPI_RTOS_Transfer(dspi_rtos_handle_t *handle, dspi_transfer_t *transfer); + +/*! + * @} + */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ + +#endif /* __FSL_DSPI_FREERTOS_H__ */ diff --git a/drivers/fsl_edma.c b/drivers/fsl_edma.c index 8ad12fc..be51f4c 100644 --- a/drivers/fsl_edma.c +++ b/drivers/fsl_edma.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_edma.h" @@ -63,11 +63,13 @@ static void EDMA_InstallTCD(DMA_Type *base, uint32_t channel, edma_tcd_t *tcd); /*! @brief Array to map EDMA instance number to base pointer. */ static DMA_Type *const s_edmaBases[] = DMA_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Array to map EDMA instance number to clock name. */ static const clock_ip_name_t s_edmaClockName[] = EDMA_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Array to map EDMA instance number to IRQ number. */ -static const IRQn_Type s_edmaIRQNumber[] = DMA_CHN_IRQS; +static const IRQn_Type s_edmaIRQNumber[][FSL_FEATURE_EDMA_MODULE_CHANNEL] = DMA_CHN_IRQS; /*! @brief Pointers to transfer handle for each EDMA channel. */ static edma_handle_t *s_EDMAHandle[FSL_FEATURE_EDMA_MODULE_CHANNEL * FSL_FEATURE_SOC_EDMA_COUNT]; @@ -81,7 +83,7 @@ static uint32_t EDMA_GetInstance(DMA_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_EDMA_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_edmaBases); instance++) { if (s_edmaBases[instance] == base) { @@ -89,7 +91,7 @@ static uint32_t EDMA_GetInstance(DMA_Type *base) } } - assert(instance < FSL_FEATURE_SOC_EDMA_COUNT); + assert(instance < ARRAY_SIZE(s_edmaBases)); return instance; } @@ -122,8 +124,10 @@ void EDMA_Init(DMA_Type *base, const edma_config_t *config) uint32_t tmpreg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate EDMA periphral clock */ CLOCK_EnableClock(s_edmaClockName[EDMA_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure EDMA peripheral according to the configuration structure. */ tmpreg = base->CR; tmpreg &= ~(DMA_CR_ERCA_MASK | DMA_CR_HOE_MASK | DMA_CR_CLM_MASK | DMA_CR_EDBG_MASK); @@ -134,8 +138,10 @@ void EDMA_Init(DMA_Type *base, const edma_config_t *config) void EDMA_Deinit(DMA_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate EDMA periphral clock */ CLOCK_DisableClock(s_edmaClockName[EDMA_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void EDMA_GetDefaultConfig(edma_config_t *config) @@ -409,46 +415,32 @@ void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask) } } -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel) +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel) { assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL); - uint32_t nbytes = 0; - uint32_t remainingBytes = 0; + uint32_t remainingCount = 0; if (DMA_CSR_DONE_MASK & base->TCD[channel].CSR) { - remainingBytes = 0; + remainingCount = 0; } else { - /* Calculate the nbytes */ - if (base->TCD[channel].NBYTES_MLOFFYES & (DMA_NBYTES_MLOFFYES_SMLOE_MASK | DMA_NBYTES_MLOFFYES_DMLOE_MASK)) - { - nbytes = (base->TCD[channel].NBYTES_MLOFFYES & DMA_NBYTES_MLOFFYES_NBYTES_MASK) >> - DMA_NBYTES_MLOFFYES_NBYTES_SHIFT; - } - else - { - nbytes = - (base->TCD[channel].NBYTES_MLOFFNO & DMA_NBYTES_MLOFFNO_NBYTES_MASK) >> DMA_NBYTES_MLOFFNO_NBYTES_SHIFT; - } /* Calculate the unfinished bytes */ if (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_ELINK_MASK) { - remainingBytes = ((base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> - DMA_CITER_ELINKYES_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKYES & DMA_CITER_ELINKYES_CITER_MASK) >> DMA_CITER_ELINKYES_CITER_SHIFT; } else { - remainingBytes = - ((base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT) * - nbytes; + remainingCount = + (base->TCD[channel].CITER_ELINKNO & DMA_CITER_ELINKNO_CITER_MASK) >> DMA_CITER_ELINKNO_CITER_SHIFT; } } - return remainingBytes; + return remainingCount; } uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel) @@ -497,14 +489,19 @@ void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel) uint32_t channelIndex; edma_tcd_t *tcdRegs; + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + handle->base = base; handle->channel = channel; /* Get the DMA instance number */ edmaInstance = EDMA_GetInstance(base); channelIndex = (edmaInstance * FSL_FEATURE_EDMA_MODULE_CHANNEL) + channel; s_EDMAHandle[channelIndex] = handle; + /* Enable NVIC interrupt */ - EnableIRQ(s_edmaIRQNumber[channelIndex]); + EnableIRQ(s_edmaIRQNumber[edmaInstance][channel]); + /* Reset TCD registers to zero. Unlike the EDMA_TcdReset(DREQ will be set), CSR will be 0. Because in order to suit EDMA busy check mechanism in @@ -829,7 +826,7 @@ void EDMA_HandleIRQ(edma_handle_t *handle) { (handle->callback)(handle, handle->userData, true, 0); } - else /* Use the TCD queue. */ + else /* Use the TCD queue. Please refer to the API descriptions in the eDMA header file for detailed information. */ { uint32_t sga = handle->base->TCD[handle->channel].DLAST_SGA; uint32_t sga_index; @@ -839,19 +836,19 @@ void EDMA_HandleIRQ(edma_handle_t *handle) /* Check if transfer is already finished. */ transfer_done = ((handle->base->TCD[handle->channel].CSR & DMA_CSR_DONE_MASK) != 0); - /* Get the offset of the current transfer TCD blcoks. */ + /* Get the offset of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga -= (uint32_t)handle->tcdPool; - /* Get the index of the current transfer TCD blcoks. */ + /* Get the index of the next transfer TCD blcoks to be loaded into the eDMA engine. */ sga_index = sga / sizeof(edma_tcd_t); /* Adjust header positions. */ if (transfer_done) { - /* New header shall point to the next TCD (current one is already finished) */ + /* New header shall point to the next TCD to be loaded (current one is already finished) */ new_header = sga_index; } else { - /* New header shall point to this descriptor (not finished yet) */ + /* New header shall point to this descriptor currently loaded (not finished yet) */ new_header = sga_index ? sga_index - 1U : handle->tcdSize - 1U; } /* Calculate the number of finished TCDs */ @@ -863,7 +860,7 @@ void EDMA_HandleIRQ(edma_handle_t *handle) } else { - /* Internal error occurs. */ + /* No TCD in the memory are going to be loaded or internal error occurs. */ tcds_done = 0; } } @@ -875,9 +872,9 @@ void EDMA_HandleIRQ(edma_handle_t *handle) tcds_done += handle->tcdSize; } } - /* Advance header to the point beyond the last finished TCD block. */ + /* Advance header which points to the TCD to be loaded into the eDMA engine from memory. */ handle->header = new_header; - /* Release TCD blocks. */ + /* Release TCD blocks. tcdUsed is the TCD number which can be used/loaded in the memory pool. */ handle->tcdUsed -= tcds_done; /* Invoke callback function. */ if (handle->callback) @@ -937,12 +934,260 @@ void DMA0_37_DriverIRQHandler(void) EDMA_HandleIRQ(s_EDMAHandle[7]); } } + +#if defined(DMA1) +void DMA1_04_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA1_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA1_26_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA1_37_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} +#endif #endif /* 8 channels (Shared) */ +/* 16 channels (Shared): K32H844P */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 16U + +void DMA0_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } +} + +void DMA0_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } +} + +void DMA0_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } +} + +void DMA0_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } +} + +void DMA0_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +#if defined(DMA1) +void DMA1_08_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } +} + +void DMA1_19_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } +} + +void DMA1_210_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } +} + +void DMA1_311_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } +} + +void DMA1_412_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA1_513_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA1_614_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA1_715_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA1, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } + if ((EDMA_GetChannelStatusFlags(DMA1, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif +#endif /* 16 channels (Shared) */ + /* 32 channels (Shared): k80 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U -void DMA0_DMA16_IRQHandler(void) +void DMA0_DMA16_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) { @@ -954,7 +1199,7 @@ void DMA0_DMA16_IRQHandler(void) } } -void DMA1_DMA17_IRQHandler(void) +void DMA1_DMA17_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) { @@ -966,7 +1211,7 @@ void DMA1_DMA17_IRQHandler(void) } } -void DMA2_DMA18_IRQHandler(void) +void DMA2_DMA18_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) { @@ -978,7 +1223,7 @@ void DMA2_DMA18_IRQHandler(void) } } -void DMA3_DMA19_IRQHandler(void) +void DMA3_DMA19_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) { @@ -990,7 +1235,7 @@ void DMA3_DMA19_IRQHandler(void) } } -void DMA4_DMA20_IRQHandler(void) +void DMA4_DMA20_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) { @@ -1002,7 +1247,7 @@ void DMA4_DMA20_IRQHandler(void) } } -void DMA5_DMA21_IRQHandler(void) +void DMA5_DMA21_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) { @@ -1014,7 +1259,7 @@ void DMA5_DMA21_IRQHandler(void) } } -void DMA6_DMA22_IRQHandler(void) +void DMA6_DMA22_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) { @@ -1026,7 +1271,7 @@ void DMA6_DMA22_IRQHandler(void) } } -void DMA7_DMA23_IRQHandler(void) +void DMA7_DMA23_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) { @@ -1038,7 +1283,7 @@ void DMA7_DMA23_IRQHandler(void) } } -void DMA8_DMA24_IRQHandler(void) +void DMA8_DMA24_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) { @@ -1050,7 +1295,7 @@ void DMA8_DMA24_IRQHandler(void) } } -void DMA9_DMA25_IRQHandler(void) +void DMA9_DMA25_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) { @@ -1062,7 +1307,7 @@ void DMA9_DMA25_IRQHandler(void) } } -void DMA10_DMA26_IRQHandler(void) +void DMA10_DMA26_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) { @@ -1074,7 +1319,7 @@ void DMA10_DMA26_IRQHandler(void) } } -void DMA11_DMA27_IRQHandler(void) +void DMA11_DMA27_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) { @@ -1086,7 +1331,7 @@ void DMA11_DMA27_IRQHandler(void) } } -void DMA12_DMA28_IRQHandler(void) +void DMA12_DMA28_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) { @@ -1098,7 +1343,7 @@ void DMA12_DMA28_IRQHandler(void) } } -void DMA13_DMA29_IRQHandler(void) +void DMA13_DMA29_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) { @@ -1110,7 +1355,7 @@ void DMA13_DMA29_IRQHandler(void) } } -void DMA14_DMA30_IRQHandler(void) +void DMA14_DMA30_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) { @@ -1122,7 +1367,7 @@ void DMA14_DMA30_IRQHandler(void) } } -void DMA15_DMA31_IRQHandler(void) +void DMA15_DMA31_DriverIRQHandler(void) { if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) { @@ -1135,6 +1380,202 @@ void DMA15_DMA31_IRQHandler(void) } #endif /* 32 channels (Shared) */ +/* 32 channels (Shared): MCIMX7U5_M4 */ +#if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL == 32U + +void DMA0_0_4_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 0U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[0]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 4U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[4]); + } +} + +void DMA0_1_5_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 1U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[1]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 5U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[5]); + } +} + +void DMA0_2_6_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 2U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[2]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 6U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[6]); + } +} + +void DMA0_3_7_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 3U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[3]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 7U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[7]); + } +} + +void DMA0_8_12_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 8U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[8]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 12U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[12]); + } +} + +void DMA0_9_13_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 9U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[9]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 13U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[13]); + } +} + +void DMA0_10_14_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 10U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[10]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 14U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[14]); + } +} + +void DMA0_11_15_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 11U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[11]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 15U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[15]); + } +} + +void DMA0_16_20_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 16U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[16]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 20U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[20]); + } +} + +void DMA0_17_21_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 17U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[17]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 21U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[21]); + } +} + +void DMA0_18_22_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 18U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[18]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 22U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[22]); + } +} + +void DMA0_19_23_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 19U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[19]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 23U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[23]); + } +} + +void DMA0_24_28_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 24U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[24]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 28U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[28]); + } +} + +void DMA0_25_29_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 25U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[25]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 29U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[29]); + } +} + +void DMA0_26_30_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 26U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[26]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 30U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[30]); + } +} + +void DMA0_27_31_DriverIRQHandler(void) +{ + if ((EDMA_GetChannelStatusFlags(DMA0, 27U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[27]); + } + if ((EDMA_GetChannelStatusFlags(DMA0, 31U) & kEDMA_InterruptFlag) != 0U) + { + EDMA_HandleIRQ(s_EDMAHandle[31]); + } +} +#endif /* 32 channels (Shared): MCIMX7U5 */ + /* 4 channels (No Shared): kv10 */ #if defined(FSL_FEATURE_EDMA_MODULE_CHANNEL) && FSL_FEATURE_EDMA_MODULE_CHANNEL > 0 diff --git a/drivers/fsl_edma.h b/drivers/fsl_edma.h index 02c4fab..a97622d 100644 --- a/drivers/fsl_edma.h +++ b/drivers/fsl_edma.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_EDMA_H_ #define _FSL_EDMA_H_ @@ -45,7 +45,7 @@ /*! @name Driver version */ /*@{*/ /*! @brief eDMA driver version */ -#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1. */ +#define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*!< Version 2.1.1. */ /*@}*/ /*! @brief Compute the offset unit from DCHPRI3 */ @@ -77,28 +77,28 @@ typedef enum _edma_modulo kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */ kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */ kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */ - kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1K bytes. */ - kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2K bytes. */ - kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4K bytes. */ - kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8K bytes. */ - kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16K bytes. */ - kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32K bytes. */ - kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64K bytes. */ - kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128K bytes. */ - kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256K bytes. */ - kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512K bytes. */ - kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1M bytes. */ - kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2M bytes. */ - kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4M bytes. */ - kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8M bytes. */ - kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16M bytes. */ - kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32M bytes. */ - kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64M bytes. */ - kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128M bytes. */ - kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256M bytes. */ - kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512M bytes. */ - kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1G bytes. */ - kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2G bytes. */ + kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1 K bytes. */ + kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2 K bytes. */ + kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4 K bytes. */ + kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8 K bytes. */ + kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16 K bytes. */ + kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32 K bytes. */ + kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64 K bytes. */ + kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128 K bytes. */ + kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256 K bytes. */ + kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512 K bytes. */ + kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1 M bytes. */ + kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2 M bytes. */ + kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4 M bytes. */ + kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8 M bytes. */ + kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16 M bytes. */ + kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32 M bytes. */ + kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64 M bytes. */ + kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128 M bytes. */ + kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256 M bytes. */ + kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512 M bytes. */ + kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1 G bytes. */ + kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2 G bytes. */ } edma_modulo_t; /*! @brief Bandwidth control */ @@ -177,7 +177,7 @@ typedef struct _edma_config the link channel is itself. */ bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set. Subsequently, all service requests are ignored until the HALT bit is cleared.*/ - bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method, or fixed priority + bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method or fixed priority arbitration is used for channel selection */ bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of a new channel. Executing channels are allowed to complete. */ @@ -211,15 +211,15 @@ typedef struct _edma_transfer_config form the next-state value as each source read is completed. */ int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to form the next-state value as each destination write is completed. */ - uint16_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ + uint32_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/ uint32_t majorLoopCounts; /*!< Major loop iteration count. */ } edma_transfer_config_t; /*! @brief eDMA channel priority configuration */ typedef struct _edma_channel_Preemption_config { - bool enableChannelPreemption; /*!< If true: channel can be suspended by other channel with higher priority */ - bool enablePreemptAbility; /*!< If true: channel can suspend other channel with low priority */ + bool enableChannelPreemption; /*!< If true: a channel can be suspended by other channel with higher priority */ + bool enablePreemptAbility; /*!< If true: a channel can suspend other channel with low priority */ uint8_t channelPriority; /*!< Channel priority */ } edma_channel_Preemption_config_t; @@ -228,7 +228,7 @@ typedef struct _edma_minor_offset_config { bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */ bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */ - uint32_t minorOffset; /*!< Offset for minor loop mapping. */ + uint32_t minorOffset; /*!< Offset for a minor loop mapping. */ } edma_minor_offset_config_t; /*! @@ -255,20 +255,21 @@ typedef struct _edma_tcd /*! @brief Callback for eDMA */ struct _edma_handle; -/*! @brief Define Callback function for eDMA. */ +/*! @brief Define callback function for eDMA. */ typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds); /*! @brief eDMA transfer handle structure */ typedef struct _edma_handle { - edma_callback callback; /*!< Callback function for major count exhausted. */ - void *userData; /*!< Callback function parameter. */ - DMA_Type *base; /*!< eDMA peripheral base address. */ - edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ - uint8_t channel; /*!< eDMA channel number. */ - volatile int8_t header; /*!< The first TCD index. */ - volatile int8_t tail; /*!< The last TCD index. */ - volatile int8_t tcdUsed; /*!< The number of used TCD slots. */ + edma_callback callback; /*!< Callback function for major count exhausted. */ + void *userData; /*!< Callback function parameter. */ + DMA_Type *base; /*!< eDMA peripheral base address. */ + edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */ + uint8_t channel; /*!< eDMA channel number. */ + volatile int8_t header; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */ + volatile int8_t tail; /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */ + volatile int8_t tcdUsed; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in + the memory. */ volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */ uint8_t flags; /*!< The status of the current channel. */ } edma_handle_t; @@ -281,24 +282,24 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name eDMA initialization and De-initialization + * @name eDMA initialization and de-initialization * @{ */ /*! - * @brief Initializes eDMA peripheral. + * @brief Initializes the eDMA peripheral. * * This function ungates the eDMA clock and configures the eDMA peripheral according * to the configuration structure. * * @param base eDMA peripheral base address. - * @param config Pointer to configuration structure, see "edma_config_t". - * @note This function enable the minor loop map feature. + * @param config A pointer to the configuration structure, see "edma_config_t". + * @note This function enables the minor loop map feature. */ void EDMA_Init(DMA_Type *base, const edma_config_t *config); /*! - * @brief Deinitializes eDMA peripheral. + * @brief Deinitializes the eDMA peripheral. * * This function gates the eDMA clock. * @@ -309,8 +310,8 @@ void EDMA_Deinit(DMA_Type *base); /*! * @brief Gets the eDMA default configuration structure. * - * This function sets the configuration structure to a default value. - * The default configuration is set to the following value: + * This function sets the configuration structure to default values. + * The default configuration is set to the following values. * @code * config.enableContinuousLinkMode = false; * config.enableHaltOnError = true; @@ -318,7 +319,7 @@ void EDMA_Deinit(DMA_Type *base); * config.enableDebugMode = false; * @endcode * - * @param config Pointer to eDMA configuration structure. + * @param config A pointer to the eDMA configuration structure. */ void EDMA_GetDefaultConfig(edma_config_t *config); @@ -329,13 +330,13 @@ void EDMA_GetDefaultConfig(edma_config_t *config); */ /*! - * @brief Sets all TCD registers to a default value. + * @brief Sets all TCD registers to default values. * - * This function sets TCD registers for this channel to default value. + * This function sets TCD registers for this channel to default values. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @note This function must not be called while the channel transfer is on-going, + * @note This function must not be called while the channel transfer is ongoing * or it causes unpredictable results. * @note This function enables the auto stop request feature. */ @@ -364,7 +365,7 @@ void EDMA_ResetChannel(DMA_Type *base, uint32_t channel); * do not want to enable scatter/gather feature. * @note If nextTcd is not NULL, it means scatter gather feature is enabled * and DREQ bit is cleared in the previous transfer configuration, which - * is set in eDMA_ResetChannel. + * is set in the eDMA_ResetChannel. */ void EDMA_SetTransferConfig(DMA_Type *base, uint32_t channel, @@ -374,12 +375,12 @@ void EDMA_SetTransferConfig(DMA_Type *base, /*! * @brief Configures the eDMA minor offset feature. * - * Minor offset means signed-extended value added to source address or destination + * The minor offset means that the signed-extended value is added to the source address or destination * address after each minor loop. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param config Pointer to Minor offset configuration structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config); @@ -390,7 +391,7 @@ void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_mino * * @param base eDMA peripheral base address. * @param channel eDMA channel number - * @param config Pointer to channel preemption configuration structure. + * @param config A pointer to the channel preemption configuration structure. */ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, uint32_t channel, @@ -407,13 +408,13 @@ static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base, /*! * @brief Sets the channel link for the eDMA transfer. * - * This function configures minor link or major link mode. The minor link means that the channel link is + * This function configures either the minor link or the major link mode. The minor link means that the channel link is * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is * exhausted. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param type Channel link type, it can be one of: + * @param type A channel link type, which can be one of the following: * @arg kEDMA_LinkNone * @arg kEDMA_MinorLink * @arg kEDMA_MajorLink @@ -425,13 +426,13 @@ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_typ /*! * @brief Sets the bandwidth for the eDMA transfer. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences + * Because the eDMA processes the minor loop, it continuously generates read/write sequences * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param bandWidth Bandwidth setting, it can be one of: + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -439,7 +440,7 @@ void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_typ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth); /*! - * @brief Sets the source modulo and destination modulo for eDMA transfer. + * @brief Sets the source modulo and the destination modulo for the eDMA transfer. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data @@ -447,8 +448,8 @@ void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWi * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -458,7 +459,7 @@ void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, e * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable(ture) or disable(false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -475,7 +476,7 @@ static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, boo * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param enable The command for enable (true) or disable (false). + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable) { @@ -499,7 +500,7 @@ void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mas * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @param mask The mask of interrupt source to be set. Use + * @param mask The mask of the interrupt source to be set. Use * the defined edma_interrupt_enable_t type. */ void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask); @@ -523,8 +524,8 @@ void EDMA_TcdReset(edma_tcd_t *tcd); /*! * @brief Configures the eDMA TCD transfer attribute. * - * TCD is a transfer control descriptor. The content of the TCD is the same as hardware TCD registers. - * STCD is used in scatter-gather mode. + * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers. + * The STCD is used in the scatter-gather mode. * This function configures the TCD transfer attribute, including source address, destination address, * transfer size, address offset, and so on. It also configures the scatter gather feature if the * user supplies the next TCD address. @@ -542,7 +543,7 @@ void EDMA_TcdReset(edma_tcd_t *tcd); * @param config Pointer to eDMA transfer configuration structure. * @param nextTcd Pointer to the next TCD structure. It can be NULL if users * do not want to enable scatter/gather feature. - * @note TCD address should be 32 bytes aligned, or it causes an eDMA error. + * @note TCD address should be 32 bytes aligned or it causes an eDMA error. * @note If the nextTcd is not NULL, the scatter gather feature is enabled * and DREQ bit is cleared in the previous transfer configuration, which * is set in the EDMA_TcdReset. @@ -552,16 +553,16 @@ void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *co /*! * @brief Configures the eDMA TCD minor offset feature. * - * Minor offset is a signed-extended value added to the source address or destination + * A minor offset is a signed-extended value added to the source address or a destination * address after each minor loop. * - * @param tcd Point to the TCD structure. - * @param config Pointer to Minor offset configuration structure. + * @param tcd A point to the TCD structure. + * @param config A pointer to the minor offset configuration structure. */ void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config); /*! - * @brief Sets the channel link for eDMA TCD. + * @brief Sets the channel link for the eDMA TCD. * * This function configures either a minor link or a major link. The minor link means the channel link is * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is @@ -580,11 +581,11 @@ void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint /*! * @brief Sets the bandwidth for the eDMA TCD. * - * In general, because the eDMA processes the minor loop, it continuously generates read/write sequences - * until the minor count is exhausted. Bandwidth forces the eDMA to stall after the completion of + * Because the eDMA processes the minor loop, it continuously generates read/write sequences + * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of * each read/write access to control the bus request bandwidth seen by the crossbar switch. - * @param tcd Point to the TCD structure. - * @param bandWidth Bandwidth setting, it can be one of: + * @param tcd A pointer to the TCD structure. + * @param bandWidth A bandwidth setting, which can be one of the following: * @arg kEDMABandwidthStallNone * @arg kEDMABandwidthStall4Cycle * @arg kEDMABandwidthStall8Cycle @@ -598,15 +599,15 @@ static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWi } /*! - * @brief Sets the source modulo and destination modulo for eDMA TCD. + * @brief Sets the source modulo and the destination modulo for the eDMA TCD. * * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF) * calculation is performed or the original register value. It provides the ability to implement a circular data * queue easily. * - * @param tcd Point to the TCD structure. - * @param srcModulo Source modulo value. - * @param destModulo Destination modulo value. + * @param tcd A pointer to the TCD structure. + * @param srcModulo A source modulo value. + * @param destModulo A destination modulo value. */ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo); @@ -615,8 +616,8 @@ void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t d * * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request. * - * @param tcd Point to the TCD structure. - * @param enable The command for enable(ture) or disable(false). + * @param tcd A pointer to the TCD structure. + * @param enable The command to enable (true) or disable (false). */ static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable) { @@ -681,7 +682,7 @@ static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel) } /*! - * @brief Starts the eDMA transfer by software trigger. + * @brief Starts the eDMA transfer by using the software trigger. * * This function starts a minor loop transfer. * @@ -702,25 +703,34 @@ static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel) */ /*! - * @brief Gets the Remaining bytes from the eDMA current channel TCD. + * @brief Gets the remaining major loop count from the eDMA current channel TCD. * * This function checks the TCD (Task Control Descriptor) status for a specified - * eDMA channel and returns the the number of bytes that have not finished. + * eDMA channel and returns the the number of major loop count that has not finished. * * @param base eDMA peripheral base address. * @param channel eDMA channel number. - * @return Bytes have not been transferred yet for the current TCD. - * @note This function can only be used to get unfinished bytes of transfer without - * the next TCD, or it might be inaccuracy. - */ -uint32_t EDMA_GetRemainingBytes(DMA_Type *base, uint32_t channel); + * @return Major loop count which has not been transferred yet for the current TCD. + * @note 1. This function can only be used to get unfinished major loop count of transfer without + * the next TCD, or it might be inaccuracy. + * 2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while + * the channel is running. + * Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO + * register is needed while the eDMA IP does not support getting it while a channel is active. + * In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine + * is working with while a channel is running. + * Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example + * copied before enabling the channel) is needed. The formula to calculate it is shown below: + * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured) + */ +uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel); /*! * @brief Gets the eDMA channel error status flags. * * @param base eDMA peripheral base address. * @return The mask of error status flags. Users need to use the - * _edma_error_status_flags type to decode the return variables. +* _edma_error_status_flags type to decode the return variables. */ static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base) { @@ -755,8 +765,8 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas /*! * @brief Creates the eDMA handle. * - * This function is called if using transaction API for eDMA. This function - * initializes the internal state of eDMA handle. + * This function is called if using the transactional API for eDMA. This function + * initializes the internal state of the eDMA handle. * * @param handle eDMA handle pointer. The eDMA handle stores callback function and * parameters. @@ -766,12 +776,12 @@ void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mas void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel); /*! - * @brief Installs the TCDs memory pool into eDMA handle. + * @brief Installs the TCDs memory pool into the eDMA handle. * * This function is called after the EDMA_CreateHandle to use scatter/gather feature. * * @param handle eDMA handle pointer. - * @param tcdPool Memory pool to store TCDs. It must be 32 bytes aligned. + * @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned. * @param tcdSize The number of TCD slots. */ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize); @@ -779,12 +789,12 @@ void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t /*! * @brief Installs a callback function for the eDMA transfer. * - * This callback is called in eDMA IRQ handler. Use the callback to do something after + * This callback is called in the eDMA IRQ handler. Use the callback to do something after * the current major loop transfer completes. * * @param handle eDMA handle pointer. * @param callback eDMA callback function pointer. - * @param userData Parameter for callback function. + * @param userData A parameter for the callback function. */ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData); @@ -802,8 +812,8 @@ void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userD * @param transferBytes eDMA transfer bytes to be transferred. * @param type eDMA transfer type. * @note The data address and the data width must be consistent. For example, if the SRC - * is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in - * source address error(SAE). + * is 4 bytes, the source address must be 4 bytes aligned, or it results in + * source address error (SAE). */ void EDMA_PrepareTransfer(edma_transfer_config_t *config, void *srcAddr, @@ -818,7 +828,7 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, * @brief Submits the eDMA transfer request. * * This function submits the eDMA transfer request according to the transfer configuration structure. - * If the user submits the transfer request repeatedly, this function packs an unprocessed request as + * If submitting the transfer request repeatedly, this function packs an unprocessed request as * a TCD and enables scatter/gather feature to process it in the next time. * * @param handle eDMA handle pointer. @@ -830,7 +840,7 @@ void EDMA_PrepareTransfer(edma_transfer_config_t *config, status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config); /*! - * @brief eDMA start transfer. + * @brief eDMA starts transfer. * * This function enables the channel request. Users can call this function after submitting the transfer request * or before submitting the transfer request. @@ -840,7 +850,7 @@ status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t void EDMA_StartTransfer(edma_handle_t *handle); /*! - * @brief eDMA stop transfer. + * @brief eDMA stops transfer. * * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer() * again to resume the transfer. @@ -850,7 +860,7 @@ void EDMA_StartTransfer(edma_handle_t *handle); void EDMA_StopTransfer(edma_handle_t *handle); /*! - * @brief eDMA abort transfer. + * @brief eDMA aborts transfer. * * This function disables the channel request and clear transfer status bits. * Users can submit another transfer after calling this API. @@ -860,11 +870,31 @@ void EDMA_StopTransfer(edma_handle_t *handle); void EDMA_AbortTransfer(edma_handle_t *handle); /*! - * @brief eDMA IRQ handler for current major loop transfer complete. + * @brief eDMA IRQ handler for the current major loop transfer completion. * - * This function clears the channel major interrupt flag and call + * This function clears the channel major interrupt flag and calls * the callback function if it is not NULL. * + * Note: + * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed. + * These include the final address adjustments and reloading of the BITER field into the CITER. + * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from + * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled). + * + * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine. + * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index + * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be + * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have + * been loaded into the eDMA engine at this point already.). + * + * For the last two continuous ISRs in a scatter/gather process, they both load the last TCD (The last ISR does not + * load a new TCD) from the memory pool to the eDMA engine when major loop completes. + * Therefore, ensure that the header and tcdUsed updated are identical for them. + * tcdUsed are both 0 in this case as no TCD to be loaded. + * + * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for + * further details. + * * @param handle eDMA handle pointer. */ void EDMA_HandleIRQ(edma_handle_t *handle); diff --git a/drivers/fsl_ewm.c b/drivers/fsl_ewm.c index 1a71a07..f22eff9 100644 --- a/drivers/fsl_ewm.c +++ b/drivers/fsl_ewm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -40,7 +40,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) uint32_t value = 0U; +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif value = EWM_CTRL_EWMEN(config->enableEwm) | EWM_CTRL_ASSIN(config->setInputAssertLogic) | EWM_CTRL_INEN(config->enableEwmInput) | EWM_CTRL_INTEN(config->enableInterrupt); #if defined(FSL_FEATURE_EWM_HAS_PRESCALER) && FSL_FEATURE_EWM_HAS_PRESCALER @@ -59,7 +64,12 @@ void EWM_Init(EWM_Type *base, const ewm_config_t *config) void EWM_Deinit(EWM_Type *base) { EWM_DisableInterrupts(base, kEWM_InterruptEnable); +#if !((defined(FSL_FEATURE_SOC_PCC_COUNT) && FSL_FEATURE_SOC_PCC_COUNT) && \ + (defined(FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE) && FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE)) +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Ewm0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +#endif /* FSL_FEATURE_PCC_SUPPORT_EWM_CLOCK_REMOVE */ } void EWM_GetDefaultConfig(ewm_config_t *config) diff --git a/drivers/fsl_ewm.h b/drivers/fsl_ewm.h index 180575e..aa32ed3 100644 --- a/drivers/fsl_ewm.h +++ b/drivers/fsl_ewm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -81,13 +81,13 @@ typedef struct _ewm_config } ewm_config_t; /*! - * @brief EWM interrupt configuration structure, default settings all disabled. + * @brief EWM interrupt configuration structure with default settings all disabled. * - * This structure contains the settings for all of the EWM interrupt configurations. + * This structure contains the settings for all of EWM interrupt configurations. */ enum _ewm_interrupt_enable_t { - kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable EWM to generate an interrupt*/ + kEWM_InterruptEnable = EWM_CTRL_INTEN_MASK, /*!< Enable the EWM to generate an interrupt*/ }; /*! @@ -109,7 +109,7 @@ extern "C" { #endif /* __cplusplus */ /*! - * @name EWM Initialization and De-initialization + * @name EWM initialization and de-initialization * @{ */ @@ -118,10 +118,10 @@ extern "C" { * * This function is used to initialize the EWM. After calling, the EWM * runs immediately according to the configuration. - * Note that except for interrupt enable control bit, other control bits and registers are write once after a + * Note that, except for the interrupt enable control bit, other control bits and registers are write once after a * CPU reset. Modifying them more than once generates a bus transfer error. * - * Example: + * This is an example. * @code * ewm_config_t config; * EWM_GetDefaultConfig(&config); @@ -130,7 +130,7 @@ extern "C" { * @endcode * * @param base EWM peripheral base address - * @param config The configuration of EWM + * @param config The configuration of the EWM */ void EWM_Init(EWM_Type *base, const ewm_config_t *config); @@ -147,7 +147,7 @@ void EWM_Deinit(EWM_Type *base); * @brief Initializes the EWM configuration structure. * * This function initializes the EWM configuration structure to default values. The default - * values are: + * values are as follows. * @code * ewmConfig->enableEwm = true; * ewmConfig->enableEwmInput = false; @@ -159,7 +159,7 @@ void EWM_Deinit(EWM_Type *base); * ewmConfig->compareHighValue = 0xFEU; * @endcode * - * @param config Pointer to EWM configuration structure. + * @param config Pointer to the EWM configuration structure. * @see ewm_config_t */ void EWM_GetDefaultConfig(ewm_config_t *config); @@ -178,7 +178,7 @@ void EWM_GetDefaultConfig(ewm_config_t *config); * * @param base EWM peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) @@ -193,7 +193,7 @@ static inline void EWM_EnableInterrupts(EWM_Type *base, uint32_t mask) * * @param base EWM peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined * @arg kEWM_InterruptEnable */ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) @@ -202,19 +202,19 @@ static inline void EWM_DisableInterrupts(EWM_Type *base, uint32_t mask) } /*! - * @brief Gets EWM all status flags. + * @brief Gets all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the running flag. * @code * uint32_t status; * status = EWM_GetStatusFlags(ewm_base) & kEWM_RunningFlag; * @endcode * @param base EWM peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _ewm_status_flags_t - * - true: a related status flag has been set. - * - false: a related status flag is not set. + * - True: a related status flag has been set. + * - False: a related status flag is not set. */ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) { @@ -224,7 +224,7 @@ static inline uint32_t EWM_GetStatusFlags(EWM_Type *base) /*! * @brief Services the EWM. * - * This function reset EWM counter to zero. + * This function resets the EWM counter to zero. * * @param base EWM peripheral base address */ diff --git a/drivers/fsl_flash.c b/drivers/fsl_flash.c index 9251c49..f63e6c9 100644 --- a/drivers/fsl_flash.c +++ b/drivers/fsl_flash.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -38,6 +38,7 @@ * @name Misc utility defines * @{ */ +/*! @brief Alignment utility. */ #ifndef ALIGN_DOWN #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a)))) #endif @@ -45,18 +46,74 @@ #define ALIGN_UP(x, a) (-((int32_t)((uint32_t)(-((int32_t)(x))) & (uint32_t)(-((int32_t)(a)))))) #endif -#define BYTES_JOIN_TO_WORD_1_3(x, y) ((((uint32_t)(x)&0xFFU) << 24) | ((uint32_t)(y)&0xFFFFFFU)) -#define BYTES_JOIN_TO_WORD_2_2(x, y) ((((uint32_t)(x)&0xFFFFU) << 16) | ((uint32_t)(y)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_3_1(x, y) ((((uint32_t)(x)&0xFFFFFFU) << 8) | ((uint32_t)(y)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | ((uint32_t)(z)&0xFFFFU)) -#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) \ - ((((uint32_t)(x)&0xFFFFU) << 16) | (((uint32_t)(y)&0xFFU) << 8) | ((uint32_t)(z)&0xFFU)) -#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) \ - ((((uint32_t)(x)&0xFFU) << 24) | (((uint32_t)(y)&0xFFU) << 16) | (((uint32_t)(z)&0xFFU) << 8) | \ - ((uint32_t)(w)&0xFFU)) +/*! @brief Join bytes to word utility. */ +#define B1P4(b) (((uint32_t)(b)&0xFFU) << 24) +#define B1P3(b) (((uint32_t)(b)&0xFFU) << 16) +#define B1P2(b) (((uint32_t)(b)&0xFFU) << 8) +#define B1P1(b) ((uint32_t)(b)&0xFFU) +#define B2P3(b) (((uint32_t)(b)&0xFFFFU) << 16) +#define B2P2(b) (((uint32_t)(b)&0xFFFFU) << 8) +#define B2P1(b) ((uint32_t)(b)&0xFFFFU) +#define B3P2(b) (((uint32_t)(b)&0xFFFFFFU) << 8) +#define B3P1(b) ((uint32_t)(b)&0xFFFFFFU) +#define BYTES_JOIN_TO_WORD_1_3(x, y) (B1P4(x) | B3P1(y)) +#define BYTES_JOIN_TO_WORD_2_2(x, y) (B2P3(x) | B2P1(y)) +#define BYTES_JOIN_TO_WORD_3_1(x, y) (B3P2(x) | B1P1(y)) +#define BYTES_JOIN_TO_WORD_1_1_2(x, y, z) (B1P4(x) | B1P3(y) | B2P1(z)) +#define BYTES_JOIN_TO_WORD_1_2_1(x, y, z) (B1P4(x) | B2P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_2_1_1(x, y, z) (B2P3(x) | B1P2(y) | B1P1(z)) +#define BYTES_JOIN_TO_WORD_1_1_1_1(x, y, z, w) (B1P4(x) | B1P3(y) | B1P2(z) | B1P1(w)) +/*@}*/ + +/*! + * @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 FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER (0) +#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 FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (1) +#else +#define FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER (0) +#endif +/*@}*/ + +/*! + * @name Flash cache ands speculation control defines + * @{ + */ +#if defined(MCM_PLACR_CFCC_MASK) || defined(MCM_CPCR2_CCBC_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(FMC_PFB0CR_CINV_WAY_MASK) || defined(FMC_PFB01CR_CINV_WAY_MASK) +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (1) +#else +#define FLASH_CACHE_IS_CONTROLLED_BY_FMC (0) +#endif +#if defined(MCM_PLACR_DFCS_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM (0) +#endif +#if defined(MSCM_OCMDR_OCM1_MASK) || defined(MSCM_OCMDR_OCMC1_MASK) +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM (0) +#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 (1) +#else +#define FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC (0) +#endif /*@}*/ /*! @brief Data flash IFR map Field*/ @@ -121,6 +178,7 @@ #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*/ @@ -192,6 +250,51 @@ /*@}*/ /*! + * @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(FTFA_FPROTH0_PROT_MASK) || defined(FTFE_FPROTH0_PROT_MASK) || defined(FTFL_FPROTH0_PROT_MASK) +#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) +#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 FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +#define FTFx_FPROTSH_REG (FTFx->FPROTSH) +#define FTFx_FPROTSL_REG (FTFx->FPROTSL) +#endif + +#define FTFx_XACCH3_REG (FTFx->XACCH3) +#define FTFx_XACCL3_REG (FTFx->XACCL3) + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER +#define FTFx_XACCSH_REG (FTFx->XACCSH) +#define FTFx_XACCSL_REG (FTFx->XACCSL) +#endif +/*@}*/ + +/*! * @brief Enumeration for access segment property. */ enum _flash_access_segment_property @@ -208,18 +311,74 @@ enum _flash_config_area_range kFLASH_ConfigAreaEnd = 0x40FU }; -/*! @brief Total flash region count*/ -#define FSL_FEATURE_FTFx_REGION_COUNT (32U) - /*! * @name Flash register access type defines * @{ */ -#if FLASH_DRIVER_IS_FLASH_RESIDENT -#define FTFx_REG_ACCESS_TYPE volatile uint8_t * +#define FTFx_REG8_ACCESS_TYPE volatile uint8_t * #define FTFx_REG32_ACCESS_TYPE volatile uint32_t * -#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ - /*@}*/ +/*@}*/ + +/*! + * @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(MCM) +#define MCM0_CACHE_REG MCM->PLACR +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->PLACR +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->PLACR +#endif +#elif defined(MCM_CPCR2_CCBC_MASK) +#define MCM_CACHE_CLEAR_MASK MCM_CPCR2_CCBC_MASK +#define MCM_CACHE_CLEAR_SHIFT MCM_CPCR2_CCBC_SHIFT +#if defined(MCM) +#define MCM0_CACHE_REG MCM->CPCR2 +#elif defined(MCM0) +#define MCM0_CACHE_REG MCM0->CPCR2 +#endif +#if defined(MCM1) +#define MCM1_CACHE_REG MCM1->CPCR2 +#endif +#endif + +/*! + * @brief MSCM cache register access info defines. + */ +#if defined(MSCM_OCMDR_OCM1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCM1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCM1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCM1(x) +#elif defined(MSCM_OCMDR_OCMC1_MASK) +#define MSCM_SPECULATION_DISABLE_MASK MSCM_OCMDR_OCMC1_MASK +#define MSCM_SPECULATION_DISABLE_SHIFT MSCM_OCMDR_OCMC1_SHIFT +#define MSCM_SPECULATION_DISABLE(x) MSCM_OCMDR_OCMC1(x) +#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 Flash size encoding rule. + */ +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2 (0x00U) +#define FLASH_MEMORY_SIZE_ENCODING_RULE_K3 (0x01U) + +#if defined(K32W042S1M2_M0P_SERIES) || defined(K32W042S1M2_M4_SERIES) +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +#else +#define FLASH_MEMORY_SIZE_ENCODING_RULE (FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) +#endif /******************************************************************************* * Prototypes @@ -229,7 +388,7 @@ enum _flash_config_area_range /*! @brief Copy flash_run_command() to RAM*/ static void copy_flash_run_command(uint32_t *flashRunCommand); /*! @brief Copy flash_cache_clear_command() to RAM*/ -static void copy_flash_cache_clear_command(uint32_t *flashCacheClearCommand); +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation); /*! @brief Check whether flash execute-in-ram functions are ready*/ static status_t flash_check_execute_in_ram_function_info(flash_config_t *config); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -240,6 +399,9 @@ static status_t flash_command_sequence(flash_config_t *config); /*! @brief Perform the cache clear to the flash*/ void flash_cache_clear(flash_config_t *config); +/*! @brief Process the cache to the flash*/ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process); + /*! @brief Validates the range and alignment of the given address range.*/ static status_t flash_check_range(flash_config_t *config, uint32_t startAddress, @@ -280,44 +442,66 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui static inline status_t flasn_check_flexram_function_option_range(flash_flexram_function_option_t option); #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info); + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info); +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config); +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void); +#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(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(void); +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ + /******************************************************************************* * Variables ******************************************************************************/ /*! @brief Access to FTFx->FCCOB */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFA->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFE->FCCOB3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFL->FCCOB3; -#else -#error "Unknown flash controller" +volatile uint32_t *const kFCCOBx = (volatile uint32_t *)&FTFx_FCCOB3_REG; +/*! @brief Access to FTFx->FPROT */ +volatile uint32_t *const kFPROTL = (volatile uint32_t *)&FTFx_FPROT_LOW_REG; +#if defined(FTFx_FPROT_HIGH_REG) +volatile uint32_t *const kFPROTH = (volatile uint32_t *)&FTFx_FPROT_HIGH_REG; #endif -/*! @brief Access to FTFx->FPROT */ -#if defined(FSL_FEATURE_FLASH_IS_FTFA) && FSL_FEATURE_FLASH_IS_FTFA -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFA->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFE) && FSL_FEATURE_FLASH_IS_FTFE -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFE->FPROT3; -#elif defined(FSL_FEATURE_FLASH_IS_FTFL) && FSL_FEATURE_FLASH_IS_FTFL -volatile uint32_t *const kFPROT = (volatile uint32_t *)&FTFL->FPROT3; -#else -#error "Unknown flash controller" +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER +volatile uint8_t *const kFPROTSL = (volatile uint8_t *)&FTFx_FPROTSL_REG; +volatile uint8_t *const kFPROTSH = (volatile uint8_t *)&FTFx_FPROTSH_REG; #endif #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief A function pointer used to point to relocated flash_run_command() */ -static void (*callFlashRunCommand)(FTFx_REG_ACCESS_TYPE ftfx_fstat); -/*! @brief A function pointer used to point to relocated flash_cache_clear_command() */ -static void (*callFlashCacheClearCommand)(FTFx_REG32_ACCESS_TYPE ftfx_reg); +static void (*callFlashRunCommand)(FTFx_REG8_ACCESS_TYPE ftfx_fstat); +/*! @brief A function pointer used to point to relocated flash_common_bit_operation() */ +static void (*callFlashCommonBitOperation)(FTFx_REG32_ACCESS_TYPE base, + uint32_t bitMask, + uint32_t bitShift, + uint32_t bitValue); /*! * @brief Position independent code of flash_run_command() * * Note1: The prototype of C function is shown as below: * @code - * void flash_run_command(FTFx_REG_ACCESS_TYPE ftfx_fstat) + * void flash_run_command(FTFx_REG8_ACCESS_TYPE ftfx_fstat) * { * // clear CCIF bit * *ftfx_fstat = FTFx_FSTAT_CCIF_MASK; @@ -329,7 +513,7 @@ static void (*callFlashCacheClearCommand)(FTFx_REG32_ACCESS_TYPE ftfx_reg); * } * } * @endcode - * Note2: The binary code is generated by IAR 7.50.1 + * Note2: The binary code is generated by IAR 7.70.1 */ const static uint16_t s_flashRunCommandFunctionCode[] = { 0x2180, /* MOVS R1, #128 ; 0x80 */ @@ -342,102 +526,47 @@ const static uint16_t s_flashRunCommandFunctionCode[] = { }; /*! - * @brief Position independent code of flash_cache_clear_command() + * @brief Position independent code of flash_common_bit_operation() * * Note1: The prototype of C function is shown as below: * @code - * void flash_cache_clear_command(FTFx_REG32_ACCESS_TYPE ftfx_reg) + * void flash_common_bit_operation(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, uint32_t + * bitValue) * { - * #if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS - * *ftfx_reg |= MCM_PLACR_CFCC_MASK; - * #elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS - * #if defined(FMC_PFB01CR_CINV_WAY_MASK) - * *ftfx_reg = (*ftfx_reg & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); - * #else - * *ftfx_reg = (*ftfx_reg & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); - * #endif - * #elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - * *ftfx_reg |= MSCM_OCMDR_OCMC1(2); - * *ftfx_reg |= MSCM_OCMDR_OCMC1(1); - * #else - * #if defined(FMC_PFB0CR_S_INV_MASK) - * *ftfx_reg |= FMC_PFB0CR_S_INV_MASK; - * #elif defined(FMC_PFB01CR_S_INV_MASK) - * *ftfx_reg |= FMC_PFB01CR_S_INV_MASK; - * #endif - * // #error "Unknown flash cache controller" - * #endif // FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS - * // Memory barriers for good measure. - * // All Cache, Branch predictor and TLB maintenance operations before this instruction complete + * 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.50.1 + * Note2: The binary code is generated by IAR 7.70.1 */ -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -const static uint16_t s_flashCacheClearCommandFunctionCode[] = { - 0x6801, /* LDR R1, [R0] */ - 0x2280, /* MOVS R2, #128 ; 0x80 */ - 0x00d2, /* LSLS R2, R2, #3 */ - 0x430a, /* ORRS R2, R2, R1 */ - 0x6002, /* STR R2, [R0] */ - 0xf3bf, 0x8f6f, /* ISB */ - 0xf3bf, 0x8f4f, /* DSB */ - 0x4770 /* BX LR */ -}; -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -const static uint16_t s_flashCacheClearCommandFunctionCode[] = { - 0x6801, /* LDR R1, [R0] */ - 0x22f0, /* MOVS R2, #240 ; 0xf0 */ - 0x0412, /* LSLS R2, R2, #16 */ - 0x430a, /* ORRS R2, R2, R1 */ - 0x6002, /* STR R2, [R0] */ - 0xf3bf, 0x8f6f, /* ISB */ - 0xf3bf, 0x8f4f, /* DSB */ - 0x4770 /* BX LR */ -}; -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS -const static uint16_t s_flashCacheClearCommandFunctionCode[] = { - 0x6801, /* LDR R1, [R0] */ - 0x2220, /* MOVS R2, #32 ; 0x20 */ - 0x430a, /* ORRS R2, R2, R1 */ - 0x6002, /* STR R2, [R0] */ - 0x6801, /* LDR R1, [R0] */ - 0x2210, /* MOVS R2, #16 ; 0x10 */ - 0x430a, /* ORRS R2, R2, R1 */ - 0x6002, /* STR R2, [R0] */ - 0xf3bf, 0x8f6f, /* ISB */ - 0xf3bf, 0x8f4f, /* DSB */ - 0x4770 /* BX LR */ -}; -#else -#if defined(FMC_PFB0CR_S_INV_MASK) || defined(FMC_PFB01CR_S_INV_MASK) -const static uint16_t s_flashCacheClearCommandFunctionCode[] = { - 0x6801, /* LDR R1, [R0] */ - 0x2280, /* MOVS R2, #128 ; 0x80 */ - 0x0312, /* LSLS R2, R2, #12 */ - 0x430a, /* ORRS R2, R2, R1 */ - 0x6002, /* STR R2, [R0] */ - 0xf3bf, 0x8f6f, /* ISB */ - 0xf3bf, 0x8f4f, /* DSB */ - 0x4770 /* BX LR */ -}; -#else -const static uint16_t s_flashCacheClearCommandFunctionCode[] = { +const static uint16_t s_flashCommonBitOperationFunctionCode[] = { + 0xb510, /* PUSH {R4, LR} */ + 0x2900, /* CMP R1, #0 */ + 0xd005, /* BEQ.N @12 */ + 0x6804, /* LDR R4, [R0] */ + 0x438c, /* BICS R4, R4, R1 */ + 0x4093, /* LSLS R3, R3, R2 */ + 0x4019, /* ANDS R1, R1, R3 */ + 0x4321, /* ORRS R1, R1, R4 */ + 0x6001, /* STR R1, [R0] */ + /* @12: */ 0xf3bf, 0x8f6f, /* ISB */ 0xf3bf, 0x8f4f, /* DSB */ - 0x4770 /* BX LR */ + 0xbd10 /* POP {R4, PC} */ }; -#endif -#endif #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ #if (FLASH_DRIVER_IS_FLASH_RESIDENT && !FLASH_DRIVER_IS_EXPORTED) /*! @brief A static buffer used to hold flash_run_command() */ static uint32_t s_flashRunCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; -/*! @brief A static buffer used to hold flash_cache_clear_command() */ -static uint32_t s_flashCacheClearCommand[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; +/*! @brief A static buffer used to hold flash_common_bit_operation() */ +static uint32_t s_flashCommonBitOperation[kFLASH_ExecuteInRamFunctionMaxSizeInWords]; /*! @brief Flash execute-in-ram function information */ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; #endif @@ -460,6 +589,7 @@ static flash_execute_in_ram_function_config_t s_flashExecuteInRamFunctionInfo; * flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; * @endcode */ +#if (FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K1_2) const uint16_t kPFlashDensities[] = { 8, /* 0x0 - 8192, 8KB */ 16, /* 0x1 - 16384, 16KB */ @@ -478,6 +608,26 @@ const uint16_t kPFlashDensities[] = { 1536, /* 0xe - 1572864, 1.5MB */ /* 2048, 0xf - 2097152, 2MB */ }; +#elif(FLASH_MEMORY_SIZE_ENCODING_RULE == FLASH_MEMORY_SIZE_ENCODING_RULE_K3) +const uint16_t kPFlashDensities[] = { + 0, /* 0x0 - undefined */ + 0, /* 0x1 - undefined */ + 0, /* 0x2 - undefined */ + 0, /* 0x3 - undefined */ + 0, /* 0x4 - undefined */ + 0, /* 0x5 - undefined */ + 0, /* 0x6 - undefined */ + 0, /* 0x7 - undefined */ + 0, /* 0x8 - undefined */ + 0, /* 0x9 - undefined */ + 256, /* 0xa - 262144, 256KB */ + 0, /* 0xb - undefined */ + 1024, /* 0xc - 1048576, 1MB */ + 0, /* 0xd - undefined */ + 0, /* 0xe - undefined */ + 0, /* 0xf - undefined */ +}; +#endif /******************************************************************************* * Code @@ -485,39 +635,86 @@ const uint16_t kPFlashDensities[] = { status_t FLASH_Init(flash_config_t *config) { - uint32_t flashDensity; - if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - /* calculate the flash density from SIM_FCFG1.PFSIZE */ - uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; - /* 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 */ - if (pfsize == 0xf) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE1_PFSIZE_MASK) + uint32_t flashDensity; + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE1_PFSIZE_MASK) >> SIM_FCFG1_CORE1_PFSIZE_SHIFT; + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } + config->PFlashTotalSize = flashDensity; +#else + /* Unused code to solve MISRA-C issue*/ + config->PFlashBlockBase = kPFlashDensities[0]; + config->PFlashTotalSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; +#endif + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_1_START_ADDRESS; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SECTOR_SIZE; } else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ { - flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; - } + uint32_t flashDensity; - /* fill out a few of the structure members */ - config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; - config->PFlashTotalSize = flashDensity; - config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; - config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; +/* calculate the flash density from SIM_FCFG1.PFSIZE */ +#if defined(SIM_FCFG1_CORE0_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_CORE0_PFSIZE_MASK) >> SIM_FCFG1_CORE0_PFSIZE_SHIFT; +#elif defined(SIM_FCFG1_PFSIZE_MASK) + uint8_t pfsize = (SIM->FCFG1 & SIM_FCFG1_PFSIZE_MASK) >> SIM_FCFG1_PFSIZE_SHIFT; +#else +#error "Unknown flash size" +#endif + /* 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 */ + if (pfsize == 0xf) + { + flashDensity = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE; + } + else + { + flashDensity = ((uint32_t)kPFlashDensities[pfsize]) << 10; + } + + /* fill out a few of the structure members */ + config->PFlashBlockBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; + config->PFlashTotalSize = flashDensity; + config->PFlashBlockCount = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT; + config->PFlashSectorSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE; + } + { #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL - config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSS; - config->PFlashAccessSegmentCount = FTFx->FACSN; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSSS; + config->PFlashAccessSegmentCount = FTFx->FACSNS; + } + else +#endif + { + config->PFlashAccessSegmentSize = kFLASH_AccessSegmentBase << FTFx->FACSS; + config->PFlashAccessSegmentCount = FTFx->FACSN; + } #else - config->PFlashAccessSegmentSize = 0; - config->PFlashAccessSegmentCount = 0; + config->PFlashAccessSegmentSize = 0; + config->PFlashAccessSegmentCount = 0; #endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ + } config->PFlashCallback = NULL; @@ -527,7 +724,7 @@ status_t FLASH_Init(flash_config_t *config) { s_flashExecuteInRamFunctionInfo.activeFunctionCount = 0; s_flashExecuteInRamFunctionInfo.flashRunCommand = s_flashRunCommand; - s_flashExecuteInRamFunctionInfo.flashCacheClearCommand = s_flashCacheClearCommand; + s_flashExecuteInRamFunctionInfo.flashCommonBitOperation = s_flashCommonBitOperation; config->flashExecuteInRamFunctionInfo = &s_flashExecuteInRamFunctionInfo.activeFunctionCount; FLASH_PrepareExecuteInRamFunctions(config); } @@ -576,7 +773,7 @@ status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config) flashExecuteInRamFunctionInfo = (flash_execute_in_ram_function_config_t *)config->flashExecuteInRamFunctionInfo; copy_flash_run_command(flashExecuteInRamFunctionInfo->flashRunCommand); - copy_flash_cache_clear_command(flashExecuteInRamFunctionInfo->flashCacheClearCommand); + copy_flash_common_bit_operation(flashExecuteInRamFunctionInfo->flashCommonBitOperation); flashExecuteInRamFunctionInfo->activeFunctionCount = kFLASH_ExecuteInRamFunctionTotalNum; return kStatus_FLASH_Success; @@ -602,6 +799,8 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -622,22 +821,29 @@ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key) status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key) { uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t endAddress; /* storing end address */ uint32_t numberOfSectors; /* number of sectors calculated by endAddress */ status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectorCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + /* Validate the user key */ + returnCode = flash_check_user_key(key); + if (returnCode) + { + return returnCode; + } + + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; /* calculating Flash end address */ endAddress = start + lengthInBytes - 1; @@ -650,6 +856,8 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy endAddress = numberOfSectors * sectorSize - 1; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* the start address will increment to the next sector address * until it reaches the endAdddress */ while (start <= endAddress) @@ -657,13 +865,6 @@ status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBy /* preparing passing parameter to erase a flash block */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_SECTOR, start); - /* Validate the user key */ - returnCode = flash_check_user_key(key); - if (returnCode) - { - return returnCode; - } - /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -710,6 +911,8 @@ status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -748,6 +951,8 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) return returnCode; } + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -759,33 +964,35 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (src == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.blockWriteUnitSize); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.blockWriteUnitSize); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; + + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); while (lengthInBytes > 0) { /* preparing passing parameter to program the flash block */ kFCCOBx[1] = *src++; - if (4 == flashInfo.blockWriteUnitSize) + if (4 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_LONGWORD, start); } - else if (8 == flashInfo.blockWriteUnitSize) + else if (8 == flashOperationInfo.blockWriteUnitSize) { kFCCOBx[2] = *src++; kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_PHRASE, start); @@ -811,10 +1018,10 @@ status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, ui else { /* update start address for next iteration */ - start += flashInfo.blockWriteUnitSize; + start += flashOperationInfo.blockWriteUnitSize; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.blockWriteUnitSize; + lengthInBytes -= flashOperationInfo.blockWriteUnitSize; } } @@ -851,6 +1058,8 @@ status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src } #endif /* FLASH_PROGRAM_ONCE_IS_8BYTES_UNIT_SUPPORT */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -864,7 +1073,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * { status_t returnCode; uint32_t sectorSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; #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 */ @@ -874,17 +1083,17 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; - sectorSize = flashInfo.activeSectorSize; + start = flashOperationInfo.convertedAddress; + sectorSize = flashOperationInfo.activeSectorSize; #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD /* Switch function of FlexRAM if needed */ @@ -900,6 +1109,8 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + while (lengthInBytes > 0) { /* Make sure the write operation doesn't span two sectors */ @@ -942,7 +1153,7 @@ status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t * /* Set start address of the data to be programmed */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_PROGRAM_SECTION, start + currentOffset); /* Set program size in terms of FEATURE_FLASH_SECTION_CMD_ADDRESS_ALIGMENT */ - numberOfPhases = programSizeOfCurrentPass / flashInfo.sectionCmdAddressAligment; + numberOfPhases = programSizeOfCurrentPass / flashOperationInfo.sectionCmdAddressAligment; kFCCOBx[1] = BYTES_JOIN_TO_WORD_2_2(numberOfPhases, 0xFFFFU); @@ -1075,17 +1286,18 @@ status_t FLASH_ReadResource( flash_config_t *config, uint32_t start, uint32_t *dst, uint32_t lengthInBytes, flash_read_resource_option_t option) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if ((config == NULL) || (dst == NULL)) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); /* Check the supplied address range. */ - returnCode = flash_check_resource_range(start, lengthInBytes, flashInfo.resourceCmdAddressAligment, option); + returnCode = + flash_check_resource_range(start, lengthInBytes, flashOperationInfo.resourceCmdAddressAligment, option); if (returnCode != kStatus_FLASH_Success) { return returnCode; @@ -1095,11 +1307,11 @@ status_t FLASH_ReadResource( { /* preparing passing parameter */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_READ_RESOURCE, start); - if (flashInfo.resourceCmdAddressAligment == 4) + if (flashOperationInfo.resourceCmdAddressAligment == 4) { kFCCOBx[2] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } - else if (flashInfo.resourceCmdAddressAligment == 8) + else if (flashOperationInfo.resourceCmdAddressAligment == 8) { kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_3(option, 0xFFFFFFU); } @@ -1117,14 +1329,14 @@ status_t FLASH_ReadResource( /* fetch data */ *dst++ = kFCCOBx[1]; - if (flashInfo.resourceCmdAddressAligment == 8) + if (flashOperationInfo.resourceCmdAddressAligment == 8) { *dst++ = kFCCOBx[2]; } /* update start address for next iteration */ - start += flashInfo.resourceCmdAddressAligment; + start += flashOperationInfo.resourceCmdAddressAligment; /* update lengthInBytes for next iteration */ - lengthInBytes -= flashInfo.resourceCmdAddressAligment; + lengthInBytes -= flashOperationInfo.resourceCmdAddressAligment; } return (returnCode); @@ -1255,22 +1467,22 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng { /* Check arguments. */ uint32_t blockSize; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; uint32_t nextBlockStartAddress; uint32_t remainingBytes; status_t returnCode; - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.sectionCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectionCmdAddressAligment); if (returnCode) { return returnCode; } - flash_get_matched_operation_info(config, start, &flashInfo); - start = flashInfo.convertedAddress; - blockSize = flashInfo.activeBlockSize; + flash_get_matched_operation_info(config, start, &flashOperationInfo); + start = flashOperationInfo.convertedAddress; + blockSize = flashOperationInfo.activeBlockSize; nextBlockStartAddress = ALIGN_UP(start, blockSize); if (nextBlockStartAddress == start) @@ -1289,7 +1501,7 @@ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t leng verifyLength = remainingBytes; } - numberOfPhrases = verifyLength / flashInfo.sectionCmdAddressAligment; + numberOfPhrases = verifyLength / flashOperationInfo.sectionCmdAddressAligment; /* Fill in verify section command parameters. */ kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_VERIFY_SECTION, start); @@ -1319,22 +1531,22 @@ status_t FLASH_VerifyProgram(flash_config_t *config, uint32_t *failedData) { status_t returnCode; - flash_operation_config_t flashInfo; + flash_operation_config_t flashOperationInfo; if (expectedData == NULL) { return kStatus_FLASH_InvalidArgument; } - flash_get_matched_operation_info(config, start, &flashInfo); + flash_get_matched_operation_info(config, start, &flashOperationInfo); - returnCode = flash_check_range(config, start, lengthInBytes, flashInfo.checkCmdAddressAligment); + returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.checkCmdAddressAligment); if (returnCode) { return returnCode; } - start = flashInfo.convertedAddress; + start = flashOperationInfo.convertedAddress; while (lengthInBytes) { @@ -1360,9 +1572,9 @@ status_t FLASH_VerifyProgram(flash_config_t *config, break; } - lengthInBytes -= flashInfo.checkCmdAddressAligment; - expectedData += flashInfo.checkCmdAddressAligment / sizeof(*expectedData); - start += flashInfo.checkCmdAddressAligment; + lengthInBytes -= flashOperationInfo.checkCmdAddressAligment; + expectedData += flashOperationInfo.checkCmdAddressAligment / sizeof(*expectedData); + start += flashOperationInfo.checkCmdAddressAligment; } return (returnCode); @@ -1388,19 +1600,21 @@ status_t FLASH_IsProtected(flash_config_t *config, flash_protection_state_t *protection_state) { uint32_t endAddress; /* end address for protection check */ - uint32_t protectionRegionSize; /* size of flash protection region */ 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[FSL_FEATURE_FTFx_REGION_COUNT]; /* array of the protection status for each + uint8_t flashRegionProtectStatus[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT]; /* array of the protection + * status for each * protection region */ - uint32_t flashRegionAddress[FSL_FEATURE_FTFx_REGION_COUNT + 1]; /* 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 */ + uint32_t flashRegionAddress[FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT + + 1]; /* 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 */ + flash_protection_config_t flashProtectionInfo; /* flash protection information */ status_t returnCode; if (protection_state == NULL) @@ -1415,28 +1629,24 @@ status_t FLASH_IsProtected(flash_config_t *config, return returnCode; } - /* calculating Flash end address */ - endAddress = start + lengthInBytes; - - /* 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 (config->PFlashTotalSize > 32 * 1024) - { - protectionRegionSize = (config->PFlashTotalSize) / FSL_FEATURE_FTFx_REGION_COUNT; - } - else + /* Get necessary flash protection information. */ + returnCode = flash_get_protection_info(config, &flashProtectionInfo); + if (returnCode) { - protectionRegionSize = 1024; + return returnCode; } + /* calculating Flash end address */ + endAddress = start + lengthInBytes; + /* populate the flashRegionAddress array with the start address of each flash region */ regionCounter = 0; /* 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 <= FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter <= flashProtectionInfo.regionCount) { - flashRegionAddress[regionCounter] = config->PFlashBlockBase + protectionRegionSize * regionCounter; + flashRegionAddress[regionCounter] = + flashProtectionInfo.regionBase + flashProtectionInfo.regionSize * regionCounter; regionCounter++; } @@ -1450,24 +1660,80 @@ status_t FLASH_IsProtected(flash_config_t *config, * 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 = 0; /* make sure regionCounter is initialized to 0 first */ - while (regionCounter < FSL_FEATURE_FTFx_REGION_COUNT) + while (regionCounter < flashProtectionInfo.regionCount) { - if (regionCounter < 8) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT3) >> regionCounter) & (0x01u); - } - else if ((regionCounter >= 8) && (regionCounter < 16)) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT2) >> (regionCounter - 8)) & (0x01u); - } - else if ((regionCounter >= 16) && (regionCounter < 24)) - { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT1) >> (regionCounter - 16)) & (0x01u); + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSL_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTSH_REG >> (regionCounter - 8)) & (0x01u); + } + else + { + break; + } } else +#endif { - flashRegionProtectStatus[regionCounter] = ((FTFx->FPROT0) >> (regionCounter - 24)) & (0x01u); + /* Note: So far protection region count may be 16/20/24/32/64 */ + if (regionCounter < 8) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL3_REG >> regionCounter) & (0x01u); + } + else if ((regionCounter >= 8) && (regionCounter < 16)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL2_REG >> (regionCounter - 8)) & (0x01u); + } +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 16) +#if (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) + else if ((regionCounter >= 16) && (regionCounter < 20)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#else + else if ((regionCounter >= 16) && (regionCounter < 24)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL1_REG >> (regionCounter - 16)) & (0x01u); + } +#endif /* (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 20) */ +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT > 24) + else if ((regionCounter >= 24) && (regionCounter < 32)) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTL0_REG >> (regionCounter - 24)) & (0x01u); + } +#endif +#if defined(FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT) && \ + (FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT == 64) + else if (regionCounter < 40) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH3_REG >> (regionCounter - 32)) & (0x01u); + } + else if (regionCounter < 48) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH2_REG >> (regionCounter - 40)) & (0x01u); + } + else if (regionCounter < 56) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH1_REG >> (regionCounter - 48)) & (0x01u); + } + else if (regionCounter < 64) + { + flashRegionProtectStatus[regionCounter] = (FTFx_FPROTH0_REG >> (regionCounter - 56)) & (0x01u); + } +#endif + else + { + break; + } } + regionCounter++; } @@ -1495,7 +1761,7 @@ status_t FLASH_IsProtected(flash_config_t *config, /* increment protectStatusCounter to indicate this region is protected */ protectStatusCounter++; } - start += protectionRegionSize; /* increment to an address within the next region */ + start += flashProtectionInfo.regionSize; /* increment to an address within the next region */ } regionCounter++; /* increment regionCounter to check for the next flash protection region */ } @@ -1525,6 +1791,9 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t lengthInBytes, flash_execute_only_access_state_t *access_state) { +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + flash_access_config_t flashAccessInfo; /* flash Execute-Only information */ +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ status_t returnCode; if (access_state == NULL) @@ -1540,6 +1809,13 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, } #if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL + /* Get necessary flash Execute-Only information. */ + returnCode = flash_get_access_info(config, &flashAccessInfo); + if (returnCode) + { + return returnCode; + } + { uint32_t executeOnlySegmentCounter = 0; @@ -1547,31 +1823,56 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t endAddress = start + lengthInBytes; /* Aligning start address and end address */ - uint32_t alignedStartAddress = ALIGN_DOWN(start, config->PFlashAccessSegmentSize); - uint32_t alignedEndAddress = ALIGN_UP(endAddress, config->PFlashAccessSegmentSize); + uint32_t alignedStartAddress = ALIGN_DOWN(start, flashAccessInfo.SegmentSize); + uint32_t alignedEndAddress = ALIGN_UP(endAddress, flashAccessInfo.SegmentSize); uint32_t segmentIndex = 0; uint32_t maxSupportedExecuteOnlySegmentCount = - (alignedEndAddress - alignedStartAddress) / config->PFlashAccessSegmentSize; + (alignedEndAddress - alignedStartAddress) / flashAccessInfo.SegmentSize; while (start < endAddress) { uint32_t xacc; - segmentIndex = start / config->PFlashAccessSegmentSize; + segmentIndex = (start - flashAccessInfo.SegmentBase) / flashAccessInfo.SegmentSize; - if (segmentIndex < 32) - { - xacc = *(const volatile uint32_t *)&FTFx->XACCL3; - } - else if (segmentIndex < config->PFlashAccessSegmentCount) +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) { - xacc = *(const volatile uint32_t *)&FTFx->XACCH3; - segmentIndex -= 32; + /* For secondary flash, The two XACCS registers allow up to 16 restricted segments of equal memory size. + */ + if (segmentIndex < 8) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSL_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint8_t *)&FTFx_XACCSH_REG; + segmentIndex -= 8; + } + else + { + break; + } } else +#endif { - break; + /* For primary flash, The eight XACC registers allow up to 64 restricted segments of equal memory size. + */ + if (segmentIndex < 32) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCL3_REG; + } + else if (segmentIndex < flashAccessInfo.SegmentCount) + { + xacc = *(const volatile uint32_t *)&FTFx_XACCH3_REG; + segmentIndex -= 32; + } + else + { + break; + } } /* Determine if this address range is in a execute-only protection flash segment. */ @@ -1580,7 +1881,7 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, executeOnlySegmentCounter++; } - start += config->PFlashAccessSegmentSize; + start += flashAccessInfo.SegmentSize; } if (executeOnlySegmentCounter < 1u) @@ -1625,7 +1926,7 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro break; case kFLASH_PropertyPflashBlockCount: - *value = config->PFlashBlockCount; + *value = (uint32_t)config->PFlashBlockCount; break; case kFLASH_PropertyPflashBlockBaseAddr: @@ -1684,6 +1985,65 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro return kStatus_FLASH_Success; } +status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value) +{ + status_t status = kStatus_FLASH_Success; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + switch (whichProperty) + { +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + case kFLASH_PropertyFlashMemoryIndex: + if ((value != (uint32_t)kFLASH_MemoryIndexPrimaryFlash) && + (value != (uint32_t)kFLASH_MemoryIndexSecondaryFlash)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashMemoryIndex = (uint8_t)value; + break; +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + + case kFLASH_PropertyFlashCacheControllerIndex: + if ((value != (uint32_t)kFLASH_CacheControllerIndexForCore0) && + (value != (uint32_t)kFLASH_CacheControllerIndexForCore1)) + { + return kStatus_FLASH_InvalidPropertyValue; + } + config->FlashCacheControllerIndex = (uint8_t)value; + break; + + case kFLASH_PropertyPflashSectorSize: + case kFLASH_PropertyPflashTotalSize: + case kFLASH_PropertyPflashBlockSize: + case kFLASH_PropertyPflashBlockCount: + case kFLASH_PropertyPflashBlockBaseAddr: + case kFLASH_PropertyPflashFacSupport: + case kFLASH_PropertyPflashAccessSegmentSize: + case kFLASH_PropertyPflashAccessSegmentCount: + case kFLASH_PropertyFlexRamBlockBaseAddr: + case kFLASH_PropertyFlexRamTotalSize: +#if FLASH_SSD_IS_FLEXNVM_ENABLED + case kFLASH_PropertyDflashSectorSize: + case kFLASH_PropertyDflashTotalSize: + case kFLASH_PropertyDflashBlockSize: + case kFLASH_PropertyDflashBlockCount: + case kFLASH_PropertyDflashBlockBaseAddr: + case kFLASH_PropertyEepromTotalSize: +#endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ + status = kStatus_FLASH_ReadOnlyProperty; + break; + default: /* catch inputs that are not recognized */ + status = kStatus_FLASH_UnknownProperty; + break; + } + + return status; +} + #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function_option_t option) { @@ -1745,9 +2105,9 @@ status_t FLASH_SwapControl(flash_config_t *config, returnCode = flash_command_sequence(config); - returnInfo->flashSwapState = (flash_swap_state_t)FTFx->FCCOB5; - returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB6; - returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx->FCCOB7; + returnInfo->flashSwapState = (flash_swap_state_t)FTFx_FCCOB5_REG; + returnInfo->currentSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB6_REG; + returnInfo->nextSwapBlockStatus = (flash_swap_block_status_t)FTFx_FCCOB7_REG; return returnCode; } @@ -1867,6 +2227,8 @@ status_t FLASH_ProgramPartition(flash_config_t *config, kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_2_1(FTFx_PROGRAM_PARTITION, 0xFFFFU, option); kFCCOBx[1] = BYTES_JOIN_TO_WORD_1_1_2(eepromDataSizeCode, flexnvmPartitionCode, 0xFFFFU); + flash_cache_clear_process(config, kFLASH_CacheClearProcessPre); + /* calling flash command sequence function to execute the command */ returnCode = flash_command_sequence(config); @@ -1883,31 +2245,70 @@ status_t FLASH_ProgramPartition(flash_config_t *config, } #endif /* FSL_FEATURE_FLASH_HAS_PROGRAM_PARTITION_CMD */ -status_t FLASH_PflashSetProtection(flash_config_t *config, uint32_t protectStatus) +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if (config == NULL) { return kStatus_FLASH_InvalidArgument; } - *kFPROT = protectStatus; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + *kFPROTSL = protectStatus->valueLow32b.prots16b.protsl; + if (protectStatus->valueLow32b.prots16b.protsl != *kFPROTSL) + { + return kStatus_FLASH_CommandFailure; + } - if (protectStatus != *kFPROT) + *kFPROTSH = protectStatus->valueLow32b.prots16b.protsh; + if (protectStatus->valueLow32b.prots16b.protsh != *kFPROTSH) + { + return kStatus_FLASH_CommandFailure; + } + } + else +#endif { - return kStatus_FLASH_CommandFailure; + *kFPROTL = protectStatus->valueLow32b.protl32b; + if (protectStatus->valueLow32b.protl32b != *kFPROTL) + { + return kStatus_FLASH_CommandFailure; + } + +#if defined(FTFx_FPROT_HIGH_REG) + *kFPROTH = protectStatus->valueHigh32b.proth32b; + if (protectStatus->valueHigh32b.proth32b != *kFPROTH) + { + return kStatus_FLASH_CommandFailure; + } +#endif } return kStatus_FLASH_Success; } -status_t FLASH_PflashGetProtection(flash_config_t *config, uint32_t *protectStatus) +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus) { if ((config == NULL) || (protectStatus == NULL)) { return kStatus_FLASH_InvalidArgument; } - *protectStatus = *kFPROT; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + protectStatus->valueLow32b.prots16b.protsl = *kFPROTSL; + protectStatus->valueLow32b.prots16b.protsh = *kFPROTSH; + } + else +#endif + { + protectStatus->valueLow32b.protl32b = *kFPROTL; +#if defined(FTFx_FPROT_HIGH_REG) + protectStatus->valueHigh32b.proth32b = *kFPROTH; +#endif + } return kStatus_FLASH_Success; } @@ -1998,6 +2399,203 @@ status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatu } #endif /* FLASH_SSD_IS_FLEXNVM_ENABLED */ +status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) +{ +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + FTFx_REG32_ACCESS_TYPE regBase; +#if defined(MCM) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM->PLACR; +#elif defined(MCM0) + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= MCM_PLACR_DFCS_MASK; + } + } + else + { + *regBase &= ~MCM_PLACR_DFCS_MASK; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= MCM_PLACR_EFDS_MASK; + } + else + { + *regBase &= ~MCM_PLACR_EFDS_MASK; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0ipeMask; + } + else + { + *regBase &= ~b0ipeMask; + } + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase |= b0dpeMask; + } + else + { + *regBase &= ~b0dpeMask; + } + +/* Invalidate Prefetch Speculation Buffer */ +#if defined(FMC_PFB01CR_S_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; +#endif + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + FTFx_REG32_ACCESS_TYPE regBase; + uint32_t flashSpeculationMask, dataPrefetchMask; + regBase = (FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (speculationStatus->instructionOption == kFLASH_prefetchSpeculationOptionDisable) + { + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + return kStatus_FLASH_InvalidSpeculationOption; + } + else + { + *regBase |= flashSpeculationMask; + } + } + else + { + *regBase &= ~flashSpeculationMask; + if (speculationStatus->dataOption == kFLASH_prefetchSpeculationOptionEnable) + { + *regBase &= ~dataPrefetchMask; + } + else + { + *regBase |= dataPrefetchMask; + } + } + } +#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ + + return kStatus_FLASH_Success; +} + +status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus) +{ + memset(speculationStatus, 0, sizeof(flash_prefetch_speculation_status_t)); + + /* Assuming that all speculation options are enabled. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionEnable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionEnable; + +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MCM + { + uint32_t value; +#if defined(MCM) + value = MCM->PLACR; +#elif defined(MCM0) + value = MCM0->PLACR; +#endif + if (value & MCM_PLACR_DFCS_MASK) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (!(value & MCM_PLACR_EFDS_MASK)) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + { + uint32_t value; + uint32_t b0dpeMask, b0ipeMask; +#if defined(FMC_PFB01CR_B0DPE_MASK) + value = FMC->PFB01CR; + b0dpeMask = FMC_PFB01CR_B0DPE_MASK; + b0ipeMask = FMC_PFB01CR_B0IPE_MASK; +#elif defined(FMC_PFB0CR_B0DPE_MASK) + value = FMC->PFB0CR; + b0dpeMask = FMC_PFB0CR_B0DPE_MASK; + b0ipeMask = FMC_PFB0CR_B0IPE_MASK; +#endif + if (!(value & b0dpeMask)) + { + /* Do not prefetch in response to data references. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + if (!(value & b0ipeMask)) + { + /* Do not prefetch in response to instruction fetches. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + } + } +#elif FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + { + uint32_t value; + uint32_t flashSpeculationMask, dataPrefetchMask; + value = MSCM->OCMDR[0]; + flashSpeculationMask = MSCM_OCMDR_OCMC1_DFCS_MASK; + dataPrefetchMask = MSCM_OCMDR_OCMC1_DFDS_MASK; + + if (value & flashSpeculationMask) + { + /* Speculation buffer is off. */ + speculationStatus->instructionOption = kFLASH_prefetchSpeculationOptionDisable; + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + else + { + /* Speculation buffer is on for instruction. */ + if (value & dataPrefetchMask) + { + /* Speculation buffer is off for data. */ + speculationStatus->dataOption = kFLASH_prefetchSpeculationOptionDisable; + } + } + } +#endif + + return kStatus_FLASH_Success; +} + #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! * @brief Copy PIC of flash_run_command() to RAM @@ -2009,7 +2607,7 @@ static void copy_flash_run_command(uint32_t *flashRunCommand) /* 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. */ memcpy((void *)flashRunCommand, (void *)s_flashRunCommandFunctionCode, sizeof(s_flashRunCommandFunctionCode)); - callFlashRunCommand = (void (*)(FTFx_REG_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); + callFlashRunCommand = (void (*)(FTFx_REG8_ACCESS_TYPE ftfx_fstat))((uint32_t)flashRunCommand + 1); } #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ @@ -2038,7 +2636,7 @@ static status_t flash_command_sequence(flash_config_t *config) /* 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). */ - callFlashRunCommand((FTFx_REG_ACCESS_TYPE)(&FTFx->FSTAT)); + callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); #else /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */ FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK; @@ -2080,118 +2678,207 @@ static status_t flash_command_sequence(flash_config_t *config) #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! - * @brief Copy PIC of flash_cache_clear_command() to RAM + * @brief Copy PIC of flash_common_bit_operation() to RAM * */ -static void copy_flash_cache_clear_command(uint32_t *flashCacheClearCommand) +static void copy_flash_common_bit_operation(uint32_t *flashCommonBitOperation) { - assert(sizeof(s_flashCacheClearCommandFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); + assert(sizeof(s_flashCommonBitOperationFunctionCode) <= (kFLASH_ExecuteInRamFunctionMaxSizeInWords * 4)); /* 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. */ - memcpy((void *)flashCacheClearCommand, (void *)s_flashCacheClearCommandFunctionCode, - sizeof(s_flashCacheClearCommandFunctionCode)); - callFlashCacheClearCommand = (void (*)(FTFx_REG32_ACCESS_TYPE ftfx_reg))((uint32_t)flashCacheClearCommand + 1); + memcpy((void *)flashCommonBitOperation, (void *)s_flashCommonBitOperationFunctionCode, + sizeof(s_flashCommonBitOperationFunctionCode)); + callFlashCommonBitOperation = (void (*)(FTFx_REG32_ACCESS_TYPE base, uint32_t bitMask, uint32_t bitShift, + uint32_t bitValue))((uint32_t)flashCommonBitOperation + 1); + /* Workround for some devices which doesn't need this function */ + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)0, 0, 0, 0); } #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ -/*! - * @brief Flash Cache Clear - * - * This function is used to perform the cache clear to the flash. - */ -#if (defined(__GNUC__)) -/* #pragma GCC push_options */ -/* #pragma GCC optimize("O0") */ -void __attribute__((optimize("O0"))) flash_cache_clear(flash_config_t *config) -#else -#if (defined(__ICCARM__)) -#pragma optimize = none -#endif -#if (defined(__CC_ARM)) -#pragma push -#pragma O0 -#endif -void flash_cache_clear(flash_config_t *config) -#endif +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM +/*! @brief Performs the cache clear to the flash by MCM.*/ +void mcm_flash_cache_clear(flash_config_t *config) { -#if FLASH_DRIVER_IS_FLASH_RESIDENT - status_t returnCode = flash_check_execute_in_ram_function_info(config); - if (kStatus_FLASH_Success != returnCode) + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)&MCM0_CACHE_REG; + +#if defined(MCM0) && defined(MCM1) + if (config->FlashCacheControllerIndex == (uint8_t)kFLASH_CacheControllerIndexForCore1) { - return; + regBase = (FTFx_REG32_ACCESS_TYPE)&MCM1_CACHE_REG; } - -/* We pass the ftfx register address as a parameter to flash_cache_clear_comamnd() instead of using - * pre-processed MACROs or a global variable in flash_cache_clear_comamnd() - * to make sure that flash_cache_clear_command() will be compiled into position-independent code (PIC). */ -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM->PLACR); -#endif -#if defined(MCM0) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM0->PLACR); #endif -#if defined(MCM1) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MCM1->PLACR); -#endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS + +#if FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation(regBase, MCM_CACHE_CLEAR_MASK, MCM_CACHE_CLEAR_SHIFT, 1U); +#else /* !FLASH_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 /* FLASH_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_MCM */ + +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC +/*! @brief Performs the cache clear to the flash by FMC.*/ +void fmc_flash_cache_clear(void) +{ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; #if defined(FMC_PFB01CR_CINV_WAY_MASK) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR); + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_CINV_WAY_MASK, FMC_PFB01CR_CINV_WAY_SHIFT, 0xFU); #else - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR); + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_CINV_WAY_MASK, FMC_PFB0CR_CINV_WAY_SHIFT, 0xFU); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0]); -#else -#if defined(FMC_PFB0CR_S_INV_MASK) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR); -#elif defined(FMC_PFB01CR_S_INV_MASK) - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR); +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_CINV_WAY_MASK) + FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); #else - /* meaningless code, just a workaround to solve warning*/ - callFlashCacheClearCommand((FTFx_REG32_ACCESS_TYPE)0); + FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); #endif -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ +} +#endif /* FLASH_CACHE_IS_CONTROLLED_BY_FMC */ -#else +#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(bool enable) +{ + uint8_t setValue; + if (enable) + { + setValue = 0x0U; + } + else + { + setValue = 0x3U; + } -#if defined(FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MCM_FLASH_CACHE_CONTROLS -#if defined(MCM) - MCM->PLACR |= MCM_PLACR_CFCC_MASK; -#endif -#if defined(MCM0) - MCM0->PLACR |= MCM_PLACR_CFCC_MASK; +/* 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 FLASH_DRIVER_IS_FLASH_RESIDENT + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[0], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + callFlashCommonBitOperation((FTFx_REG32_ACCESS_TYPE)&MSCM->OCMDR[1], MSCM_SPECULATION_DISABLE_MASK, + MSCM_SPECULATION_DISABLE_SHIFT, setValue); #endif -#if defined(MCM1) - MCM1->PLACR |= MCM_PLACR_CFCC_MASK; +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ + MSCM->OCMDR[0] |= MSCM_SPECULATION_DISABLE(setValue); + + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); +#if FLASH_SSD_IS_FLEXNVM_ENABLED || BL_HAS_SECONDARY_INTERNAL_FLASH + MSCM->OCMDR[1] |= MSCM_SPECULATION_DISABLE(setValue); + + /* Each cahce clear instaruction should be followed by below code*/ + __ISB(); + __DSB(); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_FMC_FLASH_CACHE_CONTROLS -#if defined(FMC_PFB01CR_CINV_WAY_MASK) - FMC->PFB01CR = (FMC->PFB01CR & ~FMC_PFB01CR_CINV_WAY_MASK) | FMC_PFB01CR_CINV_WAY(~0); -#else - FMC->PFB0CR = (FMC->PFB0CR & ~FMC_PFB0CR_CINV_WAY_MASK) | FMC_PFB0CR_CINV_WAY(~0); + +#endif /* FLASH_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(void) +{ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + FTFx_REG32_ACCESS_TYPE regBase = (FTFx_REG32_ACCESS_TYPE)0; +#if defined(FMC_PFB01CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_INV_MASK, FMC_PFB01CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB01CR; + callFlashCommonBitOperation(regBase, FMC_PFB01CR_S_B_INV_MASK, FMC_PFB01CR_S_B_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_INV_MASK, FMC_PFB0CR_S_INV_SHIFT, 1U); +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + regBase = (FTFx_REG32_ACCESS_TYPE)&FMC->PFB0CR; + callFlashCommonBitOperation(regBase, FMC_PFB0CR_S_B_INV_MASK, FMC_PFB0CR_S_B_INV_SHIFT, 1U); #endif -#elif defined(FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS) && FSL_FEATURE_FLASH_HAS_MSCM_FLASH_CACHE_CONTROLS - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(2); - MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(1); -#else -#if defined(FMC_PFB0CR_S_INV_MASK) - FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; -#elif defined(FMC_PFB01CR_S_INV_MASK) +#else /* !FLASH_DRIVER_IS_FLASH_RESIDENT */ +#if defined(FMC_PFB01CR_S_INV_MASK) FMC->PFB01CR |= FMC_PFB01CR_S_INV_MASK; +#elif defined(FMC_PFB01CR_S_B_INV_MASK) + FMC->PFB01CR |= FMC_PFB01CR_S_B_INV_MASK; +#elif defined(FMC_PFB0CR_S_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_INV_MASK; +#elif defined(FMC_PFB0CR_S_B_INV_MASK) + FMC->PFB0CR |= FMC_PFB0CR_S_B_INV_MASK; #endif -/* #error "Unknown flash cache controller" */ -#endif /* FSL_FEATURE_FTFx_MCM_FLASH_CACHE_CONTROLS */ + /* Memory barriers for good measure. + * All Cache, Branch predictor and TLB maintenance operations before this instruction complete */ + __ISB(); + __DSB(); #endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ } -#if (defined(__CC_ARM)) -#pragma pop +#endif /* FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC */ + +/*! + * @brief Flash Cache Clear + * + * This function is used to perform the cache and prefetch speculation clear to the flash. + */ +void flash_cache_clear(flash_config_t *config) +{ + flash_cache_clear_process(config, kFLASH_CacheClearProcessPost); +} + +/*! + * @brief Flash Cache Clear Process + * + * This function is used to perform the cache and prefetch speculation clear process to the flash. + */ +static void flash_cache_clear_process(flash_config_t *config, flash_cache_clear_process_t process) +{ +#if FLASH_DRIVER_IS_FLASH_RESIDENT + status_t returnCode = flash_check_execute_in_ram_function_info(config); + if (kStatus_FLASH_Success != returnCode) + { + return; + } +#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */ + + /* We pass the ftfx register address as a parameter to flash_common_bit_operation() instead of using + * pre-processed MACROs or a global variable in flash_common_bit_operation() + * to make sure that flash_common_bit_operation() will be compiled into position-independent code (PIC). */ + if (process == kFLASH_CacheClearProcessPost) + { +#if FLASH_CACHE_IS_CONTROLLED_BY_MCM + mcm_flash_cache_clear(config); #endif -#if (defined(__GNUC__)) -/* #pragma GCC pop_options */ +#if FLASH_CACHE_IS_CONTROLLED_BY_FMC + fmc_flash_cache_clear(); #endif +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(true); +#endif +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_FMC + fmc_flash_prefetch_speculation_clear(); +#endif + } + if (process == kFLASH_CacheClearProcessPre) + { +#if FLASH_PREFETCH_SPECULATION_IS_CONTROLLED_BY_MSCM + mscm_flash_prefetch_speculation_enable(false); +#endif + } +} #if FLASH_DRIVER_IS_FLASH_RESIDENT /*! @brief Check whether flash execute-in-ram functions are ready */ @@ -2233,21 +2920,19 @@ static status_t flash_check_range(flash_config_t *config, return kStatus_FLASH_AlignmentError; } -/* check for valid range of the target addresses */ -#if !FLASH_SSD_IS_FLEXNVM_ENABLED - if ((startAddress < config->PFlashBlockBase) || - ((startAddress + lengthInBytes) > (config->PFlashBlockBase + config->PFlashTotalSize))) -#else - if (!(((startAddress >= config->PFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize))) || - ((startAddress >= config->DFlashBlockBase) && - ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))))) + /* check for valid range of the target addresses */ + if ( +#if FLASH_SSD_IS_FLEXNVM_ENABLED + ((startAddress >= config->DFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->DFlashBlockBase + config->DFlashTotalSize))) || #endif + ((startAddress >= config->PFlashBlockBase) && + ((startAddress + lengthInBytes) <= (config->PFlashBlockBase + config->PFlashTotalSize)))) { - return kStatus_FLASH_AddressError; + return kStatus_FLASH_Success; } - return kStatus_FLASH_Success; + return kStatus_FLASH_AddressError; } /*! @brief Gets the right address, sector and block size of current flash type which is indicated by address.*/ @@ -2263,11 +2948,11 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, /* Clean up info Structure*/ memset(info, 0, sizeof(flash_operation_config_t)); -/* When required by the command, address bit 23 selects between program flash memory - * (=0) and data flash memory (=1).*/ #if FLASH_SSD_IS_FLEXNVM_ENABLED if ((address >= config->DFlashBlockBase) && (address <= (config->DFlashBlockBase + config->DFlashTotalSize))) { + /* When required by the command, address bit 23 selects between program flash memory + * (=0) and data flash memory (=1).*/ info->convertedAddress = address - config->DFlashBlockBase + 0x800000U; info->activeSectorSize = FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_SECTOR_SIZE; info->activeBlockSize = config->DFlashTotalSize / FSL_FEATURE_FLASH_FLEX_NVM_BLOCK_COUNT; @@ -2284,8 +2969,22 @@ static status_t flash_get_matched_operation_info(flash_config_t *config, info->convertedAddress = address - config->PFlashBlockBase; info->activeSectorSize = config->PFlashSectorSize; info->activeBlockSize = config->PFlashTotalSize / config->PFlashBlockCount; +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { +#if FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER || FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER + /* When required by the command, address bit 23 selects between main flash memory + * (=0) and secondary flash memory (=1).*/ + info->convertedAddress += 0x800000U; +#endif + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_1_BLOCK_WRITE_UNIT_SIZE; + } + else +#endif /* FLASH_SSD_IS_SECONDARY_FLASH_ENABLED */ + { + info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; + } - info->blockWriteUnitSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE; info->sectorCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTOR_CMD_ADDRESS_ALIGMENT; info->sectionCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_SECTION_CMD_ADDRESS_ALIGMENT; info->resourceCmdAddressAligment = FSL_FEATURE_FLASH_PFLASH_RESOURCE_CMD_ADDRESS_ALIGMENT; @@ -2325,6 +3024,7 @@ static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *con return kStatus_FLASH_InvalidArgument; } +#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 = FLASH_ReadResource(config, DFLASH_IFR_READRESOURCE_START_ADDRESS, (uint32_t *)&dataIFRReadOut, sizeof(dataIFRReadOut), kFLASH_ResourceOptionFlashIfr); @@ -2332,6 +3032,9 @@ static status_t flash_update_flexnvm_memory_partition_status(flash_config_t *con { return kStatus_FLASH_PartitionStatusUpdateFailure; } +#else +#error "Cannot get FlexNVM memory partition info" +#endif /* Fill out partitioned EEPROM size */ dataIFRReadOut.EEPROMDataSetSize &= 0x0FU; @@ -2593,6 +3296,7 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui uint32_t swapIndicatorAddress; status_t returnCode; +#if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD returnCode = FLASH_ReadResource(config, kFLASH_ResourceRangePflashSwapIfrStart, flashSwapIfrFieldData.flashSwapIfrData, sizeof(flashSwapIfrFieldData.flashSwapIfrData), kFLASH_ResourceOptionFlashIfr); @@ -2601,6 +3305,30 @@ static status_t flash_validate_swap_indicator_address(flash_config_t *config, ui { return returnCode; } +#else + { + /* From RM, the actual info are stored in FCCOB6,7 */ + uint32_t returnValue[2]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapAddr, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapIndicatorAddress = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapEnable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapEnableWord = (uint16_t)returnValue[0]; + returnCode = FLASH_ReadOnce(config, kFLASH_RecordIndexSwapDisable, returnValue, 4); + if (returnCode != kStatus_FLASH_Success) + { + return returnCode; + } + flashSwapIfrFieldData.flashSwapIfrField.swapDisableWord = (uint16_t)returnValue[0]; + } +#endif /* The high bits value of Swap Indicator Address is stored in Program Flash Swap IFR Field, * the low severval bit value of Swap Indicator Address is always 1'b0 */ @@ -2628,3 +3356,77 @@ static inline status_t flasn_check_flexram_function_option_range(flash_flexram_f return kStatus_FLASH_Success; } #endif /* FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD */ + +/*! @brief Gets the flash protection information (region size, region count).*/ +static status_t flash_get_protection_info(flash_config_t *config, flash_protection_config_t *info) +{ + uint32_t pflashTotalSize; + + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_protection_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent protection register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER) + pflashTotalSize = FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE + + FSL_FEATURE_FLASH_PFLASH_1_BLOCK_COUNT * FSL_FEATURE_FLASH_PFLASH_1_BLOCK_SIZE; + info->regionBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + pflashTotalSize = config->PFlashTotalSize; + info->regionBase = config->PFlashBlockBase; +#endif + +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_PROTECTION_REGISTER + if (config->FlashMemoryIndex == (uint8_t)kFLASH_MemoryIndexSecondaryFlash) + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_1_PROTECTION_REGION_COUNT; + } + else +#endif + { + info->regionCount = FSL_FEATURE_FLASH_PFLASH_PROTECTION_REGION_COUNT; + } + + /* 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 (pflashTotalSize > info->regionCount * 1024) + { + info->regionSize = (pflashTotalSize) / info->regionCount; + } + else + { + info->regionSize = 1024; + } + + return kStatus_FLASH_Success; +} + +#if defined(FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL) && FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL +/*! @brief Gets the flash Execute-Only access information (Segment size, Segment count).*/ +static status_t flash_get_access_info(flash_config_t *config, flash_access_config_t *info) +{ + if (config == NULL) + { + return kStatus_FLASH_InvalidArgument; + } + + /* Clean up info Structure*/ + memset(info, 0, sizeof(flash_access_config_t)); + +/* Note: KW40 has a secondary flash, but it doesn't have independent access register*/ +#if FLASH_SSD_IS_SECONDARY_FLASH_ENABLED && (!FLASH_SSD_SECONDARY_FLASH_HAS_ITS_OWN_ACCESS_REGISTER) + info->SegmentBase = FSL_FEATURE_FLASH_PFLASH_START_ADDRESS; +#else + info->SegmentBase = config->PFlashBlockBase; +#endif + info->SegmentSize = config->PFlashAccessSegmentSize; + info->SegmentCount = config->PFlashAccessSegmentCount; + + return kStatus_FLASH_Success; +} +#endif /* FSL_FEATURE_FLASH_HAS_ACCESS_CONTROL */ diff --git a/drivers/fsl_flash.h b/drivers/fsl_flash.h index 8941ad7..e143cb3 100644 --- a/drivers/fsl_flash.h +++ b/drivers/fsl_flash.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2016, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -53,21 +53,21 @@ * @name Flash version * @{ */ -/*! @brief Construct the version number for drivers. */ +/*! @brief Constructs the version number for drivers. */ #if !defined(MAKE_VERSION) #define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix)) #endif -/*! @brief FLASH driver version for SDK*/ -#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */ +/*! @brief Flash driver version for SDK*/ +#define FSL_FLASH_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*!< Version 2.3.1. */ -/*! @brief FLASH driver version for ROM*/ +/*! @brief Flash driver version for ROM*/ enum _flash_driver_version_constants { kFLASH_DriverVersionName = 'F', /*!< Flash driver version name.*/ kFLASH_DriverVersionMajor = 2, /*!< Major flash driver version.*/ - kFLASH_DriverVersionMinor = 1, /*!< Minor flash driver version.*/ - kFLASH_DriverVersionBugfix = 0 /*!< Bugfix for flash driver version.*/ + kFLASH_DriverVersionMinor = 3, /*!< Minor flash driver version.*/ + kFLASH_DriverVersionBugfix = 1 /*!< Bugfix for flash driver version.*/ }; /*@}*/ @@ -75,29 +75,41 @@ enum _flash_driver_version_constants * @name Flash configuration * @{ */ -/*! @brief Whether to support FlexNVM in flash driver */ +/*! @brief Indicates whether to support FlexNVM in the Flash driver */ #if !defined(FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT) -#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enable FlexNVM support by default. */ +#define FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT 1 /*!< Enables the FlexNVM support by default. */ #endif -/*! @brief Whether the FlexNVM is enabled in flash driver */ +/*! @brief Indicates whether the FlexNVM is enabled in the Flash driver */ #define FLASH_SSD_IS_FLEXNVM_ENABLED (FLASH_SSD_CONFIG_ENABLE_FLEXNVM_SUPPORT && FSL_FEATURE_FLASH_HAS_FLEX_NVM) +/*! @brief Indicates whether to support Secondary flash in the Flash driver */ +#if !defined(FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#define FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT 1 /*!< Enables the secondary flash support by default. */ +#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 FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (FLASH_SSD_CONFIG_ENABLE_SECONDARY_FLASH_SUPPORT) +#else +#define FLASH_SSD_IS_SECONDARY_FLASH_ENABLED (0) +#endif + /*! @brief Flash driver location. */ #if !defined(FLASH_DRIVER_IS_FLASH_RESIDENT) #if (!defined(BL_TARGET_ROM) && !defined(BL_TARGET_RAM)) -#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 1 /*!< Used for the flash resident application. */ #else -#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for non-flash resident application. */ +#define FLASH_DRIVER_IS_FLASH_RESIDENT 0 /*!< Used for the non-flash resident application. */ #endif #endif /*! @brief Flash Driver Export option */ #if !defined(FLASH_DRIVER_IS_EXPORTED) #if (defined(BL_TARGET_ROM) || defined(BL_TARGET_FLASH)) -#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for ROM bootloader. */ +#define FLASH_DRIVER_IS_EXPORTED 1 /*!< Used for the ROM bootloader. */ #else -#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for SDK application. */ +#define FLASH_DRIVER_IS_EXPORTED 0 /*!< Used for the MCUXpresso SDK application. */ #endif #endif /*@}*/ @@ -118,7 +130,7 @@ enum _flash_driver_version_constants #define kStatusGroupFlashDriver 1 #endif -/*! @brief Construct a status code value from a group and code number. */ +/*! @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 @@ -132,33 +144,39 @@ enum _flash_status kStatus_FLASH_InvalidArgument = MAKE_STATUS(kStatusGroupGeneric, 4), /*!< Invalid argument*/ kStatus_FLASH_SizeError = MAKE_STATUS(kStatusGroupFlashDriver, 0), /*!< Error size*/ kStatus_FLASH_AlignmentError = - MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with specified baseline*/ + MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with the specified baseline*/ kStatus_FLASH_AddressError = MAKE_STATUS(kStatusGroupFlashDriver, 2), /*!< Address is out of range */ kStatus_FLASH_AccessError = - MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bounds addresses */ + MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bound addresses */ kStatus_FLASH_ProtectionViolation = MAKE_STATUS( kStatusGroupFlashDriver, 4), /*!< The program/erase operation is requested to execute on protected areas */ kStatus_FLASH_CommandFailure = MAKE_STATUS(kStatusGroupFlashDriver, 5), /*!< Run-time error during command execution. */ - kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ - kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< API erase key is invalid.*/ - kStatus_FLASH_RegionExecuteOnly = MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< Current region is execute only.*/ + kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/ + kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7), /*!< API erase key is invalid.*/ + kStatus_FLASH_RegionExecuteOnly = + MAKE_STATUS(kStatusGroupFlashDriver, 8), /*!< The current region is execute-only.*/ kStatus_FLASH_ExecuteInRamFunctionNotReady = MAKE_STATUS(kStatusGroupFlashDriver, 9), /*!< Execute-in-RAM function is not available.*/ kStatus_FLASH_PartitionStatusUpdateFailure = MAKE_STATUS(kStatusGroupFlashDriver, 10), /*!< Failed to update partition status.*/ kStatus_FLASH_SetFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set flexram as eeprom.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 11), /*!< Failed to set FlexRAM as EEPROM.*/ kStatus_FLASH_RecoverFlexramAsRamError = - MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover flexram as RAM.*/ - kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set flexram as RAM.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 12), /*!< Failed to recover FlexRAM as RAM.*/ + kStatus_FLASH_SetFlexramAsRamError = MAKE_STATUS(kStatusGroupFlashDriver, 13), /*!< Failed to set FlexRAM as RAM.*/ kStatus_FLASH_RecoverFlexramAsEepromError = - MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover flexram as eeprom.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 14), /*!< Failed to recover FlexRAM as EEPROM.*/ kStatus_FLASH_CommandNotSupported = MAKE_STATUS(kStatusGroupFlashDriver, 15), /*!< Flash API is not supported.*/ kStatus_FLASH_SwapSystemNotInUninitialized = - MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in uninitialzed state.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 16), /*!< Swap system is not in an uninitialzed state.*/ kStatus_FLASH_SwapIndicatorAddressError = - MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< Swap indicator address is invalid.*/ + MAKE_STATUS(kStatusGroupFlashDriver, 17), /*!< The swap indicator address is invalid.*/ + kStatus_FLASH_ReadOnlyProperty = MAKE_STATUS(kStatusGroupFlashDriver, 18), /*!< The flash property is read-only.*/ + kStatus_FLASH_InvalidPropertyValue = + MAKE_STATUS(kStatusGroupFlashDriver, 19), /*!< The flash property value is out of range.*/ + kStatus_FLASH_InvalidSpeculationOption = + MAKE_STATUS(kStatusGroupFlashDriver, 20), /*!< The option of flash prefetch speculation is invalid.*/ }; /*@}*/ @@ -166,13 +184,13 @@ enum _flash_status * @name Flash API key * @{ */ -/*! @brief Construct the four char code for flash driver API key. */ +/*! @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) (((d) << 24) | ((c) << 16) | ((b) << 8) | ((a))) #endif /*! - * @brief Enumeration for flash driver API keys. + * @brief Enumeration for Flash 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 @@ -220,9 +238,9 @@ typedef enum _flash_protection_state */ typedef enum _flash_execute_only_access_state { - kFLASH_AccessStateUnLimited, /*!< Flash region is unLimited.*/ + kFLASH_AccessStateUnLimited, /*!< Flash region is unlimited.*/ kFLASH_AccessStateExecuteOnly, /*!< Flash region is execute only.*/ - kFLASH_AccessStateMixed /*!< Flash is mixed with unLimited and execute only region.*/ + kFLASH_AccessStateMixed /*!< Flash is mixed with unlimited and execute only region.*/ } flash_execute_only_access_state_t; /*! @@ -242,10 +260,12 @@ typedef enum _flash_property_tag kFLASH_PropertyFlexRamTotalSize = 0x09U, /*!< FlexRam total size property.*/ kFLASH_PropertyDflashSectorSize = 0x10U, /*!< Dflash sector size property.*/ kFLASH_PropertyDflashTotalSize = 0x11U, /*!< Dflash total size property.*/ - kFLASH_PropertyDflashBlockSize = 0x12U, /*!< Dflash block count property.*/ - kFLASH_PropertyDflashBlockCount = 0x13U, /*!< Dflash block base address property.*/ - kFLASH_PropertyDflashBlockBaseAddr = 0x14U, /*!< Eeprom total size property.*/ - kFLASH_PropertyEepromTotalSize = 0x15U + kFLASH_PropertyDflashBlockSize = 0x12U, /*!< Dflash block size property.*/ + kFLASH_PropertyDflashBlockCount = 0x13U, /*!< Dflash block count property.*/ + kFLASH_PropertyDflashBlockBaseAddr = 0x14U, /*!< Dflash block base address property.*/ + kFLASH_PropertyEepromTotalSize = 0x15U, /*!< EEPROM total size property.*/ + kFLASH_PropertyFlashMemoryIndex = 0x20U, /*!< Flash memory index property.*/ + kFLASH_PropertyFlashCacheControllerIndex = 0x21U /*!< Flash cache controller index property.*/ } flash_property_tag_t; /*! @@ -253,7 +273,7 @@ typedef enum _flash_property_tag */ enum _flash_execute_in_ram_function_constants { - kFLASH_ExecuteInRamFunctionMaxSizeInWords = 16U, /*!< Max size of execute-in-RAM function.*/ + kFLASH_ExecuteInRamFunctionMaxSizeInWords = 16U, /*!< The maximum size of execute-in-RAM function.*/ kFLASH_ExecuteInRamFunctionTotalNum = 2U /*!< Total number of execute-in-RAM functions.*/ }; @@ -262,9 +282,9 @@ enum _flash_execute_in_ram_function_constants */ typedef struct _flash_execute_in_ram_function_config { - uint32_t activeFunctionCount; /*!< Number of available execute-in-RAM functions.*/ - uint32_t *flashRunCommand; /*!< execute-in-RAM function: flash_run_command.*/ - uint32_t *flashCacheClearCommand; /*!< execute-in-RAM function: flash_cache_clear_command.*/ + uint32_t activeFunctionCount; /*!< Number of available execute-in-RAM functions.*/ + uint32_t *flashRunCommand; /*!< Execute-in-RAM function: flash_run_command.*/ + uint32_t *flashCommonBitOperation; /*!< Execute-in-RAM function: flash_common_bit_operation.*/ } flash_execute_in_ram_function_config_t; /*! @@ -274,7 +294,7 @@ typedef enum _flash_read_resource_option { kFLASH_ResourceOptionFlashIfr = 0x00U, /*!< Select code for Program flash 0 IFR, Program flash swap 0 IFR, Data flash 0 IFR */ - kFLASH_ResourceOptionVersionId = 0x01U /*!< Select code for Version ID*/ + kFLASH_ResourceOptionVersionId = 0x01U /*!< Select code for the version ID*/ } flash_read_resource_option_t; /*! @@ -312,12 +332,22 @@ enum _flash_read_resource_range }; /*! - * @brief Enumeration for the two possilbe options of set flexram function command. + * @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.*/ +}; + +/*! + * @brief Enumeration for the two possilbe options of set FlexRAM function command. */ typedef enum _flash_flexram_function_option { - kFLASH_FlexramFunctionOptionAvailableAsRam = 0xFFU, /*!< Option used to make FlexRAM available as RAM */ - kFLASH_FlexramFunctionOptionAvailableForEeprom = 0x00U /*!< Option used to make FlexRAM available for EEPROM */ + kFLASH_FlexramFunctionOptionAvailableAsRam = 0xFFU, /*!< An option used to make FlexRAM available as RAM */ + kFLASH_FlexramFunctionOptionAvailableForEeprom = 0x00U /*!< An option used to make FlexRAM available for EEPROM */ } flash_flexram_function_option_t; /*! @@ -333,37 +363,37 @@ enum _flash_acceleration_ram_property */ typedef enum _flash_swap_function_option { - kFLASH_SwapFunctionOptionEnable = 0x00U, /*!< Option used to enable Swap function */ - kFLASH_SwapFunctionOptionDisable = 0x01U /*!< Option used to Disable Swap function */ + kFLASH_SwapFunctionOptionEnable = 0x00U, /*!< An option used to enable the Swap function */ + kFLASH_SwapFunctionOptionDisable = 0x01U /*!< An option used to disable the Swap function */ } flash_swap_function_option_t; /*! - * @brief Enumeration for the possible options of Swap Control commands + * @brief Enumeration for the possible options of Swap control commands */ typedef enum _flash_swap_control_option { - kFLASH_SwapControlOptionIntializeSystem = 0x01U, /*!< Option used to Intialize Swap System */ - kFLASH_SwapControlOptionSetInUpdateState = 0x02U, /*!< Option used to Set Swap in Update State */ - kFLASH_SwapControlOptionSetInCompleteState = 0x04U, /*!< Option used to Set Swap in Complete State */ - kFLASH_SwapControlOptionReportStatus = 0x08U, /*!< Option used to Report Swap Status */ - kFLASH_SwapControlOptionDisableSystem = 0x10U /*!< Option used to Disable Swap Status */ + kFLASH_SwapControlOptionIntializeSystem = 0x01U, /*!< An option used to initialize the Swap system */ + kFLASH_SwapControlOptionSetInUpdateState = 0x02U, /*!< An option used to set the Swap in an update state */ + kFLASH_SwapControlOptionSetInCompleteState = 0x04U, /*!< An option used to set the Swap in a complete state */ + kFLASH_SwapControlOptionReportStatus = 0x08U, /*!< An option used to report the Swap status */ + kFLASH_SwapControlOptionDisableSystem = 0x10U /*!< An option used to disable the Swap status */ } flash_swap_control_option_t; /*! - * @brief Enumeration for the possible flash swap status. + * @brief Enumeration for the possible flash Swap status. */ typedef enum _flash_swap_state { - kFLASH_SwapStateUninitialized = 0x00U, /*!< Flash swap system is in uninitialized state.*/ - kFLASH_SwapStateReady = 0x01U, /*!< Flash swap system is in ready state.*/ - kFLASH_SwapStateUpdate = 0x02U, /*!< Flash swap system is in update state.*/ - kFLASH_SwapStateUpdateErased = 0x03U, /*!< Flash swap system is in updateErased state.*/ - kFLASH_SwapStateComplete = 0x04U, /*!< Flash swap system is in complete state.*/ - kFLASH_SwapStateDisabled = 0x05U /*!< Flash swap system is in disabled state.*/ + kFLASH_SwapStateUninitialized = 0x00U, /*!< Flash Swap system is in an uninitialized state.*/ + kFLASH_SwapStateReady = 0x01U, /*!< Flash Swap system is in a ready state.*/ + kFLASH_SwapStateUpdate = 0x02U, /*!< Flash Swap system is in an update state.*/ + kFLASH_SwapStateUpdateErased = 0x03U, /*!< Flash Swap system is in an updateErased state.*/ + kFLASH_SwapStateComplete = 0x04U, /*!< Flash Swap system is in a complete state.*/ + kFLASH_SwapStateDisabled = 0x05U /*!< Flash Swap system is in a disabled state.*/ } flash_swap_state_t; /*! - * @breif Enumeration for the possible flash swap block status + * @breif Enumeration for the possible flash Swap block status */ typedef enum _flash_swap_block_status { @@ -374,41 +404,72 @@ typedef enum _flash_swap_block_status } flash_swap_block_status_t; /*! - * @brief Flash Swap information. + * @brief Flash Swap information */ typedef struct _flash_swap_state_config { - flash_swap_state_t flashSwapState; /*!< Current swap system status.*/ - flash_swap_block_status_t currentSwapBlockStatus; /*!< Current swap block status.*/ - flash_swap_block_status_t nextSwapBlockStatus; /*!< Next swap block status.*/ + flash_swap_state_t flashSwapState; /*!<The current Swap system status.*/ + flash_swap_block_status_t currentSwapBlockStatus; /*!< The current Swap block status.*/ + flash_swap_block_status_t nextSwapBlockStatus; /*!< The next Swap block status.*/ } flash_swap_state_config_t; /*! - * @brief Flash Swap IFR fields. + * @brief Flash Swap IFR fields */ typedef struct _flash_swap_ifr_field_config { - uint16_t swapIndicatorAddress; /*!< Swap indicator address field.*/ - uint16_t swapEnableWord; /*!< Swap enable word field.*/ - uint8_t reserved0[4]; /*!< Reserved field.*/ + uint16_t swapIndicatorAddress; /*!< A Swap indicator address field.*/ + uint16_t swapEnableWord; /*!< A Swap enable word field.*/ + uint8_t reserved0[4]; /*!< A reserved field.*/ #if (FSL_FEATURE_FLASH_IS_FTFE == 1) - uint8_t reserved1[2]; /*!< Reserved field.*/ - uint16_t swapDisableWord; /*!< Swap disable word field.*/ - uint8_t reserved2[4]; /*!< Reserved field.*/ + uint8_t reserved1[2]; /*!< A reserved field.*/ + uint16_t swapDisableWord; /*!< A Swap disable word field.*/ + uint8_t reserved2[4]; /*!< A reserved field.*/ #endif } flash_swap_ifr_field_config_t; /*! - * @brief Flash Swap IFR field data. + * @brief Flash Swap IFR field data */ typedef union _flash_swap_ifr_field_data { - uint32_t flashSwapIfrData[2]; /*!< Flash Swap IFR field data .*/ - flash_swap_ifr_field_config_t flashSwapIfrField; /*!< Flash Swap IFR field struct.*/ + uint32_t flashSwapIfrData[2]; /*!< A flash Swap IFR field data .*/ + flash_swap_ifr_field_config_t flashSwapIfrField; /*!< A flash Swap IFR field structure.*/ } flash_swap_ifr_field_data_t; /*! - * @brief Enumeration for FlexRAM load during reset option. + * @brief PFlash protection status - low 32bit + */ +typedef union _pflash_protection_status_low +{ + uint32_t protl32b; /*!< PROT[31:0] .*/ + struct + { + uint8_t protsl; /*!< PROTS[7:0] .*/ + uint8_t protsh; /*!< PROTS[15:8] .*/ + uint8_t reserved[2]; + } prots16b; +} pflash_protection_status_low_t; + +/*! + * @brief PFlash protection status - full + */ +typedef struct _pflash_protection_status +{ + pflash_protection_status_low_t valueLow32b; /*!< PROT[31:0] or PROTS[15:0].*/ +#if ((FSL_FEATURE_FLASH_IS_FTFA == 1) && (defined(FTFA_FPROTH0_PROT_MASK))) || \ + ((FSL_FEATURE_FLASH_IS_FTFE == 1) && (defined(FTFE_FPROTH0_PROT_MASK))) || \ + ((FSL_FEATURE_FLASH_IS_FTFL == 1) && (defined(FTFL_FPROTH0_PROT_MASK))) + // uint32_t protHigh; /*!< PROT[63:32].*/ + struct + { + uint32_t proth32b; + } valueHigh32b; +#endif +} pflash_protection_status_t; + +/*! + * @brief Enumeration for the FlexRAM load during reset option. */ typedef enum _flash_partition_flexram_load_option { @@ -417,22 +478,87 @@ typedef enum _flash_partition_flexram_load_option kFLASH_PartitionFlexramLoadOptionNotLoaded = 0x01U /*!< FlexRAM is not loaded during reset sequence.*/ } flash_partition_flexram_load_option_t; -/*! @brief callback type used for pflash block*/ +/*! + * @brief Enumeration for the flash memory index. + */ +typedef enum _flash_memory_index +{ + kFLASH_MemoryIndexPrimaryFlash = 0x00U, /*!< Current flash memory is primary flash.*/ + kFLASH_MemoryIndexSecondaryFlash = 0x01U, /*!< Current flash memory is secondary flash.*/ +} flash_memory_index_t; + +/*! + * @brief Enumeration for the flash cache controller index. + */ +typedef enum _flash_cache_controller_index +{ + kFLASH_CacheControllerIndexForCore0 = 0x00U, /*!< Current flash cache controller is for core 0.*/ + kFLASH_CacheControllerIndexForCore1 = 0x01U, /*!< Current flash cache controller is for core 1.*/ +} flash_cache_controller_index_t; + +/*! @brief A callback type used for the Pflash block*/ typedef void (*flash_callback_t)(void); /*! - * @brief Active flash information for current operation. + * @brief Enumeration for the two possible options of flash prefetch speculation. + */ +typedef enum _flash_prefetch_speculation_option +{ + kFLASH_prefetchSpeculationOptionEnable = 0x00U, + kFLASH_prefetchSpeculationOptionDisable = 0x01U +} flash_prefetch_speculation_option_t; + +/*! + * @brief Flash prefetch speculation status. + */ +typedef struct _flash_prefetch_speculation_status +{ + flash_prefetch_speculation_option_t instructionOption; /*!< Instruction speculation.*/ + flash_prefetch_speculation_option_t dataOption; /*!< Data speculation.*/ +} flash_prefetch_speculation_status_t; + +/*! + * @brief Flash cache clear process code. + */ +typedef enum _flash_cache_clear_process +{ + kFLASH_CacheClearProcessPre = 0x00U, /*!< Pre flash cache clear process.*/ + kFLASH_CacheClearProcessPost = 0x01U, /*!< Post flash cache clear process.*/ +} flash_cache_clear_process_t; + +/*! + * @brief Active flash protection information for the current operation. + */ +typedef struct _flash_protection_config +{ + uint32_t regionBase; /*!< Base address of flash protection region.*/ + uint32_t regionSize; /*!< size of flash protection region.*/ + uint32_t regionCount; /*!< flash protection region count.*/ +} flash_protection_config_t; + +/*! + * @brief Active flash Execute-Only access information for the current operation. + */ +typedef struct _flash_access_config +{ + uint32_t SegmentBase; /*!< Base address of flash Execute-Only segment.*/ + uint32_t SegmentSize; /*!< size of flash Execute-Only segment.*/ + uint32_t SegmentCount; /*!< flash Execute-Only segment count.*/ +} flash_access_config_t; + +/*! + * @brief Active flash information for the current operation. */ typedef struct _flash_operation_config { - uint32_t convertedAddress; /*!< Converted address for current flash type.*/ - uint32_t activeSectorSize; /*!< Sector size of current flash type.*/ - uint32_t activeBlockSize; /*!< Block size of current flash type.*/ - uint32_t blockWriteUnitSize; /*!< write unit size.*/ - uint32_t sectorCmdAddressAligment; /*!< Erase sector command address alignment.*/ - uint32_t sectionCmdAddressAligment; /*!< Program/Verify section command address alignment.*/ - uint32_t resourceCmdAddressAligment; /*!< Read resource command address alignment.*/ - uint32_t checkCmdAddressAligment; /*!< Program check command address alignment.*/ + uint32_t convertedAddress; /*!< A converted address for the current flash type.*/ + uint32_t activeSectorSize; /*!< A sector size of the current flash type.*/ + uint32_t activeBlockSize; /*!< A block size of the current flash type.*/ + uint32_t blockWriteUnitSize; /*!< The write unit size.*/ + uint32_t sectorCmdAddressAligment; /*!< An erase sector command address alignment.*/ + uint32_t sectionCmdAddressAligment; /*!< A program/verify section command address alignment.*/ + uint32_t resourceCmdAddressAligment; /*!< A read resource command address alignment.*/ + uint32_t checkCmdAddressAligment; /*!< A program check command address alignment.*/ } flash_operation_config_t; /*! @brief Flash driver state information. @@ -442,25 +568,29 @@ typedef struct _flash_operation_config */ typedef struct _flash_config { - uint32_t PFlashBlockBase; /*!< Base address of the first PFlash block */ - uint32_t PFlashTotalSize; /*!< Size of all combined PFlash block. */ - uint32_t PFlashBlockCount; /*!< Number of PFlash blocks. */ - uint32_t PFlashSectorSize; /*!< Size in bytes of a sector of PFlash. */ - flash_callback_t PFlashCallback; /*!< Callback function for flash API. */ - uint32_t PFlashAccessSegmentSize; /*!< Size in bytes of a access segment of PFlash. */ - uint32_t PFlashAccessSegmentCount; /*!< Number of PFlash access segments. */ - uint32_t *flashExecuteInRamFunctionInfo; /*!< Info struct of flash execute-in-RAM function. */ - uint32_t FlexRAMBlockBase; /*!< For FlexNVM device, this is the base address of FlexRAM - For non-FlexNVM device, this is the base address of acceleration RAM memory */ - uint32_t FlexRAMTotalSize; /*!< For FlexNVM device, this is the size of FlexRAM - For non-FlexNVM device, this is the size of acceleration RAM memory */ - uint32_t DFlashBlockBase; /*!< For FlexNVM device, this is the base address of D-Flash memory (FlexNVM memory); - For non-FlexNVM device, this field is unused */ - uint32_t DFlashTotalSize; /*!< For FlexNVM device, this is total size of the FlexNVM memory; - For non-FlexNVM device, this field is unused */ - uint32_t EEpromTotalSize; /*!< For FlexNVM device, this is the size in byte of EEPROM area which was partitioned - from FlexRAM; - For non-FlexNVM device, this field is unused */ + uint32_t PFlashBlockBase; /*!< A base address of the first PFlash block */ + uint32_t PFlashTotalSize; /*!< The size of the combined PFlash block. */ + uint8_t PFlashBlockCount; /*!< A number of PFlash blocks. */ + uint8_t FlashMemoryIndex; /*!< 0 - primary flash; 1 - secondary flash*/ + uint8_t FlashCacheControllerIndex; /*!< 0 - Controller for core 0; 1 - Controller for core 1 */ + uint8_t Reserved0; /*!< Reserved field 0 */ + uint32_t PFlashSectorSize; /*!< The size in bytes of a sector of PFlash. */ + flash_callback_t PFlashCallback; /*!< The callback function for the flash API. */ + uint32_t PFlashAccessSegmentSize; /*!< A size in bytes of an access segment of PFlash. */ + uint32_t PFlashAccessSegmentCount; /*!< A number of PFlash access segments. */ + uint32_t *flashExecuteInRamFunctionInfo; /*!< An information structure of the flash execute-in-RAM function. */ + uint32_t FlexRAMBlockBase; /*!< For the FlexNVM device, this is the base address of the FlexRAM */ + /*!< For the non-FlexNVM device, this is the base address of the acceleration RAM memory */ + uint32_t FlexRAMTotalSize; /*!< For the FlexNVM device, this is the size of the FlexRAM */ + /*!< For the non-FlexNVM device, this is the size of the acceleration RAM memory */ + uint32_t + DFlashBlockBase; /*!< For the FlexNVM device, this is the base address of the D-Flash memory (FlexNVM memory) */ + /*!< For the non-FlexNVM device, this field is unused */ + uint32_t DFlashTotalSize; /*!< For the FlexNVM device, this is the total size of the FlexNVM memory; */ + /*!< For the non-FlexNVM device, this field is unused */ + uint32_t EEpromTotalSize; /*!< For the FlexNVM device, this is the size in bytes of the EEPROM area which was + partitioned from FlexRAM */ + /*!< For the non-FlexNVM device, this field is unused */ } flash_config_t; /******************************************************************************* @@ -477,37 +607,37 @@ extern "C" { */ /*! - * @brief Initializes global flash properties structure members + * @brief Initializes the global flash properties structure members. * - * This function checks and initializes Flash module for the other Flash APIs. + * This function checks and initializes the Flash module for the other Flash APIs. * - * @param config Pointer to storage for the driver runtime state. + * @param config Pointer to the storage for the driver runtime state. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. - * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update partition status. + * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update the partition status. */ status_t FLASH_Init(flash_config_t *config); /*! - * @brief Set the desired flash callback function + * @brief Sets the desired flash callback function. * - * @param config Pointer to storage for the driver runtime state. - * @param callback callback function to be stored in driver + * @param config Pointer to the storage for the driver runtime state. + * @param callback A callback function to be stored in the driver. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. */ status_t FLASH_SetCallback(flash_config_t *config, flash_callback_t callback); /*! - * @brief Prepare flash execute-in-RAM functions + * @brief Prepares flash execute-in-RAM functions. * - * @param config Pointer to storage for the driver runtime state. + * @param config Pointer to the storage for the driver runtime state. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. */ #if FLASH_DRIVER_IS_FLASH_RESIDENT status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config); @@ -523,59 +653,59 @@ status_t FLASH_PrepareExecuteInRamFunctions(flash_config_t *config); /*! * @brief Erases entire flash * - * @param config Pointer to storage for the driver runtime state. - * @param key value used to validate all flash erase APIs. + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_EraseKeyError API erase key is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. - * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update partition status + * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update the partition status. */ status_t FLASH_EraseAll(flash_config_t *config, uint32_t key); /*! - * @brief Erases flash sectors encompassed by parameters passed into function + * @brief Erases the flash 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 Pointer to storage for the driver runtime state. + * @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. + * 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 value used to validate all flash erase APIs. + * to be erased. Must be word-aligned. + * @param key The value used to validate all flash erase APIs. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. - * @retval #kStatus_FLASH_AddressError Address is out of range. - * @retval #kStatus_FLASH_EraseKeyError API erase key is invalid. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_AlignmentError The parameter is not aligned with the specified baseline. + * @retval #kStatus_FLASH_AddressError The address is out of range. + * @retval #kStatus_FLASH_EraseKeyError The API erase key is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_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 entire flash, including protected sectors. + * @brief Erases the entire flash, including protected sectors. * - * @param config Pointer to storage for the driver runtime state. - * @param key value used to validate all flash erase APIs. + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_EraseKeyError API erase key is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. - * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update partition status + * @retval #kStatus_FLASH_PartitionStatusUpdateFailure Failed to update the partition status. */ #if defined(FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD) && FSL_FEATURE_FLASH_HAS_ERASE_ALL_BLOCKS_UNSECURE_CMD status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key); @@ -584,16 +714,16 @@ status_t FLASH_EraseAllUnsecure(flash_config_t *config, uint32_t key); /*! * @brief Erases all program flash execute-only segments defined by the FXACC registers. * - * @param config Pointer to storage for the driver runtime state. - * @param key value used to validate all flash erase APIs. + * @param config Pointer to the storage for the driver runtime state. + * @param key A value used to validate all flash erase APIs. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_EraseKeyError API erase key is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key); @@ -605,101 +735,101 @@ status_t FLASH_EraseAllExecuteOnlySegments(flash_config_t *config, uint32_t key) */ /*! - * @brief Programs flash with data at locations passed in through parameters + * @brief Programs flash with data at locations passed in through parameters. * - * This function programs the flash memory with desired data for a given - * flash area as determined by the start address and length. + * 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 Pointer to storage for the driver runtime state. + * @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 Pointer to the source buffer of data that is to be programmed + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be programmed. Must be word-aligned. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with the specified baseline. * @retval #kStatus_FLASH_AddressError Address is out of range. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_Program(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes); /*! - * @brief Programs Program Once Field through parameters + * @brief Programs Program Once Field through parameters. * - * This function programs the Program Once Field with desired data for a given + * This function programs the Program Once Field with the desired data for a given * flash area as determined by the index and length. * - * @param config Pointer to storage for the driver runtime state. - * @param index The index indicating which area of Program Once Field to be programmed. - * @param src Pointer to the source buffer of data that is to be programmed + * @param config A pointer to the storage for the driver runtime state. + * @param index The index indicating which area of the Program Once Field to be programmed. + * @param src A pointer to the source buffer of data that is to be programmed * into the Program Once Field. - * @param lengthInBytes The length, given in bytes (not words or long-words) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be programmed. Must be word-aligned. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_ProgramOnce(flash_config_t *config, uint32_t index, uint32_t *src, uint32_t lengthInBytes); /*! - * @brief Programs flash with data at locations passed in through parameters via Program Section command + * @brief Programs flash with data at locations passed in through parameters via the Program Section command. * - * This function programs the flash memory with desired data for a given + * 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 Pointer to storage for the driver runtime state. + * @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 Pointer to the source buffer of data that is to be programmed + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be programmed. Must be word-aligned. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. * @retval #kStatus_FLASH_AddressError Address is out of range. - * @retval #kStatus_FLASH_SetFlexramAsRamError Failed to set flexram as RAM + * @retval #kStatus_FLASH_SetFlexramAsRamError Failed to set flexram as RAM. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. - * @retval #kStatus_FLASH_RecoverFlexramAsEepromError Failed to recover flexram as eeprom + * @retval #kStatus_FLASH_RecoverFlexramAsEepromError Failed to recover FlexRAM as EEPROM. */ #if defined(FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD) && FSL_FEATURE_FLASH_HAS_PROGRAM_SECTION_CMD status_t FLASH_ProgramSection(flash_config_t *config, uint32_t start, uint32_t *src, uint32_t lengthInBytes); #endif /*! - * @brief Programs EEPROM with data at locations passed in through parameters + * @brief Programs the EEPROM with data at locations passed in through parameters. * - * This function programs the Emulated EEPROM with desired data for a given + * 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 Pointer to storage for the driver runtime state. + * @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 Pointer to the source buffer of data that is to be programmed + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be programmed. Must be word-aligned. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AddressError Address is out of range. * @retval #kStatus_FLASH_SetFlexramAsEepromError Failed to set flexram as eeprom. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_RecoverFlexramAsRamError Failed to recover flexram as RAM + * @retval #kStatus_FLASH_RecoverFlexramAsRamError Failed to recover the FlexRAM as RAM. */ #if FLASH_SSD_IS_FLEXNVM_ENABLED status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes); @@ -713,27 +843,27 @@ status_t FLASH_EepromWrite(flash_config_t *config, uint32_t start, uint8_t *src, */ /*! - * @brief Read resource with data at locations passed in through parameters + * @brief Reads the resource with data at locations passed in through parameters. * - * This function reads the flash memory with desired location for a given + * 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 Pointer to storage for the driver runtime state. + * @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 Pointer to the destination buffer of data that is used to store + * @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) + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with the specified baseline. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ #if defined(FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD) && FSL_FEATURE_FLASH_HAS_READ_RESOURCE_CMD status_t FLASH_ReadResource( @@ -741,23 +871,23 @@ status_t FLASH_ReadResource( #endif /*! - * @brief Read Program Once Field through parameters + * @brief Reads the Program Once Field through parameters. * - * This function reads the read once feild with given index and length + * This function reads the read once feild with given index and length. * - * @param config Pointer to storage for the driver runtime state. + * @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 Pointer to the destination buffer of data that is used to store + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be programmed. Must be word-aligned. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint32_t *dst, uint32_t lengthInBytes); @@ -769,35 +899,35 @@ status_t FLASH_ReadOnce(flash_config_t *config, uint32_t index, uint32_t *dst, u */ /*! - * @brief Returns the security state via the pointer passed into the function + * @brief Returns the security state via the pointer passed into the function. * - * This function retrieves the current Flash security status, including the + * This function retrieves the current flash security status, including the * security enabling state and the backdoor key enabling state. * - * @param config Pointer to storage for the driver runtime state. - * @param state Pointer to the value returned for the current security status code: + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. */ status_t FLASH_GetSecurityState(flash_config_t *config, flash_security_state_t *state); /*! - * @brief Allows user to bypass security with a backdoor key + * @brief Allows users to bypass security with a backdoor key. * - * If the MCU is in secured state, this function will unsecure the MCU by - * comparing the provided backdoor key with ones in the Flash Configuration - * Field. + * 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 Pointer to storage for the driver runtime state. - * @param backdoorKey Pointer to the user buffer containing the backdoor key. + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey); @@ -809,75 +939,75 @@ status_t FLASH_SecurityBypass(flash_config_t *config, const uint8_t *backdoorKey */ /*! - * @brief Verifies erasure of entire flash at specified margin level + * @brief Verifies erasure of the entire flash at a specified margin level. * - * This function will check to see if the flash have been erased to the + * This function checks whether the flash is erased to the * specified read margin level. * - * @param config Pointer to storage for the driver runtime state. - * @param margin Read margin choice + * @param config A pointer to the storage for the driver runtime state. + * @param margin Read margin choice. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_VerifyEraseAll(flash_config_t *config, flash_margin_value_t margin); /*! - * @brief Verifies erasure of desired flash area at specified margin level + * @brief Verifies an erasure of the desired flash area at a specified margin level. * - * This function will check the appropriate number of flash sectors based on - * the desired start address and length to see if the flash have been erased + * 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 Pointer to storage for the driver runtime state. + * @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) + * 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 + * @param margin Read margin choice. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. * @retval #kStatus_FLASH_AddressError Address is out of range. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_VerifyErase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, flash_margin_value_t margin); /*! - * @brief Verifies programming of desired flash area at specified margin level + * @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 with expected data for a given + * 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 Pointer to storage for the driver runtime state. + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be verified. Must be word-aligned. - * @param expectedData Pointer to the expected data that is to be + * @param expectedData A pointer to the expected data that is to be * verified against. - * @param margin Read margin choice - * @param failedAddress Pointer to returned failing address. - * @param failedData Pointer to returned failing data. Some derivitives do - * not included failed data as part of the FCCOBx registers. In this + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. * @retval #kStatus_FLASH_AddressError Address is out of range. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_VerifyProgram(flash_config_t *config, uint32_t start, @@ -888,18 +1018,18 @@ status_t FLASH_VerifyProgram(flash_config_t *config, uint32_t *failedData); /*! - * @brief Verifies if the program flash executeonly segments have been erased to - * the specified read margin level + * @brief Verifies whether the program flash execute-only segments have been erased to + * the specified read margin level. * - * @param config Pointer to storage for the driver runtime state. - * @param margin Read margin choice + * @param config A pointer to the storage for the driver runtime state. + * @param margin Read margin choice. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ status_t FLASH_VerifyEraseAllExecuteOnlySegments(flash_config_t *config, flash_margin_value_t margin); @@ -911,22 +1041,22 @@ status_t FLASH_VerifyEraseAllExecuteOnlySegments(flash_config_t *config, flash_m */ /*! - * @brief Returns the protection state of desired flash area via the pointer passed into the function + * @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 + * This function retrieves the current flash protect status for a given * flash area as determined by the start address and length. * - * @param config Pointer to storage for the driver runtime state. + * @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 Pointer to the value returned for the current + * @param protection_state A pointer to the value returned for the current * protection status code for the desired flash area. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. - * @retval #kStatus_FLASH_AddressError Address is out of range. + * @retval #kStatus_FLASH_AddressError The address is out of range. */ status_t FLASH_IsProtected(flash_config_t *config, uint32_t start, @@ -934,22 +1064,22 @@ status_t FLASH_IsProtected(flash_config_t *config, flash_protection_state_t *protection_state); /*! - * @brief Returns the access state of desired flash area via the pointer passed into the function + * @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 + * This function retrieves the current flash access status for a given * flash area as determined by the start address and length. * - * @param config Pointer to storage for the driver runtime state. + * @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) + * @param lengthInBytes The length, given in bytes (not words or long-words), * to be checked. Must be word-aligned. - * @param access_state Pointer to the value returned for the current + * @param access_state A pointer to the value returned for the current * access status code for the desired flash area. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. - * @retval #kStatus_FLASH_AddressError Address is out of range. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_AlignmentError The parameter is not aligned to the specified baseline. + * @retval #kStatus_FLASH_AddressError The address is out of range. */ status_t FLASH_IsExecuteOnly(flash_config_t *config, uint32_t start, @@ -966,17 +1096,33 @@ status_t FLASH_IsExecuteOnly(flash_config_t *config, /*! * @brief Returns the desired flash property. * - * @param config Pointer to storage for the driver runtime state. + * @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 Pointer to the value returned for the desired flash property + * @param value A pointer to the value returned for the desired flash property. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_UnknownProperty unknown property tag + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_UnknownProperty An unknown property tag. */ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value); +/*! + * @brief Sets 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 to set for the desired flash property. + * + * @retval #kStatus_FLASH_Success API was executed successfully. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_UnknownProperty An unknown property tag. + * @retval #kStatus_FLASH_InvalidPropertyValue An invalid property value. + * @retval #kStatus_FLASH_ReadOnlyProperty An read-only property tag. + */ +status_t FLASH_SetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t value); + /*@}*/ /*! @@ -985,17 +1131,17 @@ status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichPro */ /*! - * @brief Set FlexRAM Function command + * @brief Sets the FlexRAM function command. * - * @param config Pointer to storage for the driver runtime state. - * @param option The option used to set work mode of FlexRAM + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ #if defined(FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD) && FSL_FEATURE_FLASH_HAS_SET_FLEXRAM_FUNCTION_CMD status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function_option_t option); @@ -1009,21 +1155,21 @@ status_t FLASH_SetFlexramFunction(flash_config_t *config, flash_flexram_function */ /*! - * @brief Configure Swap function or Check the swap state of Flash Module + * @brief Configures the Swap function or checks the the swap state of the Flash module. * - * @param config Pointer to storage for the driver runtime state. - * @param address Address used to configure the flash swap function - * @param option The possible option used to configure Flash Swap function or check the flash swap status - * @param returnInfo Pointer to the data which is used to return the information of flash swap. + * @param config A pointer to the storage for the driver runtime state. + * @param address Address used to configure the flash Swap function. + * @param option The possible option used to configure Flash Swap function or check the flash Swap status + * @param returnInfo A pointer to the data which is used to return the information of flash Swap. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. - * @retval #kStatus_FLASH_SwapIndicatorAddressError Swap indicator address is invalid + * @retval #kStatus_FLASH_SwapIndicatorAddressError Swap indicator address is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. - * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. + * @retval #kStatus_FLASH_CommandFailure Run-time error during the command execution. */ #if defined(FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD) && FSL_FEATURE_FLASH_HAS_SWAP_CONTROL_CMD status_t FLASH_SwapControl(flash_config_t *config, @@ -1033,21 +1179,21 @@ status_t FLASH_SwapControl(flash_config_t *config, #endif /*! - * @brief Swap the lower half flash with the higher half flaock + * @brief Swaps the lower half flash with the higher half flash. * - * @param config Pointer to storage for the driver runtime state. + * @param config A pointer to the storage for the driver runtime state. * @param address Address used to configure the flash swap function - * @param option The possible option used to configure Flash Swap function or check the flash swap status + * @param option The possible option used to configure the Flash Swap function or check the flash Swap status. * * @retval #kStatus_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_AlignmentError Parameter is not aligned with specified baseline. - * @retval #kStatus_FLASH_SwapIndicatorAddressError Swap indicator address is invalid + * @retval #kStatus_FLASH_SwapIndicatorAddressError Swap indicator address is invalid. * @retval #kStatus_FLASH_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses. * @retval #kStatus_FLASH_ProtectionViolation The program/erase operation is requested to execute on protected areas. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. - * @retval #kStatus_FLASH_SwapSystemNotInUninitialized Swap system is not in uninitialzed state + * @retval #kStatus_FLASH_SwapSystemNotInUninitialized Swap system is not in an uninitialzed state. */ #if defined(FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP) && FSL_FEATURE_FLASH_HAS_PFLASH_BLOCK_SWAP status_t FLASH_Swap(flash_config_t *config, uint32_t address, flash_swap_function_option_t option); @@ -1090,51 +1236,54 @@ status_t FLASH_ProgramPartition(flash_config_t *config, */ /*! - * @brief Set PFLASH Protection to the intended protection status. + * @brief Sets the PFlash Protection to the intended protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus The expected protect status user wants to set to PFlash protection register. Each bit is - * corresponding to protection of 1/32 of the total PFlash. The least significant bit is corresponding to the lowest - * address area of P-Flash. The most significant bit is corresponding to the highest address area of PFlash. There are + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. */ -status_t FLASH_PflashSetProtection(flash_config_t *config, uint32_t protectStatus); +status_t FLASH_PflashSetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus); /*! - * @brief Get PFLASH Protection Status. + * @brief Gets the PFlash protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus Protect status returned by PFlash IP. Each bit is corresponding to protection of 1/32 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. Thee are two possible cases as below: + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. */ -status_t FLASH_PflashGetProtection(flash_config_t *config, uint32_t *protectStatus); +status_t FLASH_PflashGetProtection(flash_config_t *config, pflash_protection_status_t *protectStatus); /*! - * @brief Set DFLASH Protection to the intended protection status. + * @brief Sets the DFlash protection to the intended protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus The expected protect status user wants to set to DFlash protection register. Each bit is - * corresponding to protection of 1/8 of the total DFlash. The least significant bit is corresponding to the lowest - * address area of DFlash. The most significant bit is corresponding to the highest address area of DFlash. There are + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. */ #if FLASH_SSD_IS_FLEXNVM_ENABLED @@ -1142,38 +1291,39 @@ status_t FLASH_DflashSetProtection(flash_config_t *config, uint8_t protectStatus #endif /*! - * @brief Get DFLASH Protection Status. + * @brief Gets the DFlash protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus DFlash Protect status returned by PFlash IP. Each bit is corresponding to protection of 1/8 of - * the total DFlash. The least significant bit is corresponding to the lowest address area of DFlash. The most - * significant bit is corresponding to the highest address area of DFlash and so on. There are two possible cases as + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported. */ #if FLASH_SSD_IS_FLEXNVM_ENABLED status_t FLASH_DflashGetProtection(flash_config_t *config, uint8_t *protectStatus); #endif /*! - * @brief Set EEPROM Protection to the intended protection status. + * @brief Sets the EEPROM protection to the intended protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus The expected protect status user wants to set to EEPROM protection register. Each bit is - * corresponding to protection of 1/8 of the total EEPROM. The least significant bit is corresponding to the lowest - * address area of EEPROM. The most significant bit is corresponding to the highest address area of EEPROM, and so on. + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. - * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. + * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported. * @retval #kStatus_FLASH_CommandFailure Run-time error during command execution. */ #if FLASH_SSD_IS_FLEXNVM_ENABLED @@ -1181,17 +1331,18 @@ status_t FLASH_EepromSetProtection(flash_config_t *config, uint8_t protectStatus #endif /*! - * @brief Get DFLASH Protection Status. + * @brief Gets the DFlash protection status. * - * @param config Pointer to storage for the driver runtime state. - * @param protectStatus DFlash Protect status returned by PFlash IP. Each bit is corresponding to protection of 1/8 of - * the total EEPROM. The least significant bit is corresponding to the lowest address area of EEPROM. The most - * significant bit is corresponding to the highest address area of EEPROM. There are two possible cases as below: + * @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_FLASH_Success API was executed successfully. - * @retval #kStatus_FLASH_InvalidArgument Invalid argument is provided. + * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided. * @retval #kStatus_FLASH_CommandNotSupported Flash API is not supported. */ #if FLASH_SSD_IS_FLEXNVM_ENABLED @@ -1200,6 +1351,32 @@ status_t FLASH_EepromGetProtection(flash_config_t *config, uint8_t *protectStatu /*@}*/ +/*@}*/ + +/*! +* @name Flash Speculation Utilities +* @{ +*/ + +/*! + * @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_FLASH_Success API was executed successfully. + * @retval #kStatus_FLASH_InvalidSpeculationOption An invalid speculation option argument is provided. + */ +status_t FLASH_PflashSetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus); + +/*! + * @brief Gets the PFlash prefetch speculation status. + * + * @param speculationStatus Speculation status returned by the PFlash IP. + * @retval #kStatus_FLASH_Success API was executed successfully. + */ +status_t FLASH_PflashGetPrefetchSpeculation(flash_prefetch_speculation_status_t *speculationStatus); + +/*@}*/ + #if defined(__cplusplus) } #endif diff --git a/drivers/fsl_flexcan.c b/drivers/fsl_flexcan.c index 395def5..f58f3f5 100644 --- a/drivers/fsl_flexcan.c +++ b/drivers/fsl_flexcan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -165,8 +165,6 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ /******************************************************************************* * Variables ******************************************************************************/ -/* Array of FlexCAN handle. */ -static flexcan_handle_t *s_flexcanHandle[FSL_FEATURE_SOC_FLEXCAN_COUNT]; /* Array of FlexCAN peripheral base address. */ static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS; @@ -179,8 +177,17 @@ static const IRQn_Type s_flexcanErrorIRQ[] = CAN_Error_IRQS; static const IRQn_Type s_flexcanBusOffIRQ[] = CAN_Bus_Off_IRQS; static const IRQn_Type s_flexcanMbIRQ[] = CAN_ORed_Message_buffer_IRQS; +/* Array of FlexCAN handle. */ +static flexcan_handle_t *s_flexcanHandle[ARRAY_SIZE(s_flexcanBases)]; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of FlexCAN clock name. */ static const clock_ip_name_t s_flexcanClock[] = FLEXCAN_CLOCKS; +#if defined(FLEXCAN_PERIPH_CLOCKS) +/* Array of FlexCAN serial clock name. */ +static const clock_ip_name_t s_flexcanPeriphClock[] = FLEXCAN_PERIPH_CLOCKS; +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* FlexCAN ISR for transactional APIs. */ static flexcan_isr_t s_flexcanIsr; @@ -194,7 +201,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FLEXCAN_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_flexcanBases); instance++) { if (s_flexcanBases[instance] == base) { @@ -202,7 +209,7 @@ uint32_t FLEXCAN_GetInstance(CAN_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FLEXCAN_COUNT); + assert(instance < ARRAY_SIZE(s_flexcanBases)); return instance; } @@ -314,9 +321,13 @@ static bool FLEXCAN_IsMbIntEnabled(CAN_Type *base, uint8_t mbIdx) else { if (base->IMASK2 & ((uint32_t)(1 << (mbIdx - 32)))) + { return true; + } else + { return false; + } } #endif } @@ -352,7 +363,7 @@ static void FLEXCAN_Reset(CAN_Type *base) base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_WAKSRC_MASK | CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1); #else - base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1); + base->MCR |= CAN_MCR_WRNEN_MASK | CAN_MCR_MAXMB(FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base) - 1); #endif /* Reset CTRL1 and CTRL2 rigister. */ @@ -420,14 +431,25 @@ static void FLEXCAN_SetBaudRate(CAN_Type *base, uint32_t sourceClock_Hz, uint32_ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz) { uint32_t mcrTemp; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Assertion. */ assert(config); assert((config->maxMbNum > 0) && (config->maxMbNum <= FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); /* Enable FlexCAN clock. */ - CLOCK_EnableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); - + CLOCK_EnableClock(s_flexcanClock[instance]); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Enable FlexCAN serial clock. */ + CLOCK_EnableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /* Disable FlexCAN Module. */ FLEXCAN_Enable(base, false); @@ -436,6 +458,7 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc */ base->CTRL1 = (kFLEXCAN_ClkSrcOsc == config->clkSrc) ? base->CTRL1 & ~CAN_CTRL1_CLKSRC_MASK : base->CTRL1 | CAN_CTRL1_CLKSRC_MASK; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /* Enable FlexCAN Module for configuartion. */ FLEXCAN_Enable(base, true); @@ -472,14 +495,24 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc void FLEXCAN_Deinit(CAN_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + uint32_t instance; +#endif /* Reset all Register Contents. */ FLEXCAN_Reset(base); /* Disable FlexCAN module. */ FLEXCAN_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + instance = FLEXCAN_GetInstance(base); +#if defined(FLEXCAN_PERIPH_CLOCKS) + /* Disable FlexCAN serial clock. */ + CLOCK_DisableClock(s_flexcanPeriphClock[instance]); +#endif /* FLEXCAN_PERIPH_CLOCKS */ /* Disable FlexCAN clock. */ - CLOCK_DisableClock(s_flexcanClock[FLEXCAN_GetInstance(base)]); + CLOCK_DisableClock(s_flexcanClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) @@ -488,7 +521,9 @@ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config) assert(config); /* Initialize FlexCAN Module config struct with default value. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE config->clkSrc = kFLEXCAN_ClkSrcOsc; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ config->baudRate = 125000U; config->maxMbNum = 16; config->enableLoopBack = false; @@ -1293,13 +1328,13 @@ void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle) (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #else - while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || - (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | - kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); + while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) || + (0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | + kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag)))); #endif } -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 0) +#if defined(CAN0) void CAN0_DriverIRQHandler(void) { assert(s_flexcanHandle[0]); @@ -1308,7 +1343,7 @@ void CAN0_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 1) +#if defined(CAN1) void CAN1_DriverIRQHandler(void) { assert(s_flexcanHandle[1]); @@ -1317,7 +1352,7 @@ void CAN1_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 2) +#if defined(CAN2) void CAN2_DriverIRQHandler(void) { assert(s_flexcanHandle[2]); @@ -1326,7 +1361,7 @@ void CAN2_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 3) +#if defined(CAN3) void CAN3_DriverIRQHandler(void) { assert(s_flexcanHandle[3]); @@ -1335,7 +1370,7 @@ void CAN3_DriverIRQHandler(void) } #endif -#if (FSL_FEATURE_SOC_FLEXCAN_COUNT > 4) +#if defined(CAN4) void CAN4_DriverIRQHandler(void) { assert(s_flexcanHandle[4]); @@ -1343,3 +1378,30 @@ void CAN4_DriverIRQHandler(void) s_flexcanIsr(CAN4, s_flexcanHandle[4]); } #endif + +#if defined(DMA_CAN0) +void DMA_FLEXCAN0_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN0)]); +} +#endif + +#if defined(DMA_CAN1) +void DMA_FLEXCAN1_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); + + s_flexcanIsr(DMA_CAN0, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN1)]); +} +#endif + +#if defined(DMA_CAN2) +void DMA_FLEXCAN2_DriverIRQHandler(void) +{ + assert(s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); + + s_flexcanIsr(DMA_CAN2, s_flexcanHandle[FLEXCAN_GetInstance(DMA_CAN2)]); +} +#endif diff --git a/drivers/fsl_flexcan.h b/drivers/fsl_flexcan.h index 203212e..118badf 100644 --- a/drivers/fsl_flexcan.h +++ b/drivers/fsl_flexcan.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,15 +37,14 @@ * @{ */ - /****************************************************************************** * Definitions *****************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief FlexCAN driver version 2.1.0. */ -#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief FlexCAN driver version 2.2.0. */ +#define FLEXCAN_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*@}*/ /*! @brief FlexCAN Frame ID helper macro. */ @@ -69,27 +68,24 @@ (FLEXCAN_ID_STD(id) << 1)) /*!< Standard Rx FIFO Mask helper macro Type A helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_HIGH(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ - (FLEXCAN_ID_STD(id) << 16)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 19)) /*!< Standard Rx FIFO Mask helper macro Type B upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_B_LOW(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ - FLEXCAN_ID_STD(id)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ + (((uint32_t)(id) & 0x7FF) << 3)) /*!< Standard Rx FIFO Mask helper macro Type B lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ -#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. \ - */ + (((uint32_t)(id) & 0x7F8) << 21) /*!< Standard Rx FIFO Mask helper macro Type C upper part helper macro. */ +#define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_HIGH(id) \ + (((uint32_t)(id) & 0x7F8) << 13) /*!< Standard Rx FIFO Mask helper macro Type C mid-upper part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_MID_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) << 5) /*!< Standard Rx FIFO Mask helper macro Type C mid-lower part helper macro. */ #define FLEXCAN_RX_FIFO_STD_MASK_TYPE_C_LOW(id) \ - ((FLEXCAN_ID_STD(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ + (((uint32_t)(id) & 0x7F8) >> 3) /*!< Standard Rx FIFO Mask helper macro Type C lower part helper macro. */ #define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ (FLEXCAN_ID_EXT(id) << 1)) /*!< Extend Rx FIFO Mask helper macro Type A helper macro. */ #define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_HIGH(id, rtr, ide) \ - ( \ - ((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ - ((FLEXCAN_ID_EXT(id) & 0x1FFF8000) \ - << 1)) /*!< Extend Rx FIFO Mask helper macro Type B upper part helper macro. */ + (((uint32_t)((uint32_t)(rtr) << 31) | (uint32_t)((uint32_t)(ide) << 30)) | \ + ((FLEXCAN_ID_EXT(id) & 0x1FFF8000) << 1)) /*!< Extend Rx FIFO Mask helper macro Type B upper part helper macro. */ #define FLEXCAN_RX_FIFO_EXT_MASK_TYPE_B_LOW(id, rtr, ide) \ (((uint32_t)((uint32_t)(rtr) << 15) | (uint32_t)((uint32_t)(ide) << 14)) | \ ((FLEXCAN_ID_EXT(id) & 0x1FFF8000) >> \ @@ -159,7 +155,7 @@ enum _flexcan_status kStatus_FLEXCAN_RxFifoBusy = MAKE_STATUS(kStatusGroup_FLEXCAN, 6), /*!< Rx Message FIFO is Busy. */ kStatus_FLEXCAN_RxFifoIdle = MAKE_STATUS(kStatusGroup_FLEXCAN, 7), /*!< Rx Message FIFO is Idle. */ kStatus_FLEXCAN_RxFifoOverflow = MAKE_STATUS(kStatusGroup_FLEXCAN, 8), /*!< Rx Message FIFO is overflowed. */ - kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 0), /*!< Rx Message FIFO is almost overflowed. */ + kStatus_FLEXCAN_RxFifoWarning = MAKE_STATUS(kStatusGroup_FLEXCAN, 9), /*!< Rx Message FIFO is almost overflowed. */ kStatus_FLEXCAN_ErrorStatus = MAKE_STATUS(kStatusGroup_FLEXCAN, 10), /*!< FlexCAN Module Error and Status. */ kStatus_FLEXCAN_UnHandled = MAKE_STATUS(kStatusGroup_FLEXCAN, 11), /*!< UnHadled Interrupt asserted. */ }; @@ -178,12 +174,14 @@ typedef enum _flexcan_frame_type kFLEXCAN_FrameTypeRemote = 0x1U, /*!< Remote frame type attribute. */ } flexcan_frame_type_t; +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE /*! @brief FlexCAN clock source. */ typedef enum _flexcan_clock_source { kFLEXCAN_ClkSrcOsc = 0x0U, /*!< FlexCAN Protocol Engine clock from Oscillator. */ kFLEXCAN_ClkSrcPeri = 0x1U, /*!< FlexCAN Protocol Engine clock from Peripheral Clock. */ } flexcan_clock_source_t; +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ /*! @brief FlexCAN Rx Fifo Filter type. */ typedef enum _flexcan_rx_fifo_filter_type @@ -197,7 +195,7 @@ typedef enum _flexcan_rx_fifo_filter_type } flexcan_rx_fifo_filter_type_t; /*! - * @brief FlexCAN Rx FIFO priority + * @brief FlexCAN Rx FIFO priority. * * The matching process starts from the Rx MB(or Rx FIFO) with higher priority. * If no MB(or Rx FIFO filter) is satisfied, the matching process goes on with @@ -295,13 +293,13 @@ typedef struct _flexcan_frame uint32_t length : 4; /*!< CAN frame payload length in bytes(Range: 0~8). */ uint32_t type : 1; /*!< CAN Frame Type(DATA or REMOTE). */ uint32_t format : 1; /*!< CAN Frame Identifier(STD or EXT format). */ - uint32_t reserve1 : 1; /*!< Reserved for placeholder. */ + uint32_t : 1; /*!< Reserved. */ uint32_t idhit : 9; /*!< CAN Rx FIFO filter hit id(This value is only used in Rx FIFO receive mode). */ }; struct { uint32_t id : 29; /*!< CAN Frame Identifier, should be set using FLEXCAN_ID_EXT() or FLEXCAN_ID_STD() macro. */ - uint32_t reserve2 : 3; /*!< Reserved for place holder. */ + uint32_t : 3; /*!< Reserved. */ }; union { @@ -328,7 +326,9 @@ typedef struct _flexcan_frame typedef struct _flexcan_config { uint32_t baudRate; /*!< FlexCAN baud rate in bps. */ +#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE flexcan_clock_source_t clkSrc; /*!< Clock source for FlexCAN Protocol Engine. */ +#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */ uint8_t maxMbNum; /*!< The maximum number of Message Buffers used by user. */ bool enableLoopBack; /*!< Enable or Disable Loop Back Self Test Mode. */ bool enableSelfWakeup; /*!< Enable or Disable Self Wakeup Mode. */ @@ -365,10 +365,10 @@ typedef struct _flexcan_rx_mb_config flexcan_frame_type_t type; /*!< CAN Frame Type(Data or Remote). */ } flexcan_rx_mb_config_t; -/*! @brief FlexCAN Rx FIFO configure structure. */ +/*! @brief FlexCAN Rx FIFO configuration structure. */ typedef struct _flexcan_rx_fifo_config { - uint32_t *idFilterTable; /*!< Pointer to FlexCAN Rx FIFO identifier filter table. */ + uint32_t *idFilterTable; /*!< Pointer to the FlexCAN Rx FIFO identifier filter table. */ uint8_t idFilterNum; /*!< The quantity of filter elements. */ flexcan_rx_fifo_filter_type_t idFilterType; /*!< The FlexCAN Rx FIFO Filter type. */ flexcan_rx_fifo_priority_t priority; /*!< The FlexCAN Rx FIFO receive priority. */ @@ -433,10 +433,10 @@ extern "C" { * * This function initializes the FlexCAN module with user-defined settings. * This example shows how to set up the flexcan_config_t parameters and how - * to call the FLEXCAN_Init function by passing in these parameters: + * to call the FLEXCAN_Init function by passing in these parameters. * @code * flexcan_config_t flexcanConfig; - * flexcanConfig.clkSrc = KFLEXCAN_ClkSrcOsc; + * flexcanConfig.clkSrc = kFLEXCAN_ClkSrcOsc; * flexcanConfig.baudRate = 125000U; * flexcanConfig.maxMbNum = 16; * flexcanConfig.enableLoopBack = false; @@ -447,7 +447,7 @@ extern "C" { * @endcode * * @param base FlexCAN peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param sourceClock_Hz FlexCAN Protocol Engine clock source frequency in Hz. */ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourceClock_Hz); @@ -455,18 +455,18 @@ void FLEXCAN_Init(CAN_Type *base, const flexcan_config_t *config, uint32_t sourc /*! * @brief De-initializes a FlexCAN instance. * - * This function disable the FlexCAN module clock and set all register value - * to reset value. + * This function disables the FlexCAN module clock and sets all register values + * to the reset value. * * @param base FlexCAN peripheral base address. */ void FLEXCAN_Deinit(CAN_Type *base); /*! - * @brief Get the default configuration structure. + * @brief Gets the default configuration structure. * - * This function initializes the FlexCAN configure structure to default value. The default - * value are: + * This function initializes the FlexCAN configuration structure to default values. The default + * values are as follows. * flexcanConfig->clkSrc = KFLEXCAN_ClkSrcOsc; * flexcanConfig->baudRate = 125000U; * flexcanConfig->maxMbNum = 16; @@ -475,7 +475,7 @@ void FLEXCAN_Deinit(CAN_Type *base); * flexcanConfig->enableIndividMask = false; * flexcanConfig->enableDoze = false; * - * @param config Pointer to FlexCAN configuration structure. + * @param config Pointer to the FlexCAN configuration structure. */ void FLEXCAN_GetDefaultConfig(flexcan_config_t *config); @@ -505,7 +505,7 @@ void FLEXCAN_SetTimingConfig(CAN_Type *base, const flexcan_timing_config_t *conf /*! * @brief Sets the FlexCAN receive message buffer global mask. * - * This function sets the global mask for FlexCAN message buffer in a matching process. + * This function sets the global mask for the FlexCAN message buffer in a matching process. * The configuration is only effective when the Rx individual mask is disabled in the FLEXCAN_Init(). * * @param base FlexCAN peripheral base address. @@ -526,12 +526,12 @@ void FLEXCAN_SetRxFifoGlobalMask(CAN_Type *base, uint32_t mask); /*! * @brief Sets the FlexCAN receive individual mask. * - * This function sets the individual mask for FlexCAN matching process. - * The configuration is only effective when the Rx individual mask is enabled in FLEXCAN_Init(). - * If Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. - * If Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to - * the Rx Filter with same index. What calls for special attention is that only the first 32 - * individual masks can be used as Rx FIFO filter mask. + * This function sets the individual mask for the FlexCAN matching process. + * The configuration is only effective when the Rx individual mask is enabled in the FLEXCAN_Init(). + * If the Rx FIFO is disabled, the individual mask is applied to the corresponding Message Buffer. + * If the Rx FIFO is enabled, the individual mask for Rx FIFO occupied Message Buffer is applied to + * the Rx Filter with the same index. Note that only the first 32 + * individual masks can be used as the Rx FIFO filter mask. * * @param base FlexCAN peripheral base address. * @param maskIdx The Index of individual Mask. @@ -547,7 +547,7 @@ void FLEXCAN_SetRxIndividualMask(CAN_Type *base, uint8_t maskIdx, uint32_t mask) * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param enable Enable/Disable Tx Message Buffer. + * @param enable Enable/disable Tx Message Buffer. * - true: Enable Tx Message Buffer. * - false: Disable Tx Message Buffer. */ @@ -561,8 +561,8 @@ void FLEXCAN_SetTxMbConfig(CAN_Type *base, uint8_t mbIdx, bool enable); * * @param base FlexCAN peripheral base address. * @param mbIdx The Message Buffer index. - * @param config Pointer to FlexCAN Message Buffer configuration structure. - * @param enable Enable/Disable Rx Message Buffer. + * @param config Pointer to the FlexCAN Message Buffer configuration structure. + * @param enable Enable/disable Rx Message Buffer. * - true: Enable Rx Message Buffer. * - false: Disable Rx Message Buffer. */ @@ -574,8 +574,8 @@ void FLEXCAN_SetRxMbConfig(CAN_Type *base, uint8_t mbIdx, const flexcan_rx_mb_co * This function configures the Rx FIFO with given Rx FIFO configuration. * * @param base FlexCAN peripheral base address. - * @param config Pointer to FlexCAN Rx FIFO configuration structure. - * @param enable Enable/Disable Rx FIFO. + * @param config Pointer to the FlexCAN Rx FIFO configuration structure. + * @param enable Enable/disable Rx FIFO. * - true: Enable Rx FIFO. * - false: Disable Rx FIFO. */ @@ -678,7 +678,7 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFF); + base->IFLAG1 = (uint32_t)(mask & 0xFFFFFFFFU); base->IFLAG2 = (uint32_t)(mask >> 32); #else base->IFLAG1 = mask; @@ -693,9 +693,9 @@ static inline void FLEXCAN_ClearMbStatusFlags(CAN_Type *base, uint32_t mask) */ /*! - * @brief Enables FlexCAN interrupts according to provided mask. + * @brief Enables FlexCAN interrupts according to the provided mask. * - * This function enables the FlexCAN interrupts according to provided mask. The mask + * This function enables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -714,9 +714,9 @@ static inline void FLEXCAN_EnableInterrupts(CAN_Type *base, uint32_t mask) } /*! - * @brief Disables FlexCAN interrupts according to provided mask. + * @brief Disables FlexCAN interrupts according to the provided mask. * - * This function disables the FlexCAN interrupts according to provided mask. The mask + * This function disables the FlexCAN interrupts according to the provided mask. The mask * is a logical OR of enumeration members, see @ref _flexcan_interrupt_enable. * * @param base FlexCAN peripheral base address. @@ -737,7 +737,7 @@ static inline void FLEXCAN_DisableInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Enables FlexCAN Message Buffer interrupts. * - * This function enables the interrupts of given Message Buffers + * This function enables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -749,7 +749,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFF); + base->IMASK1 |= (uint32_t)(mask & 0xFFFFFFFFU); base->IMASK2 |= (uint32_t)(mask >> 32); #else base->IMASK1 |= mask; @@ -759,7 +759,7 @@ static inline void FLEXCAN_EnableMbInterrupts(CAN_Type *base, uint32_t mask) /*! * @brief Disables FlexCAN Message Buffer interrupts. * - * This function disables the interrupts of given Message Buffers + * This function disables the interrupts of given Message Buffers. * * @param base FlexCAN peripheral base address. * @param mask The ORed FlexCAN Message Buffer mask. @@ -771,7 +771,7 @@ static inline void FLEXCAN_DisableMbInterrupts(CAN_Type *base, uint32_t mask) #endif { #if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0) - base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFF)); + base->IMASK1 &= ~((uint32_t)(mask & 0xFFFFFFFFU)); base->IMASK2 &= ~((uint32_t)(mask >> 32)); #else base->IMASK1 &= ~mask; @@ -848,7 +848,7 @@ static inline void FLEXCAN_Enable(CAN_Type *base, bool enable) } /*! - * @brief Writes a FlexCAN Message to Transmit Message Buffer. + * @brief Writes a FlexCAN Message to the Transmit Message Buffer. * * This function writes a CAN Message to the specified Transmit Message Buffer * and changes the Message Buffer state to start CAN Message transmit. After @@ -940,7 +940,7 @@ status_t FLEXCAN_TransferReceiveFifoBlocking(CAN_Type *base, flexcan_frame_t *rx /*! * @brief Initializes the FlexCAN handle. * - * This function initializes the FlexCAN handle which can be used for other FlexCAN + * This function initializes the FlexCAN handle, which can be used for other FlexCAN * transactional APIs. Usually, for a specified FlexCAN instance, * call this API once to get the initialized handle. * diff --git a/drivers/fsl_ftm.c b/drivers/fsl_ftm.c index 85dc219..9cca44b 100644 --- a/drivers/fsl_ftm.c +++ b/drivers/fsl_ftm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -72,8 +72,10 @@ static void FTM_SetReloadPoints(FTM_Type *base, uint32_t reloadPoints); /*! @brief Pointers to FTM bases for each instance. */ static FTM_Type *const s_ftmBases[] = FTM_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to FTM clocks for each instance. */ static const clock_ip_name_t s_ftmClocks[] = FTM_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -228,8 +230,10 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) return kStatus_Fail; } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the FTM clock*/ CLOCK_EnableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the fault mode, enable FTM mode and disable write protection */ base->MODE = FTM_MODE_FAULTM(config->faultMode) | FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK; @@ -266,7 +270,13 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) #endif /* FSL_FEATURE_FTM_HAS_RELOAD_INITIALIZATION_TRIGGER */ /* FTM deadtime insertion control */ - base->DEADTIME = (FTM_DEADTIME_DTPS(config->deadTimePrescale) | FTM_DEADTIME_DTVAL(config->deadTimeValue)); + base->DEADTIME = (0u | +#if defined(FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) && (FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE) + /* Has extended deadtime value register) */ + FTM_DEADTIME_DTVALEX(config->deadTimeValue >> 6) | +#endif /* FSL_FEATURE_FTM_HAS_EXTENDED_DEADTIME_VALUE */ + FTM_DEADTIME_DTPS(config->deadTimePrescale) | + FTM_DEADTIME_DTVAL(config->deadTimeValue)); /* FTM fault filter value */ reg = base->FLTCTRL; @@ -282,8 +292,10 @@ void FTM_Deinit(FTM_Type *base) /* Set clock source to none to disable counter */ base->SC &= ~(FTM_SC_CLKS_MASK); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the FTM clock */ CLOCK_DisableClock(s_ftmClocks[FTM_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void FTM_GetDefaultConfig(ftm_config_t *config) diff --git a/drivers/fsl_ftm.h b/drivers/fsl_ftm.h index 7643635..8db81a6 100644 --- a/drivers/fsl_ftm.h +++ b/drivers/fsl_ftm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -44,8 +44,8 @@ /*! @name Driver version */ /*@{*/ -#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ -/*@}*/ +#define FSL_FTM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */ + /*@}*/ /*! * @brief List of FTM channels @@ -161,7 +161,7 @@ typedef struct _ftm_phase_param typedef struct _ftm_fault_param { bool enableFaultInput; /*!< True: Fault input is enabled; false: Fault input is disabled */ - bool faultLevel; /*!< True: Fault polarity is active low i.e., '0' indicates a fault; + bool faultLevel; /*!< True: Fault polarity is active low; in other words, '0' indicates a fault; False: Fault polarity is active high */ bool useFaultFilter; /*!< True: Use the filtered fault signal; False: Use the direct path from fault input */ @@ -310,6 +310,17 @@ typedef enum _ftm_status_flags } ftm_status_flags_t; /*! + * @brief List of FTM Quad Decoder flags. + */ +enum _ftm_quad_decoder_flags +{ + kFTM_QuadDecoderCountingIncreaseFlag = FTM_QDCTRL_QUADIR_MASK, /*!< Counting direction is increasing (FTM counter + increment), or the direction is decreasing. */ + kFTM_QuadDecoderCountingOverflowOnTopFlag = FTM_QDCTRL_TOFDIR_MASK, /*!< Indicates if the TOF bit was set on the top + or the bottom of counting. */ +}; + +/*! * @brief FTM configuration structure * * This structure holds the configuration settings for the FTM peripheral. To initialize this @@ -332,7 +343,9 @@ typedef struct _ftm_config ftm_fault_mode_t faultMode; /*!< FTM fault control mode */ uint8_t faultFilterValue; /*!< Fault input filter value */ ftm_deadtime_prescale_t deadTimePrescale; /*!< The dead time prescalar value */ - uint8_t deadTimeValue; /*!< The dead time value */ + uint32_t deadTimeValue; /*!< The dead time value + deadTimeValue's available range is 0-1023 when register has DTVALEX, + otherwise its available range is 0-63. */ uint32_t extTriggers; /*!< External triggers to enable. Multiple trigger sources can be enabled by providing an OR'ed list of options available in enumeration ::ftm_external_trigger_t. */ @@ -358,7 +371,7 @@ extern "C" { /*! * @brief Ungates the FTM clock and configures the peripheral for basic operation. * - * @note This API should be called at the beginning of the application using the FTM driver. + * @note This API should be called at the beginning of the application which is using the FTM driver. * * @param base FTM peripheral base address * @param config Pointer to the user configuration structure. @@ -508,19 +521,6 @@ void FTM_SetupDualEdgeCapture(FTM_Type *base, /*! @}*/ /*! - * @brief Configures the parameters and activates the quadrature decoder mode. - * - * @param base FTM peripheral base address - * @param phaseAParams Phase A configuration parameters - * @param phaseBParams Phase B configuration parameters - * @param quadMode Selects encoding mode used in quadrature decoder mode - */ -void FTM_SetupQuadDecode(FTM_Type *base, - const ftm_phase_params_t *phaseAParams, - const ftm_phase_params_t *phaseBParams, - ftm_quad_decode_mode_t quadMode); - -/*! * @brief Sets up the working of the FTM fault protection. * * FTM can have up to 4 fault inputs. This function sets up fault parameters, fault level, and a filter. @@ -593,6 +593,48 @@ void FTM_ClearStatusFlags(FTM_Type *base, uint32_t mask); /*! @}*/ /*! + * @name Read and write the timer period + * @{ + */ + +/*! + * @brief Sets the timer period in units of ticks. + * + * Timers counts from 0 until it equals the count value set here. The count value is written to + * the MOD register. + * + * @note + * 1. This API allows the user to use the FTM module as a timer. Do not mix usage + * of this API with FTM's PWM setup API's. + * 2. Call the utility macros provided in the fsl_common.h to convert usec or msec to ticks. + * + * @param base FTM peripheral base address + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. + */ +static inline void FTM_SetTimerPeriod(FTM_Type *base, uint32_t ticks) +{ + base->MOD = ticks; +} + +/*! + * @brief Reads the current timer counting value. + * + * This function returns the real-time timer counting value in a range from 0 to a + * timer period. + * + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. + * + * @param base FTM peripheral base address + * + * @return The current counter value in ticks + */ +static inline uint32_t FTM_GetCurrentTimerCount(FTM_Type *base) +{ + return (uint32_t)((base->CNT & FTM_CNT_COUNT_MASK) >> FTM_CNT_COUNT_SHIFT); +} + +/*! @}*/ +/*! * @name Timer Start and Stop * @{ */ @@ -710,7 +752,7 @@ static inline void FTM_SetOutputMask(FTM_Type *base, ftm_chnl_t chnlNumber, bool #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) /*! - * @brief Allows user to enable an output on an FTM channel. + * @brief Allows users to enable an output on an FTM channel. * * To enable the PWM channel output call this function with val=true. For input mode, * call this function with val=false. @@ -816,6 +858,76 @@ static inline void FTM_SetInvertEnable(FTM_Type *base, ftm_chnl_t chnlPairNumber /*! @}*/ /*! + * @name Quad Decoder + * @{ + */ + +/*! + * @brief Configures the parameters and activates the quadrature decoder mode. + * + * @param base FTM peripheral base address + * @param phaseAParams Phase A configuration parameters + * @param phaseBParams Phase B configuration parameters + * @param quadMode Selects encoding mode used in quadrature decoder mode + */ +void FTM_SetupQuadDecode(FTM_Type *base, + const ftm_phase_params_t *phaseAParams, + const ftm_phase_params_t *phaseBParams, + ftm_quad_decode_mode_t quadMode); + +/*! + * @brief Gets the FTM Quad Decoder flags. + * + * @param base FTM peripheral base address. + * @return Flag mask of FTM Quad Decoder, see #_ftm_quad_decoder_flags. + */ +static inline uint32_t FTM_GetQuadDecoderFlags(FTM_Type *base) +{ + return base->QDCTRL & (FTM_QDCTRL_QUADIR_MASK | FTM_QDCTRL_TOFDIR_MASK); +} + +/*! + * @brief Sets the modulo values for Quad Decoder. + * + * The modulo values configure the minimum and maximum values that the Quad decoder counter can reach. After the counter goes + * over, the counter value goes to the other side and decrease/increase again. + * + * @param base FTM peripheral base address. + * @param startValue The low limit value for Quad Decoder counter. + * @param overValue The high limit value for Quad Decoder counter. + */ +static inline void FTM_SetQuadDecoderModuloValue(FTM_Type *base, uint32_t startValue, uint32_t overValue) +{ + base->CNTIN = startValue; + base->MOD = overValue; +} + +/*! + * @brief Gets the current Quad Decoder counter value. + * + * @param base FTM peripheral base address. + * @return Current quad Decoder counter value. + */ +static inline uint32_t FTM_GetQuadDecoderCounterValue(FTM_Type *base) +{ + return base->CNT; +} + +/*! + * @brief Clears the current Quad Decoder counter value. + * + * The counter is set as the initial value. + * + * @param base FTM peripheral base address. + */ +static inline void FTM_ClearQuadDecoderCounterValue(FTM_Type *base) +{ + base->CNT = base->CNTIN; +} + +/*! @}*/ + +/*! * @brief Enables or disables the FTM software trigger for PWM synchronization. * * @param base FTM peripheral base address diff --git a/drivers/fsl_gpio.c b/drivers/fsl_gpio.c index 8fc068f..b40ee3a 100644 --- a/drivers/fsl_gpio.c +++ b/drivers/fsl_gpio.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -57,7 +57,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_GPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++) { if (s_gpioBases[instance] == base) { @@ -65,7 +65,7 @@ static uint32_t GPIO_GetInstance(GPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_GPIO_COUNT); + assert(instance < ARRAY_SIZE(s_gpioBases)); return instance; } @@ -103,6 +103,14 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) | + ((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT); +} +#endif + #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT /******************************************************************************* @@ -130,7 +138,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_FGPIO_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++) { if (s_fgpioBases[instance] == base) { @@ -138,7 +146,7 @@ static uint32_t FGPIO_GetInstance(FGPIO_Type *base) } } - assert(instance < FSL_FEATURE_SOC_FGPIO_COUNT); + assert(instance < ARRAY_SIZE(s_fgpioBases)); return instance; } @@ -176,4 +184,12 @@ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask) portBase->ISFR = mask; } +#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute) +{ + base->GACR = (attribute << FGPIO_GACR_ACB0_SHIFT) | (attribute << FGPIO_GACR_ACB1_SHIFT) | + (attribute << FGPIO_GACR_ACB2_SHIFT) | (attribute << FGPIO_GACR_ACB3_SHIFT); +} +#endif + #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/drivers/fsl_gpio.h b/drivers/fsl_gpio.h index d62545f..410e2b8 100644 --- a/drivers/fsl_gpio.h +++ b/drivers/fsl_gpio.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -38,37 +38,60 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief GPIO driver version 2.1.0. */ -#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) +/*! @brief GPIO driver version 2.1.1. */ +#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) /*@}*/ -/*! @brief GPIO direction definition*/ +/*! @brief GPIO direction definition */ typedef enum _gpio_pin_direction { kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/ kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/ } gpio_pin_direction_t; +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! @brief GPIO checker attribute */ +typedef enum _gpio_checker_attribute +{ + kGPIO_UsernonsecureRWUsersecureRWPrivilegedsecureRW = + 0x00U, /*!< User nonsecure:Read+Write; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRWPrivilegedsecureRW = + 0x01U, /*!< User nonsecure:Read; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRWPrivilegedsecureRW = + 0x02U, /*!< User nonsecure:None; User Secure:Read+Write; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureRUsersecureRPrivilegedsecureRW = + 0x03U, /*!< User nonsecure:Read; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureRPrivilegedsecureRW = + 0x04U, /*!< User nonsecure:None; User Secure:Read; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureRW = + 0x05U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read+Write */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureR = + 0x06U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read */ + kGPIO_UsernonsecureNUsersecureNPrivilegedsecureN = + 0x07U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:None */ + kGPIO_IgnoreAttributeCheck = 0x10U, /*!< Ignores the attribute check */ +} gpio_checker_attribute_t; +#endif + /*! * @brief The GPIO pin configuration structure. * - * Every pin can only be configured as either output pin or input pin at a time. - * If configured as a input pin, then leave the outputConfig unused - * Note : In some use cases, the corresponding port property should be configured in advance - * with the PORT_SetPinConfig() + * Each pin can only be configured as either an output pin or an input pin at a time. + * If configured as an input pin, leave the outputConfig unused. + * Note that in some use cases, the corresponding port property should be configured in advance + * with the PORT_SetPinConfig(). */ typedef struct _gpio_pin_config { gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */ - /* Output configurations, please ignore if configured as a input one */ - uint8_t outputLogic; /*!< Set default output logic, no use in input */ + /* Output configurations; ignore if configured as an input pin */ + uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */ } gpio_pin_config_t; /*! @} */ @@ -92,10 +115,10 @@ extern "C" { /*! * @brief Initializes a GPIO pin used by the board. * - * To initialize the GPIO, define a pin configuration, either input or output, in the user file. + * To initialize the GPIO, define a pin configuration, as either input or output, in the user file. * Then, call the GPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration. * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -111,7 +134,7 @@ extern "C" { * } * @endcode * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param pin GPIO port pin number * @param config GPIO pin configuration pointer */ @@ -125,7 +148,7 @@ void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param pin GPIO pin number * @param output GPIO pin output logic level. * - 0: corresponding pin output low-logic level. @@ -135,18 +158,18 @@ static inline void GPIO_WritePinOutput(GPIO_Type *base, uint32_t pin, uint8_t ou { if (output == 0U) { - base->PCOR = 1 << pin; + base->PCOR = 1U << pin; } else { - base->PSOR = 1 << pin; + base->PSOR = 1U << pin; } } /*! * @brief Sets the output level of the multiple GPIO pins to the logic 1. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param mask GPIO pin number macro */ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) @@ -157,7 +180,7 @@ static inline void GPIO_SetPinsOutput(GPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple GPIO pins to the logic 0. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param mask GPIO pin number macro */ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) @@ -166,9 +189,9 @@ static inline void GPIO_ClearPinsOutput(GPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple GPIO pins. + * @brief Reverses the current output logic of the multiple GPIO pins. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param mask GPIO pin number macro */ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) @@ -181,9 +204,9 @@ static inline void GPIO_TogglePinsOutput(GPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole GPIO port. + * @brief Reads the current input value of the GPIO port. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param pin GPIO pin number * @retval GPIO port input value * - 0: corresponding pin input low-logic level. @@ -199,7 +222,7 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads whole GPIO port interrupt status flag. + * @brief Reads the GPIO port interrupt status flag. * * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. @@ -207,20 +230,34 @@ static inline uint32_t GPIO_ReadPinInput(GPIO_Type *base, uint32_t pin) * If configured for a level sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current GPIO port interrupt status flag, for example, 0x00010001 means the + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @retval The current GPIO port interrupt status flag, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t GPIO_GetPinsInterruptFlags(GPIO_Type *base); /*! - * @brief Clears multiple GPIO pin interrupt status flag. + * @brief Clears multiple GPIO pin interrupt status flags. * - * @param base GPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) * @param mask GPIO pin number macro */ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The GPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.) + * @param mask GPIO pin number macro + */ +void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ /*! @} */ @@ -230,10 +267,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); */ /* - * Introduce the FGPIO feature. + * Introduces the FGPIO feature. * - * The FGPIO features are only support on some of Kinetis chips. The FGPIO registers are aliased to the IOPORT - * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and will therefore + * The FGPIO features are only support on some Kinetis MCUs. The FGPIO registers are aliased to the IOPORT + * interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and * complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO. */ @@ -245,10 +282,10 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); /*! * @brief Initializes a FGPIO pin used by the board. * - * To initialize the FGPIO driver, define a pin configuration, either input or output, in the user file. + * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file. * Then, call the FGPIO_PinInit() function. * - * This is an example to define an input pin or output pin configuration: + * This is an example to define an input pin or an output pin configuration: * @code * // Define a digital input pin configuration, * gpio_pin_config_t config = @@ -264,7 +301,7 @@ void GPIO_ClearPinsInterruptFlags(GPIO_Type *base, uint32_t mask); * } * @endcode * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param pin FGPIO port pin number * @param config FGPIO pin configuration pointer */ @@ -278,7 +315,7 @@ void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *conf /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param pin FGPIO pin number * @param output FGPIOpin output logic level. * - 0: corresponding pin output low-logic level. @@ -299,7 +336,7 @@ static inline void FGPIO_WritePinOutput(FGPIO_Type *base, uint32_t pin, uint8_t /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 1. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param mask FGPIO pin number macro */ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) @@ -310,7 +347,7 @@ static inline void FGPIO_SetPinsOutput(FGPIO_Type *base, uint32_t mask) /*! * @brief Sets the output level of the multiple FGPIO pins to the logic 0. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param mask FGPIO pin number macro */ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) @@ -319,9 +356,9 @@ static inline void FGPIO_ClearPinsOutput(FGPIO_Type *base, uint32_t mask) } /*! - * @brief Reverses current output logic of the multiple FGPIO pins. + * @brief Reverses the current output logic of the multiple FGPIO pins. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param mask FGPIO pin number macro */ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) @@ -334,9 +371,9 @@ static inline void FGPIO_TogglePinsOutput(FGPIO_Type *base, uint32_t mask) /*@{*/ /*! - * @brief Reads the current input value of the whole FGPIO port. + * @brief Reads the current input value of the FGPIO port. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param pin FGPIO pin number * @retval FGPIO port input value * - 0: corresponding pin input low-logic level. @@ -352,16 +389,16 @@ static inline uint32_t FGPIO_ReadPinInput(FGPIO_Type *base, uint32_t pin) /*@{*/ /*! - * @brief Reads the whole FGPIO port interrupt status flag. + * @brief Reads the FGPIO port interrupt status flag. * - * If a pin is configured to generate the DMA request, the corresponding flag + * If a pin is configured to generate the DMA request, the corresponding flag * is cleared automatically at the completion of the requested DMA transfer. * Otherwise, the flag remains set until a logic one is written to that flag. - * If configured for a level sensitive interrupt that remains asserted, the flag + * If configured for a level-sensitive interrupt that remains asserted, the flag * is set again immediately. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) - * @retval Current FGPIO port interrupt status flags, for example, 0x00010001 means the + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the * pin 0 and 17 have the interrupt. */ uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base); @@ -369,11 +406,25 @@ uint32_t FGPIO_GetPinsInterruptFlags(FGPIO_Type *base); /*! * @brief Clears the multiple FGPIO pin interrupt status flag. * - * @param base FGPIO peripheral base pointer(GPIOA, GPIOB, GPIOC, and so on.) + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) * @param mask FGPIO pin number macro */ void FGPIO_ClearPinsInterruptFlags(FGPIO_Type *base, uint32_t mask); +#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER +/*! + * @brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit + * words. Each 32-bit data port includes a GACR register, which defines the byte-level + * attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data + * bytes in the GACR follow a standard little endian + * data convention. + * + * @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.) + * @param mask FGPIO pin number macro + */ +void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute); +#endif + /*@}*/ #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */ diff --git a/drivers/fsl_i2c.c b/drivers/fsl_i2c.c index b51fc07..6c9770a 100644 --- a/drivers/fsl_i2c.c +++ b/drivers/fsl_i2c.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -76,6 +76,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle); uint32_t I2C_GetInstance(I2C_Type *base); /*! +* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the +* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop +* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided, +* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT +* value, then the related SDA hold time, SCL start and SCL stop hold time is used. +* +* @param base I2C peripheral base address. +* @param sourceClock_Hz I2C functional clock frequency in Hertz. +* @param sclStopHoldTime_ns SCL stop hold time in ns. +*/ +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz); + +/*! * @brief Set up master transfer, send slave address and decide the initial * transfer state. * @@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS; /*! @brief Pointers to i2c IRQ number for each instance. */ static const IRQn_Type s_i2cIrqs[] = I2C_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to i2c clocks for each instance. */ static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /*! @brief Pointer to master IRQ handler for each instance. */ static i2c_isr_t s_i2cMasterIsr; @@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++) { if (s_i2cBases[instance] == base) { @@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base) } } - assert(instance < FSL_FEATURE_SOC_I2C_COUNT); + assert(instance < ARRAY_SIZE(s_i2cBases)); return instance; } +static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz) +{ + uint32_t multiplier; + uint32_t computedSclHoldTime; + uint32_t absError; + uint32_t bestError = UINT32_MAX; + uint32_t bestMult = 0u; + uint32_t bestIcr = 0u; + uint8_t mult; + uint8_t i; + + /* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register, + * and ranges from 0-2. It selects the multiplier factor for the divider. */ + /* SDA hold time = bus period (s) * mul * SDA hold value. */ + /* SCL start hold time = bus period (s) * mul * SCL start hold value. */ + /* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */ + + for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) + { + multiplier = 1u << mult; + + /* Scan table to find best match. */ + for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i) + { + /* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */ + computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz; + absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) : + (computedSclHoldTime - sclStopHoldTime_ns); + + if (absError < bestError) + { + bestMult = mult; + bestIcr = i; + bestError = absError; + + /* If the error is 0, then we can stop searching because we won't find a better match. */ + if (absError == 0) + { + break; + } + } + } + } + + /* Set frequency register based on best settings. */ + base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr); +} + static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer) { status_t result = kStatus_Success; i2c_direction_t direction = xfer->direction; - uint16_t timeout = UINT16_MAX; /* Initialize the handle transfer information. */ handle->transfer = *xfer; @@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t /* Initial transfer state. */ if (handle->transfer.subaddressSize > 0) { - handle->state = kSendCommandState; if (xfer->direction == kI2C_Read) { direction = kI2C_Write; } } - else - { - handle->state = kCheckAddressState; - } - /* Wait until the data register is ready for transmit. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } + handle->state = kCheckAddressState; /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han result = kStatus_Success; } - if (result) - { - return result; - } - /* Handle Check address state to check the slave address is Acked in slave probe application. */ if (handle->state == kCheckAddressState) { if (statusFlags & kI2C_ReceiveNakFlag) { - return kStatus_I2C_Nak; + result = kStatus_I2C_Addr_Nak; } else { - if (handle->transfer.direction == kI2C_Write) + if (handle->transfer.subaddressSize > 0) { - /* Next state, send data. */ - handle->state = kSendDataState; + handle->state = kSendCommandState; } else { - /* Next state, receive data begin. */ - handle->state = kReceiveDataBeginState; + if (handle->transfer.direction == kI2C_Write) + { + /* Next state, send data. */ + handle->state = kSendDataState; + } + else + { + /* Next state, receive data begin. */ + handle->state = kReceiveDataBeginState; + } } } } + if (result) + { + return result; + } + /* Run state machine. */ switch (handle->state) { @@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han { result = I2C_MasterStop(base); } + else + { + base->C1 |= I2C_C1_TX_MASK; + } } /* Send NAK at the last receive byte. */ @@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle) { s_i2cSlaveIsr(base, handle); } + __DSB(); } void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz) @@ -415,14 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Temporary register for filter read. */ uint8_t fltReg; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - uint8_t c2Reg; -#endif #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE uint8_t s2Reg; #endif +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable I2C clock. */ CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Disable I2C prior to configuring it. */ base->C1 &= ~(I2C_C1_IICEN_MASK); @@ -433,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin /* Configure baud rate. */ I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Configure high drive feature. */ - c2Reg = base->C2; - c2Reg &= ~(I2C_C2_HDRS_MASK); - c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive); - base->C2 = c2Reg; -#endif - /* Read out the FLT register. */ fltReg = base->FLT; @@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) @@ -483,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig) /* Default baud rate at 100kbps. */ masterConfig->baudRate_Bps = 100000U; -/* Default pin high drive is disabled. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - masterConfig->enableHighDrive = false; -#endif - /* Default stop hold enable is disabled. */ #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF masterConfig->enableStopHold = false; @@ -654,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_ base->F = savedMult & (~I2C_F_MULT_MASK); /* We are already in a transfer, so send a repeated start. */ - base->C1 |= I2C_C1_RSTA_MASK; + base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK; /* Restore the multiplier factor. */ base->F = savedMult; @@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base) return statusFlags; } -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize) +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags) { status_t result = kStatus_Success; uint8_t statusFlags = 0; @@ -772,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t } } + if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) + { + /* Clear the IICIF flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send stop. */ + result = I2C_MasterStop(base); + } + return result; } -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags) { status_t result = kStatus_Success; volatile uint8_t dummy = 0; @@ -817,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize) /* Single byte use case. */ if (rxSize == 0) { - /* Read the final byte. */ - result = I2C_MasterStop(base); + if (!(flags & kI2C_TransferNoStopFlag)) + { + /* Issue STOP command before reading last byte. */ + result = I2C_MasterStop(base); + } + else + { + /* Change direction to Tx to avoid extra clocks. */ + base->C1 |= I2C_C1_TX_MASK; + } } if (rxSize == 1) @@ -871,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) + { + result = kStatus_I2C_Addr_Nak; + + I2C_MasterStop(base); + } + + return result; + } + /* Send subaddress. */ if (xfer->subaddressSize) { do { + /* Clear interrupt pending flag. */ + base->S = kI2C_IntPendingFlag; + + xfer->subaddressSize--; + base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear interrupt pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -897,21 +998,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) return result; } - xfer->subaddressSize--; - base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize)); - } while ((xfer->subaddressSize > 0) && (result == kStatus_Success)); if (xfer->direction == kI2C_Read) { + /* Clear pending flag. */ + base->S = kI2C_IntPendingFlag; + + /* Send repeated start and slave address. */ + result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); + + /* Return if error. */ + if (result) + { + return result; + } + /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } - /* Clear pending flag. */ - base->S = kI2C_IntPendingFlag; - /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -919,62 +1026,27 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer) { if (result == kStatus_I2C_Nak) { + result = kStatus_I2C_Addr_Nak; + I2C_MasterStop(base); } return result; } - - /* Send repeated start and slave address. */ - result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read); - - /* Return if error. */ - if (result) - { - return result; - } - } - } - - /* Wait until address + command transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); - - /* Return if error. */ - if (result) - { - if (result == kStatus_I2C_Nak) - { - I2C_MasterStop(base); } - - return result; } /* Transmit data. */ if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0)) { /* Send Data. */ - result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize); - - if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak)) - { - /* Clear the IICIF flag. */ - base->S = kI2C_IntPendingFlag; - - /* Send stop. */ - result = I2C_MasterStop(base); - } + result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } /* Receive Data. */ if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0)) { - result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize); + result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags); } return result; @@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle) { assert(handle); + volatile uint8_t dummy = 0; + + /* Add this to avoid build warning. */ + dummy++; + /* Disable interrupt. */ I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable); /* Reset the state to idle. */ handle->state = kIdleState; + + /* Send STOP signal. */ + if (handle->transfer.direction == kI2C_Read) + { + base->C1 |= I2C_C1_TXAK_MASK; + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + dummy = base->D; + } + else + { + while (!(base->S & kI2C_IntPendingFlag)) + { + } + base->S = kI2C_IntPendingFlag; + base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); + } } status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count) @@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) if (isDone || result) { /* Send stop command if transfer done or received Nak. */ - if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak)) + if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) || + (result == kStatus_I2C_Addr_Nak)) { /* Ensure stop command is a need. */ if ((base->C1 & I2C_C1_MST_MASK)) @@ -1101,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz) { assert(slaveConfig); uint8_t tmpReg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Reset the module. */ + base->A1 = 0; + base->F = 0; + base->C1 = 0; + base->S = 0xFFU; + base->C2 = 0; +#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT + base->FLT = 0x50U; +#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT + base->FLT = 0x40U; +#endif + base->RA = 0; /* Configure addressing mode. */ switch (slaveConfig->addressingMode) @@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) tmpReg &= ~I2C_C1_WUEN_MASK; base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave); - /* Configure general call & baud rate control & high drive feature. */ + /* Configure general call & baud rate control. */ tmpReg = base->C2; tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK); tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall); -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - tmpReg &= ~I2C_C2_HDRS_MASK; - tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive); -#endif base->C2 = tmpReg; /* Enable/Disable double buffering. */ @@ -1147,6 +1257,9 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig) tmpReg = base->S2 & (~I2C_S2_DFEN_MASK); base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering); #endif + + /* Set hold time. */ + I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz); } void I2C_SlaveDeinit(I2C_Type *base) @@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base) /* Disable I2C module. */ I2C_Enable(base, false); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable I2C clock. */ CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) @@ -1171,11 +1286,6 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) /* Slave address match waking up MCU from low power mode is disabled. */ slaveConfig->enableWakeUp = false; -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - /* Default pin high drive is disabled. */ - slaveConfig->enableHighDrive = false; -#endif - /* Independent slave mode baud rate at maximum frequency is disabled. */ slaveConfig->enableBaudRateCtl = false; @@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig) slaveConfig->enableDoubleBuffering = true; #endif + /* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */ + slaveConfig->sclStopHoldTime_ns = 4000; + /* Enable the I2C peripheral. */ slaveConfig->enableSlave = true; } @@ -1215,7 +1328,7 @@ status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t tx /* Read dummy to release bus. */ dummy = base->D; - result = I2C_MasterWriteBlocking(base, txBuff, txSize); + result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag); /* Switch to receive mode. */ base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); @@ -1323,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle handle->isBusy = true; /* Set up event mask. tx and rx are always enabled. */ - handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent; + handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent; /* Clear all flags. */ I2C_SlaveClearStatusFlags(base, kClearFlags); @@ -1412,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } - return; + if (!(status & kI2C_AddressMatchFlag)) + { + return; + } } #endif /* I2C_HAS_STOP_DETECT */ @@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) handle->isBusy = true; xfer->event = kI2C_SlaveAddressMatchEvent; - if ((handle->eventMask & xfer->event) && (handle->callback)) - { - handle->callback(base, xfer, handle->userData); - } - /* Slave transmit, master reading from slave. */ if (status & kI2C_TransferDirectionFlag) { @@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) /* Read dummy to release the bus. */ dummy = base->D; + + if (dummy == 0) + { + xfer->event = kI2C_SlaveGenaralcallEvent; + } + } + + if ((handle->eventMask & xfer->event) && (handle->callback)) + { + handle->callback(base, xfer, handle->userData); } } /* Check transfer complete flag. */ @@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle) } } +#if defined(I2C0) void I2C0_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]); } +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 1) +#if defined(I2C1) void I2C1_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]); } -#endif /* I2C COUNT > 1 */ +#endif -#if (FSL_FEATURE_SOC_I2C_COUNT > 2) +#if defined(I2C2) void I2C2_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]); } -#endif /* I2C COUNT > 2 */ -#if (FSL_FEATURE_SOC_I2C_COUNT > 3) +#endif + +#if defined(I2C3) void I2C3_DriverIRQHandler(void) { I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]); } -#endif /* I2C COUNT > 3 */ +#endif diff --git a/drivers/fsl_i2c.h b/drivers/fsl_i2c.h index 7117fd5..d55fd1d 100644 --- a/drivers/fsl_i2c.h +++ b/drivers/fsl_i2c.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,15 +37,14 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief I2C driver version 2.0.1. */ -#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! @brief I2C driver version 2.0.3. */ +#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ #if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \ @@ -61,6 +60,7 @@ enum _i2c_status kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */ kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */ kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */ + kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */ }; /*! @@ -108,11 +108,11 @@ enum _i2c_interrupt_enable #endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */ }; -/*! @brief Direction of master and slave transfers. */ +/*! @brief The direction of master and slave transfers. */ typedef enum _i2c_direction { - kI2C_Write = 0x0U, /*!< Master transmit to slave. */ - kI2C_Read = 0x1U, /*!< Master receive from slave. */ + kI2C_Write = 0x0U, /*!< Master transmits to the slave. */ + kI2C_Read = 0x1U, /*!< Master receives from the slave. */ } i2c_direction_t; /*! @brief Addressing mode. */ @@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode /*! @brief I2C transfer control flag. */ enum _i2c_master_transfer_flags { - kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */ - kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */ - kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */ - kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */ + kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */ + kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */ + kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */ + kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */ }; /*! * @brief Set of events sent to the callback for nonblocking slave transfers. * * These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together - * events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable. + * events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable. * Then, when the slave callback is invoked, it is passed the current event through its @a transfer * parameter. * @@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags typedef enum _i2c_slave_transfer_event { kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */ - kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit + kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit (slave-transmitter role). */ - kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received + kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received data (slave-receiver role). */ - kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */ + kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */ #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */ #endif - kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */ + kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */ - /*! Bit mask of all available events. */ + /*! A bit mask of all available events. */ kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | #if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT kI2C_SlaveStartEvent | #endif - kI2C_SlaveCompletionEvent, + kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent, } i2c_slave_transfer_event_t; /*! @brief I2C master user configuration. */ typedef struct _i2c_master_config { bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ -#endif #if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF bool enableStopHold; /*!< Controls the stop hold enable. */ #endif #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE - bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that + bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that enabling the double buffer disables the clock stretch. */ #endif uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */ @@ -184,19 +182,20 @@ typedef struct _i2c_master_config typedef struct _i2c_slave_config { bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */ - bool enableGeneralCall; /*!< Enable general call addressing mode. */ + bool enableGeneralCall; /*!< Enables the general call addressing mode. */ bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */ -#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION - bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */ -#endif #if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE - bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that + bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that enabling the double buffer disables the clock stretch. */ #endif bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */ - uint16_t slaveAddress; /*!< Slave address configuration. */ - uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */ - i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint16_t slaveAddress; /*!< A slave address configuration. */ + uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */ + i2c_slave_address_mode_t + addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */ + uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C + data) while SCL is high (stop condition), SDA hold time and SCL start hold time + are also configured according to the SCL stop hold time. */ } i2c_slave_config_t; /*! @brief I2C master handle typedef. */ @@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t; /*! @brief I2C master transfer structure. */ typedef struct _i2c_master_transfer { - uint32_t flags; /*!< Transfer flag which controls the transfer. */ + uint32_t flags; /*!< A transfer flag which controls the transfer. */ uint8_t slaveAddress; /*!< 7-bit slave address. */ - i2c_direction_t direction; /*!< Transfer direction, read or write. */ - uint32_t subaddress; /*!< Sub address. Transferred MSB first. */ - uint8_t subaddressSize; /*!< Size of command buffer. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_direction_t direction; /*!< A transfer direction, read or write. */ + uint32_t subaddress; /*!< A sub address. Transferred MSB first. */ + uint8_t subaddressSize; /*!< A size of the command buffer. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ } i2c_master_transfer_t; /*! @brief I2C master handle structure. */ @@ -228,20 +227,21 @@ struct _i2c_master_handle { i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */ size_t transferSize; /*!< Total bytes to be transferred. */ - uint8_t state; /*!< Transfer state maintained during transfer. */ - i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + uint8_t state; /*!< A transfer state maintained during transfer. */ + i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /*! @brief I2C slave transfer structure. */ typedef struct _i2c_slave_transfer { - i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */ - uint8_t *volatile data; /*!< Transfer buffer. */ - volatile size_t dataSize; /*!< Transfer size. */ + i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */ + uint8_t *volatile data; /*!< A transfer buffer. */ + volatile size_t dataSize; /*!< A transfer size. */ status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for #kI2C_SlaveCompletionEvent. */ - size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */ + size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated + start. */ } i2c_slave_transfer_t; /*! @brief I2C slave transfer callback typedef. */ @@ -250,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer /*! @brief I2C slave handle structure. */ struct _i2c_slave_handle { - bool isBusy; /*!< Whether transfer is busy. */ + volatile bool isBusy; /*!< Indicates whether a transfer is busy. */ i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */ - uint32_t eventMask; /*!< Mask of enabled events. */ - i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */ - void *userData; /*!< Callback parameter passed to callback. */ + uint32_t eventMask; /*!< A mask of enabled events. */ + i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */ + void *userData; /*!< A callback parameter passed to the callback. */ }; /******************************************************************************* @@ -274,12 +274,12 @@ extern "C" { * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock * and configure the I2C with master configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module may cause a hard fault - * because clock is not enabled. The configuration structure can be filled by user - * from scratch, or be set with default values by I2C_MasterGetDefaultConfig(). + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault + * because the clock is not enabled. The configuration structure can be custom filled + * or it can be set with default values by using the I2C_MasterGetDefaultConfig(). * After calling this API, the master is ready to transfer. - * Example: + * This is an example. * @code * i2c_master_config_t config = { * .enableMaster = true, @@ -292,20 +292,20 @@ extern "C" { * @endcode * * @param base I2C base pointer - * @param masterConfig pointer to master configuration structure + * @param masterConfig A pointer to the master configuration structure * @param srcClock_Hz I2C peripheral clock frequency in Hz */ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz); /*! * @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock - * and initializes the I2C with slave configuration. + * and initialize the I2C with the slave configuration. * - * @note This API should be called at the beginning of the application to use - * the I2C driver, or any operation to the I2C module can cause a hard fault + * @note This API should be called at the beginning of the application. + * Otherwise, any operation to the I2C module can cause a hard fault * because the clock is not enabled. The configuration structure can partly be set - * with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user. - * Example + * with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user. + * This is an example. * @code * i2c_slave_config_t config = { * .enableSlave = true, @@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin * .slaveAddress = 0x1DU, * .enableWakeUp = false, * .enablehighDrive = false, - * .enableBaudRateCtl = false + * .enableBaudRateCtl = false, + * .sclStopHoldTime_ns = 4000 * }; - * I2C_SlaveInit(I2C0, &config); + * I2C_SlaveInit(I2C0, &config, 12000000U); * @endcode * * @param base I2C base pointer - * @param slaveConfig pointer to slave configuration structure + * @param slaveConfig A pointer to the slave configuration structure + * @param srcClock_Hz I2C peripheral clock frequency in Hz */ -void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig); +void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz); /*! * @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock. @@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base); * @brief Sets the I2C master configuration structure to default values. * * The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure(). - * Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of - * the structure before calling I2C_MasterConfigure(). - * Example: + * Use the initialized structure unchanged in the I2C_MasterConfigure() or modify + * the structure before calling the I2C_MasterConfigure(). + * This is an example. * @code * i2c_master_config_t config; * I2C_MasterGetDefaultConfig(&config); * @endcode - * @param masterConfig Pointer to the master configuration structure. + * @param masterConfig A pointer to the master configuration structure. */ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig); /*! * @brief Sets the I2C slave configuration structure to default values. * - * The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure(). + * The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure(). * Modify fields of the structure before calling the I2C_SlaveConfigure(). - * Example: + * This is an example. * @code * i2c_slave_config_t config; * I2C_SlaveGetDefaultConfig(&config); * @endcode - * @param slaveConfig Pointer to the slave configuration structure. + * @param slaveConfig A pointer to the slave configuration structure. */ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); @@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig); * @brief Enables or disabless the I2C peripheral operation. * * @param base I2C base pointer - * @param enable pass true to enable module, false to disable module + * @param enable Pass true to enable and false to disable the module. */ static inline void I2C_Enable(I2C_Type *base, bool enable) { @@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base) /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag. * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. @@ -449,7 +451,7 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas /*! * @brief Clears the I2C status flag state. * - * The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag + * The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag * * @param base I2C base pointer * @param statusMask The status flag mask, defined in type i2c_status_flag_t. @@ -581,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base); status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction); /*! - * @brief Performs a polling send transaction on the I2C bus without a STOP signal. + * @brief Performs a polling send transaction on the I2C bus. * * @param base The I2C peripheral base pointer. * @param txBuff The pointer to the data to be transferred. * @param txSize The length in bytes of the data to be transferred. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ -status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize); +status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags); /*! - * @brief Performs a polling receive transaction on the I2C bus with a STOP signal. + * @brief Performs a polling receive transaction on the I2C bus. * * @note The I2C_MasterReadBlocking function stops the bus before reading the final byte. * Without stopping the bus prior for the final read, the bus issues another read, resulting @@ -602,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t * @param base I2C peripheral base pointer. * @param rxBuff The pointer to the data to store the received data. * @param rxSize The length in bytes of the data to be received. + * @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag +* to issue a stop and kI2C_TransferNoStop to not send a stop. * @retval kStatus_Success Successfully complete the data transmission. * @retval kStatus_I2C_Timeout Send stop signal failed, timeout. */ -status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize); +status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags); /*! * @brief Performs a polling send transaction on the I2C bus. diff --git a/drivers/fsl_i2c_edma.c b/drivers/fsl_i2c_edma.c index c8f7c20..28a415e 100644 --- a/drivers/fsl_i2c_edma.c +++ b/drivers/fsl_i2c_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData result = I2C_MasterStop(i2cPrivateHandle->base); } } + else + { + if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read) + { + /* Change to send NAK at the last byte. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK; + + /* Wait the last data to be received. */ + while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) + { + } + + /* Change direction to send. */ + i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK; + + /* Read the last data byte. */ + *(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) = + i2cPrivateHandle->base->D; + } + } i2cPrivateHandle->handle->state = kIdleState; @@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, assert(xfer); status_t result = kStatus_Success; - uint16_t timeout = UINT16_MAX; if (handle->state != kIdleState) { @@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, handle->state = kTransferDataState; - /* Wait until ready to complete. */ - while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout)) - { - } - - /* Failed to start the transfer. */ - if (timeout == 0) - { - return kStatus_I2C_Timeout; - } /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); @@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); } - /* Send subaddress. */ - if (handle->transfer.subaddressSize) + if (result) { - do + return result; + } + + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + /* Return if error. */ + if (result) + { + if (result == kStatus_I2C_Nak) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) + result = kStatus_I2C_Addr_Nak; + + if (I2C_MasterStop(base) != kStatus_Success) { + result = kStatus_I2C_Timeout; } + if (handle->completionCallback) + { + (handle->completionCallback)(base, handle, result, handle->userData); + } + } + + return result; + } + + /* Send subaddress. */ + if (handle->transfer.subaddressSize) + { + do + { /* Clear interrupt pending flag. */ base->S = kI2C_IntPendingFlag; handle->transfer.subaddressSize--; base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); @@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base, if (handle->transfer.direction == kI2C_Read) { - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { - } - /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; /* Send repeated start and slave address. */ result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); - } - } - if (result) - { - return result; - } + if (result) + { + return result; + } - /* Wait until data transfer complete. */ - while (!(base->S & kI2C_IntPendingFlag)) - { + /* Wait until data transfer complete. */ + while (!(base->S & kI2C_IntPendingFlag)) + { + } + + /* Check if there's transfer error. */ + result = I2C_CheckAndClearError(base, base->S); + + if (result) + { + return result; + } + } } /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; - - /* Check if there's transfer error. */ - result = I2C_CheckAndClearError(base, base->S); } return result; @@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ { transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base); transfer_config.destAddr = (uint32_t)(handle->transfer.data); - - /* Send stop if kI2C_TransferNoStop flag is not asserted. */ - if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) - { - transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); - } - else - { - transfer_config.majorLoopCounts = handle->transfer.dataSize; - } - + transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1); transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes; transfer_config.srcOffset = 0; transfer_config.destTransferSize = kEDMA_TransferSize1Bytes; @@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_ transfer_config.minorLoopBytes = 1; } + /* Store the initially configured eDMA minor byte transfer count into the I2C handle */ + handle->nbytes = transfer_config.minorLoopBytes; + EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config); EDMA_StartTransfer(handle->dmaHandle); } @@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle if (handle->transfer.direction == kI2C_Read) { /* Change direction for receive. */ - base->C1 &= ~I2C_C1_TX_MASK; + base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); /* Read dummy to release the bus. */ dummy = base->D; @@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle { result = I2C_MasterStop(base); } + else + { + /* Change direction to send. */ + base->C1 |= I2C_C1_TX_MASK; + } /* Read the last byte of data. */ if (handle->transfer.direction == kI2C_Read) @@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t if (kIdleState != handle->state) { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } else { diff --git a/drivers/fsl_i2c_edma.h b/drivers/fsl_i2c_edma.h index c95d6ad..40cb648 100644 --- a/drivers/fsl_i2c_edma.h +++ b/drivers/fsl_i2c_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base, /*! @brief I2C master eDMA transfer structure. */ struct _i2c_master_edma_handle { - i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */ + i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */ size_t transferSize; /*!< Total bytes to be transferred. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t state; /*!< I2C master transfer status. */ edma_handle_t *dmaHandle; /*!< The eDMA handler used. */ i2c_master_edma_transfer_callback_t - completionCallback; /*!< Callback function called after eDMA transfer finished. */ - void *userData; /*!< Callback parameter passed to callback function. */ + completionCallback; /*!< A callback function called after the eDMA transfer is finished. */ + void *userData; /*!< A callback parameter passed to the callback function. */ }; /******************************************************************************* @@ -79,12 +79,12 @@ extern "C" { */ /*! - * @brief Init the I2C handle which is used in transcational functions. + * @brief Initializes the I2C handle which is used in transcational functions. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param callback pointer to user callback function. - * @param userData user param passed to the callback function. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param callback A pointer to the user callback function. + * @param userData A user parameter passed to the callback function. * @param edmaHandle eDMA handle pointer. */ void I2C_MasterCreateEDMAHandle(I2C_Type *base, @@ -97,30 +97,30 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base, * @brief Performs a master eDMA non-blocking transfer on the I2C bus. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param xfer pointer to transfer structure of i2c_master_transfer_t. - * @retval kStatus_Success Sucessully complete the data transmission. - * @retval kStatus_I2C_Busy Previous transmission still not finished. - * @retval kStatus_I2C_Timeout Transfer error, wait signal timeout. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param xfer A pointer to the transfer structure of i2c_master_transfer_t. + * @retval kStatus_Success Sucessfully completed the data transmission. + * @retval kStatus_I2C_Busy A previous transmission is still not finished. + * @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout. * @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost. - * @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer. + * @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer. */ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer); /*! - * @brief Get master transfer status during a eDMA non-blocking transfer. + * @brief Gets a master transfer status during the eDMA non-blocking transfer. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. - * @param count Number of bytes transferred so far by the non-blocking transaction. + * @param handle A pointer to the i2c_master_edma_handle_t structure. + * @param count A number of bytes transferred by the non-blocking transaction. */ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count); /*! - * @brief Abort a master eDMA non-blocking transfer in a early time. + * @brief Aborts a master eDMA non-blocking transfer early. * * @param base I2C peripheral base address. - * @param handle pointer to i2c_master_edma_handle_t structure. + * @param handle A pointer to the i2c_master_edma_handle_t structure. */ void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle); diff --git a/drivers/fsl_i2c_freertos.c b/drivers/fsl_i2c_freertos.c new file mode 100644 index 0000000..e622fbe --- /dev/null +++ b/drivers/fsl_i2c_freertos.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_i2c_freertos.h" + +static void I2C_RTOS_Callback(I2C_Type *base, i2c_master_handle_t *drv_handle, status_t status, void *userData) +{ + i2c_rtos_handle_t *handle = (i2c_rtos_handle_t *)userData; + BaseType_t reschedule; + handle->async_status = status; + xSemaphoreGiveFromISR(handle->semaphore, &reschedule); + portYIELD_FROM_ISR(reschedule); +} + +status_t I2C_RTOS_Init(i2c_rtos_handle_t *handle, + I2C_Type *base, + const i2c_master_config_t *masterConfig, + uint32_t srcClock_Hz) +{ + if (handle == NULL) + { + return kStatus_InvalidArgument; + } + + if (base == NULL) + { + return kStatus_InvalidArgument; + } + + memset(handle, 0, sizeof(i2c_rtos_handle_t)); +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->mutex = xSemaphoreCreateMutexStatic(&handle->mutexBuffer); +#else + handle->mutex = xSemaphoreCreateMutex(); +#endif + if (handle->mutex == NULL) + { + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->semaphore = xSemaphoreCreateBinaryStatic(&handle->semaphoreBuffer); +#else + handle->semaphore = xSemaphoreCreateBinary(); +#endif + if (handle->semaphore == NULL) + { + vSemaphoreDelete(handle->mutex); + return kStatus_Fail; + } + + handle->base = base; + + I2C_MasterInit(handle->base, masterConfig, srcClock_Hz); + I2C_MasterTransferCreateHandle(base, &handle->drv_handle, I2C_RTOS_Callback, (void *)handle); + + return kStatus_Success; +} + +status_t I2C_RTOS_Deinit(i2c_rtos_handle_t *handle) +{ + I2C_MasterDeinit(handle->base); + + vSemaphoreDelete(handle->semaphore); + vSemaphoreDelete(handle->mutex); + + return kStatus_Success; +} + +status_t I2C_RTOS_Transfer(i2c_rtos_handle_t *handle, i2c_master_transfer_t *transfer) +{ + status_t status; + + /* Lock resource mutex */ + if (xSemaphoreTake(handle->mutex, portMAX_DELAY) != pdTRUE) + { + return kStatus_I2C_Busy; + } + + status = I2C_MasterTransferNonBlocking(handle->base, &handle->drv_handle, transfer); + if (status != kStatus_Success) + { + xSemaphoreGive(handle->mutex); + return status; + } + + /* Wait for transfer to finish */ + xSemaphoreTake(handle->semaphore, portMAX_DELAY); + + /* Unlock resource mutex */ + xSemaphoreGive(handle->mutex); + + /* Return status captured by callback function */ + return handle->async_status; +} diff --git a/drivers/fsl_i2c_freertos.h b/drivers/fsl_i2c_freertos.h new file mode 100644 index 0000000..52ed2d0 --- /dev/null +++ b/drivers/fsl_i2c_freertos.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __FSL_I2C_FREERTOS_H__ +#define __FSL_I2C_FREERTOS_H__ + +#include "FreeRTOSConfig.h" +#include "FreeRTOS.h" +#include "portable.h" +#include "semphr.h" + +#include "fsl_i2c.h" + +/*! + * @addtogroup i2c_freertos_driver I2C FreeRTOS driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! + * @cond RTOS_PRIVATE + * @brief I2C FreeRTOS handle + */ +typedef struct _i2c_rtos_handle +{ + I2C_Type *base; /*!< I2C base address */ + i2c_master_handle_t drv_handle; /*!< A handle of the underlying driver, treated as opaque by the RTOS layer */ + status_t async_status; /*!< Transactional state of the underlying driver */ + SemaphoreHandle_t mutex; /*!< A mutex to lock the handle during a transfer */ + SemaphoreHandle_t semaphore; /*!< A semaphore to notify and unblock task when the transfer ends */ +#if (configSUPPORT_STATIC_ALLOCATION == 1) + StaticSemaphore_t mutexBuffer; /*!< Statically allocated memory for mutex */ + StaticSemaphore_t semaphoreBuffer; /*!< Statically allocated memory for semaphore */ +#endif +} i2c_rtos_handle_t; +/*! \endcond */ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name I2C RTOS Operation + * @{ + */ + +/*! + * @brief Initializes I2C. + * + * This function initializes the I2C module and the related RTOS context. + * + * @param handle The RTOS I2C handle, the pointer to an allocated space for RTOS context. + * @param base The pointer base address of the I2C instance to initialize. + * @param masterConfig The configuration structure to set-up I2C in master mode. + * @param srcClock_Hz The frequency of an input clock of the I2C module. + * @return status of the operation. + */ +status_t I2C_RTOS_Init(i2c_rtos_handle_t *handle, + I2C_Type *base, + const i2c_master_config_t *masterConfig, + uint32_t srcClock_Hz); + +/*! + * @brief Deinitializes the I2C. + * + * This function deinitializes the I2C module and the related RTOS context. + * + * @param handle The RTOS I2C handle. + */ +status_t I2C_RTOS_Deinit(i2c_rtos_handle_t *handle); + +/*! + * @brief Performs the I2C transfer. + * + * This function performs the I2C transfer according to the data given in the transfer structure. + * + * @param handle The RTOS I2C handle. + * @param transfer A structure specifying the transfer parameters. + * @return status of the operation. + */ +status_t I2C_RTOS_Transfer(i2c_rtos_handle_t *handle, i2c_master_transfer_t *transfer); + +/*! + * @} + */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ + +#endif /* __FSL_I2C_FREERTOS_H__ */ diff --git a/drivers/fsl_llwu.c b/drivers/fsl_llwu.c index c27b91e..74b1001 100644 --- a/drivers/fsl_llwu.c +++ b/drivers/fsl_llwu.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/drivers/fsl_llwu.h b/drivers/fsl_llwu.h index 1384d51..d5a0037 100644 --- a/drivers/fsl_llwu.h +++ b/drivers/fsl_llwu.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -51,9 +51,9 @@ */ typedef enum _llwu_external_pin_mode { - kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as wakeup input. */ - kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with rising edge detection. */ - kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with falling edge detection.*/ + kLLWU_ExternalPinDisable = 0U, /*!< Pin disabled as a wakeup input. */ + kLLWU_ExternalPinRisingEdge = 1U, /*!< Pin enabled with the rising edge detection. */ + kLLWU_ExternalPinFallingEdge = 2U, /*!< Pin enabled with the falling edge detection.*/ kLLWU_ExternalPinAnyEdge = 3U /*!< Pin enabled with any change detection. */ } llwu_external_pin_mode_t; @@ -74,9 +74,9 @@ typedef enum _llwu_pin_filter_mode */ typedef struct _llwu_version_id { - uint16_t feature; /*!< Feature Specification Number. */ - uint8_t minor; /*!< Minor version number. */ - uint8_t major; /*!< Major version number. */ + uint16_t feature; /*!< A feature specification number. */ + uint8_t minor; /*!< The minor version number. */ + uint8_t major; /*!< The major version number. */ } llwu_version_id_t; #endif /* FSL_FEATURE_LLWU_HAS_VERID */ @@ -86,20 +86,20 @@ typedef struct _llwu_version_id */ typedef struct _llwu_param { - uint8_t filters; /*!< Number of pin filter. */ - uint8_t dmas; /*!< Number of wakeup DMA. */ - uint8_t modules; /*!< Number of wakeup module. */ - uint8_t pins; /*!< Number of wake up pin. */ + uint8_t filters; /*!< A number of the pin filter. */ + uint8_t dmas; /*!< A number of the wakeup DMA. */ + uint8_t modules; /*!< A number of the wakeup module. */ + uint8_t pins; /*!< A number of the wake up pin. */ } llwu_param_t; #endif /* FSL_FEATURE_LLWU_HAS_PARAM */ #if (defined(FSL_FEATURE_LLWU_HAS_PIN_FILTER) && FSL_FEATURE_LLWU_HAS_PIN_FILTER) /*! - * @brief External input pin filter control structure + * @brief An external input pin filter control structure */ typedef struct _llwu_external_pin_filter_mode { - uint32_t pinIndex; /*!< Pin number */ + uint32_t pinIndex; /*!< A pin number */ llwu_pin_filter_mode_t filterMode; /*!< Filter mode */ } llwu_external_pin_filter_mode_t; #endif /* FSL_FEATURE_LLWU_HAS_PIN_FILTER */ @@ -121,11 +121,11 @@ extern "C" { /*! * @brief Gets the LLWU version ID. * - * This function gets the LLWU version ID, including major version number, - * minor version number, and feature specification number. + * This function gets the LLWU version ID, including the major version number, + * the minor version number, and the feature specification number. * * @param base LLWU peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId A pointer to the version ID structure. */ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *versionId) { @@ -137,11 +137,11 @@ static inline void LLWU_GetVersionId(LLWU_Type *base, llwu_version_id_t *version /*! * @brief Gets the LLWU parameter. * - * This function gets the LLWU parameter, including wakeup pin number, module - * number, DMA number, and pin filter number. + * This function gets the LLWU parameter, including a wakeup pin number, a module + * number, a DMA number, and a pin filter number. * * @param base LLWU peripheral base address. - * @param param Pointer to LLWU param structure. + * @param param A pointer to the LLWU parameter structure. */ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) { @@ -157,8 +157,8 @@ static inline void LLWU_GetParam(LLWU_Type *base, llwu_param_t *param) * as a wake up source. * * @param base LLWU peripheral base address. - * @param pinIndex pin index which to be enabled as external wakeup source, start from 1. - * @param pinMode pin configuration mode defined in llwu_external_pin_modes_t + * @param pinIndex A pin index to be enabled as an external wakeup source starting from 1. + * @param pinMode A pin configuration mode defined in the llwu_external_pin_modes_t. */ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_external_pin_mode_t pinMode); @@ -166,11 +166,11 @@ void LLWU_SetExternalWakeupPinMode(LLWU_Type *base, uint32_t pinIndex, llwu_exte * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the MCU is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. - * @return true if the specific pin is wake up source. + * @param pinIndex A pin index, which starts from 1. + * @return True if the specific pin is a wakeup source. */ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); @@ -180,7 +180,7 @@ bool LLWU_GetExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * This function clears the external wakeup source flag for a specific pin. * * @param base LLWU peripheral base address. - * @param pinIndex pin index, start from 1. + * @param pinIndex A pin index, which starts from 1. */ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); #endif /* FSL_FEATURE_LLWU_HAS_EXTERNAL_PIN */ @@ -193,8 +193,8 @@ void LLWU_ClearExternalWakeupPinFlag(LLWU_Type *base, uint32_t pinIndex); * as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex module index which to be enabled as internal wakeup source, start from 1. - * @param enable enable or disable setting + * @param moduleIndex A module index to be enabled as an internal wakeup source starting from 1. + * @param enable An enable or a disable setting */ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -212,11 +212,11 @@ static inline void LLWU_EnableInternalModuleInterruptWakup(LLWU_Type *base, uint * @brief Gets the external wakeup source flag. * * This function checks the external pin flag to detect whether the system is - * woke up by the specific pin. + * woken up by the specific pin. * * @param base LLWU peripheral base address. - * @param moduleIndex module index, start from 1. - * @return true if the specific pin is wake up source. + * @param moduleIndex A module index, which starts from 1. + * @return True if the specific pin is a wake up source. */ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t moduleIndex) { @@ -247,8 +247,8 @@ static inline bool LLWU_GetInternalWakeupModuleFlag(LLWU_Type *base, uint32_t mo * This function enables/disables the internal DMA that is used as a wake up source. * * @param base LLWU peripheral base address. - * @param moduleIndex Internal module index which used as DMA request source, start from 1. - * @param enable Enable or disable DMA request source + * @param moduleIndex An internal module index which is used as a DMA request source, starting from 1. + * @param enable Enable or disable the DMA request source */ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uint32_t moduleIndex, bool enable) { @@ -270,8 +270,8 @@ static inline void LLWU_EnableInternalModuleDmaRequestWakup(LLWU_Type *base, uin * This function sets the pin filter configuration. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which used to enable/disable the digital filter, start from 1. - * @param filterMode filter mode configuration + * @param filterIndex A pin filter index used to enable/disable the digital filter, starting from 1. + * @param filterMode A filter mode configuration */ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_pin_filter_mode_t filterMode); @@ -281,18 +281,18 @@ void LLWU_SetPinFilterMode(LLWU_Type *base, uint32_t filterIndex, llwu_external_ * This function gets the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index, start from 1. - * @return true if the flag is a source of existing a low-leakage power mode. + * @param filterIndex A pin filter index, which starts from 1. + * @return True if the flag is a source of the existing low-leakage power mode. */ bool LLWU_GetPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! - * @brief Clear the pin filter configuration. + * @brief Clears the pin filter configuration. * - * This function clear the pin filter flag. + * This function clears the pin filter flag. * * @param base LLWU peripheral base address. - * @param filterIndex pin filter index which to be clear the flag, start from 1. + * @param filterIndex A pin filter index to clear the flag, starting from 1. */ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); @@ -302,10 +302,10 @@ void LLWU_ClearPinFilterFlag(LLWU_Type *base, uint32_t filterIndex); /*! * @brief Sets the reset pin mode. * - * This function sets how the reset pin is used as a low leakage mode exit source. + * This function determines how the reset pin is used as a low leakage mode exit source. * - * @param pinEnable Enable reset pin filter - * @param pinFilterEnable Specify whether pin filter is enabled in Low-Leakage power mode. + * @param pinEnable Enable reset the pin filter + * @param pinFilterEnable Specify whether the pin filter is enabled in Low-Leakage power mode. */ void LLWU_SetResetPinMode(LLWU_Type *base, bool pinEnable, bool enableInLowLeakageMode); #endif /* FSL_FEATURE_LLWU_HAS_RESET_ENABLE */ diff --git a/drivers/fsl_lptmr.c b/drivers/fsl_lptmr.c index b3dcc89..67b3b97 100644 --- a/drivers/fsl_lptmr.c +++ b/drivers/fsl_lptmr.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,9 +48,17 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base); /*! @brief Pointers to LPTMR bases for each instance. */ static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to LPTMR clocks for each instance. */ static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS; +#if defined(LPTMR_PERIPH_CLOCKS) +/* Array of LPTMR functional clock name. */ +static const clock_ip_name_t s_lptmrPeriphClocks[] = LPTMR_PERIPH_CLOCKS; +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + /******************************************************************************* * Code ******************************************************************************/ @@ -59,7 +67,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_LPTMR_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_lptmrBases); instance++) { if (s_lptmrBases[instance] == base) { @@ -67,7 +75,7 @@ static uint32_t LPTMR_GetInstance(LPTMR_Type *base) } } - assert(instance < FSL_FEATURE_SOC_LPTMR_COUNT); + assert(instance < ARRAY_SIZE(s_lptmrBases)); return instance; } @@ -76,8 +84,17 @@ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Ungate the LPTMR clock*/ - CLOCK_EnableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_EnableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_EnableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure the timers operation mode and input pin setup */ base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) | @@ -92,8 +109,17 @@ void LPTMR_Deinit(LPTMR_Type *base) { /* Disable the LPTMR and reset the internal logic */ base->CSR &= ~LPTMR_CSR_TEN_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + + uint32_t instance = LPTMR_GetInstance(base); + /* Gate the LPTMR clock*/ - CLOCK_DisableClock(s_lptmrClocks[LPTMR_GetInstance(base)]); + CLOCK_DisableClock(s_lptmrClocks[instance]); +#if defined(LPTMR_PERIPH_CLOCKS) + CLOCK_DisableClock(s_lptmrPeriphClocks[instance]); +#endif + +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void LPTMR_GetDefaultConfig(lptmr_config_t *config) diff --git a/drivers/fsl_lptmr.h b/drivers/fsl_lptmr.h index d022cbb..6cc909b 100644 --- a/drivers/fsl_lptmr.h +++ b/drivers/fsl_lptmr.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,17 +37,16 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */ +#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1 */ /*@}*/ -/*! @brief LPTMR pin selection, used in pulse counter mode.*/ +/*! @brief LPTMR pin selection used in pulse counter mode.*/ typedef enum _lptmr_pin_select { kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */ @@ -56,7 +55,7 @@ typedef enum _lptmr_pin_select kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */ } lptmr_pin_select_t; -/*! @brief LPTMR pin polarity, used in pulse counter mode.*/ +/*! @brief LPTMR pin polarity used in pulse counter mode.*/ typedef enum _lptmr_pin_polarity { kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */ @@ -103,13 +102,13 @@ typedef enum _lptmr_prescaler_clock_select kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */ } lptmr_prescaler_clock_select_t; -/*! @brief List of LPTMR interrupts */ +/*! @brief List of the LPTMR interrupts */ typedef enum _lptmr_interrupt_enable { kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */ } lptmr_interrupt_enable_t; -/*! @brief List of LPTMR status flags */ +/*! @brief List of the LPTMR status flags */ typedef enum _lptmr_status_flags { kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */ @@ -120,18 +119,18 @@ typedef enum _lptmr_status_flags * * This structure holds the configuration settings for the LPTMR peripheral. To initialize this * structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a - * pointer to your config structure instance. + * pointer to your configuration structure instance. * - * The config struct can be made const so it resides in flash + * The configuration struct can be made constant so it resides in flash. */ typedef struct _lptmr_config { lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */ lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */ lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */ - bool enableFreeRunning; /*!< true: enable free running, counter is reset on overflow - false: counter is reset when the compare flag is set */ - bool bypassPrescaler; /*!< true: bypass prescaler; false: use clock from prescaler */ + bool enableFreeRunning; /*!< True: enable free running, counter is reset on overflow + False: counter is reset when the compare flag is set */ + bool bypassPrescaler; /*!< True: bypass prescaler; false: use clock from prescaler */ lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */ lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */ } lptmr_config_t; @@ -150,26 +149,26 @@ extern "C" { */ /*! - * @brief Ungate the LPTMR clock and configures the peripheral for basic operation. + * @brief Ungates the LPTMR clock and configures the peripheral for a basic operation. * * @note This API should be called at the beginning of the application using the LPTMR driver. * * @param base LPTMR peripheral base address - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config); /*! - * @brief Gate the LPTMR clock + * @brief Gates the LPTMR clock. * * @param base LPTMR peripheral base address */ void LPTMR_Deinit(LPTMR_Type *base); /*! - * @brief Fill in the LPTMR config struct with the default settings + * @brief Fills in the LPTMR configuration structure with default settings. * - * The default values are: + * The default values are as follows. * @code * config->timerMode = kLPTMR_TimerModeTimeCounter; * config->pinSelect = kLPTMR_PinSelectInput_0; @@ -179,7 +178,7 @@ void LPTMR_Deinit(LPTMR_Type *base); * config->prescalerClockSource = kLPTMR_PrescalerClock_1; * config->value = kLPTMR_Prescale_Glitch_0; * @endcode - * @param config Pointer to user's LPTMR config structure. + * @param config A pointer to the LPTMR configuration structure. */ void LPTMR_GetDefaultConfig(lptmr_config_t *config); @@ -212,7 +211,7 @@ static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask) * * @param base LPTMR peripheral base address * @param mask The interrupts to disable. This is a logical OR of members of the - * enumeration ::lptmr_interrupt_enable_t + * enumeration ::lptmr_interrupt_enable_t. */ static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask) { @@ -245,7 +244,7 @@ static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base) */ /*! - * @brief Gets the LPTMR status flags + * @brief Gets the LPTMR status flags. * * @param base LPTMR peripheral base address * @@ -258,11 +257,11 @@ static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base) } /*! - * @brief Clears the LPTMR status flags + * @brief Clears the LPTMR status flags. * * @param base LPTMR peripheral base address * @param mask The status flags to clear. This is a logical OR of members of the - * enumeration ::lptmr_status_flags_t + * enumeration ::lptmr_status_flags_t. */ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) { @@ -272,47 +271,48 @@ static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask) /*! @}*/ /*! - * @name Read and Write the timer period + * @name Read and write the timer period * @{ */ /*! * @brief Sets the timer period in units of count. * - * Timers counts from 0 till it equals the count value set here. The count value is written to + * Timers counts from 0 until it equals the count value set here. The count value is written to * the CMR register. * * @note * 1. The TCF flag is set with the CNR equals the count provided here and then increments. - * 2. User can call the utility macros provided in fsl_common.h to convert to ticks + * 2. Call the utility macros provided in the fsl_common.h to convert to ticks. * * @param base LPTMR peripheral base address - * @param ticks Timer period in units of ticks + * @param ticks A timer period in units of ticks, which should be equal or greater than 1. */ -static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint16_t ticks) +static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint32_t ticks) { - base->CMR = ticks; + assert(ticks > 0); + base->CMR = ticks - 1; } /*! * @brief Reads the current timer counting value. * - * This function returns the real-time timer counting value, in a range from 0 to a + * This function returns the real-time timer counting value in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec. * * @param base LPTMR peripheral base address * - * @return Current counter value in ticks + * @return The current counter value in ticks */ -static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) +static inline uint32_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) { /* Must first write any value to the CNR. This synchronizes and registers the current value * of the CNR into a temporary register which can then be read */ base->CNR = 0U; - return (uint16_t)base->CNR; + return (uint32_t)((base->CNR & LPTMR_CNR_COUNTER_MASK) >> LPTMR_CNR_COUNTER_SHIFT); } /*! @}*/ @@ -323,10 +323,10 @@ static inline uint16_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base) */ /*! - * @brief Starts the timer counting. + * @brief Starts the timer. * * After calling this function, the timer counts up to the CMR register value. - * Each time the timer reaches CMR value and then increments, it generates a + * Each time the timer reaches the CMR value and then increments, it generates a * trigger pulse and sets the timeout interrupt flag. An interrupt is also * triggered if the timer interrupt is enabled. * @@ -336,16 +336,16 @@ static inline void LPTMR_StartTimer(LPTMR_Type *base) { uint32_t reg = base->CSR; - /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ reg &= ~(LPTMR_CSR_TCF_MASK); reg |= LPTMR_CSR_TEN_MASK; base->CSR = reg; } /*! - * @brief Stops the timer counting. + * @brief Stops the timer. * - * This function stops the timer counting and resets the timer's counter register + * This function stops the timer and resets the timer's counter register. * * @param base LPTMR peripheral base address */ @@ -353,7 +353,7 @@ static inline void LPTMR_StopTimer(LPTMR_Type *base) { uint32_t reg = base->CSR; - /* Clear the TCF bit so that we don't clear this w1c bit when writing back */ + /* Clear the TCF bit to avoid clearing the w1c bit when writing back. */ reg &= ~(LPTMR_CSR_TCF_MASK); reg &= ~LPTMR_CSR_TEN_MASK; base->CSR = reg; diff --git a/drivers/fsl_pdb.c b/drivers/fsl_pdb.c index dcc03ba..1fc4a9a 100644 --- a/drivers/fsl_pdb.c +++ b/drivers/fsl_pdb.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -45,8 +45,10 @@ static uint32_t PDB_GetInstance(PDB_Type *base); ******************************************************************************/ /*! @brief Pointers to PDB bases for each instance. */ static PDB_Type *const s_pdbBases[] = PDB_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PDB clocks for each instance. */ static const clock_ip_name_t s_pdbClocks[] = PDB_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Codes @@ -56,7 +58,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PDB_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pdbBases); instance++) { if (s_pdbBases[instance] == base) { @@ -64,7 +66,7 @@ static uint32_t PDB_GetInstance(PDB_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PDB_COUNT); + assert(instance < ARRAY_SIZE(s_pdbBases)); return instance; } @@ -75,8 +77,10 @@ void PDB_Init(PDB_Type *base, const pdb_config_t *config) uint32_t tmp32; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable the clock. */ CLOCK_EnableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure. */ /* PDBx_SC. */ @@ -98,8 +102,10 @@ void PDB_Deinit(PDB_Type *base) { PDB_Enable(base, false); /* Disable the PDB module. */ +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_pdbClocks[PDB_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void PDB_GetDefaultConfig(pdb_config_t *config) diff --git a/drivers/fsl_pdb.h b/drivers/fsl_pdb.h index 5fed10a..3dec946 100644 --- a/drivers/fsl_pdb.h +++ b/drivers/fsl_pdb.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -66,32 +66,32 @@ enum _pdb_status_flags enum _pdb_adc_pretrigger_flags { /* PDB PreTrigger channel match flags. */ - kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-Trigger 0 flag. */ - kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-Trigger 1 flag. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-Trigger 2 flag. */ - kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-Trigger 3 flag. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-Trigger 4 flag. */ - kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-Trigger 5 flag. */ - kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-Trigger 6 flag. */ - kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-Trigger 7 flag. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0Flag = PDB_S_CF(1U << 0), /*!< Pre-trigger 0 flag. */ + kPDB_ADCPreTriggerChannel1Flag = PDB_S_CF(1U << 1), /*!< Pre-trigger 1 flag. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2Flag = PDB_S_CF(1U << 2), /*!< Pre-trigger 2 flag. */ + kPDB_ADCPreTriggerChannel3Flag = PDB_S_CF(1U << 3), /*!< Pre-trigger 3 flag. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4Flag = PDB_S_CF(1U << 4), /*!< Pre-trigger 4 flag. */ + kPDB_ADCPreTriggerChannel5Flag = PDB_S_CF(1U << 5), /*!< Pre-trigger 5 flag. */ + kPDB_ADCPreTriggerChannel6Flag = PDB_S_CF(1U << 6), /*!< Pre-trigger 6 flag. */ + kPDB_ADCPreTriggerChannel7Flag = PDB_S_CF(1U << 7), /*!< Pre-trigger 7 flag. */ +#endif /* PDB_DLY_COUNT2 > 4 */ /* PDB PreTrigger channel error flags. */ - kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-Trigger 0 Error. */ - kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-Trigger 1 Error. */ -#if (PDB_DLY_COUNT > 2) - kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-Trigger 2 Error. */ - kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-Trigger 3 Error. */ -#endif /* PDB_DLY_COUNT > 2 */ -#if (PDB_DLY_COUNT > 4) - kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-Trigger 4 Error. */ - kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-Trigger 5 Error. */ - kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-Trigger 6 Error. */ - kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-Trigger 7 Error. */ -#endif /* PDB_DLY_COUNT > 4 */ + kPDB_ADCPreTriggerChannel0ErrorFlag = PDB_S_ERR(1U << 0), /*!< Pre-trigger 0 Error. */ + kPDB_ADCPreTriggerChannel1ErrorFlag = PDB_S_ERR(1U << 1), /*!< Pre-trigger 1 Error. */ +#if (PDB_DLY_COUNT2 > 2) + kPDB_ADCPreTriggerChannel2ErrorFlag = PDB_S_ERR(1U << 2), /*!< Pre-trigger 2 Error. */ + kPDB_ADCPreTriggerChannel3ErrorFlag = PDB_S_ERR(1U << 3), /*!< Pre-trigger 3 Error. */ +#endif /* PDB_DLY_COUNT2 > 2 */ +#if (PDB_DLY_COUNT2 > 4) + kPDB_ADCPreTriggerChannel4ErrorFlag = PDB_S_ERR(1U << 4), /*!< Pre-trigger 4 Error. */ + kPDB_ADCPreTriggerChannel5ErrorFlag = PDB_S_ERR(1U << 5), /*!< Pre-trigger 5 Error. */ + kPDB_ADCPreTriggerChannel6ErrorFlag = PDB_S_ERR(1U << 6), /*!< Pre-trigger 6 Error. */ + kPDB_ADCPreTriggerChannel7ErrorFlag = PDB_S_ERR(1U << 7), /*!< Pre-trigger 7 Error. */ +#endif /* PDB_DLY_COUNT2 > 4 */ }; /*! @@ -107,7 +107,7 @@ enum _pdb_interrupt_enable * @brief PDB load value mode. * * Selects the mode to load the internal values after doing the load operation (write 1 to PDBx_SC[LDOK]). - * These values are for: + * These values are for the following operations. * - PDB counter (PDBx_MOD, PDBx_IDLY) * - ADC trigger (PDBx_CHnDLYm) * - DAC trigger (PDBx_DACINTx) @@ -192,15 +192,15 @@ typedef struct _pdb_config } pdb_config_t; /*! - * @brief PDB ADC Pre-Trigger configuration. + * @brief PDB ADC Pre-trigger configuration. */ typedef struct _pdb_adc_pretrigger_config { - uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-Trigger Enable. */ - uint32_t enableOutputMask; /*!< PDB Channel Pre-Trigger Output Select. + uint32_t enablePreTriggerMask; /*!< PDB Channel Pre-trigger Enable. */ + uint32_t enableOutputMask; /*!< PDB Channel Pre-trigger Output Select. PDB channel's corresponding pre-trigger asserts when the counter reaches the channel delay register. */ - uint32_t enableBackToBackOperationMask; /*!< PDB Channel Pre-Trigger Back-to-Back Operation Enable. + uint32_t enableBackToBackOperationMask; /*!< PDB Channel pre-trigger Back-to-Back Operation Enable. Back-to-back operation enables the ADC conversions complete to trigger the next PDB channel pre-trigger and trigger output, so that the ADC conversions can be triggered on next set of configuration and results @@ -229,20 +229,20 @@ extern "C" { */ /*! - * @brief Initializes the PDB module. + * @brief Initializes the PDB module. * - * This function is to make the initialization for PDB module. The operations includes are: + * This function initializes the PDB module. The operations included are as follows. * - Enable the clock for PDB instance. * - Configure the PDB module. * - Enable the PDB module. * * @param base PDB peripheral base address. - * @param config Pointer to configuration structure. See "pdb_config_t". + * @param config Pointer to the configuration structure. See "pdb_config_t". */ void PDB_Init(PDB_Type *base, const pdb_config_t *config); /*! - * @brief De-initializes the PDB module. + * @brief De-initializes the PDB module. * * @param base PDB peripheral base address. */ @@ -251,7 +251,7 @@ void PDB_Deinit(PDB_Type *base); /*! * @brief Initializes the PDB user configuration structure. * - * This function initializes the user configuration structure to default value. The default values are: + * This function initializes the user configuration structure to a default value. The default values are as follows. * @code * config->loadValueMode = kPDB_LoadValueImmediately; * config->prescalerDivider = kPDB_PrescalerDivider1; @@ -301,7 +301,7 @@ static inline void PDB_DoSoftwareTrigger(PDB_Type *base) /*! * @brief Loads the counter values. * - * This function is to load the counter values from their internal buffer. + * This function loads the counter values from the internal buffer. * See "pdb_load_value_mode_t" about PDB's load mode. * * @param base PDB peripheral base address. @@ -381,7 +381,7 @@ static inline void PDB_ClearStatusFlags(PDB_Type *base, uint32_t mask) } /*! - * @brief Specifies the period of the counter. + * @brief Specifies the counter period. * * @param base PDB peripheral base address. * @param value Setting value for the modulus. 16-bit is available. @@ -404,7 +404,7 @@ static inline uint32_t PDB_GetCounterValue(PDB_Type *base) } /*! - * @brief Sets the value for PDB counter delay event. + * @brief Sets the value for the PDB counter delay event. * * @param base PDB peripheral base address. * @param value Setting value for PDB counter delay event. 16-bit is available. @@ -416,16 +416,16 @@ static inline void PDB_SetCounterDelayValue(PDB_Type *base, uint32_t value) /* @} */ /*! - * @name ADC Pre-Trigger + * @name ADC Pre-trigger * @{ */ /*! - * @brief Configures the ADC PreTrigger in PDB module. + * @brief Configures the ADC pre-trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. - * @param config Pointer to configuration structure. See "pdb_adc_pretrigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_adc_pretrigger_config_t". */ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, pdb_adc_pretrigger_config_t *config) { @@ -437,26 +437,27 @@ static inline void PDB_SetADCPreTriggerConfig(PDB_Type *base, uint32_t channel, } /*! - * @brief Sets the value for ADC Pre-Trigger delay event. + * @brief Sets the value for the ADC pre-trigger delay event. * - * This function is to set the value for ADC Pre-Trigger delay event. IT Specifies the delay value for the channel's - * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the setting value here. + * This function sets the value for ADC pre-trigger delay event. It specifies the delay value for the channel's + * corresponding pre-trigger. The pre-trigger asserts when the PDB counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. * @param preChannel Channel group index for ADC instance. - * @param value Setting value for ADC Pre-Trigger delay event. 16-bit is available. + * @param value Setting value for ADC pre-trigger delay event. 16-bit is available. */ static inline void PDB_SetADCPreTriggerDelayValue(PDB_Type *base, uint32_t channel, uint32_t preChannel, uint32_t value) { assert(channel < PDB_C1_COUNT); - assert(preChannel < PDB_DLY_COUNT); + assert(preChannel < PDB_DLY_COUNT2); + /* xx_COUNT2 is actually the count for pre-triggers in header file. xx_COUNT is used for the count of channels. */ base->CH[channel].DLY[preChannel] = PDB_DLY_DLY(value); } /*! - * @brief Gets the ADC Pre-Trigger's status flags. + * @brief Gets the ADC pre-trigger's status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -471,7 +472,7 @@ static inline uint32_t PDB_GetADCPreTriggerStatusFlags(PDB_Type *base, uint32_t } /*! - * @brief Clears the ADC Pre-Trigger's status flags. + * @brief Clears the ADC pre-trigger status flags. * * @param base PDB peripheral base address. * @param channel Channel index for ADC instance. @@ -493,19 +494,19 @@ static inline void PDB_ClearADCPreTriggerStatusFlags(PDB_Type *base, uint32_t ch */ /*! - * @brief Configures the DAC trigger in PDB module. + * @brief Configures the DAC trigger in the PDB module. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. - * @param config Pointer to configuration structure. See "pdb_dac_trigger_config_t". + * @param config Pointer to the configuration structure. See "pdb_dac_trigger_config_t". */ void PDB_SetDACTriggerConfig(PDB_Type *base, uint32_t channel, pdb_dac_trigger_config_t *config); /*! * @brief Sets the value for the DAC interval event. * - * This fucntion is to set the value for DAC interval event. DAC interval trigger would trigger the DAC module to update - * buffer when the DAC interval counter is equal to the setting value here. + * This fucntion sets the value for DAC interval event. DAC interval trigger triggers the DAC module to update + * the buffer when the DAC interval counter is equal to the set value. * * @param base PDB peripheral base address. * @param channel Channel index for DAC instance. @@ -531,7 +532,7 @@ static inline void PDB_SetDACTriggerIntervalValue(PDB_Type *base, uint32_t chann * * @param base PDB peripheral base address. * @param channelMask Channel mask value for multiple pulse out trigger channel. - * @param enable Enable the feature or not. + * @param enable Whether the feature is enabled or not. */ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMask, bool enable) { @@ -546,11 +547,11 @@ static inline void PDB_EnablePulseOutTrigger(PDB_Type *base, uint32_t channelMas } /*! - * @brief Sets event values for pulse out trigger. + * @brief Sets event values for the pulse out trigger. * - * This function is used to set event values for pulse output trigger. - * These pulse output trigger delay values specify the delay for the PDB Pulse-Out. Pulse-Out goes high when the PDB - * counter is equal to the pulse output high value (value1). Pulse-Out goes low when the PDB counter is equal to the + * This function is used to set event values for the pulse output trigger. + * These pulse output trigger delay values specify the delay for the PDB Pulse-out. Pulse-out goes high when the PDB + * counter is equal to the pulse output high value (value1). Pulse-out goes low when the PDB counter is equal to the * pulse output low value (value2). * * @param base PDB peripheral base address. diff --git a/drivers/fsl_pit.c b/drivers/fsl_pit.c index 1f2fdfe..e5c3c4e 100644 --- a/drivers/fsl_pit.c +++ b/drivers/fsl_pit.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,8 +48,10 @@ static uint32_t PIT_GetInstance(PIT_Type *base); /*! @brief Pointers to PIT bases for each instance. */ static PIT_Type *const s_pitBases[] = PIT_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to PIT clocks for each instance. */ static const clock_ip_name_t s_pitClocks[] = PIT_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -59,7 +61,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_PIT_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_pitBases); instance++) { if (s_pitBases[instance] == base) { @@ -67,7 +69,7 @@ static uint32_t PIT_GetInstance(PIT_Type *base) } } - assert(instance < FSL_FEATURE_SOC_PIT_COUNT); + assert(instance < ARRAY_SIZE(s_pitBases)); return instance; } @@ -76,8 +78,10 @@ void PIT_Init(PIT_Type *base, const pit_config_t *config) { assert(config); +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate the PIT clock*/ CLOCK_EnableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Enable PIT timers */ base->MCR &= ~PIT_MCR_MDIS_MASK; @@ -98,8 +102,10 @@ void PIT_Deinit(PIT_Type *base) /* Disable PIT timers */ base->MCR |= PIT_MCR_MDIS_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the PIT clock*/ CLOCK_DisableClock(s_pitClocks[PIT_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } #if defined(FSL_FEATURE_PIT_HAS_LIFETIME_TIMER) && FSL_FEATURE_PIT_HAS_LIFETIME_TIMER diff --git a/drivers/fsl_pit.h b/drivers/fsl_pit.h index f94c14a..99c30e1 100644 --- a/drivers/fsl_pit.h +++ b/drivers/fsl_pit.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -72,13 +72,13 @@ typedef enum _pit_status_flags } pit_status_flags_t; /*! - * @brief PIT config structure + * @brief PIT configuration structure * * This structure holds the configuration settings for the PIT peripheral. To initialize this * structure to reasonable defaults, call the PIT_GetDefaultConfig() function and pass a * pointer to your config structure instance. * - * The config struct can be made const so it resides in flash + * The configuration structure can be made constant so it resides in flash. */ typedef struct _pit_config { @@ -99,30 +99,30 @@ extern "C" { */ /*! - * @brief Ungates the PIT clock, enables the PIT module and configures the peripheral for basic operation. + * @brief Ungates the PIT clock, enables the PIT module, and configures the peripheral for basic operations. * * @note This API should be called at the beginning of the application using the PIT driver. * * @param base PIT peripheral base address - * @param config Pointer to user's PIT config structure + * @param config Pointer to the user's PIT config structure */ void PIT_Init(PIT_Type *base, const pit_config_t *config); /*! - * @brief Gate the PIT clock and disable the PIT module + * @brief Gates the PIT clock and disables the PIT module. * * @param base PIT peripheral base address */ void PIT_Deinit(PIT_Type *base); /*! - * @brief Fill in the PIT config struct with the default settings + * @brief Fills in the PIT configuration structure with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->enableRunInDebug = false; * @endcode - * @param config Pointer to user's PIT config structure. + * @param config Pointer to the onfiguration structure. */ static inline void PIT_GetDefaultConfig(pit_config_t *config) { @@ -139,9 +139,9 @@ static inline void PIT_GetDefaultConfig(pit_config_t *config) * * When a timer has a chain mode enabled, it only counts after the previous * timer has expired. If the timer n-1 has counted down to 0, counter n - * decrements the value by one. Each timer is 32-bits, this allows the developers + * decrements the value by one. Each timer is 32-bits, which allows the developers * to chain timers together and form a longer timer (64-bits and larger). The first timer - * (timer 0) cannot be chained to any other timer. + * (timer 0) can't be chained to any other timer. * * @param base PIT peripheral base address * @param channel Timer channel number which is chained with the previous timer @@ -218,7 +218,7 @@ static inline uint32_t PIT_GetEnabledInterrupts(PIT_Type *base, pit_chnl_t chann */ /*! - * @brief Gets the PIT status flags + * @brief Gets the PIT status flags. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -259,7 +259,7 @@ static inline void PIT_ClearStatusFlags(PIT_Type *base, pit_chnl_t channel, uint * Writing a new value to this register does not restart the timer. Instead, the value * is loaded after the timer expires. * - * @note User can call the utility macros provided in fsl_common.h to convert to ticks + * @note Users can call the utility macros provided in fsl_common.h to convert to ticks. * * @param base PIT peripheral base address * @param channel Timer channel number @@ -276,7 +276,7 @@ static inline void PIT_SetTimerPeriod(PIT_Type *base, pit_chnl_t channel, uint32 * This function returns the real-time timer counting value, in a range from 0 to a * timer period. * - * @note User can call the utility macros provided in fsl_common.h to convert ticks to usec or msec + * @note Users can call the utility macros provided in fsl_common.h to convert ticks to usec or msec. * * @param base PIT peripheral base address * @param channel Timer channel number diff --git a/drivers/fsl_pmc.c b/drivers/fsl_pmc.c index 82d7b7a..bcdd5cb 100644 --- a/drivers/fsl_pmc.c +++ b/drivers/fsl_pmc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/drivers/fsl_pmc.h b/drivers/fsl_pmc.h index f39a22f..99fc149 100644 --- a/drivers/fsl_pmc.h +++ b/drivers/fsl_pmc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -48,36 +48,36 @@ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) /*! - * @brief Low-Voltage Detect Voltage Select + * @brief Low-voltage Detect Voltage Select */ typedef enum _pmc_low_volt_detect_volt_select { - kPMC_LowVoltDetectLowTrip = 0U, /*!< Low trip point selected (VLVD = VLVDL )*/ - kPMC_LowVoltDetectHighTrip = 1U /*!< High trip point selected (VLVD = VLVDH )*/ + kPMC_LowVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VLVD = VLVDL )*/ + kPMC_LowVoltDetectHighTrip = 1U /*!< High-trip point selected (VLVD = VLVDH )*/ } pmc_low_volt_detect_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_LVWV) && FSL_FEATURE_PMC_HAS_LVWV) /*! - * @brief Low-Voltage Warning Voltage Select + * @brief Low-voltage Warning Voltage Select */ typedef enum _pmc_low_volt_warning_volt_select { - kPMC_LowVoltWarningLowTrip = 0U, /*!< Low trip point selected (VLVW = VLVW1)*/ + kPMC_LowVoltWarningLowTrip = 0U, /*!< Low-trip point selected (VLVW = VLVW1)*/ kPMC_LowVoltWarningMid1Trip = 1U, /*!< Mid 1 trip point selected (VLVW = VLVW2)*/ kPMC_LowVoltWarningMid2Trip = 2U, /*!< Mid 2 trip point selected (VLVW = VLVW3)*/ - kPMC_LowVoltWarningHighTrip = 3U /*!< High trip point selected (VLVW = VLVW4)*/ + kPMC_LowVoltWarningHighTrip = 3U /*!< High-trip point selected (VLVW = VLVW4)*/ } pmc_low_volt_warning_volt_select_t; #endif #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Voltage Select + * @brief High-voltage Detect Voltage Select */ typedef enum _pmc_high_volt_detect_volt_select { - kPMC_HighVoltDetectLowTrip = 0U, /*!< Low trip point selected (VHVD = VHVDL )*/ - kPMC_HighVoltDetectHighTrip = 1U /*!< High trip point selected (VHVD = VHVDH )*/ + kPMC_HighVoltDetectLowTrip = 0U, /*!< Low-trip point selected (VHVD = VHVDL )*/ + kPMC_HighVoltDetectHighTrip = 1U /*!< High-trip point selected (VHVD = VHVDH )*/ } pmc_high_volt_detect_volt_select_t; #endif /* FSL_FEATURE_PMC_HAS_HVDSC1 */ @@ -87,8 +87,8 @@ typedef enum _pmc_high_volt_detect_volt_select */ typedef enum _pmc_bandgap_buffer_drive_select { - kPMC_BandgapBufferDriveLow = 0U, /*!< Low drive. */ - kPMC_BandgapBufferDriveHigh = 1U /*!< High drive. */ + kPMC_BandgapBufferDriveLow = 0U, /*!< Low-drive. */ + kPMC_BandgapBufferDriveHigh = 1U /*!< High-drive. */ } pmc_bandgap_buffer_drive_select_t; #endif /* FSL_FEATURE_PMC_HAS_BGBDS */ @@ -125,19 +125,19 @@ typedef struct _pmc_param #endif /* FSL_FEATURE_PMC_HAS_PARAM */ /*! - * @brief Low-Voltage Detect Configuration Structure + * @brief Low-voltage Detect Configuration Structure */ typedef struct _pmc_low_volt_detect_config { - bool enableInt; /*!< Enable interrupt when low-voltage detect*/ - bool enableReset; /*!< Enable system reset when low-voltage detect*/ + bool enableInt; /*!< Enable interrupt when Low-voltage detect*/ + bool enableReset; /*!< Enable system reset when Low-voltage detect*/ #if (defined(FSL_FEATURE_PMC_HAS_LVDV) && FSL_FEATURE_PMC_HAS_LVDV) pmc_low_volt_detect_volt_select_t voltSelect; /*!< Low-voltage detect trip point voltage selection*/ #endif } pmc_low_volt_detect_config_t; /*! - * @brief Low-Voltage Warning Configuration Structure + * @brief Low-voltage Warning Configuration Structure */ typedef struct _pmc_low_volt_warning_config { @@ -149,7 +149,7 @@ typedef struct _pmc_low_volt_warning_config #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief High-Voltage Detect Configuration Structure + * @brief High-voltage Detect Configuration Structure */ typedef struct _pmc_high_volt_detect_config { @@ -195,7 +195,7 @@ extern "C" { * @brief Gets the PMC version ID. * * This function gets the PMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and a feature specification number. * * @param base PMC peripheral base address. * @param versionId Pointer to version ID structure. @@ -210,7 +210,7 @@ static inline void PMC_GetVersionId(PMC_Type *base, pmc_version_id_t *versionId) /*! * @brief Gets the PMC parameter. * - * This function gets the PMC parameter, including VLPO enable and HVD enable. + * This function gets the PMC parameter including the VLPO enable and the HVD enable. * * @param base PMC peripheral base address. * @param param Pointer to PMC param structure. @@ -219,18 +219,18 @@ void PMC_GetParam(PMC_Type *base, pmc_param_t *param); #endif /*! - * @brief Configure the low-voltage detect setting. + * @brief Configures the low-voltage detect setting. * * This function configures the low-voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * point voltage setting, enables or disables the interrupt, enables or disables the system reset. * * @param base PMC peripheral base address. - * @param config Low-Voltage detect configuration structure. + * @param config Low-voltage detect configuration structure. */ void PMC_ConfigureLowVoltDetect(PMC_Type *base, const pmc_low_volt_detect_config_t *config); /*! - * @brief Get Low-Voltage Detect Flag status + * @brief Gets the Low-voltage Detect Flag status. * * This function reads the current LVDF status. If it returns 1, a low-voltage event is detected. * @@ -245,7 +245,7 @@ static inline bool PMC_GetLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the Low-voltage Detect flag + * @brief Acknowledges clearing the Low-voltage Detect flag. * * This function acknowledges the low-voltage detection errors (write 1 to * clear LVDF). @@ -258,18 +258,18 @@ static inline void PMC_ClearLowVoltDetectFlag(PMC_Type *base) } /*! - * @brief Configure the low-voltage warning setting. + * @brief Configures the low-voltage warning setting. * * This function configures the low-voltage warning setting, including the trip - * point voltage setting and enable interrupt or not. + * point voltage setting and enabling or disabling the interrupt. * * @param base PMC peripheral base address. - * @param config Low-Voltage warning configuration structure. + * @param config Low-voltage warning configuration structure. */ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_config_t *config); /*! - * @brief Get Low-Voltage Warning Flag status + * @brief Gets the Low-voltage Warning Flag status. * * This function polls the current LVWF status. When 1 is returned, it * indicates a low-voltage warning event. LVWF is set when V Supply transitions @@ -277,8 +277,8 @@ void PMC_ConfigureLowVoltWarning(PMC_Type *base, const pmc_low_volt_warning_conf * * @param base PMC peripheral base address. * @return Current LVWF status - * - true: Low-Voltage Warning Flag is set. - * - false: the Low-Voltage Warning does not happen. + * - true: Low-voltage Warning Flag is set. + * - false: the Low-voltage Warning does not happen. */ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) { @@ -286,7 +286,7 @@ static inline bool PMC_GetLowVoltWarningFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Low-Voltage Warning flag + * @brief Acknowledges the Low-voltage Warning flag. * * This function acknowledges the low voltage warning errors (write 1 to * clear LVWF). @@ -300,10 +300,10 @@ static inline void PMC_ClearLowVoltWarningFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_HVDSC1) && FSL_FEATURE_PMC_HAS_HVDSC1) /*! - * @brief Configure the high-voltage detect setting. + * @brief Configures the high-voltage detect setting. * * This function configures the high-voltage detect setting, including the trip - * point voltage setting, enable interrupt or not, enable system reset or not. + * point voltage setting, enabling or disabling the interrupt, enabling or disabling the system reset. * * @param base PMC peripheral base address. * @param config High-voltage detect configuration structure. @@ -311,15 +311,15 @@ static inline void PMC_ClearLowVoltWarningFlag(PMC_Type *base) void PMC_ConfigureHighVoltDetect(PMC_Type *base, const pmc_high_volt_detect_config_t *config); /*! - * @brief Get High-Voltage Detect Flag status + * @brief Gets the High-voltage Detect Flag status. * * This function reads the current HVDF status. If it returns 1, a low * voltage event is detected. * * @param base PMC peripheral base address. * @return Current high-voltage detect flag - * - true: High-Voltage detected - * - false: High-Voltage not detected + * - true: High-voltage detected + * - false: High-voltage not detected */ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) { @@ -327,7 +327,7 @@ static inline bool PMC_GetHighVoltDetectFlag(PMC_Type *base) } /*! - * @brief Acknowledge to clear the High-Voltage Detect flag + * @brief Acknowledges clearing the High-voltage Detect flag. * * This function acknowledges the high-voltage detection errors (write 1 to * clear HVDF). @@ -344,7 +344,7 @@ static inline void PMC_ClearHighVoltDetectFlag(PMC_Type *base) (defined(FSL_FEATURE_PMC_HAS_BGEN) && FSL_FEATURE_PMC_HAS_BGEN) || \ (defined(FSL_FEATURE_PMC_HAS_BGBDS) && FSL_FEATURE_PMC_HAS_BGBDS)) /*! - * @brief Configure the PMC bandgap + * @brief Configures the PMC bandgap. * * This function configures the PMC bandgap, including the drive select and * behavior in low-power mode. @@ -376,7 +376,7 @@ static inline bool PMC_GetPeriphIOIsolationFlag(PMC_Type *base) } /*! - * @brief Acknowledge to Peripherals and I/O pads isolation flag. + * @brief Acknowledges the isolation flag to Peripherals and I/O pads. * * This function clears the ACK Isolation flag. Writing one to this setting * when it is set releases the I/O pads and certain peripherals to their normal @@ -392,9 +392,9 @@ static inline void PMC_ClearPeriphIOIsolationFlag(PMC_Type *base) #if (defined(FSL_FEATURE_PMC_HAS_REGONS) && FSL_FEATURE_PMC_HAS_REGONS) /*! - * @brief Gets the Regulator regulation status. + * @brief Gets the regulator regulation status. * - * This function returns the regulator to a run regulation status. It provides + * This function returns the regulator to run a regulation status. It provides * the current status of the internal voltage regulator. * * @param base PMC peripheral base address. diff --git a/drivers/fsl_port.h b/drivers/fsl_port.h index 935b032..eb8e77e 100644 --- a/drivers/fsl_port.h +++ b/drivers/fsl_port.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SDRVL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -37,17 +37,17 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! Version 2.0.1. */ -#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) +/*! Version 2.0.2. */ +#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*@}*/ +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE /*! @brief Internal resistor pull feature selection */ enum _port_pull { @@ -55,36 +55,43 @@ enum _port_pull kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */ kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */ }; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE /*! @brief Slew rate selection */ enum _port_slew_rate { kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */ kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN -/*! @brief Internal resistor pull feature enable/disable */ +/*! @brief Open Drain feature enable/disable */ enum _port_open_drain_enable { - kPORT_OpenDrainDisable = 0U, /*!< Internal pull-down resistor is disabled. */ - kPORT_OpenDrainEnable = 1U, /*!< Internal pull-up resistor is enabled. */ + kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */ + kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */ }; #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER /*! @brief Passive filter feature enable/disable */ enum _port_passive_filter_enable { - kPORT_PassiveFilterDisable = 0U, /*!< Fast slew rate is configured. */ - kPORT_PassiveFilterEnable = 1U, /*!< Slow slew rate is configured. */ + kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */ + kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */ }; +#endif +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH /*! @brief Configures the drive strength. */ enum _port_drive_strength { kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */ kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */ }; +#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */ #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK /*! @brief Unlock/lock the pin control register field[15:0] */ @@ -95,6 +102,7 @@ enum _port_lock_register }; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @brief Pin mux selection */ typedef enum _port_mux { @@ -106,7 +114,16 @@ typedef enum _port_mux kPORT_MuxAlt5 = 5U, /*!< Chip-specific */ kPORT_MuxAlt6 = 6U, /*!< Chip-specific */ kPORT_MuxAlt7 = 7U, /*!< Chip-specific */ + kPORT_MuxAlt8 = 8U, /*!< Chip-specific */ + kPORT_MuxAlt9 = 9U, /*!< Chip-specific */ + kPORT_MuxAlt10 = 10U, /*!< Chip-specific */ + kPORT_MuxAlt11 = 11U, /*!< Chip-specific */ + kPORT_MuxAlt12 = 12U, /*!< Chip-specific */ + kPORT_MuxAlt13 = 13U, /*!< Chip-specific */ + kPORT_MuxAlt14 = 14U, /*!< Chip-specific */ + kPORT_MuxAlt15 = 15U, /*!< Chip-specific */ } port_mux_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /*! @brief Configures the interrupt generation condition. */ typedef enum _port_interrupt @@ -149,44 +166,76 @@ typedef struct _port_digital_filter_config } port_digital_filter_config_t; #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */ +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @brief PORT pin configuration structure */ typedef struct _port_pin_config { +#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */ - uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */ +#else + uint16_t : 2; +#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */ + +#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE + uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */ + uint16_t : 1; + +#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */ +#else + uint16_t : 1; +#endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */ + #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */ #else uint16_t : 1; -#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ +#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */ + +#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */ +#else + uint16_t : 1; +#endif + uint16_t : 1; + +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH uint16_t mux : 3; /*!< Pin mux Configure */ +#else + uint16_t : 3; +#endif + uint16_t : 4; + #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */ #else uint16_t : 1; #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */ } port_pin_config_t; +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ /******************************************************************************* - * API - ******************************************************************************/ +* API +******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif +#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH /*! @name Configuration */ /*@{*/ /*! * @brief Sets the port PCR register. * - * This is an example to define an input pin or output pin PCR configuration: + * This is an example to define an input pin or output pin PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -214,7 +263,7 @@ static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_p /*! * @brief Sets the port PCR register for multiple pins. * - * This is an example to define input pins or output pins PCR configuration: + * This is an example to define input pins or output pins PCR configuration. * @code * // Define a digital input pin PCR configuration * port_pin_config_t config = { @@ -273,6 +322,7 @@ static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux) { base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux); } +#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */ #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER @@ -352,7 +402,7 @@ static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, por * * @param base PORT peripheral base pointer. * @return Current port interrupt status flags, for example, 0x00010001 means the - * pin 0 and 17 have the interrupt. + * pin 0 and 16 have the interrupt. */ static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base) { diff --git a/drivers/fsl_rcm.c b/drivers/fsl_rcm.c index 9cf7479..0d73864 100644 --- a/drivers/fsl_rcm.c +++ b/drivers/fsl_rcm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/drivers/fsl_rcm.h b/drivers/fsl_rcm.h index fbc5169..99b843a 100644 --- a/drivers/fsl_rcm.h +++ b/drivers/fsl_rcm.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -111,7 +111,7 @@ typedef enum _rcm_reset_source } rcm_reset_source_t; /*! - * @brief Reset pin filter select in Run and Wait modes + * @brief Reset pin filter select in Run and Wait modes. */ typedef enum _rcm_run_wait_filter_mode { @@ -135,7 +135,7 @@ typedef enum _rcm_boot_rom_config #if (defined(FSL_FEATURE_RCM_HAS_SRIE) && FSL_FEATURE_RCM_HAS_SRIE) /*! - * @brief Max delay time from interrupt asserts to system reset. + * @brief Maximum delay time from interrupt asserts to system reset. */ typedef enum _rcm_reset_delay { @@ -186,7 +186,7 @@ typedef struct _rcm_version_id #endif /*! - * @brief Reset pin filter configuration + * @brief Reset pin filter configuration. */ typedef struct _rcm_reset_pin_filter_config { @@ -213,7 +213,7 @@ extern "C" { * the minor version number, and the feature specification number. * * @param base RCM peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) { @@ -228,7 +228,7 @@ static inline void RCM_GetVersionId(RCM_Type *base, rcm_version_id_t *versionId) * This function gets the RCM parameter that indicates whether the corresponding reset source is implemented. * Use source masks defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t status; @@ -251,7 +251,7 @@ static inline uint32_t RCM_GetResetSourceImplementedStatus(RCM_Type *base) * This function gets the current reset source status. Use source masks * defined in the rcm_reset_source_t to get the desired source status. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -282,9 +282,9 @@ static inline uint32_t RCM_GetPreviousResetSources(RCM_Type *base) * @brief Gets the sticky reset source status. * * This function gets the current reset source status that has not been cleared - * by software for some specific source. + * by software for a specific source. * - * Example: + * This is an example. @code uint32_t resetStatus; @@ -315,7 +315,7 @@ static inline uint32_t RCM_GetStickyResetSources(RCM_Type *base) * * This function clears the sticky system reset flags indicated by source masks. * - * Example: + * This is an example. @code // Clears multiple reset sources. RCM_ClearStickyResetSources(kRCM_SourceWdog | kRCM_SourcePin); diff --git a/drivers/fsl_rtc.c b/drivers/fsl_rtc.c index db6a2fa..d68055a 100644 --- a/drivers/fsl_rtc.c +++ b/drivers/fsl_rtc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -211,7 +211,9 @@ void RTC_Init(RTC_Type *base, const rtc_config_t *config) uint32_t reg; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Issue a software reset if timer is invalid */ if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag) diff --git a/drivers/fsl_rtc.h b/drivers/fsl_rtc.h index 4357c2e..99effc6 100644 --- a/drivers/fsl_rtc.h +++ b/drivers/fsl_rtc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -69,10 +69,10 @@ typedef enum _rtc_status_flags /*! @brief List of RTC Oscillator capacitor load settings */ typedef enum _rtc_osc_cap_load { - kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2pF capacitor load */ - kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4pF capacitor load */ - kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8pF capacitor load */ - kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16pF capacitor load */ + kRTC_Capacitor_2p = RTC_CR_SC2P_MASK, /*!< 2 pF capacitor load */ + kRTC_Capacitor_4p = RTC_CR_SC4P_MASK, /*!< 4 pF capacitor load */ + kRTC_Capacitor_8p = RTC_CR_SC8P_MASK, /*!< 8 pF capacitor load */ + kRTC_Capacitor_16p = RTC_CR_SC16P_MASK /*!< 16 pF capacitor load */ } rtc_osc_cap_load_t; #endif /* FSL_FEATURE_SCG_HAS_OSC_SCXP */ @@ -125,17 +125,17 @@ extern "C" { /*! * @brief Ungates the RTC clock and configures the peripheral for basic operation. * - * This function will issue a software reset if the timer invalid flag is set. + * This function issues a software reset if the timer invalid flag is set. * * @note This API should be called at the beginning of the application using the RTC driver. * * @param base RTC peripheral base address - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_Init(RTC_Type *base, const rtc_config_t *config); /*! - * @brief Stop the timer and gate the RTC clock + * @brief Stops the timer and gate the RTC clock. * * @param base RTC peripheral base address */ @@ -144,14 +144,16 @@ static inline void RTC_Deinit(RTC_Type *base) /* Stop the RTC timer */ base->SR &= ~RTC_SR_TCE_MASK; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate the module clock */ CLOCK_DisableClock(kCLOCK_Rtc0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } /*! - * @brief Fill in the RTC config struct with the default settings + * @brief Fills in the RTC config struct with the default settings. * - * The default values are: + * The default values are as follows. * @code * config->wakeupSelect = false; * config->updateMode = false; @@ -159,7 +161,7 @@ static inline void RTC_Deinit(RTC_Type *base) * config->compensationInterval = 0; * config->compensationTime = 0; * @endcode - * @param config Pointer to user's RTC config structure. + * @param config Pointer to the user's RTC configuration structure. */ void RTC_GetDefaultConfig(rtc_config_t *config); @@ -173,11 +175,11 @@ void RTC_GetDefaultConfig(rtc_config_t *config); /*! * @brief Sets the RTC date and time according to the given time structure. * - * The RTC counter must be stopped prior to calling this function as writes to the RTC - * seconds register will fail if the RTC counter is running. + * The RTC counter must be stopped prior to calling this function because writes to the RTC + * seconds register fail if the RTC counter is running. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details to set are stored + * @param datetime Pointer to the structure where the date and time details are stored. * * @return kStatus_Success: Success in setting the time and starting the RTC * kStatus_InvalidArgument: Error because the datetime format is incorrect @@ -188,18 +190,18 @@ status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime); * @brief Gets the RTC time and stores it in the given time structure. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the date and time details are stored. + * @param datetime Pointer to the structure where the date and time details are stored. */ void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime); /*! - * @brief Sets the RTC alarm time + * @brief Sets the RTC alarm time. * * The function checks whether the specified alarm time is greater than the present * time. If not, the function does not set the alarm and returns an error. * * @param base RTC peripheral base address - * @param alarmTime Pointer to structure where the alarm time is stored. + * @param alarmTime Pointer to the structure where the alarm time is stored. * * @return kStatus_Success: success in setting the RTC alarm * kStatus_InvalidArgument: Error because the alarm datetime format is incorrect @@ -211,7 +213,7 @@ status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime); * @brief Returns the RTC alarm time. * * @param base RTC peripheral base address - * @param datetime Pointer to structure where the alarm date and time details are stored. + * @param datetime Pointer to the structure where the alarm date and time details are stored. */ void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime); @@ -267,7 +269,7 @@ static inline uint32_t RTC_GetEnabledInterrupts(RTC_Type *base) */ /*! - * @brief Gets the RTC status flags + * @brief Gets the RTC status flags. * * @param base RTC peripheral base address * diff --git a/drivers/fsl_sdhc.c b/drivers/fsl_sdhc.c index 7697cdc..3151cd2 100644 --- a/drivers/fsl_sdhc.c +++ b/drivers/fsl_sdhc.c @@ -1,34 +1,28 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * - * Redistribution and use in source and binary forms, with or without - * modification, + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this - * list + * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * - * o Redistributions in binary form must reproduce the above copyright notice, - * this + * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @@ -42,14 +36,13 @@ /*! @brief Clock setting */ /* Max SD clock divisor from base clock */ #define SDHC_MAX_DVS ((SDHC_SYSCTL_DVS_MASK >> SDHC_SYSCTL_DVS_SHIFT) + 1U) -#define SDHC_INITIAL_DVS (1U) /* Initial value of SD clock divisor */ -#define SDHC_INITIAL_CLKFS (2U) /* Initial value of SD clock frequency selector */ -#define SDHC_NEXT_DVS(x) ((x) += 1U) #define SDHC_PREV_DVS(x) ((x) -= 1U) #define SDHC_MAX_CLKFS ((SDHC_SYSCTL_SDCLKFS_MASK >> SDHC_SYSCTL_SDCLKFS_SHIFT) + 1U) -#define SDHC_NEXT_CLKFS(x) ((x) <<= 1U) #define SDHC_PREV_CLKFS(x) ((x) >>= 1U) +/* Typedef for interrupt handler. */ +typedef void (*sdhc_isr_t)(SDHC_Type *base, sdhc_handle_t *handle); + /*! @brief ADMA table configuration */ typedef struct _sdhc_adma_table_config { @@ -82,8 +75,9 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal * @param base SDHC peripheral base address. * @param command Command to be sent. * @param data Data to be transferred. + * @param DMA mode selection */ -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data); +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode); /*! * @brief Receive command response @@ -91,7 +85,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da * @param base SDHC peripheral base address. * @param command Command to be sent. */ -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command); /*! * @brief Read DATAPORT when buffer enable bit is set. @@ -227,8 +221,13 @@ static SDHC_Type *const s_sdhcBase[] = SDHC_BASE_PTRS; /*! @brief SDHC IRQ name array */ static const IRQn_Type s_sdhcIRQ[] = SDHC_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief SDHC clock array name */ static const clock_ip_name_t s_sdhcClock[] = SDHC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/* SDHC ISR for transactional APIs. */ +static sdhc_isr_t s_sdhcIsr; /******************************************************************************* * Code @@ -237,12 +236,12 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) { uint8_t instance = 0; - while ((instance < FSL_FEATURE_SOC_SDHC_COUNT) && (s_sdhcBase[instance] != base)) + while ((instance < ARRAY_SIZE(s_sdhcBase)) && (s_sdhcBase[instance] != base)) { instance++; } - assert(instance < FSL_FEATURE_SOC_SDHC_COUNT); + assert(instance < ARRAY_SIZE(s_sdhcBase)); return instance; } @@ -250,7 +249,6 @@ static uint32_t SDHC_GetInstance(SDHC_Type *base) static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal) { uint32_t interruptEnabled; /* The Interrupt status flags to be enabled */ - sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); bool cardDetectDat3 = (bool)(base->PROCTL & SDHC_PROCTL_D3CD_MASK); /* Disable all interrupts */ @@ -261,23 +259,12 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal interruptEnabled = (kSDHC_CommandIndexErrorFlag | kSDHC_CommandCrcErrorFlag | kSDHC_CommandEndBitErrorFlag | kSDHC_CommandTimeoutFlag | kSDHC_CommandCompleteFlag | kSDHC_DataTimeoutFlag | kSDHC_DataCrcErrorFlag | - kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag); + kSDHC_DataEndBitErrorFlag | kSDHC_DataCompleteFlag | kSDHC_AutoCommand12ErrorFlag | kSDHC_BufferReadReadyFlag | + kSDHC_BufferWriteReadyFlag | kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); if (cardDetectDat3) { interruptEnabled |= (kSDHC_CardInsertionFlag | kSDHC_CardRemovalFlag); } - switch (dmaMode) - { - case kSDHC_DmaModeAdma1: - case kSDHC_DmaModeAdma2: - interruptEnabled |= (kSDHC_DmaErrorFlag | kSDHC_DmaCompleteFlag); - break; - case kSDHC_DmaModeNo: - interruptEnabled |= (kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); - break; - default: - break; - } SDHC_EnableInterruptStatus(base, interruptEnabled); if (usingInterruptSignal) @@ -286,50 +273,47 @@ static void SDHC_SetTransferInterrupt(SDHC_Type *base, bool usingInterruptSignal } } -static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data) +static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_data_t *data, sdhc_dma_mode_t dmaMode) { - assert(command); - uint32_t flags = 0U; - sdhc_transfer_config_t sdhcTransferConfig; - sdhc_dma_mode_t dmaMode; + sdhc_transfer_config_t sdhcTransferConfig = {0}; /* Define the flag corresponding to each response type. */ switch (command->responseType) { - case kSDHC_ResponseTypeNone: + case kCARD_ResponseTypeNone: break; - case kSDHC_ResponseTypeR1: /* Response 1 */ + case kCARD_ResponseTypeR1: /* Response 1 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR1b: /* Response 1 with busy */ + case kCARD_ResponseTypeR1b: /* Response 1 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR2: /* Response 2 */ + case kCARD_ResponseTypeR2: /* Response 2 */ flags |= (kSDHC_ResponseLength136Flag | kSDHC_EnableCrcCheckFlag); break; - case kSDHC_ResponseTypeR3: /* Response 3 */ + case kCARD_ResponseTypeR3: /* Response 3 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR4: /* Response 4 */ + case kCARD_ResponseTypeR4: /* Response 4 */ flags |= (kSDHC_ResponseLength48Flag); break; - case kSDHC_ResponseTypeR5: /* Response 5 */ - flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag); + case kCARD_ResponseTypeR5: /* Response 5 */ + flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR5b: /* Response 5 with busy */ + case kCARD_ResponseTypeR5b: /* Response 5 with busy */ flags |= (kSDHC_ResponseLength48BusyFlag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR6: /* Response 6 */ + case kCARD_ResponseTypeR6: /* Response 6 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; - case kSDHC_ResponseTypeR7: /* Response 7 */ + case kCARD_ResponseTypeR7: /* Response 7 */ flags |= (kSDHC_ResponseLength48Flag | kSDHC_EnableCrcCheckFlag | kSDHC_EnableIndexCheckFlag); break; default: break; } - if (command->type == kSDHC_CommandTypeAbort) + if (command->type == kCARD_CommandTypeAbort) { flags |= kSDHC_CommandTypeAbortFlag; } @@ -337,7 +321,7 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da if (data) { flags |= kSDHC_DataPresentFlag; - dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); + if (dmaMode != kSDHC_DmaModeNo) { flags |= kSDHC_EnableDmaFlag; @@ -355,18 +339,9 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da flags |= kSDHC_EnableAutoCommand12Flag; } } - if (data->blockCount > SDHC_MAX_BLOCK_COUNT) - { - sdhcTransferConfig.dataBlockSize = data->blockSize; - sdhcTransferConfig.dataBlockCount = SDHC_MAX_BLOCK_COUNT; - flags &= ~(uint32_t)kSDHC_EnableBlockCountFlag; - } - else - { - sdhcTransferConfig.dataBlockSize = data->blockSize; - sdhcTransferConfig.dataBlockCount = data->blockCount; - } + sdhcTransferConfig.dataBlockSize = data->blockSize; + sdhcTransferConfig.dataBlockCount = data->blockCount; } else { @@ -380,16 +355,14 @@ static void SDHC_StartTransfer(SDHC_Type *base, sdhc_command_t *command, sdhc_da SDHC_SetTransferConfig(base, &sdhcTransferConfig); } -static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) +static status_t SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command) { - assert(command); - uint32_t i; - if (command->responseType != kSDHC_ResponseTypeNone) + if (command->responseType != kCARD_ResponseTypeNone) { command->response[0U] = SDHC_GetCommandResponse(base, 0U); - if (command->responseType == kSDHC_ResponseTypeR2) + if (command->responseType == kCARD_ResponseTypeR2) { command->response[1U] = SDHC_GetCommandResponse(base, 1U); command->response[2U] = SDHC_GetCommandResponse(base, 2U); @@ -408,17 +381,38 @@ static void SDHC_ReceiveCommandResponse(SDHC_Type *base, sdhc_command_t *command } while (i--); } } + /* check response error flag */ + if ((command->responseErrorFlags != 0U) && + ((command->responseType == kCARD_ResponseTypeR1) || (command->responseType == kCARD_ResponseTypeR1b) || + (command->responseType == kCARD_ResponseTypeR6) || (command->responseType == kCARD_ResponseTypeR5))) + { + if (((command->responseErrorFlags) & (command->response[0U])) != 0U) + { + return kStatus_SDHC_SendCommandFailed; + } + } + + return kStatus_Success; } static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) { - assert(data); - uint32_t i; uint32_t totalWords; uint32_t wordsCanBeRead; /* The words can be read at this time. */ uint32_t readWatermark = ((base->WML & SDHC_WML_RDWML_MASK) >> SDHC_WML_RDWML_SHIFT); + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (data->blockSize % sizeof(uint32_t) != 0U) + { + data->blockSize += + sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */ + } + totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); /* If watermark level is equal or bigger than totalWords, transfers totalWords data. */ @@ -451,12 +445,21 @@ static uint32_t SDHC_ReadDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t t static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { - assert(data); - uint32_t totalWords; uint32_t transferredWords = 0U; status_t error = kStatus_Success; + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (data->blockSize % sizeof(uint32_t) != 0U) + { + data->blockSize += + sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */ + } + totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); while ((error == kStatus_Success) && (transferredWords < totalWords)) @@ -476,26 +479,34 @@ static status_t SDHC_ReadByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { transferredWords = SDHC_ReadDataPort(base, data, transferredWords); } - - /* Clear buffer enable flag to trigger transfer. Clear data error flag when SDHC encounter error */ - SDHC_ClearInterruptStatusFlags(base, (kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag)); + /* clear buffer ready and error */ + SDHC_ClearInterruptStatusFlags(base, kSDHC_BufferReadReadyFlag | kSDHC_DataErrorFlag); } /* Clear data complete flag after the last read operation. */ - SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag); + SDHC_ClearInterruptStatusFlags(base, kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag); return error; } static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t transferredWords) { - assert(data); - uint32_t i; uint32_t totalWords; uint32_t wordsCanBeWrote; /* Words can be wrote at this time. */ uint32_t writeWatermark = ((base->WML & SDHC_WML_WRWML_MASK) >> SDHC_WML_WRWML_SHIFT); + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (data->blockSize % sizeof(uint32_t) != 0U) + { + data->blockSize += + sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */ + } + totalWords = ((data->blockCount * data->blockSize) / sizeof(uint32_t)); /* If watermark level is equal or bigger than totalWords, transfers totalWords data.*/ @@ -528,12 +539,21 @@ static uint32_t SDHC_WriteDataPort(SDHC_Type *base, sdhc_data_t *data, uint32_t static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { - assert(data); - uint32_t totalWords; uint32_t transferredWords = 0U; status_t error = kStatus_Success; + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (data->blockSize % sizeof(uint32_t) != 0U) + { + data->blockSize += + sizeof(uint32_t) - (data->blockSize % sizeof(uint32_t)); /* make the block size as word-aligned */ + } + totalWords = (data->blockCount * data->blockSize) / sizeof(uint32_t); while ((error == kStatus_Success) && (transferredWords < totalWords)) @@ -569,6 +589,7 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) error = kStatus_Fail; } } + SDHC_ClearInterruptStatusFlags(base, (kSDHC_DataCompleteFlag | kSDHC_DataErrorFlag)); return error; @@ -576,8 +597,6 @@ static status_t SDHC_WriteByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *command) { - assert(command); - status_t error = kStatus_Success; /* Wait command complete or SDHC encounters error. */ @@ -592,7 +611,7 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman /* Receive response when command completes successfully. */ if (error == kStatus_Success) { - SDHC_ReceiveCommandResponse(base, command); + error = SDHC_ReceiveCommandResponse(base, command); } SDHC_ClearInterruptStatusFlags(base, (kSDHC_CommandCompleteFlag | kSDHC_CommandErrorFlag)); @@ -602,8 +621,6 @@ static status_t SDHC_SendCommandBlocking(SDHC_Type *base, sdhc_command_t *comman static status_t SDHC_TransferByDataPortBlocking(SDHC_Type *base, sdhc_data_t *data) { - assert(data); - status_t error = kStatus_Success; if (data->rxData) @@ -669,8 +686,6 @@ static status_t SDHC_TransferDataBlocking(sdhc_dma_mode_t dmaMode, SDHC_Type *ba static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interruptFlags) { - assert(interruptFlags & kSDHC_CardDetectFlag); - if (interruptFlags & kSDHC_CardInsertionFlag) { if (handle->callback.CardInserted) @@ -689,7 +704,7 @@ static void SDHC_TransferHandleCardDetect(sdhc_handle_t *handle, uint32_t interr static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) { - assert(interruptFlags & kSDHC_CommandFlag); + assert(handle->command); if ((interruptFlags & kSDHC_CommandErrorFlag) && (!(handle->data)) && (handle->callback.TransferComplete)) { @@ -709,7 +724,6 @@ static void SDHC_TransferHandleCommand(SDHC_Type *base, sdhc_handle_t *handle, u static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint32_t interruptFlags) { assert(handle->data); - assert(interruptFlags & kSDHC_DataFlag); if ((!(handle->data->enableIgnoreError)) && (interruptFlags & (kSDHC_DataErrorFlag | kSDHC_DmaErrorFlag)) && (handle->callback.TransferComplete)) @@ -726,7 +740,11 @@ static void SDHC_TransferHandleData(SDHC_Type *base, sdhc_handle_t *handle, uint { handle->transferredWords = SDHC_WriteDataPort(base, handle->data, handle->transferredWords); } - else if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) + else + { + } + + if ((interruptFlags & kSDHC_DataCompleteFlag) && (handle->callback.TransferComplete)) { handle->callback.TransferComplete(base, handle, kStatus_Success, handle->userData); } @@ -759,12 +777,16 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) #if !defined FSL_SDHC_ENABLE_ADMA1 assert(config->dmaMode != kSDHC_DmaModeAdma1); #endif /* FSL_SDHC_ENABLE_ADMA1 */ + assert((config->writeWatermarkLevel >= 1U) && (config->writeWatermarkLevel <= 128U)); + assert((config->readWatermarkLevel >= 1U) && (config->readWatermarkLevel <= 128U)); uint32_t proctl; uint32_t wml; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable SDHC clock. */ CLOCK_EnableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Reset SDHC. */ SDHC_Reset(base, kSDHC_ResetAll, 100); @@ -798,8 +820,10 @@ void SDHC_Init(SDHC_Type *base, const sdhc_config_t *config) void SDHC_Deinit(SDHC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable clock. */ CLOCK_DisableClock(s_sdhcClock[SDHC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } bool SDHC_Reset(SDHC_Type *base, uint32_t mask, uint32_t timeout) @@ -850,46 +874,86 @@ void SDHC_GetCapability(SDHC_Type *base, sdhc_capability_t *capability) uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz) { - assert(busClock_Hz && (busClock_Hz < srcClock_Hz)); + assert(srcClock_Hz != 0U); + assert((busClock_Hz != 0U) && (busClock_Hz <= srcClock_Hz)); - uint32_t divisor; - uint32_t prescaler; - uint32_t sysctl; - uint32_t nearestFrequency = 0; + uint32_t totalDiv = 0U; + uint32_t divisor = 0U; + uint32_t prescaler = 0U; + uint32_t sysctl = 0U; + uint32_t nearestFrequency = 0U; - divisor = SDHC_INITIAL_DVS; - prescaler = SDHC_INITIAL_CLKFS; + /* calucate total divisor first */ + totalDiv = srcClock_Hz / busClock_Hz; - /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ - base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; - - if (busClock_Hz > 0U) + if (totalDiv != 0U) { - while ((srcClock_Hz / prescaler / SDHC_MAX_DVS > busClock_Hz) && (prescaler < SDHC_MAX_CLKFS)) + /* calucate the divisor (srcClock_Hz / divisor) <= busClock_Hz */ + if ((srcClock_Hz / totalDiv) > busClock_Hz) { - SDHC_NEXT_CLKFS(prescaler); + totalDiv++; } - while ((srcClock_Hz / prescaler / divisor > busClock_Hz) && (divisor < SDHC_MAX_DVS)) + + /* divide the total divisor to div and prescaler */ + if (totalDiv > SDHC_MAX_DVS) { - SDHC_NEXT_DVS(divisor); + prescaler = totalDiv / SDHC_MAX_DVS; + /* prescaler must be a value which equal 2^n and smaller than SDHC_MAX_CLKFS */ + while (((SDHC_MAX_CLKFS % prescaler) != 0U) || (prescaler == 1U)) + { + prescaler++; + } + /* calucate the divisor */ + divisor = totalDiv / prescaler; + /* fine tuning the divisor until divisor * prescaler >= totalDiv */ + while ((divisor * prescaler) < totalDiv) + { + divisor++; + } + nearestFrequency = srcClock_Hz / divisor / prescaler; } - nearestFrequency = srcClock_Hz / prescaler / divisor; - SDHC_PREV_CLKFS(prescaler); + else + { + divisor = totalDiv; + prescaler = 0U; + nearestFrequency = srcClock_Hz / divisor; + } + } + /* in this condition , srcClock_Hz = busClock_Hz, */ + else + { + /* total divider = 1U */ + divisor = 0U; + prescaler = 0U; + nearestFrequency = srcClock_Hz; + } + + /* calucate the value write to register */ + if (divisor != 0U) + { SDHC_PREV_DVS(divisor); + } + /* calucate the value write to register */ + if (prescaler != 0U) + { + SDHC_PREV_CLKFS(prescaler); + } - /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ - sysctl = base->SYSCTL; - sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); - sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); - base->SYSCTL = sysctl; + /* Disable SD clock. It should be disabled before changing the SD clock frequency.*/ + base->SYSCTL &= ~SDHC_SYSCTL_SDCLKEN_MASK; - /* Wait until the SD clock is stable. */ - while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) - { - } - /* Enable the SD clock. */ - base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; + /* Set the SD clock frequency divisor, SD clock frequency select, data timeout counter value. */ + sysctl = base->SYSCTL; + sysctl &= ~(SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK | SDHC_SYSCTL_DTOCV_MASK); + sysctl |= (SDHC_SYSCTL_DVS(divisor) | SDHC_SYSCTL_SDCLKFS(prescaler) | SDHC_SYSCTL_DTOCV(0xEU)); + base->SYSCTL = sysctl; + + /* Wait until the SD clock is stable. */ + while (!(base->PRSSTAT & SDHC_PRSSTAT_SDSTB_MASK)) + { } + /* Enable the SD clock. */ + base->SYSCTL |= SDHC_SYSCTL_SDCLKEN_MASK; return nearestFrequency; } @@ -898,7 +962,7 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout) { base->SYSCTL |= SDHC_SYSCTL_INITA_MASK; /* Delay some time to wait card become active state. */ - while (!(base->SYSCTL & SDHC_SYSCTL_INITA_MASK)) + while (base->SYSCTL & SDHC_SYSCTL_INITA_MASK) { if (!timeout) { @@ -913,6 +977,8 @@ bool SDHC_SetCardActive(SDHC_Type *base, uint32_t timeout) void SDHC_SetTransferConfig(SDHC_Type *base, const sdhc_transfer_config_t *config) { assert(config); + assert(config->dataBlockSize <= (SDHC_BLKATTR_BLKSIZE_MASK >> SDHC_BLKATTR_BLKSIZE_SHIFT)); + assert(config->dataBlockCount <= (SDHC_BLKATTR_BLKCNT_MASK >> SDHC_BLKATTR_BLKCNT_SHIFT)); base->BLKATTR = ((base->BLKATTR & ~(SDHC_BLKATTR_BLKSIZE_MASK | SDHC_BLKATTR_BLKCNT_MASK)) | (SDHC_BLKATTR_BLKSIZE(config->dataBlockSize) | SDHC_BLKATTR_BLKCNT(config->dataBlockCount))); @@ -975,12 +1041,13 @@ void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable) void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config) { assert(config); + assert(config->ackTimeoutCount <= (SDHC_MMCBOOT_DTOCVACK_MASK >> SDHC_MMCBOOT_DTOCVACK_SHIFT)); + assert(config->blockCount <= (SDHC_MMCBOOT_BOOTBLKCNT_MASK >> SDHC_MMCBOOT_BOOTBLKCNT_SHIFT)); - uint32_t mmcboot; + uint32_t mmcboot = 0U; - mmcboot = base->MMCBOOT; - mmcboot |= (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | - SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); + mmcboot = (SDHC_MMCBOOT_DTOCVACK(config->ackTimeoutCount) | SDHC_MMCBOOT_BOOTMODE(config->bootMode) | + SDHC_MMCBOOT_BOOTBLKCNT(config->blockCount)); if (config->enableBootAck) { mmcboot |= SDHC_MMCBOOT_BOOTACK_MASK; @@ -1004,7 +1071,7 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, uint32_t dataBytes) { status_t error = kStatus_Success; - const uint32_t *startAddress; + const uint32_t *startAddress = data; uint32_t entries; uint32_t i; #if defined FSL_SDHC_ENABLE_ADMA1 @@ -1016,14 +1083,19 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, (!data) || (!dataBytes) #if !defined FSL_SDHC_ENABLE_ADMA1 || (dmaMode == kSDHC_DmaModeAdma1) -#else - /* Buffer address configured in ADMA1 descriptor must be 4KB aligned. */ - || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)data % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) -#endif /* FSL_SDHC_ENABLE_ADMA1 */ +#endif ) { error = kStatus_InvalidArgument; } + else if (((dmaMode == kSDHC_DmaModeAdma2) && (((uint32_t)startAddress % SDHC_ADMA2_LENGTH_ALIGN) != 0U)) +#if defined FSL_SDHC_ENABLE_ADMA1 + || ((dmaMode == kSDHC_DmaModeAdma1) && (((uint32_t)startAddress % SDHC_ADMA1_LENGTH_ALIGN) != 0U)) +#endif + ) + { + error = kStatus_SDHC_DMADataBufferAddrNotAlign; + } else { switch (dmaMode) @@ -1032,7 +1104,17 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, break; #if defined FSL_SDHC_ENABLE_ADMA1 case kSDHC_DmaModeAdma1: - startAddress = data; + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (dataBytes % sizeof(uint32_t) != 0U) + { + dataBytes += + sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ + } + /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA1_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); /* ADMA1 needs two descriptors to finish a transfer */ @@ -1074,11 +1156,24 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer ready flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; #endif /* FSL_SDHC_ENABLE_ADMA1 */ case kSDHC_DmaModeAdma2: - startAddress = data; + /* + * Add non aligned access support ,user need make sure your buffer size is big + * enough to hold the data,in other words,user need make sure the buffer size + * is 4 byte aligned + */ + if (dataBytes % sizeof(uint32_t) != 0U) + { + dataBytes += + sizeof(uint32_t) - (dataBytes % sizeof(uint32_t)); /* make the data length as word-aligned */ + } + /* Check if ADMA descriptor's number is enough. */ entries = ((dataBytes / SDHC_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY) + 1U); if (entries > ((tableWords * sizeof(uint32_t)) / sizeof(sdhc_adma2_descriptor_t))) @@ -1115,6 +1210,9 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, /* When use ADMA, disable simple DMA */ base->DSADDR = 0U; base->ADSADDR = (uint32_t)table; + /* disable the buffer read flag in DMA mode */ + SDHC_DisableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_DisableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } break; default: @@ -1128,55 +1226,62 @@ status_t SDHC_SetAdmaTableConfig(SDHC_Type *base, status_t SDHC_TransferBlocking(SDHC_Type *base, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer) { assert(transfer); - assert(transfer->command); /* Command must not be NULL, data can be NULL. */ status_t error = kStatus_Success; sdhc_dma_mode_t dmaMode = (sdhc_dma_mode_t)((base->PROCTL & SDHC_PROCTL_DMAS_MASK) >> SDHC_PROCTL_DMAS_SHIFT); sdhc_command_t *command = transfer->command; sdhc_data_t *data = transfer->data; - /* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ - if ((!command) || (data && (data->blockSize % 4U))) + /* make sure the cmd/block count is valid */ + if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) { - /* Wait until command/data bus out of busy status. */ - while (SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) - { - } - while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + } + while (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag)) + { + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); } - - /* Update ADMA descriptor table if data isn't NULL. */ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) + else if (error != kStatus_Success) { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; + return error; } else { - SDHC_StartTransfer(base, command, data); - - /* Send command and receive data. */ - if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) - { - error = kStatus_SDHC_SendCommandFailed; - } - else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) - { - error = kStatus_SDHC_TransferDataFailed; - } - else - { - } } } - return error; + /* Send command and receive data. */ + SDHC_StartTransfer(base, command, data, dmaMode); + if (kStatus_Success != SDHC_SendCommandBlocking(base, command)) + { + return kStatus_SDHC_SendCommandFailed; + } + else if (data && (kStatus_Success != SDHC_TransferDataBlocking(dmaMode, base, data))) + { + return kStatus_SDHC_TransferDataFailed; + } + else + { + } + + return kStatus_Success; } void SDHC_TransferCreateHandle(SDHC_Type *base, @@ -1203,6 +1308,10 @@ void SDHC_TransferCreateHandle(SDHC_Type *base, /* Enable interrupt in NVIC. */ SDHC_SetTransferInterrupt(base, true); + + /* save IRQ handler */ + s_sdhcIsr = SDHC_TransferHandleIRQ; + EnableIRQ(s_sdhcIRQ[SDHC_GetInstance(base)]); } @@ -1216,42 +1325,52 @@ status_t SDHC_TransferNonBlocking( sdhc_command_t *command = transfer->command; sdhc_data_t *data = transfer->data; - /* DATA-PORT is 32-bit align, ADMA2 4 bytes align, ADMA1 is 4096 bytes align */ - if ((!(transfer->command)) || ((transfer->data) && (transfer->data->blockSize % 4U))) + /* make sure cmd/block count is valid */ + if ((!command) || (data && (data->blockCount > SDHC_MAX_BLOCK_COUNT))) { - error = kStatus_InvalidArgument; + return kStatus_InvalidArgument; } - else + + /* Wait until command/data bus out of busy status. */ + if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || + (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) { - /* Wait until command/data bus out of busy status. */ - if ((SDHC_GetPresentStatusFlags(base) & kSDHC_CommandInhibitFlag) || - (data && (SDHC_GetPresentStatusFlags(base) & kSDHC_DataInhibitFlag))) + return kStatus_SDHC_BusyTransferring; + } + + /* Update ADMA descriptor table according to different DMA mode(no DMA, ADMA1, ADMA2).*/ + if (data && (NULL != admaTable)) + { + error = + SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, + (data->rxData ? data->rxData : data->txData), (data->blockCount * data->blockSize)); + /* in this situation , we disable the DMA instead of polling transfer mode */ + if (error == kStatus_SDHC_DMADataBufferAddrNotAlign) { - error = kStatus_SDHC_BusyTransferring; + /* change to polling mode */ + dmaMode = kSDHC_DmaModeNo; + SDHC_EnableInterruptSignal(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + SDHC_EnableInterruptStatus(base, kSDHC_BufferReadReadyFlag | kSDHC_BufferWriteReadyFlag); + } + else if (error != kStatus_Success) + { + return error; } else { - /* Update ADMA descriptor table and reset transferred words if data isn't NULL. */ - if (data && (kStatus_Success != SDHC_SetAdmaTableConfig(base, dmaMode, admaTable, admaTableWords, - (data->rxData ? data->rxData : data->txData), - (data->blockCount * data->blockSize)))) - { - error = kStatus_SDHC_PrepareAdmaDescriptorFailed; - } - else - { - /* Save command and data into handle before transferring. */ - handle->command = command; - handle->data = data; - handle->interruptFlags = 0U; - /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ - handle->transferredWords = 0U; - SDHC_StartTransfer(base, command, data); - } } } - return error; + /* Save command and data into handle before transferring. */ + handle->command = command; + handle->data = data; + handle->interruptFlags = 0U; + /* transferredWords will only be updated in ISR when transfer way is DATAPORT. */ + handle->transferredWords = 0U; + + SDHC_StartTransfer(base, command, data, dmaMode); + + return kStatus_Success; } void SDHC_TransferHandleIRQ(SDHC_Type *base, sdhc_handle_t *handle) @@ -1292,6 +1411,6 @@ void SDHC_DriverIRQHandler(void) { assert(s_sdhcHandle[0]); - SDHC_TransferHandleIRQ(SDHC, s_sdhcHandle[0]); + s_sdhcIsr(SDHC, s_sdhcHandle[0]); } #endif diff --git a/drivers/fsl_sdhc.h b/drivers/fsl_sdhc.h index 2c5c61d..336b961 100644 --- a/drivers/fsl_sdhc.h +++ b/drivers/fsl_sdhc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,14 +12,14 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON @@ -37,15 +37,14 @@ * @{ */ - /****************************************************************************** * Definitions. *****************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief Driver version 2.1.1. */ -#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 1U)) +/*! @brief Driver version 2.1.5. */ +#define FSL_SDHC_DRIVER_VERSION (MAKE_VERSION(2U, 1U, 5U)) /*@}*/ /*! @brief Maximum block count can be set one time */ @@ -58,6 +57,8 @@ enum _sdhc_status kStatus_SDHC_PrepareAdmaDescriptorFailed = MAKE_STATUS(kStatusGroup_SDHC, 1U), /*!< Set DMA descriptor failed */ kStatus_SDHC_SendCommandFailed = MAKE_STATUS(kStatusGroup_SDHC, 2U), /*!< Send command failed */ kStatus_SDHC_TransferDataFailed = MAKE_STATUS(kStatusGroup_SDHC, 3U), /*!< Transfer data failed */ + kStatus_SDHC_DMADataBufferAddrNotAlign = + MAKE_STATUS(kStatusGroup_SDHC, 4U), /*!< data buffer addr not align in DMA mode */ }; /*! @brief Host controller capabilities flag mask */ @@ -283,32 +284,32 @@ typedef enum _sdhc_boot_mode } sdhc_boot_mode_t; /*! @brief The command type */ -typedef enum _sdhc_command_type +typedef enum _sdhc_card_command_type { - kSDHC_CommandTypeNormal = 0U, /*!< Normal command */ - kSDHC_CommandTypeSuspend = 1U, /*!< Suspend command */ - kSDHC_CommandTypeResume = 2U, /*!< Resume command */ - kSDHC_CommandTypeAbort = 3U, /*!< Abort command */ -} sdhc_command_type_t; + kCARD_CommandTypeNormal = 0U, /*!< Normal command */ + kCARD_CommandTypeSuspend = 1U, /*!< Suspend command */ + kCARD_CommandTypeResume = 2U, /*!< Resume command */ + kCARD_CommandTypeAbort = 3U, /*!< Abort command */ +} sdhc_card_command_type_t; /*! * @brief The command response type. * * Define the command response type from card to host controller. */ -typedef enum _sdhc_response_type +typedef enum _sdhc_card_response_type { - kSDHC_ResponseTypeNone = 0U, /*!< Response type: none */ - kSDHC_ResponseTypeR1 = 1U, /*!< Response type: R1 */ - kSDHC_ResponseTypeR1b = 2U, /*!< Response type: R1b */ - kSDHC_ResponseTypeR2 = 3U, /*!< Response type: R2 */ - kSDHC_ResponseTypeR3 = 4U, /*!< Response type: R3 */ - kSDHC_ResponseTypeR4 = 5U, /*!< Response type: R4 */ - kSDHC_ResponseTypeR5 = 6U, /*!< Response type: R5 */ - kSDHC_ResponseTypeR5b = 7U, /*!< Response type: R5b */ - kSDHC_ResponseTypeR6 = 8U, /*!< Response type: R6 */ - kSDHC_ResponseTypeR7 = 9U, /*!< Response type: R7 */ -} sdhc_response_type_t; + kCARD_ResponseTypeNone = 0U, /*!< Response type: none */ + kCARD_ResponseTypeR1 = 1U, /*!< Response type: R1 */ + kCARD_ResponseTypeR1b = 2U, /*!< Response type: R1b */ + kCARD_ResponseTypeR2 = 3U, /*!< Response type: R2 */ + kCARD_ResponseTypeR3 = 4U, /*!< Response type: R3 */ + kCARD_ResponseTypeR4 = 5U, /*!< Response type: R4 */ + kCARD_ResponseTypeR5 = 6U, /*!< Response type: R5 */ + kCARD_ResponseTypeR5b = 7U, /*!< Response type: R5b */ + kCARD_ResponseTypeR6 = 8U, /*!< Response type: R6 */ + kCARD_ResponseTypeR7 = 9U, /*!< Response type: R7 */ +} sdhc_card_response_type_t; /*! @brief The alignment size for ADDRESS filed in ADMA1's descriptor */ #define SDHC_ADMA1_ADDRESS_ALIGN (4096U) @@ -456,9 +457,9 @@ typedef struct _sdhc_transfer_config /*! @brief Data structure to configure the MMC boot feature */ typedef struct _sdhc_boot_config { - uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK */ + uint32_t ackTimeoutCount; /*!< Timeout value for the boot ACK. The available range is 0 ~ 15. */ sdhc_boot_mode_t bootMode; /*!< Boot mode selection. */ - uint32_t blockCount; /*!< Stop at block gap value of automatic mode */ + uint32_t blockCount; /*!< Stop at block gap value of automatic mode. Available range is 0 ~ 65535. */ bool enableBootAck; /*!< Enable or disable boot ACK */ bool enableBoot; /*!< Enable or disable fast boot */ bool enableAutoStopAtBlockGap; /*!< Enable or disable auto stop at block gap function in boot period */ @@ -470,14 +471,15 @@ typedef struct _sdhc_config bool cardDetectDat3; /*!< Enable DAT3 as card detection pin */ sdhc_endian_mode_t endianMode; /*!< Endian mode */ sdhc_dma_mode_t dmaMode; /*!< DMA mode */ - uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation */ - uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation */ + uint32_t readWatermarkLevel; /*!< Watermark level for DMA read operation. Available range is 1 ~ 128. */ + uint32_t writeWatermarkLevel; /*!< Watermark level for DMA write operation. Available range is 1 ~ 128. */ } sdhc_config_t; /*! * @brief Card data descriptor * - * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card driver + * Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card + * driver * want to ignore the error event to read/write all the data not to stop read/write immediately when error event * happen for example bus testing procedure for MMC card. */ @@ -498,11 +500,13 @@ typedef struct _sdhc_data */ typedef struct _sdhc_command { - uint32_t index; /*!< Command index */ - uint32_t argument; /*!< Command argument */ - sdhc_command_type_t type; /*!< Command type */ - sdhc_response_type_t responseType; /*!< Command response type */ - uint32_t response[4U]; /*!< Response for this command */ + uint32_t index; /*!< Command index */ + uint32_t argument; /*!< Command argument */ + sdhc_card_command_type_t type; /*!< Command type */ + sdhc_card_response_type_t responseType; /*!< Command response type */ + uint32_t response[4U]; /*!< Response for this command */ + uint32_t responseErrorFlags; /*!< response error flag, the flag which need to check + the command reponse*/ } sdhc_command_t; /*! @brief Transfer state */ @@ -531,8 +535,9 @@ typedef struct _sdhc_transfer_callback /*! * @brief SDHC handle * - * Defines the structure to save the SDHC state information and callback function. The detail interrupt status when - * send command or transfer data can be obtained from interruptFlags field by using mask defined in sdhc_interrupt_flag_t; + * Defines the structure to save the SDHC state information and callback function. The detailed interrupt status when + * sending a command or transfering data can be obtained from the interruptFlags field by using the mask defined in + * sdhc_interrupt_flag_t. * * @note All the fields except interruptFlags and transferredWords must be allocated by the user. */ @@ -584,11 +589,11 @@ extern "C" { * Example: @code sdhc_config_t config; - config.enableDat3AsCDPin = false; + config.cardDetectDat3 = false; config.endianMode = kSDHC_EndianModeLittle; config.dmaMode = kSDHC_DmaModeAdma2; - config.readWatermarkLevel = 512U; - config.writeWatermarkLevel = 512U; + config.readWatermarkLevel = 128U; + config.writeWatermarkLevel = 128U; SDHC_Init(SDHC, &config); @endcode * @@ -672,7 +677,7 @@ static inline void SDHC_DisableInterruptStatus(SDHC_Type *base, uint32_t mask) } /*! - * @brief Enables interrupts signal corresponding to the interrupt status flag. + * @brief Enables the interrupt signal corresponding to the interrupt status flag. * * @param base SDHC peripheral base address. * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). @@ -683,7 +688,7 @@ static inline void SDHC_EnableInterruptSignal(SDHC_Type *base, uint32_t mask) } /*! - * @brief Disables interrupts signal corresponding to the interrupt status flag. + * @brief Disables the interrupt signal corresponding to the interrupt status flag. * * @param base SDHC peripheral base address. * @param mask The interrupt status flags mask(_sdhc_interrupt_status_flag). @@ -747,7 +752,7 @@ static inline uint32_t SDHC_GetAdmaErrorStatusFlags(SDHC_Type *base) /*! * @brief Gets a present status. * - * This function gets the present SDHC's status except for interrupt status and error status. + * This function gets the present SDHC's status except for an interrupt status and an error status. * * @param base SDHC peripheral base address. * @return Present SDHC's status flags mask(_sdhc_present_status_flag). @@ -765,7 +770,7 @@ static inline uint32_t SDHC_GetPresentStatusFlags(SDHC_Type *base) */ /*! - * @brief Gets the capability information + * @brief Gets the capability information. * * @param base SDHC peripheral base address. * @param capability Structure to save capability information. @@ -802,9 +807,10 @@ static inline void SDHC_EnableSdClock(SDHC_Type *base, bool enable) uint32_t SDHC_SetSdClock(SDHC_Type *base, uint32_t srcClock_Hz, uint32_t busClock_Hz); /*! - * @brief Sends 80 clocks to the card to set it to be active state. + * @brief Sends 80 clocks to the card to set it to the active state. * - * This function must be called after each time the card is inserted to make card can receive command correctly. + * This function must be called each time the card is inserted to ensure that the card can receive the command + * correctly. * * @param base SDHC peripheral base address. * @param timeout Timeout to initialize card. @@ -827,7 +833,8 @@ static inline void SDHC_SetDataBusWidth(SDHC_Type *base, sdhc_data_bus_width_t w /*! * @brief Sets the card transfer-related configuration. * - * This function fills card transfer-related command argument/transfer flag/data size. Command and data are sent by + * This function fills the card transfer-related command argument/transfer flag/data size. The command and data are sent + by * SDHC after calling this function. * * Example: @@ -863,7 +870,7 @@ static inline uint32_t SDHC_GetCommandResponse(SDHC_Type *base, uint32_t index) /*! * @brief Fills the the data port. * - * This function is mainly used to implement the data transfer by Data Port instead of DMA. + * This function is used to implement the data transfer by Data Port instead of DMA. * * @param base SDHC peripheral base address. * @param data The data about to be sent. @@ -876,7 +883,7 @@ static inline void SDHC_WriteData(SDHC_Type *base, uint32_t data) /*! * @brief Retrieves the data from the data port. * - * This function is mainly used to implement the data transfer by Data Port instead of DMA. + * This function is used to implement the data transfer by Data Port instead of DMA. * * @param base SDHC peripheral base address. * @return The data has been read. @@ -906,7 +913,7 @@ static inline void SDHC_EnableWakeupEvent(SDHC_Type *base, uint32_t mask, bool e } /*! - * @brief Enables or disables the card detection level for test. + * @brief Enables or disables the card detection level for testing. * * @param base SDHC peripheral base address. * @param enable True to enable, false to disable. @@ -926,8 +933,9 @@ static inline void SDHC_EnableCardDetectTest(SDHC_Type *base, bool enable) /*! * @brief Sets the card detection test level. * - * This function set the card detection test level to indicate whether the card is inserted into SDHC when DAT[3]/ - * CD pin is selected as card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is select + * This function sets the card detection test level to indicate whether the card is inserted into the SDHC when DAT[3]/ + * CD pin is selected as a card detection pin. This function can also assert the pin logic when DAT[3]/CD pin is + * selected * as the card detection pin. * * @param base SDHC peripheral base address. @@ -955,7 +963,7 @@ static inline void SDHC_SetCardDetectTestLevel(SDHC_Type *base, bool high) void SDHC_EnableSdioControl(SDHC_Type *base, uint32_t mask, bool enable); /*! - * @brief Restarts a transaction which has stopped at the block gap for SDIO card. + * @brief Restarts a transaction which has stopped at the block GAP for the SDIO card. * * @param base SDHC peripheral base address. */ @@ -969,14 +977,14 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base) * * Example: @code - sdhc_boot_config_t bootConfig; - bootConfig.ackTimeoutCount = 4; - bootConfig.bootMode = kSDHC_BootModeNormal; - bootConfig.blockCount = 5; - bootConfig.enableBootAck = true; - bootConfig.enableBoot = true; - enableBoot.enableAutoStopAtBlockGap = true; - SDHC_SetMmcBootConfig(SDHC, &bootConfig); + sdhc_boot_config_t config; + config.ackTimeoutCount = 4; + config.bootMode = kSDHC_BootModeNormal; + config.blockCount = 5; + config.enableBootAck = true; + config.enableBoot = true; + config.enableAutoStopAtBlockGap = true; + SDHC_SetMmcBootConfig(SDHC, &config); @endcode * * @param base SDHC peripheral base address. @@ -985,7 +993,7 @@ static inline void SDHC_SetContinueRequest(SDHC_Type *base) void SDHC_SetMmcBootConfig(SDHC_Type *base, const sdhc_boot_config_t *config); /*! - * @brief Forces to generate events according to the given mask. + * @brief Forces generating events according to the given mask. * * @param base SDHC peripheral base address. * @param mask The force events mask(_sdhc_force_event). @@ -1003,11 +1011,14 @@ static inline void SDHC_SetForceEvent(SDHC_Type *base, uint32_t mask) */ /*! - * @brief Transfers the command/data using blocking way. + * @brief Transfers the command/data using a blocking method. * - * This function waits until the command response/data is got or SDHC encounters error by polling the status flag. - * Application must not call this API in multiple threads at the same time because of that this API doesn't support - * re-entry mechanism. + * This function waits until the command response/data is received or the SDHC encounters an error by polling the status + * flag. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * the re-entry mechanism. * * @note There is no need to call the API 'SDHC_TransferCreateHandle' when calling this API. * @@ -1040,13 +1051,16 @@ void SDHC_TransferCreateHandle(SDHC_Type *base, void *userData); /*! - * @brief Transfers the command/data using interrupt and asynchronous way. + * @brief Transfers the command/data using an interrupt and an asynchronous method. * - * This function send command and data and return immediately. It doesn't wait the transfer complete or encounter error. - * Application must not call this API in multiple threads at the same time because of that this API doesn't support - * re-entry mechanism. + * This function sends a command and data and returns immediately. It doesn't wait the transfer complete or encounter an + * error. + * This function support non word align data addr transfer support, if data buffer addr is not align in DMA mode, + * the API will continue finish the transfer by polling IO directly + * The application must not call this API in multiple threads at the same time. Because of that this API doesn't support + * the re-entry mechanism. * - * @note Must call the API 'SDHC_TransferCreateHandle' when calling this API. + * @note Call the API 'SDHC_TransferCreateHandle' when calling this API. * * @param base SDHC peripheral base address. * @param handle SDHC handle. @@ -1062,9 +1076,9 @@ status_t SDHC_TransferNonBlocking( SDHC_Type *base, sdhc_handle_t *handle, uint32_t *admaTable, uint32_t admaTableWords, sdhc_transfer_t *transfer); /*! - * @brief IRQ handler for SDHC + * @brief IRQ handler for the SDHC. * - * This function deals with IRQs on the given host controller. + * This function deals with the IRQs on the given host controller. * * @param base SDHC peripheral base address. * @param handle SDHC handle. diff --git a/drivers/fsl_sim.c b/drivers/fsl_sim.c index 3a4b801..ade512f 100644..100755 --- a/drivers/fsl_sim.c +++ b/drivers/fsl_sim.c @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "fsl_sim.h" diff --git a/drivers/fsl_sim.h b/drivers/fsl_sim.h index 77958f8..0a0e4fb 100644..100755 --- a/drivers/fsl_sim.h +++ b/drivers/fsl_sim.h @@ -1,32 +1,32 @@ /* -* Copyright (c) 2015, Freescale Semiconductor, Inc. -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, -* are permitted provided that the following conditions are met: -* -* o Redistributions of source code must retain the above copyright notice, this list -* of conditions and the following disclaimer. -* -* o Redistributions in binary form must reproduce the above copyright notice, this -* list of conditions and the following disclaimer in the documentation and/or -* other materials provided with the distribution. -* -* o Neither the name of Freescale Semiconductor, Inc. nor the names of its -* contributors may be used to endorse or promote products derived from this -* software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _FSL_SIM_H_ #define _FSL_SIM_H_ @@ -89,10 +89,10 @@ extern "C" { * @brief Sets the USB voltage regulator setting. * * This function configures whether the USB voltage regulator is enabled in - * normal RUN mode, STOP/VLPS/LLS/VLLS modes and VLPR/VLPW modes. The configurations - * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, enable + * normal RUN mode, STOP/VLPS/LLS/VLLS modes, and VLPR/VLPW modes. The configurations + * are passed in as mask value of \ref _sim_usb_volt_reg_enable_mode. For example, to enable * USB voltage regulator in RUN/VLPR/VLPW modes and disable in STOP/VLPS/LLS/VLLS mode, - * please use: + * use: * * SIM_SetUsbVoltRegulatorEnableMode(kSIM_UsbVoltRegEnable | kSIM_UsbVoltRegEnableInLowPower); * @@ -102,16 +102,16 @@ void SIM_SetUsbVoltRegulatorEnableMode(uint32_t mask); #endif /* FSL_FEATURE_SIM_OPT_HAS_USB_VOLTAGE_REGULATOR */ /*! - * @brief Get the unique identification register value. + * @brief Gets the unique identification register value. * * @param uid Pointer to the structure to save the UID value. */ void SIM_GetUniqueId(sim_uid_t *uid); /*! - * @brief Set the flash enable mode. + * @brief Sets the flash enable mode. * - * @param mode The mode to set, see \ref _sim_flash_mode for mode details. + * @param mode The mode to set; see \ref _sim_flash_mode for mode details. */ static inline void SIM_SetFlashMode(uint8_t mode) { diff --git a/drivers/fsl_smc.c b/drivers/fsl_smc.c index 45382fd..dacf193 100644 --- a/drivers/fsl_smc.c +++ b/drivers/fsl_smc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -29,6 +29,7 @@ */ #include "fsl_smc.h" +#include "fsl_flash.h" #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM) void SMC_GetParam(SMC_Type *base, smc_param_t *param) @@ -41,6 +42,39 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param) } #endif /* FSL_FEATURE_SMC_HAS_PARAM */ +void SMC_PreEnterStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/ + }; + + __disable_irq(); + __ISB(); + + /* + * Before enter stop modes, the flash cache prefetch should be disabled. + * Otherwise the prefetch might be interrupted by stop, then the data and + * and instruction from flash are wrong. + */ + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); +} + +void SMC_PostExitStopModes(void) +{ + flash_prefetch_speculation_status_t speculationStatus = + { + kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/ + kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/ + }; + + FLASH_PflashSetPrefetchSpeculation(&speculationStatus); + + __enable_irq(); + __ISB(); +} + status_t SMC_SetPowerModeRun(SMC_Type *base) { uint8_t reg; diff --git a/drivers/fsl_smc.h b/drivers/fsl_smc.h index 4148734..168ce83 100644 --- a/drivers/fsl_smc.h +++ b/drivers/fsl_smc.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -43,8 +43,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SMC driver version 2.0.2. */ -#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*! @brief SMC driver version 2.0.3. */ +#define FSL_SMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ /*! @@ -53,14 +53,14 @@ typedef enum _smc_power_mode_protection { #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeVlls = SMC_PMPROT_AVLLS_MASK, /*!< Allow Very-low-leakage Stop Mode. */ #endif #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-Leakage Stop Mode. */ + kSMC_AllowPowerModeLls = SMC_PMPROT_ALLS_MASK, /*!< Allow Low-leakage Stop Mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ - kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-Power Mode. */ + kSMC_AllowPowerModeVlp = SMC_PMPROT_AVLP_MASK, /*!< Allow Very-Low-power Mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High Speed Run mode. */ + kSMC_AllowPowerModeHsrun = SMC_PMPROT_AHSRUN_MASK, /*!< Allow High-speed Run mode. */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ kSMC_AllowPowerModeAll = (0U #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) @@ -106,10 +106,10 @@ typedef enum _smc_power_state */ typedef enum _smc_run_mode { - kSMC_RunNormal = 0U, /*!< normal RUN mode. */ - kSMC_RunVlpr = 2U, /*!< Very-Low-Power RUN mode. */ + kSMC_RunNormal = 0U, /*!< Normal RUN mode. */ + kSMC_RunVlpr = 2U, /*!< Very-low-power RUN mode. */ #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) - kSMC_Hsrun = 3U /*!< High Speed Run mode (HSRUN). */ + kSMC_Hsrun = 3U /*!< High-speed Run mode (HSRUN). */ #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ } smc_run_mode_t; @@ -119,12 +119,12 @@ typedef enum _smc_run_mode typedef enum _smc_stop_mode { kSMC_StopNormal = 0U, /*!< Normal STOP mode. */ - kSMC_StopVlps = 2U, /*!< Very-Low-Power STOP mode. */ + kSMC_StopVlps = 2U, /*!< Very-low-power STOP mode. */ #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) - kSMC_StopLls = 3U, /*!< Low-Leakage Stop mode. */ + kSMC_StopLls = 3U, /*!< Low-leakage Stop mode. */ #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */ #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) - kSMC_StopVlls = 4U /*!< Very-Low-Leakage Stop mode. */ + kSMC_StopVlls = 4U /*!< Very-low-leakage Stop mode. */ #endif } smc_stop_mode_t; @@ -154,7 +154,7 @@ typedef enum _smc_partial_stop_mode } smc_partial_stop_option_t; /*! - * @brief SMC configuration status + * @brief SMC configuration status. */ enum _smc_status { @@ -189,7 +189,7 @@ typedef struct _smc_param #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO) /*! - * @brief SMC Low-Leakage Stop power mode config + * @brief SMC Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_lls_config { @@ -204,7 +204,7 @@ typedef struct _smc_power_mode_lls_config #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief SMC Very Low-Leakage Stop power mode config + * @brief SMC Very Low-Leakage Stop power mode configuration. */ typedef struct _smc_power_mode_vlls_config { @@ -241,10 +241,10 @@ extern "C" { * @brief Gets the SMC version ID. * * This function gets the SMC version ID, including major version number, - * minor version number and feature specification number. + * minor version number, and feature specification number. * * @param base SMC peripheral base address. - * @param versionId Pointer to version ID structure. + * @param versionId Pointer to the version ID structure. */ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) { @@ -256,10 +256,10 @@ static inline void SMC_GetVersionId(SMC_Type *base, smc_version_id_t *versionId) /*! * @brief Gets the SMC parameter. * - * This function gets the SMC parameter, including the enabled power mdoes. + * This function gets the SMC parameter including the enabled power mdoes. * * @param base SMC peripheral base address. - * @param param Pointer to SMC param structure. + * @param param Pointer to the SMC param structure. */ void SMC_GetParam(SMC_Type *base, smc_param_t *param); #endif @@ -273,7 +273,7 @@ void SMC_GetParam(SMC_Type *base, smc_param_t *param); * system level initialization stage. See the reference manual for details. * This register can only write once after the power reset. * - * The allowed modes are passed as bit map, for example, to allow LLS and VLLS, + * The allowed modes are passed as bit map. For example, to allow LLS and VLLS, * use SMC_SetPowerModeProtection(kSMC_AllowPowerModeVlls | kSMC_AllowPowerModeVlps). * To allow all modes, use SMC_SetPowerModeProtection(kSMC_AllowPowerModeAll). * @@ -288,13 +288,13 @@ static inline void SMC_SetPowerModeProtection(SMC_Type *base, uint8_t allowedMod /*! * @brief Gets the current power mode status. * - * This function returns the current power mode stat. Once application - * switches the power mode, it should always check the stat to check whether it - * runs into the specified mode or not. An application should check + * This function returns the current power mode status. After the application + * switches the power mode, it should always check the status to check whether it + * runs into the specified mode or not. The application should check * this mode before switching to a different mode. The system requires that * only certain modes can switch to other specific modes. See the * reference manual for details and the smc_power_state_t for information about - * the power stat. + * the power status. * * @param base SMC peripheral base address. * @return Current power mode status. @@ -305,7 +305,45 @@ static inline smc_power_state_t SMC_GetPowerModeState(SMC_Type *base) } /*! - * @brief Configure the system to RUN power mode. + * @brief Prepares to enter stop modes. + * + * This function should be called before entering STOP/VLPS/LLS/VLLS modes. + */ +void SMC_PreEnterStopModes(void); + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from STOP/VLPS/LLS/VLLS modes. + * It is used with @ref SMC_PreEnterStopModes. + */ +void SMC_PostExitStopModes(void); + +/*! + * @brief Prepares to enter wait modes. + * + * This function should be called before entering WAIT/VLPW modes. + */ +static inline void SMC_PreEnterWaitModes(void) +{ + __disable_irq(); + __ISB(); +} + +/*! + * @brief Recovers after wake up from stop modes. + * + * This function should be called after wake up from WAIT/VLPW modes. + * It is used with @ref SMC_PreEnterWaitModes. + */ +static inline void SMC_PostExitWaitModes(void) +{ + __enable_irq(); + __ISB(); +} + +/*! + * @brief Configures the system to RUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -314,7 +352,7 @@ status_t SMC_SetPowerModeRun(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) /*! - * @brief Configure the system to HSRUN power mode. + * @brief Configures the system to HSRUN power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -323,7 +361,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */ /*! - * @brief Configure the system to WAIT power mode. + * @brief Configures the system to WAIT power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -331,7 +369,7 @@ status_t SMC_SetPowerModeHsrun(SMC_Type *base); status_t SMC_SetPowerModeWait(SMC_Type *base); /*! - * @brief Configure the system to Stop power mode. + * @brief Configures the system to Stop power mode. * * @param base SMC peripheral base address. * @param option Partial Stop mode option. @@ -341,7 +379,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI) /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @param wakeupMode Enter Normal Run mode if true, else stay in VLPR mode. @@ -350,7 +388,7 @@ status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option); status_t SMC_SetPowerModeVlpr(SMC_Type *base, bool wakeupMode); #else /*! - * @brief Configure the system to VLPR power mode. + * @brief Configures the system to VLPR power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -359,7 +397,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); #endif /* FSL_FEATURE_SMC_HAS_LPWUI */ /*! - * @brief Configure the system to VLPW power mode. + * @brief Configures the system to VLPW power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -367,7 +405,7 @@ status_t SMC_SetPowerModeVlpr(SMC_Type *base); status_t SMC_SetPowerModeVlpw(SMC_Type *base); /*! - * @brief Configure the system to VLPS power mode. + * @brief Configures the system to VLPS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -378,7 +416,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \ (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)) /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @param config The LLS power mode configuration structure @@ -387,7 +425,7 @@ status_t SMC_SetPowerModeVlps(SMC_Type *base); status_t SMC_SetPowerModeLls(SMC_Type *base, const smc_power_mode_lls_config_t *config); #else /*! - * @brief Configure the system to LLS power mode. + * @brief Configures the system to LLS power mode. * * @param base SMC peripheral base address. * @return SMC configuration error code. @@ -398,7 +436,7 @@ status_t SMC_SetPowerModeLls(SMC_Type *base); #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) /*! - * @brief Configure the system to VLLS power mode. + * @brief Configures the system to VLLS power mode. * * @param base SMC peripheral base address. * @param config The VLLS power mode configuration structure. diff --git a/drivers/fsl_sysmpu.c b/drivers/fsl_sysmpu.c new file mode 100644 index 0000000..b89a7b2 --- /dev/null +++ b/drivers/fsl_sysmpu.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_sysmpu.h" + +/******************************************************************************* + * Variables + ******************************************************************************/ + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) +const clock_ip_name_t g_sysmpuClock[FSL_FEATURE_SOC_SYSMPU_COUNT] = SYSMPU_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Codes + ******************************************************************************/ + +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config) +{ + assert(config); + uint8_t count; + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Un-gate SYSMPU clock */ + CLOCK_EnableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + + /* Initializes the regions. */ + for (count = 1; count < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT; count++) + { + base->WORD[count][3] = 0; /* VLD/VID+PID. */ + base->WORD[count][0] = 0; /* Start address. */ + base->WORD[count][1] = 0; /* End address. */ + base->WORD[count][2] = 0; /* Access rights. */ + base->RGDAAC[count] = 0; /* Alternate access rights. */ + } + + /* SYSMPU configure. */ + while (config) + { + SYSMPU_SetRegionConfig(base, &(config->regionConfig)); + config = config->next; + } + /* Enable SYSMPU. */ + SYSMPU_Enable(base, true); +} + +void SYSMPU_Deinit(SYSMPU_Type *base) +{ + /* Disable SYSMPU. */ + SYSMPU_Enable(base, false); + +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) + /* Gate the clock. */ + CLOCK_DisableClock(g_sysmpuClock[0]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform) +{ + assert(hardwareInform); + + uint32_t cesReg = base->CESR; + + hardwareInform->hardwareRevisionLevel = (cesReg & SYSMPU_CESR_HRL_MASK) >> SYSMPU_CESR_HRL_SHIFT; + hardwareInform->slavePortsNumbers = (cesReg & SYSMPU_CESR_NSP_MASK) >> SYSMPU_CESR_NSP_SHIFT; + hardwareInform->regionsNumbers = (sysmpu_region_total_num_t)((cesReg & SYSMPU_CESR_NRGD_MASK) >> SYSMPU_CESR_NRGD_SHIFT); +} + +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig) +{ + assert(regionConfig); + assert(regionConfig->regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + uint32_t wordReg = 0; + uint8_t msPortNum; + uint8_t regNumber = regionConfig->regionNum; + + /* The start and end address of the region descriptor. */ + base->WORD[regNumber][0] = regionConfig->startAddress; + base->WORD[regNumber][1] = regionConfig->endAddress; + + /* Set the privilege rights for master 0 ~ master 3. */ + for (msPortNum = 0; msPortNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum++) + { + wordReg |= SYSMPU_REGION_RWXRIGHTS_MASTER( + msPortNum, (((uint32_t)regionConfig->accessRights1[msPortNum].superAccessRights << 3U) | + (uint32_t)regionConfig->accessRights1[msPortNum].userAccessRights)); + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= + SYSMPU_REGION_RWXRIGHTS_MASTER_PE(msPortNum, regionConfig->accessRights1[msPortNum].processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + } + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT + /* Set the normal read write rights for master 4 ~ master 7. */ + for (msPortNum = SYSMPU_MASTER_RWATTRIBUTE_START_PORT; msPortNum < FSL_FEATURE_SYSMPU_MASTER_COUNT; + msPortNum++) + { + wordReg |= SYSMPU_REGION_RWRIGHTS_MASTER(msPortNum, + ((uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].readEnable << 1U | + (uint32_t)regionConfig->accessRights2[msPortNum - SYSMPU_MASTER_RWATTRIBUTE_START_PORT].writeEnable)); + } +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > SYSMPU_MASTER_RWATTRIBUTE_START_PORT */ + + /* Set region descriptor access rights. */ + base->WORD[regNumber][2] = wordReg; + + wordReg = SYSMPU_WORD_VLD(1); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + wordReg |= SYSMPU_WORD_PID(regionConfig->processIdentifier) | SYSMPU_WORD_PIDMASK(regionConfig->processIdMask); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + base->WORD[regNumber][3] = wordReg; +} + +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr) +{ + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + + base->WORD[regionNum][0] = startAddr; + base->WORD[regionNum][1] = endAddr; +} + +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum < SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + + uint32_t mask = SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + mask |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(masterNum); +#endif + + /* Build rights control value. */ + right &= ~mask; + right |= SYSMPU_REGION_RWXRIGHTS_MASTER( + masterNum, ((uint32_t)(accessRights->superAccessRights << 3U) | accessRights->userAccessRights)); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + right |= SYSMPU_REGION_RWXRIGHTS_MASTER_PE(masterNum, accessRights->processIdentifierEnable); +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ + + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} + +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights) +{ + assert(accessRights); + assert(regionNum < FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT); + assert(masterNum >= SYSMPU_MASTER_RWATTRIBUTE_START_PORT); + assert(masterNum <= (FSL_FEATURE_SYSMPU_MASTER_COUNT - 1)); + + uint32_t mask = SYSMPU_REGION_RWRIGHTS_MASTER_MASK(masterNum); + uint32_t right = base->RGDAAC[regionNum]; + + /* Build rights control value. */ + right &= ~mask; + right |= + SYSMPU_REGION_RWRIGHTS_MASTER(masterNum, (((uint32_t)accessRights->readEnable << 1U) | accessRights->writeEnable)); + /* Set low master region access rights. */ + base->RGDAAC[regionNum] = right; +} +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ + +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum) +{ + uint8_t sperr; + + sperr = ((base->CESR & SYSMPU_CESR_SPERR_MASK) >> SYSMPU_CESR_SPERR_SHIFT) & (0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)); + + return (sperr != 0) ? true : false; +} + +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform) +{ + assert(errInform); + + uint16_t value; + uint32_t cesReg; + + /* Error address. */ + errInform->address = base->SP[slaveNum].EAR; + + /* Error detail information. */ + value = (base->SP[slaveNum].EDR & SYSMPU_EDR_EACD_MASK) >> SYSMPU_EDR_EACD_SHIFT; + if (!value) + { + errInform->accessControl = kSYSMPU_NoRegionHit; + } + else if (!(value & (uint16_t)(value - 1))) + { + errInform->accessControl = kSYSMPU_NoneOverlappRegion; + } + else + { + errInform->accessControl = kSYSMPU_OverlappRegion; + } + + value = base->SP[slaveNum].EDR; + errInform->master = (uint32_t)((value & SYSMPU_EDR_EMN_MASK) >> SYSMPU_EDR_EMN_SHIFT); + errInform->attributes = (sysmpu_err_attributes_t)((value & SYSMPU_EDR_EATTR_MASK) >> SYSMPU_EDR_EATTR_SHIFT); + errInform->accessType = (sysmpu_err_access_type_t)((value & SYSMPU_EDR_ERW_MASK) >> SYSMPU_EDR_ERW_SHIFT); +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + errInform->processorIdentification = (uint8_t)((value & SYSMPU_EDR_EPID_MASK) >> SYSMPU_EDR_EPID_SHIFT); +#endif + + /* Clears error slave port bit. */ + cesReg = (base->CESR & ~SYSMPU_CESR_SPERR_MASK) | ((0x1U << (FSL_FEATURE_SYSMPU_SLAVE_COUNT - slaveNum - 1)) << SYSMPU_CESR_SPERR_SHIFT); + base->CESR = cesReg; +} diff --git a/drivers/fsl_sysmpu.h b/drivers/fsl_sysmpu.h new file mode 100644 index 0000000..6341a31 --- /dev/null +++ b/drivers/fsl_sysmpu.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FSL_SYSMPU_H_ +#define _FSL_SYSMPU_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup sysmpu + * @{ + */ + + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief SYSMPU driver version 2.2.0. */ +#define FSL_SYSMPU_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +/*! @brief define the start master port with read and write attributes. */ +#define SYSMPU_MASTER_RWATTRIBUTE_START_PORT (4) + +/*! @brief SYSMPU the bit shift for masters with privilege rights: read write and execute. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n) (n * 6) + +/*! @brief SYSMPU masters with read, write and execute rights bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n) (0x1Fu << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights bit width. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH 5 + +/*! @brief SYSMPU masters with read, write and execute rights priority setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_MASK(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit shift. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n) (n * 6 + SYSMPU_REGION_RWXRIGHTS_MASTER_WIDTH) + +/*! @brief SYSMPU masters with read, write and execute rights process enable bit mask. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n) (0x1u << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n)) + +/*! @brief SYSMPU masters with read, write and execute rights process enable setting. */ +#define SYSMPU_REGION_RWXRIGHTS_MASTER_PE(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWXRIGHTS_MASTER_PE_SHIFT(n))) & SYSMPU_REGION_RWXRIGHTS_MASTER_PE_MASK(n)) + +/*! @brief SYSMPU masters with normal read write permission bit shift. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n) ((n - SYSMPU_MASTER_RWATTRIBUTE_START_PORT) * 2 + 24) + +/*! @brief SYSMPU masters with normal read write rights bit mask. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n) (0x3u << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n)) + +/*! @brief SYSMPU masters with normal read write rights priority setting. */ +#define SYSMPU_REGION_RWRIGHTS_MASTER(n, x) \ + (((uint32_t)(((uint32_t)(x)) << SYSMPU_REGION_RWRIGHTS_MASTER_SHIFT(n))) & SYSMPU_REGION_RWRIGHTS_MASTER_MASK(n)) + + +/*! @brief Describes the number of SYSMPU regions. */ +typedef enum _sysmpu_region_total_num +{ + kSYSMPU_8Regions = 0x0U, /*!< SYSMPU supports 8 regions. */ + kSYSMPU_12Regions = 0x1U, /*!< SYSMPU supports 12 regions. */ + kSYSMPU_16Regions = 0x2U /*!< SYSMPU supports 16 regions. */ +} sysmpu_region_total_num_t; + +/*! @brief SYSMPU slave port number. */ +typedef enum _sysmpu_slave +{ + kSYSMPU_Slave0 = 0U, /*!< SYSMPU slave port 0. */ + kSYSMPU_Slave1 = 1U, /*!< SYSMPU slave port 1. */ + kSYSMPU_Slave2 = 2U, /*!< SYSMPU slave port 2. */ + kSYSMPU_Slave3 = 3U, /*!< SYSMPU slave port 3. */ + kSYSMPU_Slave4 = 4U, /*!< SYSMPU slave port 4. */ +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 5 + kSYSMPU_Slave5 = 5U, /*!< SYSMPU slave port 5. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 6 + kSYSMPU_Slave6 = 6U, /*!< SYSMPU slave port 6. */ +#endif +#if FSL_FEATURE_SYSMPU_SLAVE_COUNT > 7 + kSYSMPU_Slave7 = 7U, /*!< SYSMPU slave port 7. */ +#endif +} sysmpu_slave_t; + +/*! @brief SYSMPU error access control detail. */ +typedef enum _sysmpu_err_access_control +{ + kSYSMPU_NoRegionHit = 0U, /*!< No region hit error. */ + kSYSMPU_NoneOverlappRegion = 1U, /*!< Access single region error. */ + kSYSMPU_OverlappRegion = 2U /*!< Access overlapping region error. */ +} sysmpu_err_access_control_t; + +/*! @brief SYSMPU error access type. */ +typedef enum _sysmpu_err_access_type +{ + kSYSMPU_ErrTypeRead = 0U, /*!< SYSMPU error access type --- read. */ + kSYSMPU_ErrTypeWrite = 1U /*!< SYSMPU error access type --- write. */ +} sysmpu_err_access_type_t; + +/*! @brief SYSMPU access error attributes.*/ +typedef enum _sysmpu_err_attributes +{ + kSYSMPU_InstructionAccessInUserMode = 0U, /*!< Access instruction error in user mode. */ + kSYSMPU_DataAccessInUserMode = 1U, /*!< Access data error in user mode. */ + kSYSMPU_InstructionAccessInSupervisorMode = 2U, /*!< Access instruction error in supervisor mode. */ + kSYSMPU_DataAccessInSupervisorMode = 3U /*!< Access data error in supervisor mode. */ +} sysmpu_err_attributes_t; + +/*! @brief SYSMPU access rights in supervisor mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_supervisor_access_rights +{ + kSYSMPU_SupervisorReadWriteExecute = 0U, /*!< Read write and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadExecute = 1U, /*!< Read and execute operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorReadWrite = 2U, /*!< Read write operations are allowed in supervisor mode. */ + kSYSMPU_SupervisorEqualToUsermode = 3U /*!< Access permission equal to user mode. */ +} sysmpu_supervisor_access_rights_t; + +/*! @brief SYSMPU access rights in user mode for bus master 0 ~ 3. */ +typedef enum _sysmpu_user_access_rights +{ + kSYSMPU_UserNoAccessRights = 0U, /*!< No access allowed in user mode. */ + kSYSMPU_UserExecute = 1U, /*!< Execute operation is allowed in user mode. */ + kSYSMPU_UserWrite = 2U, /*!< Write operation is allowed in user mode. */ + kSYSMPU_UserWriteExecute = 3U, /*!< Write and execute operations are allowed in user mode. */ + kSYSMPU_UserRead = 4U, /*!< Read is allowed in user mode. */ + kSYSMPU_UserReadExecute = 5U, /*!< Read and execute operations are allowed in user mode. */ + kSYSMPU_UserReadWrite = 6U, /*!< Read and write operations are allowed in user mode. */ + kSYSMPU_UserReadWriteExecute = 7U /*!< Read write and execute operations are allowed in user mode. */ +} sysmpu_user_access_rights_t; + +/*! @brief SYSMPU hardware basic information. */ +typedef struct _sysmpu_hardware_info +{ + uint8_t hardwareRevisionLevel; /*!< Specifies the SYSMPU's hardware and definition reversion level. */ + uint8_t slavePortsNumbers; /*!< Specifies the number of slave ports connected to SYSMPU. */ + sysmpu_region_total_num_t regionsNumbers; /*!< Indicates the number of region descriptors implemented. */ +} sysmpu_hardware_info_t; + +/*! @brief SYSMPU detail error access information. */ +typedef struct _sysmpu_access_err_info +{ + uint32_t master; /*!< Access error master. */ + sysmpu_err_attributes_t attributes; /*!< Access error attributes. */ + sysmpu_err_access_type_t accessType; /*!< Access error type. */ + sysmpu_err_access_control_t accessControl; /*!< Access error control. */ + uint32_t address; /*!< Access error address. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processorIdentification; /*!< Access error processor identification. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_access_err_info_t; + +/*! @brief SYSMPU read/write/execute rights control for bus master 0 ~ 3. */ +typedef struct _sysmpu_rwxrights_master_access_control +{ + sysmpu_supervisor_access_rights_t superAccessRights; /*!< Master access rights in supervisor mode. */ + sysmpu_user_access_rights_t userAccessRights; /*!< Master access rights in user mode. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + bool processIdentifierEnable; /*!< Enables or disables process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_rwxrights_master_access_control_t; + +/*! @brief SYSMPU read/write access control for bus master 4 ~ 7. */ +typedef struct _sysmpu_rwrights_master_access_control +{ + bool writeEnable; /*!< Enables or disables write permission. */ + bool readEnable; /*!< Enables or disables read permission. */ +} sysmpu_rwrights_master_access_control_t; + +/*! + * @brief SYSMPU region configuration structure. + * + * This structure is used to configure the regionNum region. + * The accessRights1[0] ~ accessRights1[3] are used to configure the bus master + * 0 ~ 3 with the privilege rights setting. The accessRights2[0] ~ accessRights2[3] + * are used to configure the high master 4 ~ 7 with the normal read write permission. + * The master port assignment is the chip configuration. Normally, the core is the + * master 0, debugger is the master 1. + * Note that the SYSMPU assigns a priority scheme where the debugger is treated as the highest + * priority master followed by the core and then all the remaining masters. + * SYSMPU protection does not allow writes from the core to affect the "regionNum 0" start + * and end address nor the permissions associated with the debugger. It can only write + * the permission fields associated with the other masters. This protection guarantees that + * the debugger always has access to the entire address space and those rights can't + * be changed by the core or any other bus master. Prepare + * the region configuration when regionNum is 0. + */ +typedef struct _sysmpu_region_config +{ + uint32_t regionNum; /*!< SYSMPU region number, range form 0 ~ FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. */ + uint32_t startAddress; /*!< Memory region start address. Note: bit0 ~ bit4 always be marked as 0 by SYSMPU. The actual + start address is 0-modulo-32 byte address. */ + uint32_t endAddress; /*!< Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. The actual end + address is 31-modulo-32 byte address. */ + sysmpu_rwxrights_master_access_control_t accessRights1[4]; /*!< Masters with read, write and execute rights setting. */ + sysmpu_rwrights_master_access_control_t accessRights2[4]; /*!< Masters with normal read write rights setting. */ +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + uint8_t processIdentifier; /*!< Process identifier used when "processIdentifierEnable" set with true. */ + uint8_t + processIdMask; /*!< Process identifier mask. The setting bit will ignore the same bit in process identifier. */ +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +} sysmpu_region_config_t; + +/*! + * @brief The configuration structure for the SYSMPU initialization. + * + * This structure is used when calling the SYSMPU_Init function. + */ +typedef struct _sysmpu_config +{ + sysmpu_region_config_t regionConfig; /*!< Region access permission. */ + struct _sysmpu_config *next; /*!< Pointer to the next structure. */ +} sysmpu_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* _cplusplus */ + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initializes the SYSMPU with the user configuration structure. + * + * This function configures the SYSMPU module with the user-defined configuration. + * + * @param base SYSMPU peripheral base address. + * @param config The pointer to the configuration structure. + */ +void SYSMPU_Init(SYSMPU_Type *base, const sysmpu_config_t *config); + +/*! + * @brief Deinitializes the SYSMPU regions. + * + * @param base SYSMPU peripheral base address. + */ +void SYSMPU_Deinit(SYSMPU_Type *base); + +/* @}*/ + +/*! + * @name Basic Control Operations + * @{ + */ + +/*! + * @brief Enables/disables the SYSMPU globally. + * + * Call this API to enable or disable the SYSMPU module. + * + * @param base SYSMPU peripheral base address. + * @param enable True enable SYSMPU, false disable SYSMPU. + */ +static inline void SYSMPU_Enable(SYSMPU_Type *base, bool enable) +{ + if (enable) + { + /* Enable the SYSMPU globally. */ + base->CESR |= SYSMPU_CESR_VLD_MASK; + } + else + { /* Disable the SYSMPU globally. */ + base->CESR &= ~SYSMPU_CESR_VLD_MASK; + } +} + +/*! + * @brief Enables/disables the SYSMPU for a special region. + * + * When SYSMPU is enabled, call this API to disable an unused region + * of an enabled SYSMPU. Call this API to minimize the power dissipation. + * + * @param base SYSMPU peripheral base address. + * @param number SYSMPU region number. + * @param enable True enable the special region SYSMPU, false disable the special region SYSMPU. + */ +static inline void SYSMPU_RegionEnable(SYSMPU_Type *base, uint32_t number, bool enable) +{ + if (enable) + { + /* Enable the #number region SYSMPU. */ + base->WORD[number][3] |= SYSMPU_WORD_VLD_MASK; + } + else + { /* Disable the #number region SYSMPU. */ + base->WORD[number][3] &= ~SYSMPU_WORD_VLD_MASK; + } +} + +/*! + * @brief Gets the SYSMPU basic hardware information. + * + * @param base SYSMPU peripheral base address. + * @param hardwareInform The pointer to the SYSMPU hardware information structure. See "sysmpu_hardware_info_t". + */ +void SYSMPU_GetHardwareInfo(SYSMPU_Type *base, sysmpu_hardware_info_t *hardwareInform); + +/*! + * @brief Sets the SYSMPU region. + * + * Note: Due to the SYSMPU protection, the region number 0 does not allow writes from + * core to affect the start and end address nor the permissions associated with + * the debugger. It can only write the permission fields associated + * with the other masters. + * + * @param base SYSMPU peripheral base address. + * @param regionConfig The pointer to the SYSMPU user configuration structure. See "sysmpu_region_config_t". + */ +void SYSMPU_SetRegionConfig(SYSMPU_Type *base, const sysmpu_region_config_t *regionConfig); + +/*! + * @brief Sets the region start and end address. + * + * Memory region start address. Note: bit0 ~ bit4 is always marked as 0 by SYSMPU. + * The actual start address by SYSMPU is 0-modulo-32 byte address. + * Memory region end address. Note: bit0 ~ bit4 always be marked as 1 by SYSMPU. + * The end address used by the SYSMPU is 31-modulo-32 byte address. + * Note: Due to the SYSMPU protection, the startAddr and endAddr can't be + * changed by the core when regionNum is 0. + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param startAddr Region start address. + * @param endAddr Region end address. + */ +void SYSMPU_SetRegionAddr(SYSMPU_Type *base, uint32_t regionNum, uint32_t startAddr, uint32_t endAddr); + +/*! + * @brief Sets the SYSMPU region access rights for masters with read, write, and execute rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The privilege rights masters have the read, write, and execute access rights. + * Except the normal read and write rights, the execute rights are also + * allowed for these masters. The privilege rights masters normally range from + * bus masters 0 - 3. However, the maximum master number is device-specific. + * See the "SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX". + * The normal rights masters access rights control see + * "SYSMPU_SetRegionRwMasterAccessRights()". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. Should range from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from 0 to + * SYSMPU_PRIVILEGED_RIGHTS_MASTER_MAX_INDEX. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwxrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwxMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwxrights_master_access_control_t *accessRights); +#if FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 +/*! + * @brief Sets the SYSMPU region access rights for masters with read and write rights. + * The SYSMPU access rights depend on two board classifications of bus masters. + * The privilege rights masters and the normal rights masters. + * The normal rights masters only have the read and write access permissions. + * The privilege rights access control see "SYSMPU_SetRegionRwxMasterAccessRights". + * + * @param base SYSMPU peripheral base address. + * @param regionNum SYSMPU region number. The range is from 0 to + * FSL_FEATURE_SYSMPU_DESCRIPTOR_COUNT - 1. + * @param masterNum SYSMPU bus master number. Should range from SYSMPU_MASTER_RWATTRIBUTE_START_PORT + * to ~ FSL_FEATURE_SYSMPU_MASTER_COUNT - 1. + * @param accessRights The pointer to the SYSMPU access rights configuration. See "sysmpu_rwrights_master_access_control_t". + */ +void SYSMPU_SetRegionRwMasterAccessRights(SYSMPU_Type *base, + uint32_t regionNum, + uint32_t masterNum, + const sysmpu_rwrights_master_access_control_t *accessRights); +#endif /* FSL_FEATURE_SYSMPU_MASTER_COUNT > 4 */ +/*! + * @brief Gets the numbers of slave ports where errors occur. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @return The slave ports error status. + * true - error happens in this slave port. + * false - error didn't happen in this slave port. + */ +bool SYSMPU_GetSlavePortErrorStatus(SYSMPU_Type *base, sysmpu_slave_t slaveNum); + +/*! + * @brief Gets the SYSMPU detailed error access information. + * + * @param base SYSMPU peripheral base address. + * @param slaveNum SYSMPU slave port number. + * @param errInform The pointer to the SYSMPU access error information. See "sysmpu_access_err_info_t". + */ +void SYSMPU_GetDetailErrorAccessInfo(SYSMPU_Type *base, sysmpu_slave_t slaveNum, sysmpu_access_err_info_t *errInform); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_SYSMPU_H_ */ diff --git a/drivers/fsl_tsi_v2.c b/drivers/fsl_tsi_v2.c index 0464eb2..1934982 100644 --- a/drivers/fsl_tsi_v2.c +++ b/drivers/fsl_tsi_v2.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014 - 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -36,7 +36,9 @@ void TSI_Init(TSI_Type *base, const tsi_config_t *config) bool is_module_enabled = false; bool is_int_enabled = false; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_EnableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ if (base->GENCS & TSI_GENCS_TSIEN_MASK) { is_module_enabled = true; @@ -75,7 +77,9 @@ void TSI_Deinit(TSI_Type *base) base->SCANC = 0U; base->PEN = 0U; base->THRESHOLD = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) CLOCK_DisableClock(kCLOCK_Tsi0); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void TSI_GetNormalModeDefaultConfig(tsi_config_t *userConfig) diff --git a/drivers/fsl_tsi_v2.h b/drivers/fsl_tsi_v2.h index ee0d590..a173626 100644 --- a/drivers/fsl_tsi_v2.h +++ b/drivers/fsl_tsi_v2.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/drivers/fsl_uart.c b/drivers/fsl_uart.c index 121be44..17d9260 100644 --- a/drivers/fsl_uart.c +++ b/drivers/fsl_uart.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,10 +37,12 @@ /* UART transfer state. */ enum _uart_tansfer_states { - kUART_TxIdle, /* TX idle. */ - kUART_TxBusy, /* TX busy. */ - kUART_RxIdle, /* RX idle. */ - kUART_RxBusy /* RX busy. */ + kUART_TxIdle, /* TX idle. */ + kUART_TxBusy, /* TX busy. */ + kUART_RxIdle, /* RX idle. */ + kUART_RxBusy, /* RX busy. */ + kUART_RxFramingError, /* Rx framing error */ + kUART_RxParityError /* Rx parity error */ }; /* Typedef for interrupt handler. */ @@ -138,8 +140,10 @@ static UART_Type *const s_uartBases[] = UART_BASE_PTRS; /* Array of UART IRQ number. */ static const IRQn_Type s_uartIRQ[] = UART_RX_TX_IRQS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Array of UART clock name. */ static const clock_ip_name_t s_uartClock[] = UART_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* UART ISR for transactional APIs. */ static uart_isr_t s_uartIsr; @@ -227,10 +231,14 @@ status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClo /* Determine if a fractional divider is needed to fine tune closer to the * desired baud, each value of brfa is in 1/32 increments, * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (config->baudRate_Bps * 16)) - 32 * sbr; + uint32_t tempBaud = 0; + + uint16_t brfa = (2 * srcClock_Hz / (config->baudRate_Bps)) - 32 * sbr; /* Calculate the baud rate based on the temporary SBR values and BRFA */ - baudDiff = (srcClock_Hz * 2 / ((sbr * 32 + brfa))) - config->baudRate_Bps; + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = + (tempBaud > config->baudRate_Bps) ? (tempBaud - config->baudRate_Bps) : (config->baudRate_Bps - tempBaud); #else /* Calculate the baud rate based on the temporary SBR values */ @@ -252,8 +260,10 @@ status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClo return kStatus_UART_BaudrateNotSupport; } +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Enable uart clock */ CLOCK_EnableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Disable UART TX RX before setting. */ base->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK); @@ -328,8 +338,10 @@ void UART_Deinit(UART_Type *base) /* Disable the module. */ base->C2 = 0; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable uart clock */ CLOCK_DisableClock(s_uartClock[UART_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void UART_GetDefaultConfig(uart_config_t *config) @@ -368,11 +380,13 @@ status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl /* Determine if a fractional divider is needed to fine tune closer to the * desired baud, each value of brfa is in 1/32 increments, * hence the multiply-by-32. */ - uint16_t brfa = (32 * srcClock_Hz / (baudRate_Bps * 16)) - 32 * sbr; + uint32_t tempBaud = 0; - /* Calculate the baud rate based on the temporary SBR values and BRFA */ - baudDiff = (srcClock_Hz * 2 / ((sbr * 32 + brfa))) - baudRate_Bps; + uint16_t brfa = (2 * srcClock_Hz / (baudRate_Bps)) - 32 * sbr; + /* Calculate the baud rate based on the temporary SBR values and BRFA */ + tempBaud = (srcClock_Hz * 2 / ((sbr * 32 + brfa))); + baudDiff = (tempBaud > baudRate_Bps) ? (tempBaud - baudRate_Bps) : (baudRate_Bps - tempBaud); #else /* Calculate the baud rate based on the temporary SBR values */ baudDiff = (srcClock_Hz / (sbr * 16)) - baudRate_Bps; @@ -492,8 +506,7 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask) base->SFIFO = (uint8_t)(mask >> 24); #endif - if (mask & (kUART_IdleLineFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | - kUART_ParityErrorFlag)) + if (mask & (kUART_IdleLineFlag | kUART_NoiseErrorFlag | kUART_FramingErrorFlag | kUART_ParityErrorFlag)) { /* Read base->D to clear the flags. */ (void)base->S1; @@ -649,7 +662,6 @@ void UART_TransferCreateHandle(UART_Type *base, s_uartHandle[instance] = handle; s_uartIsr = UART_TransferHandleIRQ; - /* Enable interrupt in NVIC. */ EnableIRQ(s_uartIRQ[instance]); } @@ -666,7 +678,13 @@ void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_ handle->rxRingBufferTail = 0U; /* Enable the interrupt to accept the data when user need the ring buffer. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_EnableInterrupts( + base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) @@ -675,7 +693,13 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle) if (handle->rxState == kUART_RxIdle) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxRingBuffer = NULL; @@ -757,7 +781,6 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, size_t bytesToReceive; /* How many bytes currently have received. */ size_t bytesCurrentReceived; - uint32_t regPrimask = 0U; /* How to get data: 1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize @@ -781,8 +804,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, /* If RX ring buffer is used. */ if (handle->rxRingBuffer) { - /* Disable IRQ, protect ring buffer. */ - regPrimask = DisableGlobalIRQ(); + /* Disable UART RX IRQ, protect ring buffer. */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* How many bytes in RX ring buffer currently. */ bytesToCopy = UART_TransferGetRxRingBufferLength(handle); @@ -820,8 +843,8 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxState = kUART_RxBusy; } - /* Enable IRQ if previously enabled. */ - EnableGlobalIRQ(regPrimask); + /* Enable UART RX IRQ if previously enabled. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable); /* Call user callback since all data are received. */ if (0 == bytesToReceive) @@ -840,8 +863,14 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, handle->rxDataSizeAll = bytesToReceive; handle->rxState = kUART_RxBusy; - /* Enable RX interrupt. */ - UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Enable RX/Rx overrun/framing error interrupt. */ + UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Enable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_EnableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } /* Return the how many bytes have read. */ @@ -864,7 +893,13 @@ void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle) if (!handle->rxRingBuffer) { /* Disable RX interrupt. */ - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } handle->rxDataSize = 0U; @@ -898,16 +933,62 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) uint8_t count; uint8_t tempCount; + /* If RX framing error */ + if (UART_S1_FE_MASK & base->S1) + { + /* Read base->D to clear framing error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxFramingError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_FramingError, handle->userData); + } + } + + /* If RX parity error */ + if (UART_S1_PF_MASK & base->S1) + { + /* Read base->D to clear parity error flag, otherwise the RX does not work. */ + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } +#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO + /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ + base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; +#endif + + handle->rxState = kUART_RxParityError; + handle->rxDataSize = 0U; + /* Trigger callback. */ + if (handle->callback) + { + handle->callback(base, handle, kStatus_UART_ParityError, handle->userData); + } + } + /* If RX overrun. */ if (UART_S1_OR_MASK & base->S1) { /* Read base->D to clear overrun flag, otherwise the RX does not work. */ - (void)base->D; + while (base->S1 & UART_S1_RDRF_MASK) + { + (void)base->D; + } #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */ base->CFIFO |= UART_CFIFO_RXFLUSH_MASK; #endif - /* Trigger callback. */ if (handle->callback) { @@ -994,16 +1075,38 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle) } } } - /* If no receive requst pending, stop RX interrupt. */ + else if (!handle->rxDataSize) { - UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable); + /* Disable RX interrupt/overrun interrupt/fram error interrupt */ + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } } else { } } + /* If framing error or parity error happened, stop the RX interrupt when ues no ring buffer */ + if (((handle->rxState == kUART_RxFramingError) || (handle->rxState == kUART_RxParityError)) && + (!handle->rxRingBuffer)) + { + UART_DisableInterrupts(base, kUART_RxDataRegFullInterruptEnable | kUART_RxOverrunInterruptEnable | + kUART_FramingErrorInterruptEnable); + + /* Disable parity error interrupt when parity mode is enable*/ + if (UART_C1_PE_MASK & base->C1) + { + UART_DisableInterrupts(base, kUART_ParityErrorInterruptEnable); + } + } + /* Send data register empty and the interrupt is enabled. */ if ((base->S1 & UART_S1_TDRE_MASK) && (base->C2 & UART_C2_TIE_MASK)) { @@ -1088,7 +1191,6 @@ void UART2_RX_TX_DriverIRQHandler(void) { UART2_DriverIRQHandler(); } - #endif #if defined(UART3) diff --git a/drivers/fsl_uart.h b/drivers/fsl_uart.h index 16f486a..451baa9 100644 --- a/drivers/fsl_uart.h +++ b/drivers/fsl_uart.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -37,15 +37,14 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ /*! @name Driver version */ /*@{*/ -/*! @brief UART driver version 2.1.1. */ -#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 1)) +/*! @brief UART driver version 2.1.4. */ +#define FSL_UART_DRIVER_VERSION (MAKE_VERSION(2, 1, 4)) /*@}*/ /*! @brief Error codes for the UART driver. */ @@ -65,7 +64,8 @@ enum _uart_status kStatus_UART_NoiseError = MAKE_STATUS(kStatusGroup_UART, 10), /*!< UART noise error. */ kStatus_UART_FramingError = MAKE_STATUS(kStatusGroup_UART, 11), /*!< UART framing error. */ kStatus_UART_ParityError = MAKE_STATUS(kStatusGroup_UART, 12), /*!< UART parity error. */ - kStatus_UART_BaudrateNotSupport = MAKE_STATUS(kStatusGroup_UART, 13), /*!< Baudrate is not support in current clock source */ + kStatus_UART_BaudrateNotSupport = + MAKE_STATUS(kStatusGroup_UART, 13), /*!< Baudrate is not support in current clock source */ }; /*! @brief UART parity mode. */ @@ -109,17 +109,17 @@ enum _uart_interrupt_enable #endif kUART_AllInterruptsEnable = #if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT - kUART_LinBreakInterruptEnable | + kUART_LinBreakInterruptEnable | #endif - kUART_RxActiveEdgeInterruptEnable | kUART_TxDataRegEmptyInterruptEnable | - kUART_TransmissionCompleteInterruptEnable | kUART_RxDataRegFullInterruptEnable | - kUART_IdleLineInterruptEnable | kUART_RxOverrunInterruptEnable | kUART_NoiseErrorInterruptEnable | - kUART_FramingErrorInterruptEnable | kUART_ParityErrorInterruptEnable + kUART_RxActiveEdgeInterruptEnable | kUART_TxDataRegEmptyInterruptEnable | + kUART_TransmissionCompleteInterruptEnable | kUART_RxDataRegFullInterruptEnable | kUART_IdleLineInterruptEnable | + kUART_RxOverrunInterruptEnable | kUART_NoiseErrorInterruptEnable | kUART_FramingErrorInterruptEnable | + kUART_ParityErrorInterruptEnable #if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO - | kUART_RxFifoOverflowInterruptEnable | kUART_TxFifoOverflowInterruptEnable - | kUART_RxFifoUnderflowInterruptEnable + | + kUART_RxFifoOverflowInterruptEnable | kUART_TxFifoOverflowInterruptEnable | kUART_RxFifoUnderflowInterruptEnable #endif - , + , }; /*! @@ -141,13 +141,16 @@ enum _uart_flags kUART_ParityErrorFlag = (UART_S1_PF_MASK), /*!< If parity enabled, sets upon parity error detection */ #if defined(FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT) && FSL_FEATURE_UART_HAS_LIN_BREAK_DETECT kUART_LinBreakFlag = - (UART_S2_LBKDIF_MASK << 8), /*!< LIN break detect interrupt flag, sets when - LIN break char detected and LIN circuit enabled */ + (UART_S2_LBKDIF_MASK + << 8), /*!< LIN break detect interrupt flag, sets when + LIN break char detected and LIN circuit enabled */ #endif - kUART_RxActiveEdgeFlag = (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, - sets when active edge detected */ - kUART_RxActiveFlag = (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), - sets at beginning of valid start bit */ + kUART_RxActiveEdgeFlag = + (UART_S2_RXEDGIF_MASK << 8), /*!< RX pin active edge interrupt flag, + sets when active edge detected */ + kUART_RxActiveFlag = + (UART_S2_RAF_MASK << 8), /*!< Receiver Active Flag (RAF), + sets at beginning of valid start bit */ #if defined(FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS) && FSL_FEATURE_UART_HAS_EXTENDED_DATA_REGISTER_FLAGS kUART_NoiseErrorInRxDataRegFlag = (UART_ED_NOISY_MASK << 16), /*!< Noisy bit, sets if noise detected. */ kUART_ParityErrorInRxDataRegFlag = (UART_ED_PARITYE_MASK << 16), /*!< Paritye bit, sets if parity error detected. */ @@ -226,11 +229,11 @@ extern "C" { */ /*! - * @brief Initializes a UART instance with user configuration structure and peripheral clock. + * @brief Initializes a UART instance with a user configuration structure and peripheral clock. * * This function configures the UART module with the user-defined settings. The user can configure the configuration * structure and also get the default configuration by using the UART_GetDefaultConfig() function. - * Example below shows how to use this API to configure UART. + * The example below shows how to use this API to configure UART. * @code * uart_config_t uartConfig; * uartConfig.baudRate_Bps = 115200U; @@ -242,7 +245,7 @@ extern "C" { * @endcode * * @param base UART peripheral base address. - * @param config Pointer to user-defined configuration structure. + * @param config Pointer to the user-defined configuration structure. * @param srcClock_Hz UART clock source frequency in HZ. * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in current clock source. * @retval kStatus_Success Status UART initialize succeed @@ -262,7 +265,7 @@ void UART_Deinit(UART_Type *base); * @brief Gets the default configuration structure. * * This function initializes the UART configuration structure to a default value. The default - * values are: + * values are as follows. * uartConfig->baudRate_Bps = 115200U; * uartConfig->bitCountPerChar = kUART_8BitsPerChar; * uartConfig->parityMode = kUART_ParityDisabled; @@ -287,9 +290,9 @@ void UART_GetDefaultConfig(uart_config_t *config); * * @param base UART peripheral base address. * @param baudRate_Bps UART baudrate to be set. - * @param srcClock_Hz UART clock source freqency in HZ. - * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in current clock source. - * @retval kStatus_Success Set baudrate succeed + * @param srcClock_Hz UART clock source freqency in Hz. + * @retval kStatus_UART_BaudrateNotSupport Baudrate is not support in the current clock source. + * @retval kStatus_Success Set baudrate succeeded. */ status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz); @@ -301,12 +304,12 @@ status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcCl */ /*! - * @brief Get UART status flags. + * @brief Gets UART status flags. * - * This function get all UART status flags, the flags are returned as the logical + * This function gets all UART status flags. The flags are returned as the logical * OR value of the enumerators @ref _uart_flags. To check a specific status, * compare the return value with enumerators in @ref _uart_flags. - * For example, to check whether the TX is empty: + * For example, to check whether the TX is empty, do the following. * @code * if (kUART_TxDataRegEmptyFlag & UART_GetStatusFlags(UART1)) * { @@ -322,19 +325,19 @@ uint32_t UART_GetStatusFlags(UART_Type *base); /*! * @brief Clears status flags with the provided mask. * - * This function clears UART status flags with a provided mask. Automatically cleared flag + * This function clears UART status flags with a provided mask. An automatically cleared flag * can't be cleared by this function. - * Some flags can only be cleared or set by hardware itself. These flags are: + * These flags can only be cleared or set by hardware. * kUART_TxDataRegEmptyFlag, kUART_TransmissionCompleteFlag, kUART_RxDataRegFullFlag, * kUART_RxActiveFlag, kUART_NoiseErrorInRxDataRegFlag, kUART_ParityErrorInRxDataRegFlag, * kUART_TxFifoEmptyFlag,kUART_RxFifoEmptyFlag - * Note: This API should be called when the Tx/Rx is idle, otherwise it takes no effects. + * Note that this API should be called when the Tx/Rx is idle. Otherwise it has no effect. * * @param base UART peripheral base address. - * @param mask The status flags to be cleared, it is logical OR value of @ref _uart_flags. + * @param mask The status flags to be cleared; it is logical OR value of @ref _uart_flags. * @retval kStatus_UART_FlagCannotClearManually The flag can't be cleared by this function but * it is cleared automatically by hardware. - * @retval kStatus_Success Status in the mask are cleared. + * @retval kStatus_Success Status in the mask is cleared. */ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); @@ -350,7 +353,7 @@ status_t UART_ClearStatusFlags(UART_Type *base, uint32_t mask); * * This function enables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to enable TX empty interrupt and RX full interrupt: + * For example, to enable TX empty interrupt and RX full interrupt, do the following. * @code * UART_EnableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -365,7 +368,7 @@ void UART_EnableInterrupts(UART_Type *base, uint32_t mask); * * This function disables the UART interrupts according to the provided mask. The mask * is a logical OR of enumeration members. See @ref _uart_interrupt_enable. - * For example, to disable TX empty interrupt and RX full interrupt: + * For example, to disable TX empty interrupt and RX full interrupt do the following. * @code * UART_DisableInterrupts(UART1,kUART_TxDataRegEmptyInterruptEnable | kUART_RxDataRegFullInterruptEnable); * @endcode @@ -382,7 +385,7 @@ void UART_DisableInterrupts(UART_Type *base, uint32_t mask); * as the logical OR value of the enumerators @ref _uart_interrupt_enable. To check * a specific interrupts enable status, compare the return value with enumerators * in @ref _uart_interrupt_enable. - * For example, to check whether TX empty interrupt is enabled: + * For example, to check whether TX empty interrupt is enabled, do the following. * @code * uint32_t enabledInterrupts = UART_GetEnabledInterrupts(UART1); * @@ -411,7 +414,7 @@ uint32_t UART_GetEnabledInterrupts(UART_Type *base); * This function returns the UART data register address, which is mainly used by DMA/eDMA. * * @param base UART peripheral base address. - * @return UART data register address which are used both by transmitter and receiver. + * @return UART data register addresses which are used both by the transmitter and the receiver. */ static inline uint32_t UART_GetDataRegisterAddress(UART_Type *base) { @@ -543,7 +546,7 @@ static inline void UART_WriteByte(UART_Type *base, uint8_t data) /*! * @brief Reads the RX register directly. * - * This function reads data from the TX register directly. The upper layer must + * This function reads data from the RX register directly. The upper layer must * ensure that the RX register is full or that the TX FIFO has data before calling this function. * * @param base UART peripheral base address. @@ -560,7 +563,7 @@ static inline uint8_t UART_ReadByte(UART_Type *base) * This function polls the TX register, waits for the TX register to be empty or for the TX FIFO * to have room and writes data to the TX buffer. * - * @note This function does not check whether all the data has been sent out to the bus. + * @note This function does not check whether all data is sent out to the bus. * Before disabling the TX, check kUART_TransmissionCompleteFlag to ensure that the TX is * finished. * @@ -574,15 +577,15 @@ void UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length); * @brief Read RX data register using a blocking method. * * This function polls the RX register, waits for the RX register to be full or for RX FIFO to - * have data and read data from the TX register. + * have data, and reads data from the TX register. * * @param base UART peripheral base address. * @param data Start address of the buffer to store the received data. * @param length Size of the buffer. - * @retval kStatus_UART_RxHardwareOverrun Receiver overrun happened while receiving data. - * @retval kStatus_UART_NoiseError Noise error happened while receiving data. - * @retval kStatus_UART_FramingError Framing error happened while receiving data. - * @retval kStatus_UART_ParityError Parity error happened while receiving data. + * @retval kStatus_UART_RxHardwareOverrun Receiver overrun occurred while receiving data. + * @retval kStatus_UART_NoiseError A noise error occurred while receiving data. + * @retval kStatus_UART_FramingError A framing error occurred while receiving data. + * @retval kStatus_UART_ParityError A parity error occurred while receiving data. * @retval kStatus_Success Successfully received all data. */ status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length); @@ -617,16 +620,16 @@ void UART_TransferCreateHandle(UART_Type *base, * This function sets up the RX ring buffer to a specific UART handle. * * When the RX ring buffer is used, data received are stored into the ring buffer even when the - * user doesn't call the UART_TransferReceiveNonBlocking() API. If there is already data received + * user doesn't call the UART_TransferReceiveNonBlocking() API. If data is already received * in the ring buffer, the user can get the received data from the ring buffer directly. * * @note When using the RX ring buffer, one byte is reserved for internal use. In other - * words, if @p ringBufferSize is 32, then only 31 bytes are used for saving data. + * words, if @p ringBufferSize is 32, only 31 bytes are used for saving data. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer. - * @param ringBufferSize size of the ring buffer. + * @param ringBufferSize Size of the ring buffer. */ void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize); @@ -649,23 +652,23 @@ void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle); * function and passes the @ref kStatus_UART_TxIdle as status parameter. * * @note The kStatus_UART_TxIdle is passed to the upper layer when all data is written - * to the TX register. However it does not ensure that all data are sent out. Before disabling the TX, + * to the TX register. However, it does not ensure that all data is sent out. Before disabling the TX, * check the kUART_TransmissionCompleteFlag to ensure that the TX is finished. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART transfer structure. See #uart_transfer_t. * @retval kStatus_Success Successfully start the data transmission. - * @retval kStatus_UART_TxBusy Previous transmission still not finished, data not all written to TX register yet. + * @retval kStatus_UART_TxBusy Previous transmission still not finished; data not all written to TX register yet. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Aborts the interrupt driven data transmit. + * @brief Aborts the interrupt-driven data transmit. * - * This function aborts the interrupt driven data sending. The user can get the remainBytes to find out - * how many bytes are still not sent out. + * This function aborts the interrupt-driven data sending. The user can get the remainBytes to find out + * how many bytes are not sent out. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -673,16 +676,16 @@ status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, ua void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes written to the UART TX register. * - * This function gets the number of bytes that have been written to UART TX - * register by interrupt method. + * This function gets the number of bytes written to the UART TX + * register by using the interrupt method. * * @param base UART peripheral base address. * @param handle UART handle pointer. * @param count Send bytes count. * @retval kStatus_NoTransferInProgress No send in progress. - * @retval kStatus_InvalidArgument Parameter is invalid. + * @retval kStatus_InvalidArgument The parameter is invalid. * @retval kStatus_Success Get successfully through the parameter \p count; */ status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count); @@ -722,7 +725,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, * @brief Aborts the interrupt-driven data receiving. * * This function aborts the interrupt-driven data receiving. The user can get the remainBytes to know - * how many bytes not received yet. + * how many bytes are not received yet. * * @param base UART peripheral base address. * @param handle UART handle pointer. @@ -730,7 +733,7 @@ status_t UART_TransferReceiveNonBlocking(UART_Type *base, void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of bytes that have been received. * * This function gets the number of bytes that have been received. * @@ -756,7 +759,7 @@ void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle); /*! * @brief UART Error IRQ handle function. * - * This function handle the UART error IRQ request. + * This function handles the UART error IRQ request. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/drivers/fsl_uart_edma.c b/drivers/fsl_uart_edma.c index a4faa94..c51e493 100644 --- a/drivers/fsl_uart_edma.c +++ b/drivers/fsl_uart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -246,6 +246,9 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -284,6 +287,9 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -336,7 +342,9 @@ status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *h return kStatus_NoTransferInProgress; } - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } @@ -352,7 +360,9 @@ status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *hand return kStatus_NoTransferInProgress; } - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/drivers/fsl_uart_edma.h b/drivers/fsl_uart_edma.h index ea0974a..e411ffd 100644 --- a/drivers/fsl_uart_edma.h +++ b/drivers/fsl_uart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -66,6 +65,8 @@ struct _uart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -86,18 +87,18 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param callback UART callback, NULL means no callback. * @param userData User callback function data. - * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. - * @param txEdmaHandle User requested DMA handle for TX DMA transfer. + * @param rxEdmaHandle User-requested DMA handle for RX DMA transfer. + * @param txEdmaHandle User-requested DMA handle for TX DMA transfer. */ void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -108,23 +109,23 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_TxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_TxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Receive data using eDMA. + * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns * right away. When all data is received, the receive callback function is called. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_RxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); @@ -135,7 +136,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran * This function aborts sent data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); @@ -145,12 +146,12 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); * This function aborts receive data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes that have been written to UART TX register. * * This function gets the number of bytes that have been written to UART TX * register by DMA. @@ -165,9 +166,9 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/drivers/fsl_uart_freertos.c b/drivers/fsl_uart_freertos.c new file mode 100644 index 0000000..4d1da17 --- /dev/null +++ b/drivers/fsl_uart_freertos.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_uart_freertos.h" +#include <FreeRTOS.h> +#include <event_groups.h> +#include <semphr.h> + +static void UART_RTOS_Callback(UART_Type *base, uart_handle_t *state, status_t status, void *param) +{ + uart_rtos_handle_t *handle = (uart_rtos_handle_t *)param; + BaseType_t xHigherPriorityTaskWoken, xResult; + + xHigherPriorityTaskWoken = pdFALSE; + xResult = pdFAIL; + + if (status == kStatus_UART_RxIdle) + { + xResult = xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_COMPLETE, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_TxIdle) + { + xResult = xEventGroupSetBitsFromISR(handle->txEvent, RTOS_UART_COMPLETE, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_RxRingBufferOverrun) + { + xResult = xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_RING_BUFFER_OVERRUN, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_RxHardwareOverrun) + { + /* Clear Overrun flag (OR) in UART S1 register */ + UART_ClearStatusFlags(base, kUART_RxOverrunFlag); + xResult = + xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_HARDWARE_BUFFER_OVERRUN, &xHigherPriorityTaskWoken); + } + + if (xResult != pdFAIL) + { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Init + * Description : Initializes the UART instance for application + * + *END**************************************************************************/ +int UART_RTOS_Init(uart_rtos_handle_t *handle, uart_handle_t *t_handle, const uart_rtos_config_t *cfg) +{ + uart_config_t defcfg; + + if (NULL == handle) + { + return kStatus_InvalidArgument; + } + if (NULL == t_handle) + { + return kStatus_InvalidArgument; + } + if (NULL == cfg) + { + return kStatus_InvalidArgument; + } + if (NULL == cfg->base) + { + return kStatus_InvalidArgument; + } + if (0 == cfg->srcclk) + { + return kStatus_InvalidArgument; + } + if (0 == cfg->baudrate) + { + return kStatus_InvalidArgument; + } + + handle->base = cfg->base; + handle->t_state = t_handle; +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->txSemaphore = xSemaphoreCreateMutexStatic(&handle->txSemaphoreBuffer); +#else + handle->txSemaphore = xSemaphoreCreateMutex(); +#endif + if (NULL == handle->txSemaphore) + { + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->rxSemaphore = xSemaphoreCreateMutexStatic(&handle->rxSemaphoreBuffer); +#else + handle->rxSemaphore = xSemaphoreCreateMutex(); +#endif + if (NULL == handle->rxSemaphore) + { + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->txEvent = xEventGroupCreateStatic(&handle->txEventBuffer); +#else + handle->txEvent = xEventGroupCreate(); +#endif + if (NULL == handle->txEvent) + { + vSemaphoreDelete(handle->rxSemaphore); + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->rxEvent = xEventGroupCreateStatic(&handle->rxEventBuffer); +#else + handle->rxEvent = xEventGroupCreate(); +#endif + if (NULL == handle->rxEvent) + { + vEventGroupDelete(handle->txEvent); + vSemaphoreDelete(handle->rxSemaphore); + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } + UART_GetDefaultConfig(&defcfg); + + defcfg.baudRate_Bps = cfg->baudrate; + defcfg.parityMode = cfg->parity; +#if defined(FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT + defcfg.stopBitCount = cfg->stopbits; +#endif + + UART_Init(handle->base, &defcfg, cfg->srcclk); + UART_TransferCreateHandle(handle->base, handle->t_state, UART_RTOS_Callback, handle); + UART_TransferStartRingBuffer(handle->base, handle->t_state, cfg->buffer, cfg->buffer_size); + + UART_EnableTx(handle->base, true); + UART_EnableRx(handle->base, true); + + return 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Deinit + * Description : Deinitializes the UART instance and frees resources + * + *END**************************************************************************/ +int UART_RTOS_Deinit(uart_rtos_handle_t *handle) +{ + UART_Deinit(handle->base); + + vEventGroupDelete(handle->txEvent); + vEventGroupDelete(handle->rxEvent); + + /* Give the semaphore. This is for functional safety */ + xSemaphoreGive(handle->txSemaphore); + xSemaphoreGive(handle->rxSemaphore); + + vSemaphoreDelete(handle->txSemaphore); + vSemaphoreDelete(handle->rxSemaphore); + + /* Invalidate the handle */ + handle->base = NULL; + handle->t_state = NULL; + + return 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Send + * Description : Initializes the UART instance for application + * + *END**************************************************************************/ +int UART_RTOS_Send(uart_rtos_handle_t *handle, const uint8_t *buffer, uint32_t length) +{ + EventBits_t ev; + int retval = kStatus_Success; + + if (NULL == handle->base) + { + /* Invalid handle. */ + return kStatus_Fail; + } + if (0 == length) + { + return 0; + } + if (NULL == buffer) + { + return kStatus_InvalidArgument; + } + + if (pdFALSE == xSemaphoreTake(handle->txSemaphore, 0)) + { + /* We could not take the semaphore, exit with 0 data received */ + return kStatus_Fail; + } + + handle->txTransfer.data = (uint8_t *)buffer; + handle->txTransfer.dataSize = (uint32_t)length; + + /* Non-blocking call */ + UART_TransferSendNonBlocking(handle->base, handle->t_state, &handle->txTransfer); + + ev = xEventGroupWaitBits(handle->txEvent, RTOS_UART_COMPLETE, pdTRUE, pdFALSE, portMAX_DELAY); + if (!(ev & RTOS_UART_COMPLETE)) + { + retval = kStatus_Fail; + } + + if (pdFALSE == xSemaphoreGive(handle->txSemaphore)) + { + /* We could not post the semaphore, exit with error */ + retval = kStatus_Fail; + } + + return retval; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Recv + * Description : Receives chars for the application + * + *END**************************************************************************/ +int UART_RTOS_Receive(uart_rtos_handle_t *handle, uint8_t *buffer, uint32_t length, size_t *received) +{ + EventBits_t ev; + size_t n = 0; + int retval = kStatus_Fail; + size_t local_received = 0; + + if (NULL == handle->base) + { + /* Invalid handle. */ + return kStatus_Fail; + } + if (0 == length) + { + if (received != NULL) + { + *received = n; + } + return 0; + } + if (NULL == buffer) + { + return kStatus_InvalidArgument; + } + + /* New transfer can be performed only after current one is finished */ + if (pdFALSE == xSemaphoreTake(handle->rxSemaphore, portMAX_DELAY)) + { + /* We could not take the semaphore, exit with 0 data received */ + return kStatus_Fail; + } + + handle->rxTransfer.data = buffer; + handle->rxTransfer.dataSize = (uint32_t)length; + + /* Non-blocking call */ + UART_TransferReceiveNonBlocking(handle->base, handle->t_state, &handle->rxTransfer, &n); + + ev = xEventGroupWaitBits(handle->rxEvent, + RTOS_UART_COMPLETE | RTOS_UART_RING_BUFFER_OVERRUN | RTOS_UART_HARDWARE_BUFFER_OVERRUN, + pdTRUE, pdFALSE, portMAX_DELAY); + if (ev & RTOS_UART_HARDWARE_BUFFER_OVERRUN) + { + /* Stop data transfer to application buffer, ring buffer is still active */ + UART_TransferAbortReceive(handle->base, handle->t_state); + /* Prevent false indication of successful transfer in next call of UART_RTOS_Receive. + RTOS_UART_COMPLETE flag could be set meanwhile overrun is handled */ + xEventGroupClearBits(handle->rxEvent, RTOS_UART_COMPLETE); + retval = kStatus_UART_RxHardwareOverrun; + local_received = 0; + } + else if (ev & RTOS_UART_RING_BUFFER_OVERRUN) + { + /* Stop data transfer to application buffer, ring buffer is still active */ + UART_TransferAbortReceive(handle->base, handle->t_state); + /* Prevent false indication of successful transfer in next call of UART_RTOS_Receive. + RTOS_UART_COMPLETE flag could be set meanwhile overrun is handled */ + xEventGroupClearBits(handle->rxEvent, RTOS_UART_COMPLETE); + retval = kStatus_UART_RxRingBufferOverrun; + local_received = 0; + } + else if (ev & RTOS_UART_COMPLETE) + { + retval = kStatus_Success; + local_received = length; + } + + /* Prevent repetitive NULL check */ + if (received != NULL) + { + *received = local_received; + } + + /* Enable next transfer. Current one is finished */ + if (pdFALSE == xSemaphoreGive(handle->rxSemaphore)) + { + /* We could not post the semaphore, exit with error */ + retval = kStatus_Fail; + } + return retval; +} diff --git a/drivers/fsl_uart_freertos.h b/drivers/fsl_uart_freertos.h new file mode 100644 index 0000000..0525e23 --- /dev/null +++ b/drivers/fsl_uart_freertos.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __FSL_UART_RTOS_H__ +#define __FSL_UART_RTOS_H__ + +#include "FreeRTOSConfig.h" +#include "fsl_uart.h" +#include <FreeRTOS.h> +#include <event_groups.h> +#include <semphr.h> + +/*! + * @addtogroup uart_freertos_driver + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @brief UART configuration structure */ +typedef struct _uart_rtos_config +{ + UART_Type *base; /*!< UART base address */ + uint32_t srcclk; /*!< UART source clock in Hz*/ + uint32_t baudrate; /*!< Desired communication speed */ + uart_parity_mode_t parity; /*!< Parity setting */ + uart_stop_bit_count_t stopbits; /*!< Number of stop bits to use */ + uint8_t *buffer; /*!< Buffer for background reception */ + uint32_t buffer_size; /*!< Size of buffer for background reception */ +} uart_rtos_config_t; + +/*! +* @cond RTOS_PRIVATE +* @name UART FreeRTOS handler +* +* These are the only valid states for txEvent and rxEvent (uart_rtos_handle_t). +*/ +/*@{*/ +/*! @brief Event flag - transfer complete. */ +#define RTOS_UART_COMPLETE 0x1 +/*! @brief Event flag - ring buffer overrun. */ +#define RTOS_UART_RING_BUFFER_OVERRUN 0x2 +/*! @brief Event flag - hardware buffer overrun. */ +#define RTOS_UART_HARDWARE_BUFFER_OVERRUN 0x4 +/*@}*/ + +/*! @brief UART FreeRTOS transfer structure. */ +typedef struct _uart_rtos_handle +{ + UART_Type *base; /*!< UART base address */ + uart_transfer_t txTransfer; /*!< TX transfer structure */ + uart_transfer_t rxTransfer; /*!< RX transfer structure */ + SemaphoreHandle_t rxSemaphore; /*!< RX semaphore for resource sharing */ + SemaphoreHandle_t txSemaphore; /*!< TX semaphore for resource sharing */ + EventGroupHandle_t rxEvent; /*!< RX completion event */ + EventGroupHandle_t txEvent; /*!< TX completion event */ + void *t_state; /*!< Transactional state of the underlying driver */ +#if (configSUPPORT_STATIC_ALLOCATION == 1) + StaticSemaphore_t txSemaphoreBuffer; /*!< Statically allocated memory for txSemaphore */ + StaticSemaphore_t rxSemaphoreBuffer; /*!< Statically allocated memory for rxSemaphore */ + StaticEventGroup_t txEventBuffer; /*!< Statically allocated memory for txEvent */ + StaticEventGroup_t rxEventBuffer; /*!< Statically allocated memory for rxEvent */ +#endif +} uart_rtos_handle_t; +/*! \endcond */ + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name UART RTOS Operation + * @{ + */ + +/*! + * @brief Initializes a UART instance for operation in RTOS. + * + * @param handle The RTOS UART handle, the pointer to an allocated space for RTOS context. + * @param t_handle The pointer to the allocated space to store the transactional layer internal state. + * @param cfg The pointer to the parameters required to configure the UART after initialization. + * @return 0 succeed; otherwise fail. + */ +int UART_RTOS_Init(uart_rtos_handle_t *handle, uart_handle_t *t_handle, const uart_rtos_config_t *cfg); + +/*! + * @brief Deinitializes a UART instance for operation. + * + * This function deinitializes the UART module, sets all register values to reset value, + * and frees the resources. + * + * @param handle The RTOS UART handle. + */ +int UART_RTOS_Deinit(uart_rtos_handle_t *handle); + +/*! + * @name UART transactional Operation + * @{ + */ + +/*! + * @brief Sends data in the background. + * + * This function sends data. It is a synchronous API. + * If the hardware buffer is full, the task is in the blocked state. + * + * @param handle The RTOS UART handle. + * @param buffer The pointer to the buffer to send. + * @param length The number of bytes to send. + */ +int UART_RTOS_Send(uart_rtos_handle_t *handle, const uint8_t *buffer, uint32_t length); + +/*! + * @brief Receives data. + * + * This function receives data from UART. It is a synchronous API. If data is immediately available, + * it is returned immediately and the number of bytes received. + * + * @param handle The RTOS UART handle. + * @param buffer The pointer to the buffer to write received data. + * @param length The number of bytes to receive. + * @param received The pointer to a variable of size_t where the number of received data is filled. + */ +int UART_RTOS_Receive(uart_rtos_handle_t *handle, uint8_t *buffer, uint32_t length, size_t *received); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* __FSL_UART_RTOS_H__ */ diff --git a/drivers/fsl_vref.c b/drivers/fsl_vref.c index 248132c..24f2d1d 100644 --- a/drivers/fsl_vref.c +++ b/drivers/fsl_vref.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -50,8 +50,10 @@ static uint32_t VREF_GetInstance(VREF_Type *base); /*! @brief Pointers to VREF bases for each instance. */ static VREF_Type *const s_vrefBases[] = VREF_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /*! @brief Pointers to VREF clocks for each instance. */ static const clock_ip_name_t s_vrefClocks[] = VREF_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /******************************************************************************* * Code @@ -62,7 +64,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_VREF_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_vrefBases); instance++) { if (s_vrefBases[instance] == base) { @@ -70,7 +72,7 @@ static uint32_t VREF_GetInstance(VREF_Type *base) } } - assert(instance < FSL_FEATURE_SOC_VREF_COUNT); + assert(instance < ARRAY_SIZE(s_vrefBases)); return instance; } @@ -81,8 +83,10 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) uint8_t reg = 0U; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Ungate clock for VREF */ CLOCK_EnableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Configure VREF to a known state */ #if defined(FSL_FEATURE_VREF_HAS_CHOP_OSC) && FSL_FEATURE_VREF_HAS_CHOP_OSC @@ -141,8 +145,10 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config) void VREF_Deinit(VREF_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Gate clock for VREF */ CLOCK_DisableClock(s_vrefClocks[VREF_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } void VREF_GetDefaultConfig(vref_config_t *config) diff --git a/drivers/fsl_vref.h b/drivers/fsl_vref.h index 349c124..6c6c014 100644 --- a/drivers/fsl_vref.h +++ b/drivers/fsl_vref.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -78,8 +78,8 @@ typedef enum _vref_buffer_mode { kVREF_ModeBandgapOnly = 0U, /*!< Bandgap on only, for stabilization and startup */ #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE - kVREF_ModeHighPowerBuffer = 1U, /*!< High power buffer mode enabled */ - kVREF_ModeLowPowerBuffer = 2U /*!< Low power buffer mode enabled */ + kVREF_ModeHighPowerBuffer = 1U, /*!< High-power buffer mode enabled */ + kVREF_ModeLowPowerBuffer = 2U /*!< Low-power buffer mode enabled */ #else kVREF_ModeTightRegulationBuffer = 2U /*!< Tight regulation buffer enabled */ #endif /* FSL_FEATURE_VREF_MODE_LV_TYPE */ @@ -116,11 +116,11 @@ extern "C" { /*! * @brief Enables the clock gate and configures the VREF module according to the configuration structure. * - * This function must be called before calling all the other VREF driver functions, + * This function must be called before calling all other VREF driver functions, * read/write registers, and configurations with user-defined settings. * The example below shows how to set up vref_config_t parameters and - * how to call the VREF_Init function by passing in these parameters: - * Example: + * how to call the VREF_Init function by passing in these parameters. + * This is an example. * @code * vref_config_t vrefConfig; * vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer; @@ -138,7 +138,7 @@ void VREF_Init(VREF_Type *base, const vref_config_t *config); * @brief Stops and disables the clock for the VREF module. * * This function should be called to shut down the module. - * Example: + * This is an example. * @code * vref_config_t vrefUserConfig; * VREF_Init(VREF); @@ -154,8 +154,8 @@ void VREF_Deinit(VREF_Type *base); /*! * @brief Initializes the VREF configuration structure. * - * This function initializes the VREF configuration structure to a default value. - * Example: + * This function initializes the VREF configuration structure to default values. + * This is an example. * @code * vrefConfig->bufferMode = kVREF_ModeHighPowerBuffer; * vrefConfig->enableExternalVoltRef = false; @@ -167,9 +167,9 @@ void VREF_Deinit(VREF_Type *base); void VREF_GetDefaultConfig(vref_config_t *config); /*! - * @brief Sets a TRIM value for reference voltage. + * @brief Sets a TRIM value for the reference voltage. * - * This function sets a TRIM value for reference voltage. + * This function sets a TRIM value for the reference voltage. * Note that the TRIM value maximum is 0x3F. * * @param base VREF peripheral address. @@ -192,9 +192,9 @@ static inline uint8_t VREF_GetTrimVal(VREF_Type *base) #if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4 /*! - * @brief Sets a TRIM value for reference voltage (2V1). + * @brief Sets a TRIM value for the reference voltage (2V1). * - * This function sets a TRIM value for reference voltage (2V1). + * This function sets a TRIM value for the reference voltage (2V1). * Note that the TRIM value maximum is 0x3F. * * @param base VREF peripheral address. @@ -219,10 +219,10 @@ static inline uint8_t VREF_GetTrim2V1Val(VREF_Type *base) #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE /*! - * @brief Sets the TRIM value for low voltage reference. + * @brief Sets the TRIM value for the low voltage reference. * * This function sets the TRIM value for low reference voltage. - * NOTE: + * Note the following. * - The TRIM value maximum is 0x05U * - The values 111b and 110b are not valid/allowed. * diff --git a/drivers/fsl_wdog.c b/drivers/fsl_wdog.c index 489798c..781ac13 100644 --- a/drivers/fsl_wdog.c +++ b/drivers/fsl_wdog.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * diff --git a/drivers/fsl_wdog.h b/drivers/fsl_wdog.h index f497406..580adb9 100644 --- a/drivers/fsl_wdog.h +++ b/drivers/fsl_wdog.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * o Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -163,10 +163,10 @@ extern "C" { */ /*! - * @brief Initializes WDOG configure sturcture. + * @brief Initializes the WDOG configuration sturcture. * - * This function initializes the WDOG configuration structure to default value. The default - * values are: + * This function initializes the WDOG configuration structure to default values. The default + * values are as follows. * @code * wdogConfig->enableWdog = true; * wdogConfig->clockSource = kWDOG_LpoClockSource; @@ -181,7 +181,7 @@ extern "C" { * wdogConfig->timeoutValue = 0xFFFFU; * @endcode * - * @param config Pointer to WDOG config structure. + * @param config Pointer to the WDOG configuration structure. * @see wdog_config_t */ void WDOG_GetDefaultConfig(wdog_config_t *config); @@ -190,10 +190,10 @@ void WDOG_GetDefaultConfig(wdog_config_t *config); * @brief Initializes the WDOG. * * This function initializes the WDOG. When called, the WDOG runs according to the configuration. - * If user wants to reconfigure WDOG without forcing a reset first, enableUpdate must be set to true - * in configuration. + * To reconfigure WDOG without forcing a reset first, enableUpdate must be set to true + * in the configuration. * - * Example: + * This is an example. * @code * wdog_config_t config; * WDOG_GetDefaultConfig(&config); @@ -211,18 +211,18 @@ void WDOG_Init(WDOG_Type *base, const wdog_config_t *config); * @brief Shuts down the WDOG. * * This function shuts down the WDOG. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which indicates that the register update is enabled. */ void WDOG_Deinit(WDOG_Type *base); /*! - * @brief Configures WDOG functional test. + * @brief Configures the WDOG functional test. * * This function is used to configure the WDOG functional test. When called, the WDOG goes into test mode * and runs according to the configuration. - * Make sure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. + * Ensure that the WDOG_STCTRLH.ALLOWUPDATE is 1 which means that the register update is enabled. * - * Example: + * This is an example. * @code * wdog_test_config_t test_config; * test_config.testMode = kWDOG_QuickTest; @@ -258,9 +258,9 @@ static inline void WDOG_Enable(WDOG_Type *base) /*! * @brief Disables the WDOG module. * - * This function write value into WDOG_STCTRLH register to disable the WDOG, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG. It is a write-once register. + * Ensure that the WCT window is still open and that register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address */ @@ -270,15 +270,15 @@ static inline void WDOG_Disable(WDOG_Type *base) } /*! - * @brief Enable WDOG interrupt. + * @brief Enables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to enable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to enable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to enable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) @@ -287,15 +287,15 @@ static inline void WDOG_EnableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Disable WDOG interrupt. + * @brief Disables the WDOG interrupt. * - * This function write value into WDOG_STCTRLH register to disable WDOG interrupt, it is a write-once register, - * make sure that the WCT window is still open and this register has not been written in this WCT - * while this function is called. + * This function writes a value into the WDOG_STCTRLH register to disable the WDOG interrupt. It is a write-once register. + * Ensure that the WCT window is still open and the register has not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param mask The interrupts to disable - * The parameter can be combination of the following source if defined: + * The parameter can be combination of the following source if defined. * @arg kWDOG_InterruptEnable */ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) @@ -304,14 +304,14 @@ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) } /*! - * @brief Gets WDOG all status flags. + * @brief Gets the WDOG all status flags. * * This function gets all status flags. * - * Example for getting Running Flag: + * This is an example for getting the Running Flag. * @code * uint32_t status; - * status = WDOG_GetStatusFlags(wdog_base) & kWDOG_RunningFlag; + * status = WDOG_GetStatusFlags (wdog_base) & kWDOG_RunningFlag; * @endcode * @param base WDOG peripheral base address * @return State of the status flag: asserted (true) or not-asserted (false).@see _wdog_status_flags_t @@ -321,33 +321,33 @@ static inline void WDOG_DisableInterrupts(WDOG_Type *base, uint32_t mask) uint32_t WDOG_GetStatusFlags(WDOG_Type *base); /*! - * @brief Clear WDOG flag. + * @brief Clears the WDOG flag. * - * This function clears WDOG status flag. + * This function clears the WDOG status flag. * - * Example for clearing timeout(interrupt) flag: + * This is an example for clearing the timeout (interrupt) flag. * @code * WDOG_ClearStatusFlags(wdog_base,kWDOG_TimeoutFlag); * @endcode * @param base WDOG peripheral base address * @param mask The status flags to clear. - * The parameter could be any combination of the following values: + * The parameter could be any combination of the following values. * kWDOG_TimeoutFlag */ void WDOG_ClearStatusFlags(WDOG_Type *base, uint32_t mask); /*! - * @brief Set the WDOG timeout value. + * @brief Sets the WDOG timeout value. * * This function sets the timeout value. * It should be ensured that the time-out value for the WDOG is always greater than * 2xWCT time + 20 bus clock cycles. - * This function write value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_TOVALH and WDOG_TOVALL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address - * @param timeoutCount WDOG timeout value, count of WDOG clock tick. + * @param timeoutCount WDOG timeout value; count of WDOG clock tick. */ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) { @@ -359,9 +359,9 @@ static inline void WDOG_SetTimeoutValue(WDOG_Type *base, uint32_t timeoutCount) * @brief Sets the WDOG window value. * * This function sets the WDOG window value. - * This function write value into WDOG_WINH and WDOG_WINL registers which are wirte-once. - * Make sure the WCT window is still open and these two registers have not been written in this WCT - * while this function is called. + * This function writes a value into WDOG_WINH and WDOG_WINL registers which are wirte-once. + * Ensure the WCT window is still open and the two registers have not been written to in this WCT + * while the function is called. * * @param base WDOG peripheral base address * @param windowValue WDOG window value. @@ -377,7 +377,7 @@ static inline void WDOG_SetWindowValue(WDOG_Type *base, uint32_t windowValue) * * This function unlocks the WDOG register written. * Before starting the unlock sequence and following congfiguration, disable the global interrupts. - * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire, + * Otherwise, an interrupt may invalidate the unlocking sequence and the WCT may expire. * After the configuration finishes, re-enable the global interrupts. * * @param base WDOG peripheral base address @@ -392,7 +392,7 @@ static inline void WDOG_Unlock(WDOG_Type *base) * @brief Refreshes the WDOG timer. * * This function feeds the WDOG. - * This function should be called before WDOG timer is in timeout. Otherwise, a reset is asserted. + * This function should be called before the WDOG timer is in timeout. Otherwise, a reset is asserted. * * @param base WDOG peripheral base address */ @@ -404,7 +404,7 @@ void WDOG_Refresh(WDOG_Type *base); * This function gets the WDOG reset count value. * * @param base WDOG peripheral base address - * @return WDOG reset count value + * @return WDOG reset count value. */ static inline uint16_t WDOG_GetResetCount(WDOG_Type *base) { |