From e6e1f735995c72cc33b093ad8e710655dcc7b3c0 Mon Sep 17 00:00:00 2001 From: Mahadevan Mahesh Date: Tue, 17 May 2016 12:02:09 -0500 Subject: [PATCH] Fix for Issue#1740. The latest SDK drivers for FTM & TPM has the fix for this issue This fixes issues seen when running FTM and TPM demos in certain modes Signed-off-by: Mahadevan Mahesh --- .../TARGET_K22F/drivers/fsl_ftm.c | 56 ++++-- .../TARGET_K22F/drivers/fsl_ftm.h | 4 +- .../TARGET_K64F/drivers/fsl_ftm.c | 56 ++++-- .../TARGET_K64F/drivers/fsl_ftm.h | 4 +- .../TARGET_KL27Z/drivers/fsl_tpm.c | 165 +++++++++++++----- .../TARGET_KL27Z/drivers/fsl_tpm.h | 20 ++- 6 files changed, 213 insertions(+), 92 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.c index a9056097574..85dc2194254 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.c +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.c @@ -237,11 +237,8 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) /* Configure the update mechanism for buffered registers */ FTM_SetPwmSync(base, config->pwmSyncMode); - if (config->reloadPoints) - { - /* Setup intermediate register reload points */ - FTM_SetReloadPoints(base, config->reloadPoints); - } + /* Setup intermediate register reload points */ + FTM_SetReloadPoints(base, config->reloadPoints); /* Set the clock prescale factor */ base->SC = FTM_SC_PS(config->prescale); @@ -327,6 +324,9 @@ status_t FTM_SetupPwm(FTM_Type *base, uint32_t srcClock_Hz) { assert(chnlParams); + assert(srcClock_Hz); + assert(pwmFreq_Hz); + assert(numOfChnls); uint32_t mod, reg; uint32_t ftmClock = (srcClock_Hz / (1U << (base->SC & FTM_SC_PS_MASK))); @@ -373,7 +373,7 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */ reg |= FTM_CnSC_MSB(1U); @@ -397,6 +397,10 @@ status_t FTM_SetupPwm(FTM_Type *base, } base->CONTROLS[chnlParams->chnlNumber].CnV = cnv; +#if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) + /* Set to output mode */ + FTM_SetPwmOutputEnable(base, chnlParams->chnlNumber, true); +#endif } else { @@ -445,7 +449,7 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level for channel n */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Update the mode and edge level for channel n */ base->CONTROLS[chnlParams->chnlNumber * 2].CnSC = reg; @@ -455,25 +459,25 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level for channel n + 1 */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Update the mode and edge level for channel n + 1*/ base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC = reg; - /* Set the channel pair values */ - base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; - base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; - /* Set the combine bit for the channel pair */ base->COMBINE |= (1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlParams->chnlNumber))); - } + + /* Set the channel pair values */ + base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; + base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) - /* Set to output mode */ - FTM_SetPwmOutputEnable(base, chnlParams->chnlNumber, true); + /* Set to output mode */ + FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2), true); + FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2 + 1), true); #endif - + } chnlParams++; } @@ -535,6 +539,13 @@ void FTM_SetupInputCapture(FTM_Type *base, { uint32_t reg; + /* Clear the combine bit for the channel pair */ + base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the dual edge capture mode because it's it's higher priority */ + base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the quadrature decoder mode beacause it's higher priority */ + base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK; + reg = base->CONTROLS[chnlNumber].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); reg |= captureMode; @@ -562,8 +573,12 @@ void FTM_SetupOutputCompare(FTM_Type *base, { uint32_t reg; - /* Set output on match to the requested level */ - base->CONTROLS[chnlNumber].CnV = compareValue; + /* Clear the combine bit for the channel pair */ + base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the dual edge capture mode because it's it's higher priority */ + base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the quadrature decoder mode beacause it's higher priority */ + base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK; reg = base->CONTROLS[chnlNumber].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); @@ -571,6 +586,9 @@ void FTM_SetupOutputCompare(FTM_Type *base, /* Setup the channel output behaviour when a match occurs with the compare value */ base->CONTROLS[chnlNumber].CnSC = reg; + /* Set output on match to the requested level */ + base->CONTROLS[chnlNumber].CnV = compareValue; + #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) /* Set to output mode */ FTM_SetPwmOutputEnable(base, chnlNumber, true); @@ -662,6 +680,8 @@ void FTM_SetupQuadDecode(FTM_Type *base, void FTM_SetupFault(FTM_Type *base, ftm_fault_input_t faultNumber, const ftm_fault_param_t *faultParams) { + assert(faultParams); + uint32_t reg; reg = base->FLTCTRL; diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.h index eb1ebf79f4c..2fb1c08e49c 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.h +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K22F/drivers/fsl_ftm.h @@ -33,7 +33,7 @@ #include "fsl_common.h" /*! - * @addtogroup ftm_driver + * @addtogroup ftm * @{ */ @@ -162,7 +162,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 i.e., '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 */ diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.c index a9056097574..85dc2194254 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.c +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.c @@ -237,11 +237,8 @@ status_t FTM_Init(FTM_Type *base, const ftm_config_t *config) /* Configure the update mechanism for buffered registers */ FTM_SetPwmSync(base, config->pwmSyncMode); - if (config->reloadPoints) - { - /* Setup intermediate register reload points */ - FTM_SetReloadPoints(base, config->reloadPoints); - } + /* Setup intermediate register reload points */ + FTM_SetReloadPoints(base, config->reloadPoints); /* Set the clock prescale factor */ base->SC = FTM_SC_PS(config->prescale); @@ -327,6 +324,9 @@ status_t FTM_SetupPwm(FTM_Type *base, uint32_t srcClock_Hz) { assert(chnlParams); + assert(srcClock_Hz); + assert(pwmFreq_Hz); + assert(numOfChnls); uint32_t mod, reg; uint32_t ftmClock = (srcClock_Hz / (1U << (base->SC & FTM_SC_PS_MASK))); @@ -373,7 +373,7 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */ reg |= FTM_CnSC_MSB(1U); @@ -397,6 +397,10 @@ status_t FTM_SetupPwm(FTM_Type *base, } base->CONTROLS[chnlParams->chnlNumber].CnV = cnv; +#if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) + /* Set to output mode */ + FTM_SetPwmOutputEnable(base, chnlParams->chnlNumber, true); +#endif } else { @@ -445,7 +449,7 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level for channel n */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Update the mode and edge level for channel n */ base->CONTROLS[chnlParams->chnlNumber * 2].CnSC = reg; @@ -455,25 +459,25 @@ status_t FTM_SetupPwm(FTM_Type *base, reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level for channel n + 1 */ - reg |= (FTM_CnSC_ELSA(chnlParams->level) | FTM_CnSC_ELSB(chnlParams->level)); + reg |= (uint32_t)(chnlParams->level << FTM_CnSC_ELSA_SHIFT); /* Update the mode and edge level for channel n + 1*/ base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC = reg; - /* Set the channel pair values */ - base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; - base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; - /* Set the combine bit for the channel pair */ base->COMBINE |= (1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * chnlParams->chnlNumber))); - } + + /* Set the channel pair values */ + base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; + base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) - /* Set to output mode */ - FTM_SetPwmOutputEnable(base, chnlParams->chnlNumber, true); + /* Set to output mode */ + FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2), true); + FTM_SetPwmOutputEnable(base, (ftm_chnl_t)((uint8_t)chnlParams->chnlNumber * 2 + 1), true); #endif - + } chnlParams++; } @@ -535,6 +539,13 @@ void FTM_SetupInputCapture(FTM_Type *base, { uint32_t reg; + /* Clear the combine bit for the channel pair */ + base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the dual edge capture mode because it's it's higher priority */ + base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the quadrature decoder mode beacause it's higher priority */ + base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK; + reg = base->CONTROLS[chnlNumber].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); reg |= captureMode; @@ -562,8 +573,12 @@ void FTM_SetupOutputCompare(FTM_Type *base, { uint32_t reg; - /* Set output on match to the requested level */ - base->CONTROLS[chnlNumber].CnV = compareValue; + /* Clear the combine bit for the channel pair */ + base->COMBINE &= ~(1U << (FTM_COMBINE_COMBINE0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the dual edge capture mode because it's it's higher priority */ + base->COMBINE &= ~(1U << (FTM_COMBINE_DECAPEN0_SHIFT + (FTM_COMBINE_COMBINE1_SHIFT * (chnlNumber >> 1)))); + /* Clear the quadrature decoder mode beacause it's higher priority */ + base->QDCTRL &= ~FTM_QDCTRL_QUADEN_MASK; reg = base->CONTROLS[chnlNumber].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); @@ -571,6 +586,9 @@ void FTM_SetupOutputCompare(FTM_Type *base, /* Setup the channel output behaviour when a match occurs with the compare value */ base->CONTROLS[chnlNumber].CnSC = reg; + /* Set output on match to the requested level */ + base->CONTROLS[chnlNumber].CnV = compareValue; + #if defined(FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) && (FSL_FEATURE_FTM_HAS_ENABLE_PWM_OUTPUT) /* Set to output mode */ FTM_SetPwmOutputEnable(base, chnlNumber, true); @@ -662,6 +680,8 @@ void FTM_SetupQuadDecode(FTM_Type *base, void FTM_SetupFault(FTM_Type *base, ftm_fault_input_t faultNumber, const ftm_fault_param_t *faultParams) { + assert(faultParams); + uint32_t reg; reg = base->FLTCTRL; diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.h index eb1ebf79f4c..2fb1c08e49c 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.h +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_K64F/drivers/fsl_ftm.h @@ -33,7 +33,7 @@ #include "fsl_common.h" /*! - * @addtogroup ftm_driver + * @addtogroup ftm * @{ */ @@ -162,7 +162,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 i.e., '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 */ diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.c b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.c index 8a7abea621c..e3134a97550 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.c +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.c @@ -94,9 +94,9 @@ void TPM_Init(TPM_Type *base, const tpm_config_t *config) base->SC = TPM_SC_PS(config->prescale); /* Setup the counter operation */ - base->CONF = TPM_CONF_DOZEEN(config->enableDoze) | TPM_CONF_DBGMODE(config->enableDebugMode) | - TPM_CONF_GTBEEN(config->useGlobalTimeBase) | TPM_CONF_CROT(config->enableReloadOnTrigger) | - TPM_CONF_CSOT(config->enableStartOnTrigger) | TPM_CONF_CSOO(config->enableStopOnOverflow) | + base->CONF = TPM_CONF_DOZEEN(config->enableDoze) | TPM_CONF_GTBEEN(config->useGlobalTimeBase) | + TPM_CONF_CROT(config->enableReloadOnTrigger) | TPM_CONF_CSOT(config->enableStartOnTrigger) | + TPM_CONF_CSOO(config->enableStopOnOverflow) | #if defined(FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER) && FSL_FEATURE_TPM_HAS_PAUSE_COUNTER_ON_TRIGGER TPM_CONF_CPOT(config->enablePauseOnTrigger) | #endif @@ -104,6 +104,14 @@ void TPM_Init(TPM_Type *base, const tpm_config_t *config) TPM_CONF_TRGSRC(config->triggerSource) | #endif TPM_CONF_TRGSEL(config->triggerSelect); + if (config->enableDebugMode) + { + base->CONF |= TPM_CONF_DBGMODE_MASK; + } + else + { + base->CONF &= ~TPM_CONF_DBGMODE_MASK; + } } void TPM_Deinit(TPM_Type *base) @@ -151,12 +159,20 @@ status_t TPM_SetupPwm(TPM_Type *base, uint32_t srcClock_Hz) { assert(chnlParams); + assert(pwmFreq_Hz); + assert(numOfChnls); + assert(srcClock_Hz); uint32_t mod; uint32_t tpmClock = (srcClock_Hz / (1U << (base->SC & TPM_SC_PS_MASK))); uint16_t cnv; uint8_t i; +#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL + /* Clear quadrature Decoder mode because in quadrature Decoder mode PWM doesn't operate*/ + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; +#endif + switch (mode) { case kTPM_EdgeAlignedPwm: @@ -233,9 +249,6 @@ status_t TPM_SetupPwm(TPM_Type *base, cnv = mod + 1; } } - /* Set the channel pair values */ - base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; - base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; /* Set the combine bit for the channel pair */ base->COMBINE |= (1U << (TPM_COMBINE_COMBINE0_SHIFT + (TPM_COMBINE_SHIFT * chnlParams->chnlNumber))); @@ -244,6 +257,12 @@ status_t TPM_SetupPwm(TPM_Type *base, base->CONTROLS[chnlParams->chnlNumber * 2].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlParams->chnlNumber * 2].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } + /* Set the requested PWM mode for channel n, PWM output requires mode select to be set to 2 */ base->CONTROLS[chnlParams->chnlNumber * 2].CnSC |= ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT)); @@ -253,11 +272,19 @@ status_t TPM_SetupPwm(TPM_Type *base, (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } + /* Set the channel pair values */ + base->CONTROLS[chnlParams->chnlNumber * 2].CnV = cnvFirstEdge; /* When switching mode, disable channel n + 1 first */ base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } + /* Set the requested PWM mode for channel n + 1, PWM output requires mode select to be set to 2 */ base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnSC |= ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT)); @@ -267,6 +294,8 @@ status_t TPM_SetupPwm(TPM_Type *base, (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } + /* Set the channel pair values */ + base->CONTROLS[(chnlParams->chnlNumber * 2) + 1].CnV = cnvFirstEdge + cnv; } else { @@ -286,12 +315,16 @@ status_t TPM_SetupPwm(TPM_Type *base, } } - base->CONTROLS[chnlParams->chnlNumber].CnV = cnv; - /* When switching mode, disable channel first */ base->CONTROLS[chnlParams->chnlNumber].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlParams->chnlNumber].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } + /* Set the requested PWM mode, PWM output requires mode select to be set to 2 */ base->CONTROLS[chnlParams->chnlNumber].CnSC |= ((chnlParams->level << TPM_CnSC_ELSA_SHIFT) | (2U << TPM_CnSC_MSA_SHIFT)); @@ -301,6 +334,7 @@ status_t TPM_SetupPwm(TPM_Type *base, (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } + base->CONTROLS[chnlParams->chnlNumber].CnV = cnv; #if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE } #endif @@ -364,9 +398,10 @@ void TPM_UpdateChnlEdgeLevelSelect(TPM_Type *base, tpm_chnl_t chnlNumber, uint8_ /* When switching mode, disable channel first */ base->CONTROLS[chnlNumber].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); - /* Wait till mode change is acknowledged */ - while (0U != (base->CONTROLS[chnlNumber].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlNumber].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } @@ -388,10 +423,29 @@ void TPM_SetupInputCapture(TPM_Type *base, tpm_chnl_t chnlNumber, tpm_input_capt { assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); +#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL + /* Clear quadrature Decoder mode for channel 0 or 1*/ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } +#endif + +#if defined(FSL_FEATURE_TPM_HAS_COMBINE) && FSL_FEATURE_TPM_HAS_COMBINE + /* Clear the combine bit for chnlNumber */ + base->COMBINE &= ~(1U << TPM_COMBINE_SHIFT * (chnlNumber / 2)); +#endif + /* When switching mode, disable channel first */ base->CONTROLS[chnlNumber].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlNumber].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } + /* Set the requested input capture mode */ base->CONTROLS[chnlNumber].CnSC |= captureMode; @@ -409,16 +463,30 @@ void TPM_SetupOutputCompare(TPM_Type *base, { assert(chnlNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base)); - /* Setup the compare value */ - base->CONTROLS[chnlNumber].CnV = compareValue; +#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL + /* Clear quadrature Decoder mode for channel 0 or 1 */ + if ((chnlNumber == 0) || (chnlNumber == 1)) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } +#endif /* When switching mode, disable channel first */ base->CONTROLS[chnlNumber].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlNumber].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } + /* Setup the channel output behaviour when a match occurs with the compare value */ base->CONTROLS[chnlNumber].CnSC |= compareMode; + /* Setup the compare value */ + base->CONTROLS[chnlNumber].CnV = compareValue; + /* Wait till mode change is acknowledged */ while (!(base->CONTROLS[chnlNumber].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) @@ -433,26 +501,37 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, uint32_t filterValue) { assert(edgeParam); + assert(chnlPairNumber < FSL_FEATURE_TPM_CHANNEL_COUNTn(base) / 2); uint32_t reg; +/* Clear quadrature Decoder mode for channel 0 or 1*/ +#if defined(FSL_FEATURE_TPM_HAS_QDCTRL) && FSL_FEATURE_TPM_HAS_QDCTRL + if (chnlPairNumber == 0) + { + base->QDCTRL &= ~TPM_QDCTRL_QUADEN_MASK; + } +#endif /* Unlock: When switching mode, disable channel first */ base->CONTROLS[chnlPairNumber * 2].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); - /* Wait till mode change is acknowledged */ - while (0U != (base->CONTROLS[chnlPairNumber * 2].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlPairNumber * 2].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } + base->CONTROLS[chnlPairNumber * 2 + 1].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); - /* Wait till mode change is acknowledged */ - while (0U != (base->CONTROLS[chnlPairNumber * 2 + 1].CnSC & - (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[chnlPairNumber * 2 + 1].CnSC & + (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) { } - /* Now, the registers for input mode can be operated. */ + /* Now, the registers for input mode can be operated. */ if (edgeParam->enableSwap) { /* Set the combine and swap bits for the channel pair */ @@ -484,6 +563,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Setup the edge detection from channel n */ base->CONTROLS[chnlPairNumber * 2].CnSC |= edgeParam->currChanEdgeMode; + /* Wait till mode change is acknowledged */ while (!(base->CONTROLS[chnlPairNumber * 2].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) @@ -492,6 +572,7 @@ void TPM_SetupDualEdgeCapture(TPM_Type *base, /* Setup the edge detection from channel n+1 */ base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC |= edgeParam->nextChanEdgeMode; + /* Wait till mode change is acknowledged */ while (!(base->CONTROLS[(chnlPairNumber * 2) + 1].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) @@ -509,6 +590,12 @@ void TPM_SetupQuadDecode(TPM_Type *base, assert(phaseAParams); assert(phaseBParams); + base->CONTROLS[0].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[0].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } uint32_t reg; /* Set Phase A filter value */ @@ -517,6 +604,7 @@ void TPM_SetupQuadDecode(TPM_Type *base, reg |= TPM_FILTER_CH0FVAL(phaseAParams->phaseFilterVal); base->FILTER = reg; +#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL /* Set Phase A polarity */ if (phaseAParams->phasePolarity) { @@ -526,13 +614,20 @@ void TPM_SetupQuadDecode(TPM_Type *base, { base->POL &= ~TPM_POL_POL0_MASK; } +#endif + base->CONTROLS[1].CnSC &= ~(TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK); + + /* Wait till mode change to disable channel is acknowledged */ + while ((base->CONTROLS[1].CnSC & (TPM_CnSC_MSA_MASK | TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK | TPM_CnSC_ELSB_MASK))) + { + } /* Set Phase B filter value */ reg = base->FILTER; reg &= ~(TPM_FILTER_CH1FVAL_MASK); reg |= TPM_FILTER_CH1FVAL(phaseBParams->phaseFilterVal); base->FILTER = reg; - +#if defined(FSL_FEATURE_TPM_HAS_POL) && FSL_FEATURE_TPM_HAS_POL /* Set Phase B polarity */ if (phaseBParams->phasePolarity) { @@ -542,6 +637,7 @@ void TPM_SetupQuadDecode(TPM_Type *base, { base->POL &= ~TPM_POL_POL1_MASK; } +#endif /* Set Quadrature mode */ reg = base->QDCTRL; @@ -627,30 +723,3 @@ uint32_t TPM_GetEnabledInterrupts(TPM_Type *base) return enabledInterrupts; } - -uint32_t TPM_GetStatusFlags(TPM_Type *base) -{ - uint32_t statusFlags = 0; - - /* Check timer flag */ - if (base->SC & TPM_SC_TOF_MASK) - { - statusFlags |= kTPM_TimeOverflowFlag; - } - - statusFlags |= base->STATUS; - - return statusFlags; -} - -void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask) -{ - /* Clear the timer overflow flag */ - if (mask & kTPM_TimeOverflowFlag) - { - base->SC |= TPM_SC_TOF_MASK; - } - - /* Clear the channel status flags */ - base->STATUS = (mask & 0xFF); -} diff --git a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.h b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.h index 50138a47a2a..a15e44c1fbf 100755 --- a/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.h +++ b/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_tpm.h @@ -33,7 +33,7 @@ #include "fsl_common.h" /*! - * @addtogroup tpm_driver + * @addtogroup tpm * @{ */ @@ -45,7 +45,7 @@ /*! @name Driver version */ /*@{*/ -#define FSL_TPM_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*!< Version 2.0.1 */ +#define FSL_TPM_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2 */ /*@}*/ /*! @@ -505,7 +505,10 @@ uint32_t TPM_GetEnabledInterrupts(TPM_Type *base); * @return The status flags. This is the logical OR of members of the * enumeration ::tpm_status_flags_t */ -uint32_t TPM_GetStatusFlags(TPM_Type *base); +static inline uint32_t TPM_GetStatusFlags(TPM_Type *base) +{ + return base->STATUS; +} /*! * @brief Clears the TPM status flags @@ -514,7 +517,11 @@ uint32_t TPM_GetStatusFlags(TPM_Type *base); * @param mask The status flags to clear. This is a logical OR of members of the * enumeration ::tpm_status_flags_t */ -void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask); +static inline void TPM_ClearStatusFlags(TPM_Type *base, uint32_t mask) +{ + /* Clear the status flags */ + base->STATUS = mask; +} /*! @}*/ @@ -548,6 +555,11 @@ static inline void TPM_StopTimer(TPM_Type *base) { /* Set clock source to none to disable counter */ base->SC &= ~(TPM_SC_CMOD_MASK); + + /* Wait till this reads as zero acknowledging the counter is disabled */ + while (base->SC & TPM_SC_CMOD_MASK) + { + } } /*! @}*/