Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 04:54:13 2014 +0000
Revision:
11:e0442c8b182b
Parent:
9:dff7c891ec77
Child:
12:cb395e4be69e
Commented out the interrupt disables in all three timers' getTick(). Again, not sure why this breaks things... maybe it doesn't, but for now we'll see.

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 9:dff7c891ec77 38
mgottscho 9:dff7c891ec77 39 uint16_t ticks;
mgottscho 9:dff7c891ec77 40 uint32_t count;
mgottscho 9:dff7c891ec77 41
mgottscho 11:e0442c8b182b 42 //__disable_irq(); //CRITICAL SECTION -- ALL INTERRUPTS MUST BE STOPPED!
mgottscho 1:7dde0e4d30da 43 LPTMR0->CNR = 0; //need to write to the register in order to read it due to buffering
mgottscho 9:dff7c891ec77 44 ticks = (uint16_t) LPTMR0->CNR;
mgottscho 11:e0442c8b182b 45
mgottscho 11:e0442c8b182b 46 //It is theoretically possible that the timer interrupt is invoked here, between these two lines.
mgottscho 11:e0442c8b182b 47 //However, the timer doesn't appear to work properly if I put these two in a critical section.
mgottscho 11:e0442c8b182b 48
mgottscho 9:dff7c891ec77 49 count = __count;
mgottscho 11:e0442c8b182b 50 //__enable_irq(); //END CRITICAL SECTION
mgottscho 1:7dde0e4d30da 51
mgottscho 1:7dde0e4d30da 52 //Convert to ticks
mgottscho 7:78f6ee57d324 53 return (uint32_t) count * __rolloverValue + ticks;
mgottscho 1:7dde0e4d30da 54 }
mgottscho 1:7dde0e4d30da 55
mgottscho 7:78f6ee57d324 56 void Timer_LPTMR::__init_timer() {
mgottscho 7:78f6ee57d324 57 //MCG clocks
mgottscho 7:78f6ee57d324 58 MCG->C2 &= ~MCG_C2_IRCS_MASK; //Set slow internal reference clk (32 KHz)
mgottscho 7:78f6ee57d324 59 MCG->C1 |= MCG_C1_IRCLKEN_MASK; //Enable internal reference clk (MCGIRCLK)
mgottscho 7:78f6ee57d324 60 // MCG->C1 |= MCG_C1_IREFSTEN_MASK; //Enable internal reference clk (MCGIRCLK) to work in stop mode
mgottscho 7:78f6ee57d324 61
mgottscho 7:78f6ee57d324 62 //Timer clock gating
mgottscho 7:78f6ee57d324 63 SIM->SCGC5 |= SIM_SCGC5_LPTMR_MASK; //Disable clock gating the timer
mgottscho 7:78f6ee57d324 64
mgottscho 7:78f6ee57d324 65 //Timer prescaling and clock selection
mgottscho 7:78f6ee57d324 66 LPTMR0->PSR = LPTMR_PSR_PCS(0); //Set LPTMR0 to use MCGIRCLK --> 32 KHz
mgottscho 7:78f6ee57d324 67 LPTMR0->PSR |= LPTMR_PSR_PRESCALE(4); // divide by 32 to get 1 KHz
mgottscho 7:78f6ee57d324 68
mgottscho 7:78f6ee57d324 69 //Status reset
mgottscho 7:78f6ee57d324 70 LPTMR0->CSR = 0; //Reset the timer control/status register
mgottscho 7:78f6ee57d324 71
mgottscho 7:78f6ee57d324 72 //Set interrupt handler
mgottscho 7:78f6ee57d324 73 NVIC_SetVector(LPTimer_IRQn, (uint32_t) __lptmr_isr_wrapper);
mgottscho 7:78f6ee57d324 74 NVIC_EnableIRQ(LPTimer_IRQn);
mgottscho 7:78f6ee57d324 75
mgottscho 7:78f6ee57d324 76 //Good to go!
mgottscho 7:78f6ee57d324 77 }
mgottscho 1:7dde0e4d30da 78
mgottscho 7:78f6ee57d324 79 void Timer_LPTMR::__start_timer() {
mgottscho 7:78f6ee57d324 80 LPTMR0->CSR = 0; //Reset the timer control/status register
mgottscho 7:78f6ee57d324 81 LPTMR0->CMR = __rolloverValue; //Set the compare register
mgottscho 7:78f6ee57d324 82 LPTMR0->CSR |= LPTMR_CSR_TIE_MASK; //Enable interrupt
mgottscho 7:78f6ee57d324 83 LPTMR0->CSR |= LPTMR_CSR_TEN_MASK; //Start the timer
mgottscho 7:78f6ee57d324 84 }
mgottscho 7:78f6ee57d324 85
mgottscho 7:78f6ee57d324 86 void Timer_LPTMR::__stop_timer() {
mgottscho 7:78f6ee57d324 87 LPTMR0->CSR = 0; //Reset the LPTMR timer control/status register
mgottscho 7:78f6ee57d324 88 }
mgottscho 7:78f6ee57d324 89
mgottscho 7:78f6ee57d324 90 void Timer_LPTMR::__timer_isr() {
mgottscho 1:7dde0e4d30da 91 LPTMR0->CSR |= LPTMR_CSR_TCF_MASK; //Write 1 to TCF to clear the LPT timer compare flag
mgottscho 7:78f6ee57d324 92 if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
mgottscho 7:78f6ee57d324 93 __user_fptr->call();
mgottscho 7:78f6ee57d324 94 __call_user_function = false;
mgottscho 7:78f6ee57d324 95 }
mgottscho 1:7dde0e4d30da 96 __count++;
mgottscho 1:7dde0e4d30da 97 }
mgottscho 1:7dde0e4d30da 98
mgottscho 7:78f6ee57d324 99 void Timer_LPTMR::__lptmr_isr_wrapper() {
mgottscho 7:78f6ee57d324 100 __obj->__timer_isr();
mgottscho 1:7dde0e4d30da 101 }