aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorutzig <utzig@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-11-11 21:04:26 +0000
committerutzig <utzig@35acf78f-673a-0410-8e92-d51de3d6d3f4>2014-11-11 21:04:26 +0000
commit2aa2643835dd9eb25827450349ec49b801369f47 (patch)
treee26571119bb9467e450f7713ef9394f6ed2ac6d4 /os/hal
parente872bae1e3471d7879c4c381a86f7519daa63f0f (diff)
downloadChibiOS-2aa2643835dd9eb25827450349ec49b801369f47.tar.gz
ChibiOS-2aa2643835dd9eb25827450349ec49b801369f47.tar.bz2
ChibiOS-2aa2643835dd9eb25827450349ec49b801369f47.zip
[KINETIS] Interrupt driver PWM driver
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7502 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/KINETIS/KL2x/pwm_lld.c119
1 files changed, 98 insertions, 21 deletions
diff --git a/os/hal/ports/KINETIS/KL2x/pwm_lld.c b/os/hal/ports/KINETIS/KL2x/pwm_lld.c
index 9314532ef..2f1713109 100644
--- a/os/hal/ports/KINETIS/KL2x/pwm_lld.c
+++ b/os/hal/ports/KINETIS/KL2x/pwm_lld.c
@@ -34,9 +34,9 @@
#define KINETIS_TPM1_CHANNELS 2
#define KINETIS_TPM2_CHANNELS 2
-#define KINETIS_TPM0_HANDLER
-#define KINETIS_TPM1_HANDLER
-#define KINETIS_TPM2_HANDLER
+#define KINETIS_TPM0_HANDLER Vector84
+#define KINETIS_TPM1_HANDLER Vector88
+#define KINETIS_TPM2_HANDLER Vector8C
/*===========================================================================*/
/* Driver exported variables. */
@@ -70,15 +70,85 @@ PWMDriver PWMD3;
/* Driver local variables and types. */
/*===========================================================================*/
-
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
+static void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
+ uint32_t sr;
+
+ sr = pwmp->tpm->STATUS;
+ pwmp->tpm->STATUS = 0xFFFFFFFF;
+
+ if (((sr & TPM_SC_TOF) != 0) &&
+ (pwmp->config->callback != NULL))
+ pwmp->config->callback(pwmp);
+ if (((sr & TPM_STATUS_CH0F) != 0) &&
+ (pwmp->config->channels[0].callback != NULL))
+ pwmp->config->channels[0].callback(pwmp);
+ if (((sr & TPM_STATUS_CH1F) != 0) &&
+ (pwmp->config->channels[1].callback != NULL))
+ pwmp->config->channels[1].callback(pwmp);
+ if (((sr & TPM_STATUS_CH2F) != 0) &&
+ (pwmp->config->channels[2].callback != NULL))
+ pwmp->config->channels[2].callback(pwmp);
+ if (((sr & TPM_STATUS_CH3F) != 0) &&
+ (pwmp->config->channels[3].callback != NULL))
+ pwmp->config->channels[3].callback(pwmp);
+ if (((sr & TPM_STATUS_CH4F) != 0) &&
+ (pwmp->config->channels[4].callback != NULL))
+ pwmp->config->channels[4].callback(pwmp);
+ if (((sr & TPM_STATUS_CH5F) != 0) &&
+ (pwmp->config->channels[5].callback != NULL))
+ pwmp->config->channels[5].callback(pwmp);
+}
+
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
+#if KINETIS_PWM_USE_TPM0
+/**
+ * @brief TPM0 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(KINETIS_TPM0_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+ pwm_lld_serve_interrupt(&PWMD1);
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* KINETIS_PWM_USE_TPM0 */
+
+#if KINETIS_PWM_USE_TPM1
+/**
+ * @brief TPM1 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(KINETIS_TPM1_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+ pwm_lld_serve_interrupt(&PWMD2);
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* KINETIS_PWM_USE_TPM1 */
+
+#if KINETIS_PWM_USE_TPM2
+/**
+ * @brief TPM2 interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(KINETIS_TPM2_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+ pwm_lld_serve_interrupt(&PWMD3);
+ OSAL_IRQ_EPILOGUE();
+}
+#endif /* KINETIS_PWM_USE_TPM2 */
+
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
@@ -127,18 +197,21 @@ void pwm_lld_start(PWMDriver *pwmp) {
#if KINETIS_PWM_USE_TPM0
if (&PWMD1 == pwmp) {
SIM->SCGC6 |= SIM_SCGC6_TPM0;
+ nvicEnableVector(TPM0_IRQn, KINETIS_PWM_TPM0_IRQ_PRIORITY);
}
#endif
#if KINETIS_PWM_USE_TPM1
if (&PWMD2 == pwmp) {
SIM->SCGC6 |= SIM_SCGC6_TPM1;
+ nvicEnableVector(TPM1_IRQn, KINETIS_PWM_TPM1_IRQ_PRIORITY);
}
#endif
#if KINETIS_PWM_USE_TPM2
if (&PWMD3 == pwmp) {
SIM->SCGC6 |= SIM_SCGC6_TPM2;
+ nvicEnableVector(TPM2_IRQn, KINETIS_PWM_TPM2_IRQ_PRIORITY);
}
#endif
}
@@ -184,18 +257,21 @@ void pwm_lld_stop(PWMDriver *pwmp) {
#if KINETIS_PWM_USE_TPM0
if (&PWMD1 == pwmp) {
SIM->SCGC6 &= ~SIM_SCGC6_TPM0;
+ nvicDisableVector(TPM0_IRQn);
}
#endif
#if KINETIS_PWM_USE_TPM1
if (&PWMD2 == pwmp) {
SIM->SCGC6 &= ~SIM_SCGC6_TPM1;
+ nvicDisableVector(TPM1_IRQn);
}
#endif
#if KINETIS_PWM_USE_TPM2
if (&PWMD3 == pwmp) {
SIM->SCGC6 &= ~SIM_SCGC6_TPM2;
+ nvicDisableVector(TPM2_IRQn);
}
#endif
/* Disable LPTPM counter.*/
@@ -204,6 +280,7 @@ void pwm_lld_stop(PWMDriver *pwmp) {
}
}
+
/**
* @brief Enables a PWM channel.
* @pre The PWM unit must have been activated using @p pwmStart().
@@ -220,23 +297,21 @@ void pwm_lld_stop(PWMDriver *pwmp) {
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width) {
-
- uint32_t mode = 0;
-
- osalDbgAssert(channel <= 5, "pwm_lld_enable_channel() #1, invalid channel");
+ uint32_t mode = TPM_CnSC_MSB; /* Edge-aligned PWM mode.*/
switch (pwmp->config->channels[channel].mode & PWM_OUTPUT_MASK) {
case PWM_OUTPUT_ACTIVE_HIGH:
- mode = TPM_CnSC_MSB | TPM_CnSC_ELSB;
+ mode |= TPM_CnSC_ELSB;
break;
case PWM_OUTPUT_ACTIVE_LOW:
- mode = TPM_CnSC_MSB | TPM_CnSC_ELSA;
- break;
- default:
+ mode |= TPM_CnSC_ELSA;
break;
}
- pwmp->tpm->C[channel].SC |= mode;
+ if (pwmp->tpm->C[channel].SC & TPM_CnSC_CHIE)
+ mode |= TPM_CnSC_CHIE;
+
+ pwmp->tpm->C[channel].SC = mode;
pwmp->tpm->C[channel].V = width;
}
@@ -254,8 +329,6 @@ void pwm_lld_enable_channel(PWMDriver *pwmp,
*/
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
- osalDbgAssert(channel <= 5, "pwm_lld_disable_channel() #1, invalid channel");
-
pwmp->tpm->C[channel].SC = 0;
pwmp->tpm->C[channel].V = 0;
}
@@ -271,7 +344,7 @@ void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
*/
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
- (void)pwmp;
+ pwmp->tpm->SC |= TPM_SC_TOIE;
}
/**
@@ -285,7 +358,7 @@ void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
*/
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
- (void)pwmp;
+ pwmp->tpm->SC &= ~TPM_SC_TOIE;
}
/**
@@ -302,8 +375,10 @@ void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
- (void)pwmp;
- (void)channel;
+ osalDbgAssert(channel <= 5,
+ "pwm_lld_enable_channel_notification() #1, invalid channel");
+
+ pwmp->tpm->C[channel].SC |= TPM_CnSC_CHIE;
}
/**
@@ -320,8 +395,10 @@ void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
- (void)pwmp;
- (void)channel;
+ osalDbgAssert(channel <= 5,
+ "pwm_lld_disable_channel_notification() #1, invalid channel");
+
+ pwmp->tpm->C[channel].SC &= ~TPM_CnSC_CHIE;
}
#endif /* HAL_USE_PWM */