Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 00:52:13 2014 +0000
Revision:
7:78f6ee57d324
Parent:
2:5056ec8c52e8
Child:
8:23c04123395c
MAJOR updates and refactoring of code to improve code reuse and hardware encapsulation. Now all three LPTMR, TPM, and PIT timers inherit from the same HardwareTimer base abstract class, which provides as much functionality as possible.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mgottscho 1:7dde0e4d30da 1 /* Timer_LPTMR.cpp
mgottscho 1:7dde0e4d30da 2 * Tested with mbed board: FRDM-KL46Z
mgottscho 1:7dde0e4d30da 3 * Author: Mark Gottscho
mgottscho 1:7dde0e4d30da 4 * mgottscho@ucla.edu
mgottscho 1:7dde0e4d30da 5 */
mgottscho 1:7dde0e4d30da 6
mgottscho 1:7dde0e4d30da 7 #include "mbed.h"
mgottscho 1:7dde0e4d30da 8 #include "Timer_LPTMR.h"
mgottscho 1:7dde0e4d30da 9 #include "PreciseTime.h"
mgottscho 1:7dde0e4d30da 10
mgottscho 7:78f6ee57d324 11
mgottscho 7:78f6ee57d324 12 //Init Timer_LPTMR class variables
mgottscho 7:78f6ee57d324 13 bool Timer_LPTMR::__lptmr_used = false;
mgottscho 7:78f6ee57d324 14 Timer_LPTMR *Timer_LPTMR::__obj = NULL;
mgottscho 1:7dde0e4d30da 15
mgottscho 7:78f6ee57d324 16 Timer_LPTMR::Timer_LPTMR() :
mgottscho 7:78f6ee57d324 17 HardwareTimer(0xFFFF, 1, HardwareTimer::ms) //LPTMR has 16-bit counter. And at 1 KHz, each clock cycle is 1 ms
mgottscho 7:78f6ee57d324 18 {
mgottscho 7:78f6ee57d324 19 if (__lptmr_used)
mgottscho 7:78f6ee57d324 20 __valid = false;
mgottscho 7:78f6ee57d324 21 else {
mgottscho 7:78f6ee57d324 22 __valid = true;
mgottscho 7:78f6ee57d324 23 __lptmr_used = true;
mgottscho 7:78f6ee57d324 24 __obj = this;
mgottscho 7:78f6ee57d324 25 }
mgottscho 1:7dde0e4d30da 26 }
mgottscho 1:7dde0e4d30da 27
mgottscho 7:78f6ee57d324 28 Timer_LPTMR::~Timer_LPTMR() {
mgottscho 7:78f6ee57d324 29 if (__valid) {
mgottscho 7:78f6ee57d324 30 __lptmr_used = false; //free the hardware LPTMR resource
mgottscho 7:78f6ee57d324 31 __obj = NULL;
mgottscho 7:78f6ee57d324 32 }
mgottscho 1:7dde0e4d30da 33 }
mgottscho 1:7dde0e4d30da 34
mgottscho 1:7dde0e4d30da 35 uint32_t Timer_LPTMR::getTick() {
mgottscho 1:7dde0e4d30da 36 if (!__valid)
mgottscho 1:7dde0e4d30da 37 return 0;
mgottscho 1:7dde0e4d30da 38
mgottscho 7:78f6ee57d324 39 // CRITICAL SECTION
mgottscho 7:78f6ee57d324 40 NVIC_DisableIRQ(LPTimer_IRQn);
mgottscho 1:7dde0e4d30da 41 LPTMR0->CNR = 0; //need to write to the register in order to read it due to buffering
mgottscho 1:7dde0e4d30da 42 uint16_t ticks = LPTMR0->CNR;
mgottscho 1:7dde0e4d30da 43 uint32_t count = __count;
mgottscho 7:78f6ee57d324 44 NVIC_EnableIRQ(LPTimer_IRQn);
mgottscho 7:78f6ee57d324 45 // END CRITICAL SECTION
mgottscho 1:7dde0e4d30da 46
mgottscho 1:7dde0e4d30da 47 //Convert to ticks
mgottscho 7:78f6ee57d324 48 return (uint32_t) count * __rolloverValue + ticks;
mgottscho 1:7dde0e4d30da 49 }
mgottscho 1:7dde0e4d30da 50
mgottscho 7:78f6ee57d324 51 void Timer_LPTMR::__init_timer() {
mgottscho 7:78f6ee57d324 52 //MCG clocks
mgottscho 7:78f6ee57d324 53 MCG->C2 &= ~MCG_C2_IRCS_MASK; //Set slow internal reference clk (32 KHz)
mgottscho 7:78f6ee57d324 54 MCG->C1 |= MCG_C1_IRCLKEN_MASK; //Enable internal reference clk (MCGIRCLK)
mgottscho 7:78f6ee57d324 55 // MCG->C1 |= MCG_C1_IREFSTEN_MASK; //Enable internal reference clk (MCGIRCLK) to work in stop mode
mgottscho 7:78f6ee57d324 56
mgottscho 7:78f6ee57d324 57 //Timer clock gating
mgottscho 7:78f6ee57d324 58 SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK; //Disable clock gating the timer
mgottscho 7:78f6ee57d324 59
mgottscho 7:78f6ee57d324 60 //Timer prescaling and clock selection
mgottscho 7:78f6ee57d324 61 LPTMR0->PSR = LPTMR_PSR_PCS(0); //Set LPTMR0 to use MCGIRCLK --> 32 KHz
mgottscho 7:78f6ee57d324 62 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(4); // divide by 32 to get 1 KHz
mgottscho 7:78f6ee57d324 63
mgottscho 7:78f6ee57d324 64 //Status reset
mgottscho 7:78f6ee57d324 65 LPTMR0->CSR = 0; //Reset the timer control/status register
mgottscho 7:78f6ee57d324 66
mgottscho 7:78f6ee57d324 67 //Set interrupt handler
mgottscho 7:78f6ee57d324 68 NVIC_SetVector(LPTimer_IRQn, (uint32_t) __lptmr_isr_wrapper);
mgottscho 7:78f6ee57d324 69 NVIC_EnableIRQ(LPTimer_IRQn);
mgottscho 7:78f6ee57d324 70
mgottscho 7:78f6ee57d324 71 //Good to go!
mgottscho 7:78f6ee57d324 72 }
mgottscho 1:7dde0e4d30da 73
mgottscho 7:78f6ee57d324 74 void Timer_LPTMR::__start_timer() {
mgottscho 7:78f6ee57d324 75 LPTMR0->CSR = 0; //Reset the timer control/status register
mgottscho 7:78f6ee57d324 76 LPTMR0->CMR = __rolloverValue; //Set the compare register
mgottscho 7:78f6ee57d324 77 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; //Enable interrupt
mgottscho 7:78f6ee57d324 78 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; //Start the timer
mgottscho 7:78f6ee57d324 79 }
mgottscho 7:78f6ee57d324 80
mgottscho 7:78f6ee57d324 81 void Timer_LPTMR::__stop_timer() {
mgottscho 7:78f6ee57d324 82 LPTMR0->CSR = 0; //Reset the LPTMR timer control/status register
mgottscho 7:78f6ee57d324 83 }
mgottscho 7:78f6ee57d324 84
mgottscho 7:78f6ee57d324 85 void Timer_LPTMR::__timer_isr() {
mgottscho 1:7dde0e4d30da 86 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; //Write 1 to TCF to clear the LPT timer compare flag
mgottscho 7:78f6ee57d324 87 if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
mgottscho 7:78f6ee57d324 88 __user_fptr->call();
mgottscho 7:78f6ee57d324 89 __call_user_function = false;
mgottscho 7:78f6ee57d324 90 }
mgottscho 1:7dde0e4d30da 91 __count++;
mgottscho 1:7dde0e4d30da 92 }
mgottscho 1:7dde0e4d30da 93
mgottscho 7:78f6ee57d324 94 void Timer_LPTMR::__lptmr_isr_wrapper() {
mgottscho 7:78f6ee57d324 95 __obj->__timer_isr();
mgottscho 1:7dde0e4d30da 96 }