From edd0e551e6041f7596c880cdaef13dfa67eff6b5 Mon Sep 17 00:00:00 2001 From: Kevin Rosenberg Date: Fri, 14 Mar 2008 16:13:33 -0600 Subject: [PATCH] 2008-03-14 Martin Thomas * added "volatile" to structure object and array declarations for objects sed in main-thread and ISRs. I'm not sure about the current state of implicitly "guaranteed" accesses in (avr-)gcc but it should be a "better safe than sorry" extension. * enveloped access to timer-values in timer.c to make them "atomic" since they are unsigned long * "atomic" access to singned int and unsigned int members of ADCS * it maybe better to have one place to globally enable interrupts ("sei"). Done in "initialize" now and not several times in the driver --- BaseTinyFirmware/GCC/ADC.c | 20 +++++---- BaseTinyFirmware/GCC/ADC.h | 2 +- BaseTinyFirmware/GCC/ChangeLog | 17 ++++++++ BaseTinyFirmware/GCC/USI.c | 9 ++-- BaseTinyFirmware/GCC/avr463.aps | 2 +- BaseTinyFirmware/GCC/avr463.aws | 2 +- BaseTinyFirmware/GCC/battery.c | 38 +++++++++++++---- BaseTinyFirmware/GCC/chargefunc.c | 70 +++++++++++++++++++++---------- BaseTinyFirmware/GCC/main.c | 8 ++-- BaseTinyFirmware/GCC/statefunc.c | 35 +++++++++++----- BaseTinyFirmware/GCC/time.c | 34 +++++++++++---- BaseTinyFirmware/GCC/time.h | 2 +- 12 files changed, 173 insertions(+), 66 deletions(-) diff --git a/BaseTinyFirmware/GCC/ADC.c b/BaseTinyFirmware/GCC/ADC.c index 004ba8d..50814ca 100644 --- a/BaseTinyFirmware/GCC/ADC.c +++ b/BaseTinyFirmware/GCC/ADC.c @@ -45,7 +45,7 @@ //****************************************************************************** // ADC status struct. //! \brief Holds sampled data and ADC-status -ADC_Status_t ADCS; +volatile ADC_Status_t ADCS; /*! \brief Indicates maximum battery voltage. @@ -170,10 +170,10 @@ ISR(ADC_vect) // Scale sample according to jumper setting, handle negative numbers. if (ADC > 511) { - ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE), - (1024 - (ADC-ADCS.ADC5_G20_OS))); + ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE), + (1024 - (ADC-ADCS.ADC5_G20_OS))); } else if (ADC > 0) { - ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS)); + ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS)); } else { ADCS.IBAT = 0; } @@ -206,15 +206,15 @@ ISR(ADC_vect) ADMUX = (1< + * added "volatile" to structure object and array declarations for objects + sed in main-thread and ISRs. I'm not sure about the current state of + implicitly "guaranteed" accesses in (avr-)gcc but it should be a "better + safe than sorry" extension. + * enveloped access to timer-values in timer.c to make them "atomic" since + they are unsigned long + * "atomic" access to singned int and unsigned int members of ADCS + * it maybe better to have one place to globally enable interrupts ("sei"). + Done in "initialize" now and not several times in the driver + init-functions. + * changed some space to tab as in the original code + * added header files to the AVR-Studio project workspace + * added -lm to the linker-options in the AVR Studio gcc-plugin, not + important for the basic application but might be good if someone uses the + code as a base for own developments + 2008-03-12 Kevin Rosenberg * Initial GCC port performed and compiles without error * Warning: Not yet tested on BC100 hardware! diff --git a/BaseTinyFirmware/GCC/USI.c b/BaseTinyFirmware/GCC/USI.c index efc004f..6813d15 100644 --- a/BaseTinyFirmware/GCC/USI.c +++ b/BaseTinyFirmware/GCC/USI.c @@ -44,7 +44,7 @@ // Variables //****************************************************************************** //! SPI status struct -SPI_Status_t SPI; +volatile SPI_Status_t SPI; //****************************************************************************** @@ -162,7 +162,7 @@ ISR(USI_OVF_vect) case ADR_BATTCTRL: - SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count))); + SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count))); break; case ADR_TIMERS: @@ -221,6 +221,9 @@ ISR(USI_OVF_vect) */ void SPI_Init(unsigned char spi_mode) { + unsigned char sreg_saved; + + sreg_saved = SREG; cli(); // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. @@ -241,7 +244,7 @@ void SPI_Init(unsigned char spi_mode) SPI.XferComplete = FALSE; // We haven't even started a transfer yet. SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened. - sei(); + SREG = sreg_saved; } diff --git a/BaseTinyFirmware/GCC/avr463.aps b/BaseTinyFirmware/GCC/avr463.aps index 0e89be1..360a5e2 100644 --- a/BaseTinyFirmware/GCC/avr463.aps +++ b/BaseTinyFirmware/GCC/avr463.aps @@ -1 +1 @@ -avr46313-Mar-2008 01:54:2413-Mar-2008 03:07:11241013-Mar-2008 01:54:2444, 14, 0, 580AVR GCCavr463\avr463.elfC:\Users\kevin\pub\src\bc100\GCC\AVR SimulatorATtiny861.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000ADC.cbattery.cchargefunc.cmain.cmenu.cNIMHcharge.cOWI.cPWM.cstatefunc.ctime.cUSI.cavr463\avr463.lssavr463\avr463.mapavr463NOattiny861111avr463.elfavr463\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMH avr4631C:\WinAVR\bin\avr-gcc.exeC:\WinAVR\utils\bin\make.exeC:\Users\kevin\pub\src\bc100\GCC\ADC.cC:\Users\kevin\pub\src\bc100\GCC\battery.cC:\Users\kevin\pub\src\bc100\GCC\chargefunc.cC:\Users\kevin\pub\src\bc100\GCC\main.cC:\Users\kevin\pub\src\bc100\GCC\menu.cC:\Users\kevin\pub\src\bc100\GCC\NIMHcharge.cC:\Users\kevin\pub\src\bc100\GCC\OWI.cC:\Users\kevin\pub\src\bc100\GCC\PWM.cC:\Users\kevin\pub\src\bc100\GCC\statefunc.cC:\Users\kevin\pub\src\bc100\GCC\time.cC:\Users\kevin\pub\src\bc100\GCC\USI.c00000battery.c100001chargefunc.c100002nimhcharge.c100003statefunc.c1 +avr46313-Mar-2008 01:54:2414-Mar-2008 21:11:26241013-Mar-2008 01:54:2444, 14, 0, 580AVR GCCavr463\avr463.elfD:\users\mthomas\develop\avr\bc100\bcc100_mth_20080314\BaseTinyFirmware\GCC\AVR SimulatorATtiny861falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000ADC.cbattery.cchargefunc.cmain.cmenu.cNIMHcharge.cOWI.cPWM.cstatefunc.ctime.cUSI.cADC.hbattery.hcharge.hchargefunc.hdelay_x_gcc.henums.hmain.hmenu.hNIMHspecs.hOWI.hPWM.hstatefunc.hstructs.htime.hUSI.havr463\avr463.lssavr463\avr463.mapavr463NOattiny861111avr463.elfavr463\1libm.a-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMHavr4631C:\WinAVR\bin\avr-gcc.exeC:\WinAVR\utils\bin\make.exe00000structs.h1 diff --git a/BaseTinyFirmware/GCC/avr463.aws b/BaseTinyFirmware/GCC/avr463.aws index 2773bff..e73c6bf 100644 --- a/BaseTinyFirmware/GCC/avr463.aws +++ b/BaseTinyFirmware/GCC/avr463.aws @@ -1 +1 @@ - + diff --git a/BaseTinyFirmware/GCC/battery.c b/BaseTinyFirmware/GCC/battery.c index e6cacd8..b361711 100644 --- a/BaseTinyFirmware/GCC/battery.c +++ b/BaseTinyFirmware/GCC/battery.c @@ -30,6 +30,7 @@ #include #include +#include #include "structs.h" #include "enums.h" @@ -172,6 +173,9 @@ unsigned char BatteryStatusRefresh(void) { // Assume the worst.. unsigned char success = FALSE; + unsigned char sreg_saved; + unsigned int adcs_VBAT_tmp; + signed int adcs_avgIBAT_tmp; BattData.Present = FALSE; BattData.Charged = FALSE; @@ -186,13 +190,19 @@ unsigned char BatteryStatusRefresh(void) NTCLookUp(); BattData.HasRID = RIDLookUp(); + sreg_saved = SREG; + cli(); + adcs_VBAT_tmp = ADCS.VBAT; + adcs_avgIBAT_tmp = ADCS.avgIBAT; + SREG = sreg_saved; + // Is the battery voltage above minimum safe cell voltage? - if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + if (adcs_VBAT_tmp >= BAT_VOLTAGE_MIN) { BattData.Low = FALSE; } // Is the battery charged? - if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { + if (adcs_VBAT_tmp >= BAT_VOLTAGE_LOW) { BattData.Charged = TRUE; } @@ -205,7 +215,7 @@ unsigned char BatteryStatusRefresh(void) * not 100% proof. */ if (((OCR1B == 0) && (!BattData.Low)) || - ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { + ((OCR1B != 0) && (adcs_avgIBAT_tmp > 0))) { BattData.Present = TRUE; success = TRUE; } else { @@ -299,7 +309,7 @@ unsigned char BatteryDataRefresh(void) // Erase local EEPROM page if there were any errors during transfer. if (!success) { for (i=0; i<32; i++) { - eeprom_write_byte(&BattEEPROM[page][i], 0); + eeprom_write_byte(&BattEEPROM[page][i], 0); } } } @@ -358,12 +368,18 @@ void DisableBatteries(void) unsigned char RIDLookUp (void) { unsigned char i, found = FALSE; + unsigned int adcs_rawRID_tmp; + unsigned char sreg_saved; // Lookup in the RID-table. If measured RID is within the limits // of an entry, those data are used, and TRUE is returned. for (i = 0 ; i < RID_TABLE_SIZE; i++) { - if (ADCS.rawRID >= RID[i].Low) { - if (ADCS.rawRID <= RID[i].High) { + sreg_saved = SREG; + cli(); + adcs_rawRID_tmp = ADCS.rawRID; + SREG = sreg_saved; + if (adcs_rawRID_tmp >= RID[i].Low) { + if (adcs_rawRID_tmp <= RID[i].High) { BattData.Capacity = RID[i].Capacity; BattData.MaxCurrent = RID[i].Icharge; BattData.MaxTime = RID[i].tCutOff; @@ -401,15 +417,21 @@ void NTCLookUp (void) { unsigned char i; unsigned char found = FALSE; + unsigned char adcs_rawNTC_tmp; + unsigned char sreg_saved; // Lookup in the NTC-table. Use the first entry which is equal or below // sampled NTC. Calculate temperature by using the index number, and the // difference between the measured NTC value and the one in the entry. for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { - if (ADCS.rawNTC >= NTC[i].ADCV) { + sreg_saved = SREG; + cli(); + adcs_rawNTC_tmp = ADCS.rawNTC; + SREG = sreg_saved; + if (adcs_rawNTC_tmp >= NTC[i].ADCV) { BattData.Temperature = (i<<2) ; BattData.ADCSteps = NTC[i].ADCsteps; - BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADCV)<<1) / BattData.ADCSteps; + BattData.Temperature -= ((adcs_rawNTC_tmp - NTC[i].ADCV)<<1) / BattData.ADCSteps; found = TRUE; // Could be done with a break, but that violates MISRA. } diff --git a/BaseTinyFirmware/GCC/chargefunc.c b/BaseTinyFirmware/GCC/chargefunc.c index 2194e56..5f441b7 100644 --- a/BaseTinyFirmware/GCC/chargefunc.c +++ b/BaseTinyFirmware/GCC/chargefunc.c @@ -28,6 +28,7 @@ ******************************************************************************/ #include +#include #include "enums.h" #include "structs.h" @@ -81,9 +82,11 @@ unsigned char ConstantCurrent(void) { unsigned char error = FALSE, wasStopped = FALSE; + unsigned char sreg_saved; + signed int adcs_avgIBAT_tmp; do { - // Wait for ADC conversions to complete. + // Wait for ADC conversions to complete. ADC_Wait(); // If Master has flagged for a charge inhibit, pause charging. @@ -100,11 +103,16 @@ unsigned char ConstantCurrent(void) // Timer variables are not reset by this. Time_Start(); } - + + sreg_saved = SREG; + cli(); + adcs_avgIBAT_tmp = ADCS.avgIBAT; + SREG = sreg_saved; + // Adjust the charge current to within ChargeParameters.Current // +/- BAT_CURRENT_HYST. - if ((ADCS.avgIBAT < 0) || - (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { + if ((adcs_avgIBAT_tmp < 0) || + (adcs_avgIBAT_tmp < (ChargeParameters.Current - BAT_CURRENT_HYST))) { if(!PWM_IncrementDutyCycle()) { #ifdef ABORT_IF_PWM_MAX @@ -115,8 +123,8 @@ unsigned char ConstantCurrent(void) error = TRUE; #endif } - } else if ((ADCS.avgIBAT >= 0) && - (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { + } else if ((adcs_avgIBAT_tmp >= 0) && + (adcs_avgIBAT_tmp > (ChargeParameters.Current + BAT_CURRENT_HYST))) { if(!PWM_DecrementDutyCycle()) { #ifdef ABORT_IF_PWM_MIN @@ -155,6 +163,8 @@ unsigned char ConstantVoltage(void) { unsigned char error = FALSE, wasStopped = FALSE; + unsigned char sreg_saved; + unsigned int adcs_VBAT_tmp; do{ @@ -178,9 +188,14 @@ unsigned char ConstantVoltage(void) Time_Start(); } + sreg_saved = SREG; + cli(); + adcs_VBAT_tmp = ADCS.VBAT; + SREG = sreg_saved; + // Adjust the charge voltage to within ChargeParameters.Voltage // +/- BAT_VOLTAGE_HYST. - if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { + if (adcs_VBAT_tmp < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { if(!PWM_IncrementDutyCycle()) { #ifdef ABORT_IF_PWM_MAX @@ -191,7 +206,7 @@ unsigned char ConstantVoltage(void) error = TRUE; #endif } - } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { + } else if (adcs_VBAT_tmp > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { if(!PWM_DecrementDutyCycle()) { #ifdef ABORT_IF_PWM_MIN @@ -238,6 +253,9 @@ unsigned char ConstantVoltage(void) unsigned char HaltNow(void) { unsigned char i, halt = FALSE; + unsigned int adcs_rawNTC_tmp, adcs_VBAT_tmp; + signed int adcs_avgIBAT_tmp; + unsigned char sreg_saved; // Wait for a full ADC-cycle to finish. ADC_Wait(); @@ -247,14 +265,20 @@ unsigned char HaltNow(void) // (Gets overridden if either mains is failing, or the battery changes.) for (i = 0x01; i != 0; i <<= 1) { if (HaltParameters.HaltFlags & i) { + + sreg_saved = SREG; + cli(); + adcs_VBAT_tmp = ADCS.VBAT; + adcs_avgIBAT_tmp = ADCS.avgIBAT; + SREG = sreg_saved; + switch (i) { // Is VBAT less than the recorded maximum? case HALT_VOLTAGE_DROP: - // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. - if (ADCS.VBAT > HaltParameters.VBATMax) { - HaltParameters.VBATMax = ADCS.VBAT; - } else if((HaltParameters.VBATMax - ADCS.VBAT) >= + if (adcs_VBAT_tmp > HaltParameters.VBATMax) { + HaltParameters.VBATMax = adcs_VBAT_tmp; + } else if((HaltParameters.VBATMax - adcs_VBAT_tmp) >= HaltParameters.VoltageDrop) { halt = TRUE; } @@ -264,7 +288,7 @@ unsigned char HaltNow(void) // Has VBAT reached the maximum limit? case HALT_VOLTAGE_MAX: - if (ADCS.VBAT >= HaltParameters.VoltageMax) { + if (adcs_VBAT_tmp >= HaltParameters.VoltageMax) { halt = TRUE; } break; @@ -273,7 +297,7 @@ unsigned char HaltNow(void) // Has IBAT reached the minimum limit? case HALT_CURRENT_MIN: - if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { + if (adcs_avgIBAT_tmp <= HaltParameters.CurrentMin) { halt = TRUE; } break; @@ -281,16 +305,20 @@ unsigned char HaltNow(void) // Is the temperature rising too fast? case HALT_TEMPERATURE_RISE: - + + sreg_saved = SREG; + cli(); + adcs_rawNTC_tmp = ADCS.rawNTC; + SREG = sreg_saved; // If rawNTC has increased, the temperature has dropped. // We can store this value for now, and start the timer. // Otherwise, check if NTC has changed too fast. - if (ADCS.rawNTC > HaltParameters.LastNTC) { - HaltParameters.LastNTC = ADCS.rawNTC; + if (adcs_rawNTC_tmp > HaltParameters.LastNTC) { + HaltParameters.LastNTC = adcs_rawNTC_tmp; Time_Set(TIMER_TEMP,0,30,0); // Is the increase in temperature greater than the set threshold? - } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= + } else if ((HaltParameters.LastNTC - adcs_rawNTC_tmp) >= (BattData.ADCSteps * HaltParameters.TemperatureRise)) { // If this happened within a timeframe of 30 seconds, the @@ -299,7 +327,7 @@ unsigned char HaltNow(void) if (Time_Left(TIMER_TEMP)) { halt = TRUE; } else { - HaltParameters.LastNTC = ADCS.rawNTC; + HaltParameters.LastNTC = adcs_rawNTC_tmp; Time_Set(TIMER_TEMP,0,30,0); } } @@ -317,8 +345,8 @@ unsigned char HaltNow(void) if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { PWM_Stop(); Battery_t tmp = eeprom_read_byte(&BattControl[BattActive]); - tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE; - eeprom_write_byte(&BattControl[BattActive], tmp); + tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE; + eeprom_write_byte(&BattControl[BattActive], tmp); BattData.Exhausted = TRUE; SetErrorFlag(ERR_BATTERY_EXHAUSTED); ChargeParameters.NextState = ST_ERROR; diff --git a/BaseTinyFirmware/GCC/main.c b/BaseTinyFirmware/GCC/main.c index 62f46d3..919c965 100644 --- a/BaseTinyFirmware/GCC/main.c +++ b/BaseTinyFirmware/GCC/main.c @@ -108,8 +108,8 @@ int main( void ) // Look for function associated with current state, get its address. for (i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) { - if (pgm_read_byte(&menu_state[i].state) == CurrentState) { - pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); + if (pgm_read_byte(&menu_state[i].state) == CurrentState) { + pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); } } @@ -123,8 +123,8 @@ int main( void ) if (nextstate != CurrentState) { CurrentState = nextstate; for ( i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) { - if (pgm_read_byte(&menu_state[i].state) == CurrentState) { - pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); + if (pgm_read_byte(&menu_state[i].state) == CurrentState) { + pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); } } } diff --git a/BaseTinyFirmware/GCC/statefunc.c b/BaseTinyFirmware/GCC/statefunc.c index 9df2b5c..ef1464d 100644 --- a/BaseTinyFirmware/GCC/statefunc.c +++ b/BaseTinyFirmware/GCC/statefunc.c @@ -103,7 +103,7 @@ unsigned char Initialize(unsigned char inp) // Clear on-chip EEPROM. for (page = 0; page < 4; page++) { for (i = 0; i < 32; i++) { - eeprom_write_byte(&BattEEPROM[page][i], 0); + eeprom_write_byte(&BattEEPROM[page][i], 0); } } @@ -113,13 +113,16 @@ unsigned char Initialize(unsigned char inp) ADC_Init(); Time_Init(); + // Enable interrupts + sei(); + // Attempt to get ADC-readings (also gets RID-data) from both batteries. for (i = 0; i < 2; i++) { EnableBattery(i); ADC_Wait(); BatteryStatusRefresh(); } - + DisableBatteries(); BattActive = 0; // We have to start somewhere.. @@ -166,7 +169,7 @@ unsigned char BatteryControl(unsigned char inp) // Get ADC-readings, try to read EPROM, and start prequalification // of any uncharged battery. for (i = 0; i < 2; i++) { - if (eeprom_read_byte(&BattControl[i]) & BIT_BATTERY_ENABLED) { + if (eeprom_read_byte(&BattControl[i]) & BIT_BATTERY_ENABLED) { EnableBattery(i); ADC_Wait(); @@ -174,7 +177,7 @@ unsigned char BatteryControl(unsigned char inp) if (!BattData.Charged) { BatteryDataRefresh(); - return(ST_PREQUAL); + return(ST_PREQUAL); } } } @@ -246,7 +249,7 @@ void Doze(void) ADCS.Flag = FALSE; do { - } while (ADCS.Flag == FALSE); + } while (ADCS.Flag == FALSE); WDTCR = (1< check load and jumper J405 and J406. - if (abs(ADCS.IBAT) > 100) { + if (abs(adcs_IBAT_tmp) > 100) { PWM_Stop(); return(FALSE); } @@ -415,7 +430,7 @@ unsigned char JumperCheck(void) return(FALSE); } - // Wait for ADC conversions to complete + // Wait for ADC conversions to complete ADC_Wait(); } while (Time_Left(TIMER_GEN)); diff --git a/BaseTinyFirmware/GCC/time.c b/BaseTinyFirmware/GCC/time.c index ee738bd..61df5c0 100644 --- a/BaseTinyFirmware/GCC/time.c +++ b/BaseTinyFirmware/GCC/time.c @@ -38,7 +38,7 @@ //****************************************************************************** // Variables //****************************************************************************** -unsigned long timeval[TIMERS]; //!< Contains the values for each timer. +volatile unsigned long timeval[TIMERS]; //!< Contains the values for each timer. // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms //#pragma vector = TIM0_OVF_vect @@ -76,7 +76,15 @@ ISR(TIMER0_COMPA_vect) */ unsigned char Time_Left(unsigned char timer) { - if(timeval[timer] > 0) { + unsigned long tval; + unsigned char sreg_saved; + + sreg_saved = SREG; + cli(); + tval = timeval[timer]; + SREG = sreg_saved; + + if( tval > 0 ) { return(TRUE); } else { return(FALSE); @@ -99,9 +107,18 @@ void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, // timeval[i] += 4000 * (unsigned long)sec; // timeval[i] += 4 * (unsigned long)ms; - timeval[timer] = 60000 * (unsigned long)min; - timeval[timer] += 1000 * (unsigned long)sec; - timeval[timer] += 1 * (unsigned long)ms; + unsigned long tval; + unsigned char sreg_saved; + + + tval = 60000 * (unsigned long)min; + tval += 1000 * (unsigned long)sec; + tval += 1 * (unsigned long)ms; + + sreg_saved = SREG; + cli(); + timeval[timer] = tval; + SREG = sreg_saved; } @@ -133,10 +150,14 @@ void Time_Start(void) void Time_Init(void) { unsigned char i; + unsigned char sreg_saved; + sreg_saved = SREG; + cli(); for (i = 0; i<