Fix for rare overflow issue that could cause an incorrect pulse width at very low RPM (<200rpm)

This commit is contained in:
Josh Stewart 2018-02-05 09:39:46 +11:00
parent 33b85f3b9d
commit dfa48ed250
3 changed files with 22 additions and 20 deletions

View File

@ -1,4 +1,4 @@
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
#unset CAN_COMMANDS
#unset enablehardware_test

View File

@ -412,8 +412,8 @@ struct Schedule {
void (*StartCallback)(); //Start Callback function for schedule
void (*EndCallback)(); //Start Callback function for schedule
volatile unsigned long startTime; //The system time (in uS) that the schedule started
volatile unsigned int startCompare; //The counter value of the timer when this will start
volatile unsigned int endCompare;
volatile uint16_t startCompare; //The counter value of the timer when this will start
volatile uint16_t endCompare;
unsigned int nextStartCompare;
unsigned int nextEndCompare;

View File

@ -290,13 +290,13 @@ void setFuelSchedule(struct Schedule *targetSchedule, unsigned long timeout, uns
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
if (timeout > MAX_TIMER_PERIOD) { timeout_timer_compare = uS_TO_TIMER_COMPARE( (MAX_TIMER_PERIOD - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
noInterrupts();
targetSchedule->startCompare = *targetSchedule->counter + timeout_timer_compare;
targetSchedule->endCompare = targetSchedule->startCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
targetSchedule->endCompare = targetSchedule->startCompare + uS_TO_TIMER_COMPARE(duration);
targetSchedule->Status = PENDING; //Turn this schedule on
targetSchedule->schedulesSet++; //Increment the number of times this schedule has been set
@ -308,8 +308,8 @@ void setFuelSchedule(struct Schedule *targetSchedule, unsigned long timeout, uns
{
//If the schedule is already running, we can set the next schedule so it is ready to go
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
targetSchedule->nextStartCompare = *targetSchedule->counter + uS_TO_TIMER_COMPARE_SLOW(timeout);
targetSchedule->nextEndCompare = targetSchedule->nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
targetSchedule->nextStartCompare = *targetSchedule->counter + uS_TO_TIMER_COMPARE(timeout);
targetSchedule->nextEndCompare = targetSchedule->nextStartCompare + uS_TO_TIMER_COMPARE(duration);
targetSchedule->hasNextSchedule = true;
}
}
@ -327,7 +327,7 @@ void setFuelSchedule1(unsigned long timeout, unsigned long duration)
//Need to check that the timeout doesn't exceed the overflow
uint16_t timeout_timer_compare;
if (timeout > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
if ((timeout+duration) > MAX_TIMER_PERIOD_SLOW) { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW( (MAX_TIMER_PERIOD_SLOW - 1 - duration) ); } // If the timeout is >16x (Each tick represents 16uS) the maximum allowed value of unsigned int (65535), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
else { timeout_timer_compare = uS_TO_TIMER_COMPARE_SLOW(timeout); } //Normal case
//The following must be enclosed in the noInterupts block to avoid contention caused if the relevant interrupt fires before the state is fully set
@ -350,7 +350,8 @@ void setFuelSchedule1(unsigned long timeout, unsigned long duration)
//This is required in cases of high rpm and high DC where there otherwise would not be enough time to set the schedule
fuelSchedule1.nextStartCompare = FUEL1_COUNTER + uS_TO_TIMER_COMPARE_SLOW(timeout);
fuelSchedule1.nextEndCompare = fuelSchedule1.nextStartCompare + uS_TO_TIMER_COMPARE_SLOW(duration);
fuelSchedule1.hasNextSchedule = true;
fuelSchedule1.duration = duration;
fuelSchedule1.hasNextSchedule = false;
}
}
@ -766,7 +767,7 @@ static inline void fuelSchedule1Interrupt() //Most ARM chips can simply call a f
if (configPage2.injLayout == INJ_SEMISEQUENTIAL) { openInjector1and4(); }
else { openInjector1(); }
fuelSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL1_COMPARE = fuelSchedule1.endCompare;
FUEL1_COMPARE = FUEL1_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule1.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule1.Status == RUNNING)
{
@ -803,7 +804,7 @@ static inline void fuelSchedule2Interrupt() //Most ARM chips can simply call a f
if (configPage2.injLayout == INJ_SEMISEQUENTIAL) { openInjector2and3(); }
else { openInjector2(); }
fuelSchedule2.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL2_COMPARE = fuelSchedule2.endCompare;
FUEL2_COMPARE = FUEL2_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule2.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule2.Status == RUNNING)
{
@ -839,7 +840,7 @@ static inline void fuelSchedule3Interrupt() //Most ARM chips can simply call a f
if(channel5InjEnabled) { openInjector3and5(); }
else { openInjector3(); }
fuelSchedule3.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL3_COMPARE = fuelSchedule3.endCompare;
FUEL3_COMPARE = FUEL3_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule3.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule3.Status == RUNNING)
{
@ -874,7 +875,7 @@ static inline void fuelSchedule4Interrupt() //Most ARM chips can simply call a f
//fuelSchedule4.StartCallback();
openInjector4();
fuelSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
FUEL4_COMPARE = fuelSchedule4.endCompare;
FUEL4_COMPARE = FUEL4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(fuelSchedule4.duration); //Doing this here prevents a potential overflow on restarts
}
else if (fuelSchedule4.Status == RUNNING)
{
@ -942,11 +943,12 @@ static inline void ignitionSchedule1Interrupt() //Most ARM chips can simply call
ignitionSchedule1.StartCallback();
ignitionSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule1.startTime = micros();
IGN1_COMPARE = ignitionSchedule1.endCompare;
//IGN1_COMPARE = ignitionSchedule1.endCompare;
IGN1_COMPARE = IGN1_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule1.duration); //Doing this here prevents a potential overflow on restarts
//This code is all to do with the staged ignition timing testing. That is, calling this interrupt slightly before the true ignition point and recalculating the end time for more accuracy
//IGN1_COMPARE = ignitionSchedule1.endCompare - 50;
//ignitionSchedule1.Status = STAGED;
}
}
else if (ignitionSchedule1.Status == STAGED)
{
int16_t crankAngle = getCrankAngle(timePerDegree);
@ -980,7 +982,7 @@ static inline void ignitionSchedule2Interrupt() //Most ARM chips can simply call
ignitionSchedule2.StartCallback();
ignitionSchedule2.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule2.startTime = micros();
IGN2_COMPARE = ignitionSchedule2.endCompare; //OCR5B = TCNT5 + (ignitionSchedule2.duration >> 2);
IGN2_COMPARE = IGN2_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule2.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule2.Status == RUNNING)
{
@ -1003,7 +1005,7 @@ static inline void ignitionSchedule3Interrupt() //Most ARM chips can simply call
ignitionSchedule3.StartCallback();
ignitionSchedule3.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule3.startTime = micros();
IGN3_COMPARE = ignitionSchedule3.endCompare; //OCR5C = TCNT5 + (ignitionSchedule3.duration >> 2);
IGN3_COMPARE = IGN3_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule3.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule3.Status == RUNNING)
{
@ -1036,7 +1038,7 @@ static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call
ignitionSchedule4.StartCallback();
ignitionSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule4.startTime = micros();
IGN4_COMPARE = ignitionSchedule4.endCompare;
IGN4_COMPARE = IGN4_COUNTER + uS_TO_TIMER_COMPARE_SLOW(ignitionSchedule4.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule4.Status == RUNNING)
{
@ -1069,7 +1071,7 @@ static inline void ignitionSchedule5Interrupt() //Most ARM chips can simply call
ignitionSchedule5.StartCallback();
ignitionSchedule5.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule5.startTime = micros();
IGN5_COMPARE = ignitionSchedule5.endCompare;
IGN5_COMPARE = IGN5_COUNTER + uS_TO_TIMER_COMPARE_SLOW(ignitionSchedule5.duration); //Doing this here prevents a potential overflow on restarts
}
else if (ignitionSchedule5.Status == RUNNING)
{