Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 04:54:13 2014 +0000
Revision:
11:e0442c8b182b
Parent:
10:12c1c5cef918
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_TPM.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 "HardwareTimer.h"
mgottscho 1:7dde0e4d30da 9 #include "Timer_TPM.h"
mgottscho 1:7dde0e4d30da 10
mgottscho 7:78f6ee57d324 11 //Init Timer_TPM class variables
mgottscho 7:78f6ee57d324 12 bool Timer_TPM::__tpm_used = false;
mgottscho 7:78f6ee57d324 13 Timer_TPM *Timer_TPM::__obj = NULL;
mgottscho 1:7dde0e4d30da 14
mgottscho 7:78f6ee57d324 15 Timer_TPM::Timer_TPM() :
mgottscho 7:78f6ee57d324 16 HardwareTimer(0xFFFF, 20.833333333, HardwareTimer::ns) //TPM has 16-bit counter. And at 48MHz, each clock cycle is 20.8333333 ns
mgottscho 1:7dde0e4d30da 17 {
mgottscho 7:78f6ee57d324 18 if (__tpm_used)
mgottscho 7:78f6ee57d324 19 __valid = false;
mgottscho 7:78f6ee57d324 20 else {
mgottscho 7:78f6ee57d324 21 __valid = true;
mgottscho 7:78f6ee57d324 22 __tpm_used = true;
mgottscho 7:78f6ee57d324 23 __obj = this;
mgottscho 7:78f6ee57d324 24 }
mgottscho 1:7dde0e4d30da 25 }
mgottscho 1:7dde0e4d30da 26
mgottscho 7:78f6ee57d324 27 Timer_TPM::~Timer_TPM() {
mgottscho 7:78f6ee57d324 28 if (__valid) {
mgottscho 7:78f6ee57d324 29 __tpm_used = false; //free the hardware TPM resource
mgottscho 7:78f6ee57d324 30 __obj = NULL;
mgottscho 7:78f6ee57d324 31 }
mgottscho 1:7dde0e4d30da 32 }
mgottscho 1:7dde0e4d30da 33
mgottscho 1:7dde0e4d30da 34 uint32_t Timer_TPM::getTick() {
mgottscho 7:78f6ee57d324 35 if (!__valid)
mgottscho 7:78f6ee57d324 36 return 0;
mgottscho 1:7dde0e4d30da 37
mgottscho 9:dff7c891ec77 38 uint16_t tick;
mgottscho 9:dff7c891ec77 39 uint32_t count;
mgottscho 9:dff7c891ec77 40
mgottscho 10:12c1c5cef918 41 //__disable_irq(); //CRITICAL SECTION -- ALL INTERRUPTS MUST BE STOPPED!
mgottscho 10:12c1c5cef918 42 TPM0->CNT = 0; //Need to write to the TPM CNT register in order to latch current value.
mgottscho 11:e0442c8b182b 43 tick = (uint16_t) TPM0->CNT; //Value was previously latched, just read it
mgottscho 11:e0442c8b182b 44
mgottscho 10:12c1c5cef918 45 //It is theoretically possible that the timer interrupt is invoked here, between these two lines.
mgottscho 10:12c1c5cef918 46 //However, the timer doesn't appear to work properly if I put these two in a critical section.
mgottscho 10:12c1c5cef918 47
mgottscho 10:12c1c5cef918 48 count = __count; //Latch current count value.
mgottscho 10:12c1c5cef918 49 //__enable_irq(); //END CRITICAL SECTION
mgottscho 10:12c1c5cef918 50
mgottscho 1:7dde0e4d30da 51 //Convert to ticks
mgottscho 9:dff7c891ec77 52 return count * __rolloverValue + (uint32_t) tick;
mgottscho 1:7dde0e4d30da 53 }
mgottscho 1:7dde0e4d30da 54
mgottscho 7:78f6ee57d324 55 void Timer_TPM::__init_timer() {
mgottscho 7:78f6ee57d324 56 //Set TPM clocks
mgottscho 7:78f6ee57d324 57 SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); //Set TPM global clock source: MCGFLLCLK
mgottscho 7:78f6ee57d324 58 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; //Enable TPM block (clock gating)
mgottscho 7:78f6ee57d324 59
mgottscho 7:78f6ee57d324 60 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 61
mgottscho 7:78f6ee57d324 62 //Configure TPM prescaler
mgottscho 7:78f6ee57d324 63 TPM0->SC = TPM_SC_PS(0); //Prescaler set to 1
mgottscho 7:78f6ee57d324 64
mgottscho 7:78f6ee57d324 65 //Set interrupt handler
mgottscho 7:78f6ee57d324 66 NVIC_SetVector(TPM0_IRQn, (uint32_t) __tpm_isr_wrapper);
mgottscho 7:78f6ee57d324 67 NVIC_EnableIRQ(TPM0_IRQn);
mgottscho 7:78f6ee57d324 68 }
mgottscho 7:78f6ee57d324 69
mgottscho 7:78f6ee57d324 70 void Timer_TPM::__start_timer() {
mgottscho 1:7dde0e4d30da 71 TPM0->CNT = 0; //Set the count register
mgottscho 7:78f6ee57d324 72 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 1:7dde0e4d30da 73 TPM0->SC |= TPM_SC_TOIE_MASK; //Enable interrupt
mgottscho 1:7dde0e4d30da 74 TPM0->SC |= TPM_SC_CMOD(1); //Start the timer. Timer will increment on the TPM clock edges, not an external clock
mgottscho 1:7dde0e4d30da 75 }
mgottscho 1:7dde0e4d30da 76
mgottscho 7:78f6ee57d324 77 void Timer_TPM::__stop_timer() {
mgottscho 7:78f6ee57d324 78 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 79 }
mgottscho 7:78f6ee57d324 80
mgottscho 7:78f6ee57d324 81 void Timer_TPM::__timer_isr() {
mgottscho 1:7dde0e4d30da 82 TPM0->SC |= TPM_SC_TOF_MASK;
mgottscho 7:78f6ee57d324 83 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 7:78f6ee57d324 84 if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
mgottscho 7:78f6ee57d324 85 __user_fptr->call();
mgottscho 7:78f6ee57d324 86 __call_user_function = false;
mgottscho 7:78f6ee57d324 87 }
mgottscho 1:7dde0e4d30da 88 __count++;
mgottscho 7:78f6ee57d324 89 }
mgottscho 7:78f6ee57d324 90
mgottscho 7:78f6ee57d324 91 void Timer_TPM::__tpm_isr_wrapper() {
mgottscho 7:78f6ee57d324 92 __obj->__timer_isr();
mgottscho 1:7dde0e4d30da 93 }