KL27Z: 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:52:49 -05:00 committed by Bartek Szatkowski
parent a21d21e700
commit d46af14bb6
5 changed files with 92 additions and 55 deletions

View File

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

View File

@ -180,15 +180,6 @@ const PinMap PinMap_PWM[] = {
{PTB0, PWM_7 , 3},
{PTB1, PWM_8 , 3},
{PTE22, PWM_9 , 3},
{PTE23, PWM_10, 3},
{PTA1 , PWM_9 , 3},
{PTA2 , PWM_10, 3},
{PTB2 , PWM_9 , 3},
{PTB3 , PWM_10, 3},
{PTB18, PWM_9 , 3},
{PTB19, PWM_10, 3},
{NC , NC , 0}
};

View File

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

View File

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

View File

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