mirror of https://github.com/ARMmbed/mbed-os.git
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
parent
a21d21e700
commit
d46af14bb6
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue