Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Committer:
mgottscho
Date:
Tue Mar 11 02:42:03 2014 +0000
Revision:
8:23c04123395c
Parent:
7:78f6ee57d324
Child:
9:dff7c891ec77
All timers now globally disable interrupts during computation of getTick(). If this is not done, the tick count will be corrupted.

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 8:23c04123395c 38 // CRITICAL SECTION -- ALL INTERRUPTS MUST BE STOPPED!
mgottscho 8:23c04123395c 39 __disable_irq();
mgottscho 1:7dde0e4d30da 40 TPM0->CNT = 0; //Need to write to the TPM CNT register in order to read it (buffering)
mgottscho 1:7dde0e4d30da 41 uint16_t tick = TPM0->CNT;
mgottscho 1:7dde0e4d30da 42 uint32_t count = __count;
mgottscho 8:23c04123395c 43 __enable_irq();
mgottscho 7:78f6ee57d324 44 // END CRITICAL SECTION
mgottscho 1:7dde0e4d30da 45
mgottscho 1:7dde0e4d30da 46 //Convert to ticks
mgottscho 1:7dde0e4d30da 47 return (uint32_t) count * __rolloverValue + tick;
mgottscho 1:7dde0e4d30da 48 }
mgottscho 1:7dde0e4d30da 49
mgottscho 7:78f6ee57d324 50 void Timer_TPM::__init_timer() {
mgottscho 7:78f6ee57d324 51 //Set TPM clocks
mgottscho 7:78f6ee57d324 52 SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); //Set TPM global clock source: MCGFLLCLK
mgottscho 7:78f6ee57d324 53 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; //Enable TPM block (clock gating)
mgottscho 7:78f6ee57d324 54
mgottscho 7:78f6ee57d324 55 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 56
mgottscho 7:78f6ee57d324 57 //Configure TPM prescaler
mgottscho 7:78f6ee57d324 58 TPM0->SC = TPM_SC_PS(0); //Prescaler set to 1
mgottscho 7:78f6ee57d324 59
mgottscho 7:78f6ee57d324 60 //Set interrupt handler
mgottscho 7:78f6ee57d324 61 NVIC_SetVector(TPM0_IRQn, (uint32_t) __tpm_isr_wrapper);
mgottscho 7:78f6ee57d324 62 NVIC_EnableIRQ(TPM0_IRQn);
mgottscho 7:78f6ee57d324 63 }
mgottscho 7:78f6ee57d324 64
mgottscho 7:78f6ee57d324 65 void Timer_TPM::__start_timer() {
mgottscho 1:7dde0e4d30da 66 TPM0->CNT = 0; //Set the count register
mgottscho 7:78f6ee57d324 67 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 1:7dde0e4d30da 68 TPM0->SC |= TPM_SC_TOIE_MASK; //Enable interrupt
mgottscho 1:7dde0e4d30da 69 TPM0->SC |= TPM_SC_CMOD(1); //Start the timer. Timer will increment on the TPM clock edges, not an external clock
mgottscho 1:7dde0e4d30da 70 }
mgottscho 1:7dde0e4d30da 71
mgottscho 7:78f6ee57d324 72 void Timer_TPM::__stop_timer() {
mgottscho 7:78f6ee57d324 73 TPM0->SC = 0; //Reset TPM
mgottscho 7:78f6ee57d324 74 }
mgottscho 7:78f6ee57d324 75
mgottscho 7:78f6ee57d324 76 void Timer_TPM::__timer_isr() {
mgottscho 1:7dde0e4d30da 77 TPM0->SC |= TPM_SC_TOF_MASK;
mgottscho 7:78f6ee57d324 78 TPM0->MOD = (uint16_t) __rolloverValue; //Set the modulo register
mgottscho 7:78f6ee57d324 79 if ((__periodic || __call_user_function) && __user_fptr != NULL) { //user callback
mgottscho 7:78f6ee57d324 80 __user_fptr->call();
mgottscho 7:78f6ee57d324 81 __call_user_function = false;
mgottscho 7:78f6ee57d324 82 }
mgottscho 1:7dde0e4d30da 83 __count++;
mgottscho 7:78f6ee57d324 84 }
mgottscho 7:78f6ee57d324 85
mgottscho 7:78f6ee57d324 86 void Timer_TPM::__tpm_isr_wrapper() {
mgottscho 7:78f6ee57d324 87 __obj->__timer_isr();
mgottscho 1:7dde0e4d30da 88 }