Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 04:18:04 2014 +0000
Revision:
10:12c1c5cef918
Parent:
9:dff7c891ec77
Child:
11:e0442c8b182b
Disabling interrupts inside getTick() seems to break things, not sure why, so removed those lines for Timer_TPM.

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 10:12c1c5cef918 43
mgottscho 10:12c1c5cef918 44 //It is theoretically possible that the timer interrupt is invoked here, between these two lines.
mgottscho 10:12c1c5cef918 45 //However, the timer doesn't appear to work properly if I put these two in a critical section.
mgottscho 10:12c1c5cef918 46
mgottscho 10:12c1c5cef918 47 count = __count; //Latch current count value.
mgottscho 10:12c1c5cef918 48 //__enable_irq(); //END CRITICAL SECTION
mgottscho 10:12c1c5cef918 49
mgottscho 10:12c1c5cef918 50 tick = (uint16_t) TPM0->CNT; //Value was previously latched, just read it
mgottscho 1:7dde0e4d30da 51
mgottscho 1:7dde0e4d30da 52 //Convert to ticks
mgottscho 9:dff7c891ec77 53 return count * __rolloverValue + (uint32_t) tick;
mgottscho 1:7dde0e4d30da 54 }
mgottscho 1:7dde0e4d30da 55
mgottscho 7:78f6ee57d324 56 void Timer_TPM::__init_timer() {
mgottscho 7:78f6ee57d324 57 //Set TPM clocks
mgottscho 7:78f6ee57d324 58 SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); //Set TPM global clock source: MCGFLLCLK
mgottscho 7:78f6ee57d324 59 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; //Enable TPM block (clock gating)
mgottscho 7:78f6ee57d324 60
mgottscho 7:78f6ee57d324 61 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 62
mgottscho 7:78f6ee57d324 63 //Configure TPM prescaler
mgottscho 7:78f6ee57d324 64 TPM0->SC = TPM_SC_PS(0); //Prescaler set to 1
mgottscho 7:78f6ee57d324 65
mgottscho 7:78f6ee57d324 66 //Set interrupt handler
mgottscho 7:78f6ee57d324 67 NVIC_SetVector(TPM0_IRQn, (uint32_t) __tpm_isr_wrapper);
mgottscho 7:78f6ee57d324 68 NVIC_EnableIRQ(TPM0_IRQn);
mgottscho 7:78f6ee57d324 69 }
mgottscho 7:78f6ee57d324 70
mgottscho 7:78f6ee57d324 71 void Timer_TPM::__start_timer() {
mgottscho 1:7dde0e4d30da 72 TPM0->CNT = 0; //Set the count register
mgottscho 7:78f6ee57d324 73 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 1:7dde0e4d30da 74 TPM0->SC |= TPM_SC_TOIE_MASK; //Enable interrupt
mgottscho 1:7dde0e4d30da 75 TPM0->SC |= TPM_SC_CMOD(1); //Start the timer. Timer will increment on the TPM clock edges, not an external clock
mgottscho 1:7dde0e4d30da 76 }
mgottscho 1:7dde0e4d30da 77
mgottscho 7:78f6ee57d324 78 void Timer_TPM::__stop_timer() {
mgottscho 7:78f6ee57d324 79 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 80 }
mgottscho 7:78f6ee57d324 81
mgottscho 7:78f6ee57d324 82 void Timer_TPM::__timer_isr() {
mgottscho 1:7dde0e4d30da 83 TPM0->SC |= TPM_SC_TOF_MASK;
mgottscho 7:78f6ee57d324 84 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 7:78f6ee57d324 85 if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
mgottscho 7:78f6ee57d324 86 __user_fptr->call();
mgottscho 7:78f6ee57d324 87 __call_user_function = false;
mgottscho 7:78f6ee57d324 88 }
mgottscho 1:7dde0e4d30da 89 __count++;
mgottscho 7:78f6ee57d324 90 }
mgottscho 7:78f6ee57d324 91
mgottscho 7:78f6ee57d324 92 void Timer_TPM::__tpm_isr_wrapper() {
mgottscho 7:78f6ee57d324 93 __obj->__timer_isr();
mgottscho 1:7dde0e4d30da 94 }