From a21d21e7000cd7cd29105f118571a8b22deaa1a3 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Fri, 18 May 2018 09:32:12 -0500 Subject: [PATCH] KL43Z: Update usticker to use TPM instead of LPTMR for ticker This will free up the LPTMR to be used as lpticker Signed-off-by: Mahesh Mahadevan --- .../TARGET_FRDM/PeripheralNames.h | 4 +- .../TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c | 14 +- .../TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c | 2 + .../TARGET_KL43Z/pwmout_api.c | 3 +- .../TARGET_KL43Z/us_ticker.c | 129 ++++++++++++------ 5 files changed, 95 insertions(+), 57 deletions(-) diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h index 48e2fbccd8..aadbf0c23d 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralNames.h @@ -50,9 +50,7 @@ typedef enum { PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4 PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5 PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0 - PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1 - PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0 - PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1 + PWM_8 = (1 << TPM_SHIFT) | (1) // TPM1 CH1 } PWMName; #define ADC_INSTANCE_SHIFT 8 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c index 2fcfe76e65..644f696113 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/PeripheralPins.c @@ -137,21 +137,15 @@ const PinMap PinMap_SPI_SSEL[] = { /************PWM***************/ const PinMap PinMap_PWM[] = { - {PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5 - {PTA1, PWM_9 , 3}, // PTA1 , TPM2 CH0 - {PTA2, PWM_10, 3}, // PTA2 , TPM2 CH1 + {PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5 {PTA3, PWM_1, 3}, // PTA3 , TPM0 CH0 {PTA4, PWM_2 , 3}, // PTA4 , TPM0 CH1 {PTA5, PWM_3 , 3}, // PTA5 , TPM0 CH2 {PTA12, PWM_7 , 3}, // PTA12, TPM1 CH0 - {PTA13, PWM_8 , 3}, // PTA13, TPM1 CH1 + {PTA13, PWM_8 , 3}, // PTA13, TPM1 CH1 {PTB0, PWM_7, 3}, // PTB0 , TPM1 CH0 {PTB1, PWM_8, 3}, // PTB1 , TPM1 CH1 - {PTB2, PWM_9, 3}, // PTB2 , TPM2 CH0 - {PTB3, PWM_10, 3}, // PTB3 , TPM2 CH1 - {PTB18, PWM_9, 3}, // PTB18, TPM2 CH0 - {PTB19, PWM_10, 3}, // PTB18, TPM2 CH1 {PTC1, PWM_1, 4}, // PTC1 , TPM0 CH0 {PTC2, PWM_2, 4}, // PTC2 , TPM0 CH1 @@ -161,14 +155,12 @@ const PinMap PinMap_PWM[] = { {PTD0, PWM_1 , 4}, // PTD0 , TPM0 CH0 {PTD1, PWM_2 , 4}, // PTD0 , TPM0 CH1 {PTD2, PWM_3 , 4}, // PTD2 , TPM0 CH2 - {PTD3, PWM_4 , 4}, // PTD3 , TPM0 CH3 + {PTD3, PWM_4 , 4}, // PTD3 , TPM0 CH3 {PTD4, PWM_5 , 4}, // PTD4 , TPM0 CH4 {PTD5, PWM_6 , 4}, // PTD5 , TPM0 CH5 {PTE20, PWM_7, 3}, // PTE20, TPM1 CH0 {PTE21, PWM_8, 3}, // PTE21, TPM1 CH1 - {PTE22, PWM_9, 3}, // PTE22, TPM2 CH0 - {PTE23, PWM_10, 3}, // PTE23, TPM2 CH1 {PTE24, PWM_1, 3}, // PTE24, TPM0 CH0 {PTE25, PWM_2, 3}, // PTE25, TPM0 CH1 {PTE29, PWM_3, 3}, // PTE29, TPM0 CH2 diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c index d4577de95f..1018bac9e4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/TARGET_FRDM/mbed_overrides.c @@ -22,6 +22,8 @@ void mbed_sdk_init() { BOARD_BootClockRUN(); + /* Set the TPM clock source to be IRC48M, do not change as TPM2 is used for the usticker */ + CLOCK_SetTpmClock(1U); } // Enable the RTC oscillator if available on the board diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c index 405446e694..56148464c2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/pwmout_api.c @@ -36,8 +36,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) uint32_t pwm_base_clock; - /* Set the TPM clock source to be IRC 48M */ - CLOCK_SetTpmClock(1U); + /* TPM clock source is set to IRC48M during init */ pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk); float clkval = (float)pwm_base_clock / 1000000.0f; uint32_t clkdiv = 0; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c index e2af074052..3b784bc08e 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL43Z/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,91 +17,138 @@ #include "us_ticker_api.h" #include "PeripheralNames.h" #include "fsl_pit.h" -#include "fsl_lptmr.h" +#include "fsl_tpm.h" #include "fsl_clock_config.h" -static int us_ticker_inited = 0; - -static void lptmr_isr(void) +const ticker_info_t* us_ticker_get_info() { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); - LPTMR_StopTimer(LPTMR0); + static const ticker_info_t info = { + 3000000, + 32 + }; + return &info; +} - us_ticker_irq_handler(); +static bool us_ticker_inited = false; + +static uint32_t us_ticker_int_counter = 0; +static uint16_t us_ticker_int_remainder = 0; + +static void tpm_isr(void) +{ + // Clear the TPM timer overflow flag + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_StopTimer(TPM2); + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_counter--; + } else { + if (us_ticker_int_remainder > 0) { + TPM2->MOD = us_ticker_int_remainder; + TPM_StartTimer(TPM2, kTPM_SystemClock); + us_ticker_int_remainder = 0; + } else { + // This function is going to disable the interrupts if there are + // no other events in the queue + us_ticker_irq_handler(); + } + } } void us_ticker_init(void) { + /* Common for ticker/timer. */ + uint32_t busClock; + /* Structure to initialize PIT. */ + pit_config_t pitConfig; + if (us_ticker_inited) { + /* calling init again should cancel current interrupt */ + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); return; } - us_ticker_inited = 1; - - //Timer uses PIT - //Common for ticker/timer - uint32_t busClock; - - // Structure to initialize PIT - pit_config_t pitConfig; PIT_GetDefaultConfig(&pitConfig); PIT_Init(PIT, &pitConfig); busClock = CLOCK_GetFreq(kCLOCK_BusClk); - PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, busClock / 1000000 - 1); + PIT_SetTimerPeriod(PIT, kPIT_Chnl_0, (busClock / 3000000) - 1); PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF); PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true); PIT_StartTimer(PIT, kPIT_Chnl_0); PIT_StartTimer(PIT, kPIT_Chnl_1); - //Ticker uses LPTMR - lptmr_config_t lptmrConfig; - LPTMR_GetDefaultConfig(&lptmrConfig); - lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_0; - LPTMR_Init(LPTMR0, &lptmrConfig); + /* Configure interrupt generation counters and disable ticker interrupts. */ + tpm_config_t tpmConfig; - busClock = CLOCK_GetFreq(kCLOCK_McgInternalRefClk); - LPTMR_SetTimerPeriod(LPTMR0, busClock / 1000000 - 1); - /* Set interrupt handler */ - NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr); - NVIC_EnableIRQ(LPTMR0_IRQn); + TPM_GetDefaultConfig(&tpmConfig); + /* Set to Div 16 to get 3MHz clock source for TPM */ + tpmConfig.prescale = kTPM_Prescale_Divide_16; + TPM_Init(TPM2, &tpmConfig); + NVIC_SetVector(TPM2_IRQn, (uint32_t)tpm_isr); + NVIC_EnableIRQ(TPM2_IRQn); + + us_ticker_inited = true; } uint32_t us_ticker_read() { - if (!us_ticker_inited) { - us_ticker_init(); - } - return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1)); } void us_ticker_disable_interrupt(void) { - LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); + TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); } void us_ticker_clear_interrupt(void) { - LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag); + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t now_us, delta_us; + /* We get here absolute interrupt time which takes into account counter overflow. + * Since we use additional count-down timer to generate interrupt we need to calculate + * load value based on time-stamp. + */ + const uint32_t now_ticks = us_ticker_read(); + uint32_t delta_ticks = + timestamp >= now_ticks ? timestamp - now_ticks : (uint32_t)((uint64_t) timestamp + 0xFFFFFFFF - now_ticks); - now_us = us_ticker_read(); - delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); + if (delta_ticks == 0) { + /* The requested delay is less than the minimum resolution of this counter. */ + delta_ticks = 1; + } - LPTMR_StopTimer(LPTMR0); - LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta_us); - LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); - LPTMR_StartTimer(LPTMR0); + us_ticker_int_counter = (uint32_t)(delta_ticks >> 16); + us_ticker_int_remainder = (uint16_t)(0xFFFF & delta_ticks); + + TPM_StopTimer(TPM2); + TPM2->CNT = 0; + + if (us_ticker_int_counter > 0) { + TPM2->MOD = 0xFFFF; + us_ticker_int_counter--; + } else { + TPM2->MOD = us_ticker_int_remainder; + us_ticker_int_remainder = 0; + } + + /* Clear the count and set match value */ + TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag); + TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable); + TPM_StartTimer(TPM2, kTPM_SystemClock); } void us_ticker_fire_interrupt(void) { - NVIC_SetPendingIRQ(LPTMR0_IRQn); + us_ticker_int_counter = 0; + us_ticker_int_remainder = 0; + + NVIC_SetPendingIRQ(TPM2_IRQn); }