Mark Gottscho / HardwareTimersLib

Fork of HardwareTimersLib by Mark Gottscho

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Timer_PIT.cpp Source File

Timer_PIT.cpp

00001 /* Timer_PIT.cpp
00002  * Tested with mbed board: FRDM-KL46Z
00003  * Author: Mark Gottscho
00004  * mgottscho@ucla.edu
00005  */
00006 
00007 #include "mbed.h"
00008 #include "HardwareTimer.h"
00009 #include "Timer_PIT.h"
00010 
00011 
00012 //Init Timer_PIT class variables
00013 bool Timer_PIT::__pit_used = false;
00014 Timer_PIT *Timer_PIT::__obj = NULL;
00015 
00016 Timer_PIT::Timer_PIT() :
00017         HardwareTimer(0xFFFFFFFF, 41.666666666, HardwareTimer::ns) //PIT has 32-bit counter. And at 24 MHz, each clock cycle is 41.666666 ns
00018         {   
00019     if (__pit_used)
00020         __valid = false;
00021     else {
00022         __valid = true;
00023         __pit_used = true;
00024         __obj = this;
00025     }
00026 }
00027 
00028 Timer_PIT::~Timer_PIT() {
00029     if (__valid) {
00030         __pit_used = false; //free the hardware PIT resource
00031         __obj = NULL;
00032     }
00033 }
00034 
00035 uint32_t Timer_PIT::getTick () {
00036     if (!__valid)
00037         return 0;
00038         
00039     uint32_t tick;
00040     uint32_t count;
00041 
00042     //__disable_irq(); //CRITICAL SECTION -- ALL INTERRUPTS MUST BE STOPPED!
00043     tick = PIT->CHANNEL[0].CVAL; //counts down
00044     
00045     //It is theoretically possible that the timer interrupt is invoked here, between these two lines.
00046     //However, the timer doesn't appear to work properly if I put these two in a critical section.
00047     
00048     count = __count;
00049     //__enable_irq(); //END CRITICAL SECTION
00050         
00051     //Convert to ticks
00052     return (__rolloverValue - tick) + count * __rolloverValue;
00053 }
00054 
00055 void Timer_PIT::__init_timer() {        
00056     SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;   //Enable clocking of PIT
00057     
00058     PIT->MCR |= PIT_MCR_MDIS_MASK; //Setting MDIS bit disables the timer module.
00059     
00060     //Set interrupt handler
00061     NVIC_SetVector(PIT_IRQn, (uint32_t) __pit_isr_wrapper);
00062     NVIC_EnableIRQ(PIT_IRQn);
00063     
00064     PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TIE_MASK; //Enable interrupts
00065     
00066     PIT->MCR &= ~PIT_MCR_MDIS_MASK; //Clearing MDIS bit enables the timer module.
00067 
00068     //Good to go!
00069 }
00070 
00071 void Timer_PIT::__start_timer() {
00072     PIT->CHANNEL[0].LDVAL = __rolloverValue; //Load the countdown value. PIT counts downwards.
00073     PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK; //Enable the timer.
00074 }
00075 
00076 void Timer_PIT::__stop_timer() {
00077     PIT->CHANNEL[0].TCTRL &= ~PIT_TCTRL_TEN_MASK; //Disable the timer.
00078 }
00079 
00080 void Timer_PIT::__timer_isr() {
00081     PIT->CHANNEL[0].TFLG |= PIT_TFLG_TIF_MASK; //Clear the timer interrupt flag bit
00082     if ((__periodic || __num_callbacks > 0) && __user_fptr != NULL) { //user callback
00083         __user_fptr->call();
00084         if (!__periodic)
00085             __num_callbacks--;
00086     }   
00087     __count++;
00088 }
00089 
00090 void Timer_PIT::__pit_isr_wrapper() {
00091     __obj->__timer_isr();   
00092 }