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
Mahesh Mahadevan 2018-05-18 09:32:12 -05:00 committed by Bartek Szatkowski
parent 62254c2bae
commit a21d21e700
5 changed files with 95 additions and 57 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
} }