More complete timer code for Teensy

This commit is contained in:
Josh Stewart 2016-11-23 11:51:12 +11:00
parent bea6dd17bc
commit 371b779e9d
2 changed files with 94 additions and 48 deletions

View File

@ -74,6 +74,9 @@ See page 136 of the processors datasheet: http://www.atmel.com/Images/doc2549.pd
#define IGN3_TIMER_DISABLE() TIMSK5 &= ~(1 << OCIE5C) //Turn off this output compare unit
#define IGN4_TIMER_DISABLE() TIMSK4 &= ~(1 << OCIE4A) //Turn off this output compare unit
#define MAX_TIMER_PERIOD 262140 //The longest period of time (in uS) that the timer can permit (IN this case it is 65535 * 4, as each timer tick is 4uS)
#define US_TO_TIMER_COMPARE(uS) uS >> 2 //Converts a given number of uS into the required number of timer ticks until that time has passed
#elif defined(CORE_TEENSY)
//http://shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
#define FUEL1_COUNTER FTM0_CNT
@ -96,25 +99,28 @@ See page 136 of the processors datasheet: http://www.atmel.com/Images/doc2549.pd
#define IGN3_COMPARE FTM0_C6V
#define IGN4_COMPARE FTM0_C7V
#define FUEL1_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL2_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL3_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL4_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL1_TIMER_ENABLE() FTM0_C0SC |= FTM_CSC_CHIE //Write 1 to the CHIE (Channel Interrupt Enable) bit of channel 0 Status/Control
#define FUEL2_TIMER_ENABLE() FTM0_C1SC |= FTM_CSC_CHIE
#define FUEL3_TIMER_ENABLE() FTM0_C2SC |= FTM_CSC_CHIE
#define FUEL4_TIMER_ENABLE() FTM0_C3SC |= FTM_CSC_CHIE
#define FUEL1_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL2_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL3_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL4_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define FUEL1_TIMER_DISABLE() FTM0_C0SC &= ~FTM_CSC_CHIE //Write 0 to the CHIE (Channel Interrupt Enable) bit of channel 0 Status/Control
#define FUEL2_TIMER_DISABLE() FTM0_C1SC &= ~FTM_CSC_CHIE
#define FUEL3_TIMER_DISABLE() FTM0_C2SC &= ~FTM_CSC_CHIE
#define FUEL4_TIMER_DISABLE() FTM0_C3SC &= ~FTM_CSC_CHIE
#define IGN1_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN2_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN3_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN4_TIMER_ENABLE() NVIC_ENABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN1_TIMER_ENABLE() FTM0_C4SC |= FTM_CSC_CHIE
#define IGN2_TIMER_ENABLE() FTM0_C5SC |= FTM_CSC_CHIE
#define IGN3_TIMER_ENABLE() FTM0_C6SC |= FTM_CSC_CHIE
#define IGN4_TIMER_ENABLE() FTM0_C7SC |= FTM_CSC_CHIE
#define IGN1_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN2_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN3_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN4_TIMER_DISABLE() NVIC_DISABLE_IRQ(IRQ_FTM1) //THIS IS NOT RIGHT! PLACEHOLDER ONLY!
#define IGN1_TIMER_DISABLE() FTM0_C4SC &= ~FTM_CSC_CHIE
#define IGN2_TIMER_DISABLE() FTM0_C5SC &= ~FTM_CSC_CHIE
#define IGN3_TIMER_DISABLE() FTM0_C6SC &= ~FTM_CSC_CHIE
#define IGN4_TIMER_DISABLE() FTM0_C7SC &= ~FTM_CSC_CHIE
#define MAX_TIMER_PERIOD 139808 // 2.13333333uS * 65535
#define US_TO_TIMER_COMPARE(uS) (uS * 15) >> 5 //Converts a given number of uS into the required number of timer ticks until that time has passed.
#endif
void initialiseSchedulers();

View File

@ -38,43 +38,83 @@ void initialiseSchedulers()
#elif defined (CORE_TEENSY) && defined (__MK20DX256__)
//Configure ARM timers here
FTM0_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
FTM0_MODE |= FTM_MODE_FTMEN; // Unrestricted FTM mode
FTM0_SC |= FTM_SC_TOIE; // enable Overflow Interrupt
// enable the clock for FTM0
FTM0_SC |= FTM_SC_CLKS(0b10);
// 00 No clock selected. This in effect disables the FTM counter.
// 01 System clock
// 10 Fixed frequency clock
// 11 External clock
//FlexTimer 0 is used for 4 ignition and 4 injection schedules. There are 8 channels on this module, so no other timers are needed
FTM0_MODE |= FTM_MODE_WPDIS; // Write Protection Disable
FTM0_MODE |= FTM_MODE_FTMEN; //Flex Timer module enable
FTM0_MODE |= FTM_MODE_INIT;
// set Prescaler
//FTM0_SC |= FTM_SC_PS(0b111);
FTM0_SC |= 0b000;
// 000 Divide by 1
// 001 Divide by 2
// 010 Divide by 4
// 011 Divide by 8
// 100 Divide by 16
// 101 Divide by 32
// 110 Divide by 64
// 111 Divide by 128
FTM0_SC = 0x00; // Set this to zero before changing the modulus
FTM0_CNTIN = 0x0000; //Shouldn't be needed, but just in case
FTM0_CNT = 0x0000; // Reset the count to zero
FTM0_MOD = 0xFFFF; // max modulus = 65535
// set the counter initial value
FTM0_CNT = 0;
/*
* Enable the clock for FTM0
* 00 No clock selected. Disables the FTM counter.
* 01 System clock
* 10 Fixed frequency clock
* 11 External clock
*/
FTM0_SC |= FTM_SC_CLKS(0b1);
/*
* Set Prescaler
* This is the slowest that the timer can be clocked (Without used the slow timer, which is too slow). It results in ticks of 2.13333uS on the teensy 3.5:
* 60000000 Hz = F_BUS
* 128 * 1000000uS / F_BUS = 2.133uS
*
* 000 = Divide by 1
* 001 Divide by 2
* 010 Divide by 4
* 011 Divide by 8
* 100 Divide by 16
* 101 Divide by 32
* 110 Divide by 64
* 111 Divide by 128
*/
FTM0_SC |= FTM_SC_PS(0b111);
//Setup the channels (See Pg 1014 of K64 DS).
//FTM0_C0SC &= ~FTM_CSC_ELSB; //Probably not needed as power on state should be 0
//FTM0_C0SC &= ~FTM_CSC_ELSA; //Probably not needed as power on state should be 0
//FTM0_C0SC &= ~FTM_CSC_DMA; //Probably not needed as power on state should be 0
FTM0_C0SC &= ~FTM_CSC_MSB; //According to Pg 965 of the K64 datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C0SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C0SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
// enable the clock for FTM0
SIM_SCGC6 |= SIM_SCGC6_FTM0;
FTM0_C1SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C1SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C1SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
// enable IRQ Interrupt
NVIC_ENABLE_IRQ(IRQ_FTM0);
FTM0_C2SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C2SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C2SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
FTM0_C3SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C3SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C3SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
FTM0_C4SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C4SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C4SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
FTM0_C5SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C5SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C5SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
FTM0_C6SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C6SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C6SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
FTM0_C7SC &= ~FTM_CSC_MSB; //According to Pg 965 of the datasheet, this should not be needed as MSB is reset to 0 upon reset, but the channel interrupt fails to fire without it
FTM0_C7SC |= FTM_CSC_MSA; //Enable Compare mode
FTM0_C7SC |= FTM_CSC_CHIE; //Enable channel compare interrupt
// enable IRQ Interrupt
NVIC_ENABLE_IRQ(IRQ_FTM0);
FTM0_FMS |= FTM0_WPEN;
#endif
fuelSchedule1.Status = OFF;
fuelSchedule2.Status = OFF;
fuelSchedule3.Status = OFF;
@ -118,7 +158,7 @@ void setFuelSchedule1(void (*startCallback)(), unsigned long timeout, unsigned l
fuelSchedule1.duration = duration;
/*
* The following must be enclosed in the noIntterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
* The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupts fires before the state is fully set
* We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
* As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
* unsigned int absoluteTimeout = TCNT3 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
@ -237,7 +277,7 @@ void setIgnitionSchedule1(void (*startCallback)(), unsigned long timeout, unsign
ignitionSchedule1.duration = duration;
//As the timer is ticking every 4uS (Time per Tick = (Prescale)*(1/Frequency))
if (timeout > 262140) { timeout = 262100; } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
if (timeout > MAX_TIMER_PERIOD) { timeout = 262100; } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
noInterrupts();
ignitionSchedule1.startCompare = IGN1_COUNTER + (timeout >> 2); //As there is a tick every 4uS, there are timeout/4 ticks until the interrupt should be triggered ( >>2 divides by 4)