mirror of https://github.com/ARMmbed/mbed-os.git
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 <mahesh.mahadevan@nxp.com>pull/7009/head
parent
62254c2bae
commit
a21d21e700
|
@ -50,9 +50,7 @@ typedef enum {
|
||||||
PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4
|
PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4
|
||||||
PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5
|
PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5
|
||||||
PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0
|
PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0
|
||||||
PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1
|
PWM_8 = (1 << TPM_SHIFT) | (1) // TPM1 CH1
|
||||||
PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0
|
|
||||||
PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1
|
|
||||||
} PWMName;
|
} PWMName;
|
||||||
|
|
||||||
#define ADC_INSTANCE_SHIFT 8
|
#define ADC_INSTANCE_SHIFT 8
|
||||||
|
|
|
@ -138,8 +138,6 @@ const PinMap PinMap_SPI_SSEL[] = {
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
const PinMap PinMap_PWM[] = {
|
const PinMap PinMap_PWM[] = {
|
||||||
{PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5
|
{PTA0, PWM_6, 3}, // PTA0 , TPM0 CH5
|
||||||
{PTA1, PWM_9 , 3}, // PTA1 , TPM2 CH0
|
|
||||||
{PTA2, PWM_10, 3}, // PTA2 , TPM2 CH1
|
|
||||||
{PTA3, PWM_1, 3}, // PTA3 , TPM0 CH0
|
{PTA3, PWM_1, 3}, // PTA3 , TPM0 CH0
|
||||||
{PTA4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
{PTA4, PWM_2 , 3}, // PTA4 , TPM0 CH1
|
||||||
{PTA5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
{PTA5, PWM_3 , 3}, // PTA5 , TPM0 CH2
|
||||||
|
@ -148,10 +146,6 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
{PTB0, PWM_7, 3}, // PTB0 , TPM1 CH0
|
{PTB0, PWM_7, 3}, // PTB0 , TPM1 CH0
|
||||||
{PTB1, PWM_8, 3}, // PTB1 , TPM1 CH1
|
{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
|
{PTC1, PWM_1, 4}, // PTC1 , TPM0 CH0
|
||||||
{PTC2, PWM_2, 4}, // PTC2 , TPM0 CH1
|
{PTC2, PWM_2, 4}, // PTC2 , TPM0 CH1
|
||||||
|
@ -167,8 +161,6 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
{PTE20, PWM_7, 3}, // PTE20, TPM1 CH0
|
{PTE20, PWM_7, 3}, // PTE20, TPM1 CH0
|
||||||
{PTE21, PWM_8, 3}, // PTE21, TPM1 CH1
|
{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
|
{PTE24, PWM_1, 3}, // PTE24, TPM0 CH0
|
||||||
{PTE25, PWM_2, 3}, // PTE25, TPM0 CH1
|
{PTE25, PWM_2, 3}, // PTE25, TPM0 CH1
|
||||||
{PTE29, PWM_3, 3}, // PTE29, TPM0 CH2
|
{PTE29, PWM_3, 3}, // PTE29, TPM0 CH2
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
void mbed_sdk_init()
|
void mbed_sdk_init()
|
||||||
{
|
{
|
||||||
BOARD_BootClockRUN();
|
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
|
// Enable the RTC oscillator if available on the board
|
||||||
|
|
|
@ -36,8 +36,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
|
||||||
|
|
||||||
uint32_t pwm_base_clock;
|
uint32_t pwm_base_clock;
|
||||||
|
|
||||||
/* Set the TPM clock source to be IRC 48M */
|
/* TPM clock source is set to IRC48M during init */
|
||||||
CLOCK_SetTpmClock(1U);
|
|
||||||
pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk);
|
pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk);
|
||||||
float clkval = (float)pwm_base_clock / 1000000.0f;
|
float clkval = (float)pwm_base_clock / 1000000.0f;
|
||||||
uint32_t clkdiv = 0;
|
uint32_t clkdiv = 0;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* mbed Microcontroller Library
|
/* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,91 +17,138 @@
|
||||||
#include "us_ticker_api.h"
|
#include "us_ticker_api.h"
|
||||||
#include "PeripheralNames.h"
|
#include "PeripheralNames.h"
|
||||||
#include "fsl_pit.h"
|
#include "fsl_pit.h"
|
||||||
#include "fsl_lptmr.h"
|
#include "fsl_tpm.h"
|
||||||
#include "fsl_clock_config.h"
|
#include "fsl_clock_config.h"
|
||||||
|
|
||||||
static int us_ticker_inited = 0;
|
const ticker_info_t* us_ticker_get_info()
|
||||||
|
|
||||||
static void lptmr_isr(void)
|
|
||||||
{
|
{
|
||||||
LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag);
|
static const ticker_info_t info = {
|
||||||
LPTMR_StopTimer(LPTMR0);
|
3000000,
|
||||||
|
32
|
||||||
|
};
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
us_ticker_irq_handler();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void us_ticker_init(void)
|
void us_ticker_init(void)
|
||||||
{
|
{
|
||||||
|
/* Common for ticker/timer. */
|
||||||
|
uint32_t busClock;
|
||||||
|
/* Structure to initialize PIT. */
|
||||||
|
pit_config_t pitConfig;
|
||||||
|
|
||||||
if (us_ticker_inited) {
|
if (us_ticker_inited) {
|
||||||
|
/* calling init again should cancel current interrupt */
|
||||||
|
TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable);
|
||||||
return;
|
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_GetDefaultConfig(&pitConfig);
|
||||||
PIT_Init(PIT, &pitConfig);
|
PIT_Init(PIT, &pitConfig);
|
||||||
|
|
||||||
busClock = CLOCK_GetFreq(kCLOCK_BusClk);
|
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_SetTimerPeriod(PIT, kPIT_Chnl_1, 0xFFFFFFFF);
|
||||||
PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true);
|
PIT_SetTimerChainMode(PIT, kPIT_Chnl_1, true);
|
||||||
PIT_StartTimer(PIT, kPIT_Chnl_0);
|
PIT_StartTimer(PIT, kPIT_Chnl_0);
|
||||||
PIT_StartTimer(PIT, kPIT_Chnl_1);
|
PIT_StartTimer(PIT, kPIT_Chnl_1);
|
||||||
|
|
||||||
//Ticker uses LPTMR
|
/* Configure interrupt generation counters and disable ticker interrupts. */
|
||||||
lptmr_config_t lptmrConfig;
|
tpm_config_t tpmConfig;
|
||||||
LPTMR_GetDefaultConfig(&lptmrConfig);
|
|
||||||
lptmrConfig.prescalerClockSource = kLPTMR_PrescalerClock_0;
|
|
||||||
LPTMR_Init(LPTMR0, &lptmrConfig);
|
|
||||||
|
|
||||||
busClock = CLOCK_GetFreq(kCLOCK_McgInternalRefClk);
|
TPM_GetDefaultConfig(&tpmConfig);
|
||||||
LPTMR_SetTimerPeriod(LPTMR0, busClock / 1000000 - 1);
|
/* Set to Div 16 to get 3MHz clock source for TPM */
|
||||||
/* Set interrupt handler */
|
tpmConfig.prescale = kTPM_Prescale_Divide_16;
|
||||||
NVIC_SetVector(LPTMR0_IRQn, (uint32_t)lptmr_isr);
|
TPM_Init(TPM2, &tpmConfig);
|
||||||
NVIC_EnableIRQ(LPTMR0_IRQn);
|
NVIC_SetVector(TPM2_IRQn, (uint32_t)tpm_isr);
|
||||||
|
NVIC_EnableIRQ(TPM2_IRQn);
|
||||||
|
|
||||||
|
us_ticker_inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t us_ticker_read()
|
uint32_t us_ticker_read()
|
||||||
{
|
{
|
||||||
if (!us_ticker_inited) {
|
|
||||||
us_ticker_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1));
|
return ~(PIT_GetCurrentTimerCount(PIT, kPIT_Chnl_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_disable_interrupt(void)
|
void us_ticker_disable_interrupt(void)
|
||||||
{
|
{
|
||||||
LPTMR_DisableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
|
TPM_DisableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_clear_interrupt(void)
|
void us_ticker_clear_interrupt(void)
|
||||||
{
|
{
|
||||||
LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag);
|
TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
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();
|
if (delta_ticks == 0) {
|
||||||
delta_us = timestamp >= now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us);
|
/* The requested delay is less than the minimum resolution of this counter. */
|
||||||
|
delta_ticks = 1;
|
||||||
|
}
|
||||||
|
|
||||||
LPTMR_StopTimer(LPTMR0);
|
us_ticker_int_counter = (uint32_t)(delta_ticks >> 16);
|
||||||
LPTMR_SetTimerPeriod(LPTMR0, (uint32_t)delta_us);
|
us_ticker_int_remainder = (uint16_t)(0xFFFF & delta_ticks);
|
||||||
LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
|
|
||||||
LPTMR_StartTimer(LPTMR0);
|
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)
|
void us_ticker_fire_interrupt(void)
|
||||||
{
|
{
|
||||||
NVIC_SetPendingIRQ(LPTMR0_IRQn);
|
us_ticker_int_counter = 0;
|
||||||
|
us_ticker_int_remainder = 0;
|
||||||
|
|
||||||
|
NVIC_SetPendingIRQ(TPM2_IRQn);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue