mirror of https://github.com/ARMmbed/mbed-os.git
[KL25Z] Fix us_ticker_api implementation and improve documentation
parent
c906468071
commit
5f09c37d0f
|
|
@ -17,50 +17,17 @@
|
||||||
#include "us_ticker_api.h"
|
#include "us_ticker_api.h"
|
||||||
#include "PeripheralNames.h"
|
#include "PeripheralNames.h"
|
||||||
|
|
||||||
static void (*us_ticker_interrupt_handler)(void) = NULL;
|
/******************************************************************************
|
||||||
|
* Timer for us timing.
|
||||||
static uint16_t us_ticker_int_counter = 0;
|
*
|
||||||
static uint16_t us_ticker_int_remainder = 0;
|
* Need to have 32bit resolution, we are using the PIT (2x32bit timers) for
|
||||||
|
* that. All the other timers have only 16bit resolution.
|
||||||
void lptmr_isr(void) {
|
* Unfortunately, the PIT does not have a prescaler, therefore it ticks at the
|
||||||
// write 1 to TCF to clear the LPT timer compare flag
|
* bus clock of (24)MHz.
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
|
* To keep 32bit resolution we are chaining the 2 32bit timers together dividing
|
||||||
|
* the final result by 24.
|
||||||
if (us_ticker_int_counter > 0) {
|
* NOTE: The PIT is a countdown timer.
|
||||||
us_ticker_int_counter--;
|
******************************************************************************/
|
||||||
|
|
||||||
} else {
|
|
||||||
if (us_ticker_int_remainder > 0) {
|
|
||||||
us_ticker_int_remainder = 0;
|
|
||||||
LPTMR0->CMR = us_ticker_int_remainder;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (us_ticker_interrupt_handler != NULL) {
|
|
||||||
us_ticker_interrupt_handler();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lptmr_inited = 0;
|
|
||||||
void lptmr_init(void) {
|
|
||||||
lptmr_inited = 1;
|
|
||||||
|
|
||||||
/* Clock the timer */
|
|
||||||
SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
|
|
||||||
|
|
||||||
/* Reset */
|
|
||||||
LPTMR0->CSR = 0;
|
|
||||||
|
|
||||||
/* Set interrupt handler */
|
|
||||||
NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
|
|
||||||
NVIC_EnableIRQ(LPTimer_IRQn);
|
|
||||||
|
|
||||||
/* Clock at (1)MHz -> (1)tick/us */
|
|
||||||
LPTMR0->PSR = LPTMR_PSR_PCS(3); // OSCERCLK -> 8MHz
|
|
||||||
LPTMR0->PSR |= LPTMR_PSR_PRESCALE(2); // divide by 8
|
|
||||||
}
|
|
||||||
|
|
||||||
static int us_ticker_running = 0;
|
static int us_ticker_running = 0;
|
||||||
|
|
||||||
static void us_ticker_init(void) {
|
static void us_ticker_init(void) {
|
||||||
|
|
@ -96,24 +63,51 @@ uint32_t us_ticker_read() {
|
||||||
return (uint32_t)(0xFFFFFFFF & ticks);
|
return (uint32_t)(0xFFFFFFFF & ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void us_ticker_set_interrupt(unsigned int timestamp) {
|
|
||||||
if (!lptmr_inited)
|
|
||||||
lptmr_init();
|
|
||||||
|
|
||||||
int delta = (int)(timestamp - us_ticker_read());
|
/******************************************************************************
|
||||||
if (delta < 0) {
|
* Timer Event
|
||||||
if (us_ticker_interrupt_handler != NULL) {
|
*
|
||||||
us_ticker_interrupt_handler();
|
* It schedules interrupts at given (32bit)us interval of time.
|
||||||
}
|
* It is implemented used the 16bit Low Power Timer that remains powered in all
|
||||||
return;
|
* power modes.
|
||||||
}
|
******************************************************************************/
|
||||||
us_ticker_int_counter = (uint16_t)(delta >> 16);
|
static void lptmr_isr(void);
|
||||||
us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
|
static void lptmr_irq_handler(void);
|
||||||
if (us_ticker_int_counter > 0) {
|
static void us_ticker_set_interrupt(unsigned int timestamp);
|
||||||
LPTMR0->CMR = 0xFFFF;
|
|
||||||
} else {
|
static ticker_event_handler event_handler = NULL;
|
||||||
LPTMR0->CMR = us_ticker_int_remainder;
|
void us_ticker_set_handler(ticker_event_handler handler) {
|
||||||
}
|
event_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t us_ticker_int_counter = 0;
|
||||||
|
static uint16_t us_ticker_int_remainder = 0;
|
||||||
|
|
||||||
|
static int lptmr_inited = 0;
|
||||||
|
void lptmr_init(void) {
|
||||||
|
lptmr_inited = 1;
|
||||||
|
|
||||||
|
/* Clock the timer */
|
||||||
|
SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK;
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
LPTMR0->CSR = 0;
|
||||||
|
|
||||||
|
/* Set interrupt handler */
|
||||||
|
NVIC_SetVector(LPTimer_IRQn, (uint32_t)lptmr_isr);
|
||||||
|
NVIC_EnableIRQ(LPTimer_IRQn);
|
||||||
|
|
||||||
|
/* Clock at (1)MHz -> (1)tick/us */
|
||||||
|
LPTMR0->PSR = LPTMR_PSR_PCS(3); // OSCERCLK -> 8MHz
|
||||||
|
LPTMR0->PSR |= LPTMR_PSR_PRESCALE(2); // divide by 8
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lptmr_set(unsigned short count) {
|
||||||
|
/* Reset */
|
||||||
|
LPTMR0->CSR = 0;
|
||||||
|
|
||||||
|
/* Set the compare register */
|
||||||
|
LPTMR0->CMR = count;
|
||||||
|
|
||||||
/* Enable interrupt */
|
/* Enable interrupt */
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
|
LPTMR0->CSR |= LPTMR_CSR_TIE_MASK;
|
||||||
|
|
@ -122,19 +116,35 @@ static void us_ticker_set_interrupt(unsigned int timestamp) {
|
||||||
LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
|
LPTMR0->CSR |= LPTMR_CSR_TEN_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void us_ticker_disable_interrupt(void) {
|
static void lptmr_isr(void) {
|
||||||
LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
|
// write 1 to TCF to clear the LPT timer compare flag
|
||||||
|
LPTMR0->CSR |= LPTMR_CSR_TCF_MASK;
|
||||||
|
|
||||||
|
if (us_ticker_int_counter > 0) {
|
||||||
|
lptmr_set(0xFFFF);
|
||||||
|
us_ticker_int_counter--;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (us_ticker_int_remainder > 0) {
|
||||||
|
lptmr_set(us_ticker_int_remainder);
|
||||||
|
us_ticker_int_remainder = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// This function is going to disable the interrupts if there are
|
||||||
|
// no other events in the queue
|
||||||
|
lptmr_irq_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ticker_event_handler event_handler;
|
|
||||||
static ticker_event_t *head = NULL;
|
static ticker_event_t *head = NULL;
|
||||||
|
|
||||||
void irq_handler(void) {
|
static void lptmr_irq_handler(void) {
|
||||||
/* Go through all the pending TimerEvents */
|
/* Go through all the pending TimerEvents */
|
||||||
while (1) {
|
while (1) {
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
// There are no more TimerEvents left, so disable matches.
|
// There are no more TimerEvents left, so disable matches.
|
||||||
us_ticker_disable_interrupt();
|
LPTMR0->CSR &= ~LPTMR_CSR_TIE_MASK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,9 +153,9 @@ void irq_handler(void) {
|
||||||
// point to the following one and execute its handler
|
// point to the following one and execute its handler
|
||||||
ticker_event_t *p = head;
|
ticker_event_t *p = head;
|
||||||
head = head->next;
|
head = head->next;
|
||||||
|
if (event_handler != NULL) {
|
||||||
event_handler(p->id); // NOTE: the handler can set new events
|
event_handler(p->id); // NOTE: the handler can set new events
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This event and the following ones in the list are in the future:
|
// This event and the following ones in the list are in the future:
|
||||||
// set it as next interrupt and return
|
// set it as next interrupt and return
|
||||||
|
|
@ -155,9 +165,26 @@ void irq_handler(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_set_handler(ticker_event_handler handler) {
|
static void us_ticker_set_interrupt(unsigned int timestamp) {
|
||||||
event_handler = handler;
|
if (!lptmr_inited)
|
||||||
us_ticker_interrupt_handler = irq_handler;
|
lptmr_init();
|
||||||
|
|
||||||
|
int delta = (int)(timestamp - us_ticker_read());
|
||||||
|
if (delta <= 0) {
|
||||||
|
// This event was in the past:
|
||||||
|
lptmr_irq_handler();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
us_ticker_int_counter = (uint32_t)(delta >> 16);
|
||||||
|
us_ticker_int_remainder = (uint16_t)(0xFFFF & delta);
|
||||||
|
if (us_ticker_int_counter > 0) {
|
||||||
|
lptmr_set(0xFFFF);
|
||||||
|
us_ticker_int_counter--;
|
||||||
|
} else {
|
||||||
|
lptmr_set(us_ticker_int_remainder);
|
||||||
|
us_ticker_int_remainder = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void us_ticker_insert_event(ticker_event_t *obj, unsigned int timestamp, uint32_t id) {
|
void us_ticker_insert_event(ticker_event_t *obj, unsigned int timestamp, uint32_t id) {
|
||||||
|
|
@ -198,12 +225,14 @@ void us_ticker_remove_event(ticker_event_t *obj) {
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
// remove this object from the list
|
// remove this object from the list
|
||||||
if (head == obj) { // first in the list, so just drop me
|
if (head == obj) {
|
||||||
|
// first in the list, so just drop me
|
||||||
head = obj->next;
|
head = obj->next;
|
||||||
if (obj->next != NULL) {
|
if (obj->next != NULL) {
|
||||||
us_ticker_set_interrupt(head->timestamp);
|
us_ticker_set_interrupt(head->timestamp);
|
||||||
}
|
}
|
||||||
} else { // find the object before me, then drop me
|
} else {
|
||||||
|
// find the object before me, then drop me
|
||||||
ticker_event_t* p = head;
|
ticker_event_t* p = head;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
if (p->next == obj) {
|
if (p->next == obj) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue