* 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
//******************************************************************************\r
// ADC status struct.\r
//! \brief Holds sampled data and ADC-status\r
-ADC_Status_t ADCS;\r
+volatile ADC_Status_t ADCS;\r
\r
\r
/*! \brief Indicates maximum battery voltage.\r
\r
// Scale sample according to jumper setting, handle negative numbers.\r
if (ADC > 511) {\r
- ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE),\r
- (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+ ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE),\r
+ (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
} else if (ADC > 0) {\r
- ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS));\r
+ ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS));\r
} else {\r
ADCS.IBAT = 0;\r
}\r
ADMUX = (1<<REFS0) + ADCS.MUX;\r
\r
if (Signed) {\r
- ADCSRB |= (1<<BIN);\r
+ ADCSRB |= (1<<BIN);\r
} else {\r
- ADCSRB &= ~(1<<BIN);\r
+ ADCSRB &= ~(1<<BIN);\r
}\r
\r
// Re-enable the ADC unless a halt has been flagged and a conversion\r
// cycle has completed.\r
if (!((ADCS.Halt) && (ADCS.Flag))) {\r
- ADCSRA |= (1<<ADEN)|(1<<ADSC);\r
+ ADCSRA |= (1<<ADEN)|(1<<ADSC);\r
}\r
}\r
\r
do {\r
} while (ADCS.Flag == FALSE);\r
\r
- // Repeat, so we are sure the data beong to the same cycle.\r
+ // Repeat, so we are sure the data belongs to the same cycle.\r
ADCS.Flag = FALSE;\r
do {\r
} while (ADCS.Flag == FALSE);\r
void ADC_Init(void)\r
{\r
unsigned char i;\r
+ unsigned char sreg_saved;\r
\r
+ sreg_saved = SREG;\r
cli();\r
\r
ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
\r
// Get a complete cycle of data before returning.\r
ADC_Wait();\r
+\r
+ SREG = sreg_saved;\r
}\r
// Global variables\r
//******************************************************************************\r
extern unsigned char EEMEM VBAT_RANGE;\r
-extern ADC_Status_t ADCS;\r
+extern volatile ADC_Status_t ADCS;\r
\r
\r
//******************************************************************************\r
+2008-03-14 Martin Thomas <mthomas@rhrk.uni-kl.de>\r
+ * added "volatile" to structure object and array declarations for objects\r
+ sed in main-thread and ISRs. I'm not sure about the current state of\r
+ implicitly "guaranteed" accesses in (avr-)gcc but it should be a "better\r
+ safe than sorry" extension.\r
+ * enveloped access to timer-values in timer.c to make them "atomic" since\r
+ they are unsigned long\r
+ * "atomic" access to singned int and unsigned int members of ADCS\r
+ * it maybe better to have one place to globally enable interrupts ("sei").\r
+ Done in "initialize" now and not several times in the driver\r
+ init-functions.\r
+ * changed some space to tab as in the original code\r
+ * added header files to the AVR-Studio project workspace\r
+ * added -lm to the linker-options in the AVR Studio gcc-plugin, not\r
+ important for the basic application but might be good if someone uses the\r
+ code as a base for own developments\r
+\r
2008-03-12 Kevin Rosenberg <kevin@rosenberg.net>\r
* Initial GCC port performed and compiles without error\r
* Warning: Not yet tested on BC100 hardware!\r
// Variables\r
//******************************************************************************\r
//! SPI status struct\r
-SPI_Status_t SPI;\r
+volatile SPI_Status_t SPI;\r
\r
\r
//******************************************************************************\r
\r
\r
case ADR_BATTCTRL:\r
- SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count)));\r
+ SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count)));\r
break;\r
\r
case ADR_TIMERS:\r
*/\r
void SPI_Init(unsigned char spi_mode)\r
{\r
+ unsigned char sreg_saved;\r
+\r
+ sreg_saved = SREG;\r
cli();\r
\r
// Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
SPI.XferComplete = FALSE; // We haven't even started a transfer yet.\r
SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened.\r
\r
- sei();\r
+ SREG = sreg_saved;\r
}\r
\r
\r
-<AVRStudio><MANAGEMENT><ProjectName>avr463</ProjectName><Created>13-Mar-2008 01:54:24</Created><LastEdit>13-Mar-2008 03:07:11</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>13-Mar-2008 01:54:24</Created><Version>4</Version><Build>4, 14, 0, 580</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>avr463\avr463.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\kevin\pub\src\bc100\GCC\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>AVR Simulator</CURRENT_TARGET><CURRENT_PART>ATtiny861.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>ADC.c</SOURCEFILE><SOURCEFILE>battery.c</SOURCEFILE><SOURCEFILE>chargefunc.c</SOURCEFILE><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>menu.c</SOURCEFILE><SOURCEFILE>NIMHcharge.c</SOURCEFILE><SOURCEFILE>OWI.c</SOURCEFILE><SOURCEFILE>PWM.c</SOURCEFILE><SOURCEFILE>statefunc.c</SOURCEFILE><SOURCEFILE>time.c</SOURCEFILE><SOURCEFILE>USI.c</SOURCEFILE><OTHERFILE>avr463\avr463.lss</OTHERFILE><OTHERFILE>avr463\avr463.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>avr463</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>attiny861</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>avr463.elf</OUTPUTFILENAME><OUTPUTDIR>avr463\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>ADC.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>NIMHcharge.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>OWI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>PWM.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>USI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>battery.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>chargefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>main.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>menu.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>statefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>time.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMH </OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>avr463</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>C:\Users\kevin\pub\src\bc100\GCC\ADC.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\battery.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\chargefunc.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\main.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\menu.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\NIMHcharge.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\OWI.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\PWM.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\statefunc.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\time.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\USI.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files><File00000><FileId>00000</FileId><FileName>battery.c</FileName><Status>1</Status></File00000><File00001><FileId>00001</FileId><FileName>chargefunc.c</FileName><Status>1</Status></File00001><File00002><FileId>00002</FileId><FileName>nimhcharge.c</FileName><Status>1</Status></File00002><File00003><FileId>00003</FileId><FileName>statefunc.c</FileName><Status>1</Status></File00003></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>\r
+<AVRStudio><MANAGEMENT><ProjectName>avr463</ProjectName><Created>13-Mar-2008 01:54:24</Created><LastEdit>14-Mar-2008 21:11:26</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>13-Mar-2008 01:54:24</Created><Version>4</Version><Build>4, 14, 0, 580</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>avr463\avr463.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>D:\users\mthomas\develop\avr\bc100\bcc100_mth_20080314\BaseTinyFirmware\GCC\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>AVR Simulator</CURRENT_TARGET><CURRENT_PART>ATtiny861</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>ADC.c</SOURCEFILE><SOURCEFILE>battery.c</SOURCEFILE><SOURCEFILE>chargefunc.c</SOURCEFILE><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>menu.c</SOURCEFILE><SOURCEFILE>NIMHcharge.c</SOURCEFILE><SOURCEFILE>OWI.c</SOURCEFILE><SOURCEFILE>PWM.c</SOURCEFILE><SOURCEFILE>statefunc.c</SOURCEFILE><SOURCEFILE>time.c</SOURCEFILE><SOURCEFILE>USI.c</SOURCEFILE><HEADERFILE>ADC.h</HEADERFILE><HEADERFILE>battery.h</HEADERFILE><HEADERFILE>charge.h</HEADERFILE><HEADERFILE>chargefunc.h</HEADERFILE><HEADERFILE>delay_x_gcc.h</HEADERFILE><HEADERFILE>enums.h</HEADERFILE><HEADERFILE>main.h</HEADERFILE><HEADERFILE>menu.h</HEADERFILE><HEADERFILE>NIMHspecs.h</HEADERFILE><HEADERFILE>OWI.h</HEADERFILE><HEADERFILE>PWM.h</HEADERFILE><HEADERFILE>statefunc.h</HEADERFILE><HEADERFILE>structs.h</HEADERFILE><HEADERFILE>time.h</HEADERFILE><HEADERFILE>USI.h</HEADERFILE><OTHERFILE>avr463\avr463.lss</OTHERFILE><OTHERFILE>avr463\avr463.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>avr463</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>attiny861</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>avr463.elf</OUTPUTFILENAME><OUTPUTDIR>avr463\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>ADC.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>NIMHcharge.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>OWI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>PWM.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>USI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>battery.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>chargefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>main.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>menu.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>statefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>time.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS><LIB>libm.a</LIB></LIBS><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMH</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>avr463</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="1" orderaddress="1" ordergroup="1"/></IOView><Files><File00000><FileId>00000</FileId><FileName>structs.h</FileName><Status>1</Status></File00000></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>\r
-<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATTINY861"/><Files/></AVRWorkspace>\r
+<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATTINY861"/><Files><File00000 Name="D:\users\mthomas\develop\avr\bc100\bcc100_mth_20080314\BaseTinyFirmware\GCC\structs.h" Position="343 217 1015 700" LineCol="93 53"/></Files></AVRWorkspace>\r
\r
#include <avr/io.h>\r
#include <avr/eeprom.h>\r
+#include <avr/interrupt.h>\r
\r
#include "structs.h"\r
#include "enums.h"\r
{\r
// Assume the worst..\r
unsigned char success = FALSE;\r
+ unsigned char sreg_saved;\r
+ unsigned int adcs_VBAT_tmp;\r
+ signed int adcs_avgIBAT_tmp;\r
\r
BattData.Present = FALSE;\r
BattData.Charged = FALSE;\r
NTCLookUp();\r
BattData.HasRID = RIDLookUp();\r
\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_VBAT_tmp = ADCS.VBAT;\r
+ adcs_avgIBAT_tmp = ADCS.avgIBAT;\r
+ SREG = sreg_saved;\r
+\r
// Is the battery voltage above minimum safe cell voltage?\r
- if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+ if (adcs_VBAT_tmp >= BAT_VOLTAGE_MIN) {\r
BattData.Low = FALSE;\r
}\r
\r
// Is the battery charged?\r
- if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+ if (adcs_VBAT_tmp >= BAT_VOLTAGE_LOW) {\r
BattData.Charged = TRUE;\r
}\r
\r
* not 100% proof.\r
*/\r
if (((OCR1B == 0) && (!BattData.Low)) ||\r
- ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+ ((OCR1B != 0) && (adcs_avgIBAT_tmp > 0))) {\r
BattData.Present = TRUE;\r
success = TRUE;\r
} else {\r
// Erase local EEPROM page if there were any errors during transfer.\r
if (!success) {\r
for (i=0; i<32; i++) {\r
- eeprom_write_byte(&BattEEPROM[page][i], 0);\r
+ eeprom_write_byte(&BattEEPROM[page][i], 0);\r
}\r
}\r
}\r
unsigned char RIDLookUp (void)\r
{\r
unsigned char i, found = FALSE;\r
+ unsigned int adcs_rawRID_tmp;\r
+ unsigned char sreg_saved;\r
\r
// Lookup in the RID-table. If measured RID is within the limits\r
// of an entry, those data are used, and TRUE is returned.\r
for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
- if (ADCS.rawRID >= RID[i].Low) {\r
- if (ADCS.rawRID <= RID[i].High) {\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_rawRID_tmp = ADCS.rawRID;\r
+ SREG = sreg_saved;\r
+ if (adcs_rawRID_tmp >= RID[i].Low) {\r
+ if (adcs_rawRID_tmp <= RID[i].High) {\r
BattData.Capacity = RID[i].Capacity;\r
BattData.MaxCurrent = RID[i].Icharge;\r
BattData.MaxTime = RID[i].tCutOff;\r
{\r
unsigned char i;\r
unsigned char found = FALSE;\r
+ unsigned char adcs_rawNTC_tmp;\r
+ unsigned char sreg_saved;\r
\r
// Lookup in the NTC-table. Use the first entry which is equal or below\r
// sampled NTC. Calculate temperature by using the index number, and the\r
// difference between the measured NTC value and the one in the entry.\r
for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) {\r
- if (ADCS.rawNTC >= NTC[i].ADCV) {\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_rawNTC_tmp = ADCS.rawNTC;\r
+ SREG = sreg_saved;\r
+ if (adcs_rawNTC_tmp >= NTC[i].ADCV) {\r
BattData.Temperature = (i<<2) ;\r
BattData.ADCSteps = NTC[i].ADCsteps; \r
- BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADCV)<<1) / BattData.ADCSteps;\r
+ BattData.Temperature -= ((adcs_rawNTC_tmp - NTC[i].ADCV)<<1) / BattData.ADCSteps;\r
\r
found = TRUE; // Could be done with a break, but that violates MISRA.\r
}\r
******************************************************************************/\r
\r
#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
\r
#include "enums.h"\r
#include "structs.h"\r
{\r
unsigned char error = FALSE,\r
wasStopped = FALSE;\r
+ unsigned char sreg_saved;\r
+ signed int adcs_avgIBAT_tmp;\r
\r
do {\r
- // Wait for ADC conversions to complete.\r
+ // Wait for ADC conversions to complete.\r
ADC_Wait();\r
\r
// If Master has flagged for a charge inhibit, pause charging.\r
// Timer variables are not reset by this.\r
Time_Start();\r
}\r
- \r
+\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_avgIBAT_tmp = ADCS.avgIBAT;\r
+ SREG = sreg_saved;\r
+\r
// Adjust the charge current to within ChargeParameters.Current\r
// +/- BAT_CURRENT_HYST.\r
- if ((ADCS.avgIBAT < 0) ||\r
- (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+ if ((adcs_avgIBAT_tmp < 0) ||\r
+ (adcs_avgIBAT_tmp < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
\r
if(!PWM_IncrementDutyCycle()) {\r
#ifdef ABORT_IF_PWM_MAX\r
error = TRUE;\r
#endif\r
}\r
- } else if ((ADCS.avgIBAT >= 0) &&\r
- (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+ } else if ((adcs_avgIBAT_tmp >= 0) &&\r
+ (adcs_avgIBAT_tmp > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
\r
if(!PWM_DecrementDutyCycle()) {\r
#ifdef ABORT_IF_PWM_MIN\r
{\r
unsigned char error = FALSE,\r
wasStopped = FALSE;\r
+ unsigned char sreg_saved;\r
+ unsigned int adcs_VBAT_tmp;\r
\r
do{\r
\r
Time_Start();\r
}\r
\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_VBAT_tmp = ADCS.VBAT;\r
+ SREG = sreg_saved;\r
+\r
// Adjust the charge voltage to within ChargeParameters.Voltage\r
// +/- BAT_VOLTAGE_HYST.\r
- if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+ if (adcs_VBAT_tmp < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
\r
if(!PWM_IncrementDutyCycle()) {\r
#ifdef ABORT_IF_PWM_MAX\r
error = TRUE;\r
#endif\r
}\r
- } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+ } else if (adcs_VBAT_tmp > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
\r
if(!PWM_DecrementDutyCycle()) {\r
#ifdef ABORT_IF_PWM_MIN\r
unsigned char HaltNow(void)\r
{\r
unsigned char i, halt = FALSE;\r
+ unsigned int adcs_rawNTC_tmp, adcs_VBAT_tmp;\r
+ signed int adcs_avgIBAT_tmp;\r
+ unsigned char sreg_saved;\r
\r
// Wait for a full ADC-cycle to finish.\r
ADC_Wait();\r
// (Gets overridden if either mains is failing, or the battery changes.)\r
for (i = 0x01; i != 0; i <<= 1) {\r
if (HaltParameters.HaltFlags & i) {\r
+ \r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_VBAT_tmp = ADCS.VBAT;\r
+ adcs_avgIBAT_tmp = ADCS.avgIBAT;\r
+ SREG = sreg_saved;\r
+ \r
switch (i) {\r
// Is VBAT less than the recorded maximum?\r
case HALT_VOLTAGE_DROP:\r
-\r
// Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
- if (ADCS.VBAT > HaltParameters.VBATMax) {\r
- HaltParameters.VBATMax = ADCS.VBAT;\r
- } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+ if (adcs_VBAT_tmp > HaltParameters.VBATMax) {\r
+ HaltParameters.VBATMax = adcs_VBAT_tmp;\r
+ } else if((HaltParameters.VBATMax - adcs_VBAT_tmp) >= \r
HaltParameters.VoltageDrop) {\r
halt = TRUE;\r
}\r
// Has VBAT reached the maximum limit?\r
case HALT_VOLTAGE_MAX: \r
\r
- if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+ if (adcs_VBAT_tmp >= HaltParameters.VoltageMax) {\r
halt = TRUE;\r
}\r
break;\r
// Has IBAT reached the minimum limit?\r
case HALT_CURRENT_MIN:\r
\r
- if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+ if (adcs_avgIBAT_tmp <= HaltParameters.CurrentMin) {\r
halt = TRUE;\r
}\r
break;\r
\r
// Is the temperature rising too fast?\r
case HALT_TEMPERATURE_RISE:\r
-\r
+ \r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_rawNTC_tmp = ADCS.rawNTC;\r
+ SREG = sreg_saved;\r
// If rawNTC has increased, the temperature has dropped.\r
// We can store this value for now, and start the timer.\r
// Otherwise, check if NTC has changed too fast.\r
- if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
- HaltParameters.LastNTC = ADCS.rawNTC;\r
+ if (adcs_rawNTC_tmp > HaltParameters.LastNTC) {\r
+ HaltParameters.LastNTC = adcs_rawNTC_tmp;\r
Time_Set(TIMER_TEMP,0,30,0);\r
\r
// Is the increase in temperature greater than the set threshold?\r
- } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+ } else if ((HaltParameters.LastNTC - adcs_rawNTC_tmp) >=\r
(BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
\r
// If this happened within a timeframe of 30 seconds, the \r
if (Time_Left(TIMER_TEMP)) {\r
halt = TRUE;\r
} else {\r
- HaltParameters.LastNTC = ADCS.rawNTC;\r
+ HaltParameters.LastNTC = adcs_rawNTC_tmp;\r
Time_Set(TIMER_TEMP,0,30,0);\r
}\r
}\r
if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
PWM_Stop();\r
Battery_t tmp = eeprom_read_byte(&BattControl[BattActive]);\r
- tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE;\r
- eeprom_write_byte(&BattControl[BattActive], tmp);\r
+ tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE;\r
+ eeprom_write_byte(&BattControl[BattActive], tmp);\r
BattData.Exhausted = TRUE;\r
SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
ChargeParameters.NextState = ST_ERROR;\r
\r
// Look for function associated with current state, get its address.\r
for (i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) {\r
- if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
- pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
+ if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
+ pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
}\r
}\r
\r
if (nextstate != CurrentState) {\r
CurrentState = nextstate;\r
for ( i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) {\r
- if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
- pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
+ if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
+ pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
}\r
}\r
}\r
// Clear on-chip EEPROM.\r
for (page = 0; page < 4; page++) {\r
for (i = 0; i < 32; i++) {\r
- eeprom_write_byte(&BattEEPROM[page][i], 0);\r
+ eeprom_write_byte(&BattEEPROM[page][i], 0);\r
}\r
}\r
\r
ADC_Init();\r
Time_Init();\r
\r
+ // Enable interrupts\r
+ sei();\r
+\r
// Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
for (i = 0; i < 2; i++) {\r
EnableBattery(i);\r
ADC_Wait();\r
BatteryStatusRefresh();\r
}\r
- \r
+\r
DisableBatteries();\r
\r
BattActive = 0; // We have to start somewhere..\r
// Get ADC-readings, try to read EPROM, and start prequalification\r
// of any uncharged battery.\r
for (i = 0; i < 2; i++) {\r
- if (eeprom_read_byte(&BattControl[i]) & BIT_BATTERY_ENABLED) { \r
+ if (eeprom_read_byte(&BattControl[i]) & BIT_BATTERY_ENABLED) {\r
EnableBattery(i);\r
ADC_Wait();\r
\r
if (!BattData.Charged) {\r
BatteryDataRefresh();\r
\r
- return(ST_PREQUAL); \r
+ return(ST_PREQUAL);\r
}\r
}\r
}\r
ADCS.Flag = FALSE;\r
\r
do {\r
- } while (ADCS.Flag == FALSE); \r
+ } while (ADCS.Flag == FALSE);\r
\r
WDTCR = (1<<WDP3)|(1<<WDP0); // 8.0 seconds at 5 volts VCC.\r
WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE); // Clear flag and enable watchdog.\r
\r
case ERR_NO_BATTERIES_ENABLED:\r
// Clear if any battery gets enabled.\r
- if ((eeprom_read_byte(&BattControl[0]) & BIT_BATTERY_ENABLED) || (eeprom_read_byte(&BattControl[1]) & BIT_BATTERY_ENABLED)) {\r
+ if ((eeprom_read_byte(&BattControl[0]) & BIT_BATTERY_ENABLED) || (eeprom_read_byte(&BattControl[1]) & BIT_BATTERY_ENABLED)) {\r
ErrorFlags &= ~i;\r
}\r
break;\r
*/\r
unsigned char JumperCheck(void)\r
{\r
+ unsigned char sreg_saved;\r
+ unsigned int adcs_rawVBAT_tmp, adcs_VIN_tmp, adcs_VBAT_tmp;\r
+ signed int adcs_IBAT_tmp;\r
+\r
DisableBatteries(); // Disconnect, or loads may be destroyed!\r
\r
PWM_Start(); // Start PWM (controls the buck charger).\r
do {\r
// If the PWM output voltage saturates the ADC, stop PWM output and\r
// report a failure.\r
- if (ADCS.rawVBAT == 1023) {\r
+ sreg_saved = SREG;\r
+ cli();\r
+ adcs_rawVBAT_tmp = ADCS.rawVBAT;\r
+ adcs_VBAT_tmp = ADCS.VBAT;\r
+ adcs_VIN_tmp = ADCS.VIN;\r
+ adcs_IBAT_tmp = ADCS.IBAT;\r
+ SREG = sreg_saved;\r
+\r
+ if (adcs_rawVBAT_tmp == 1023) {\r
PWM_Stop();\r
return(FALSE);\r
}\r
\r
// If the absolute difference between measured (VIN - VBAT) and the\r
// typical value are below our set maximum, everything is OK.\r
- if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+ if (abs((signed int)(adcs_VIN_tmp - VIN_VBAT_DIFF_TYP - adcs_VBAT_tmp)) <\r
VIN_VBAT_DIFF_MAX ) {\r
\r
PWM_Stop();\r
}\r
\r
// Charge current is too high -> check load and jumper J405 and J406.\r
- if (abs(ADCS.IBAT) > 100) {\r
+ if (abs(adcs_IBAT_tmp) > 100) {\r
PWM_Stop();\r
return(FALSE);\r
}\r
return(FALSE);\r
}\r
\r
- // Wait for ADC conversions to complete\r
+ // Wait for ADC conversions to complete\r
ADC_Wait();\r
} while (Time_Left(TIMER_GEN));\r
\r
//******************************************************************************\r
// Variables\r
//******************************************************************************\r
-unsigned long timeval[TIMERS]; //!< Contains the values for each timer.\r
+volatile unsigned long timeval[TIMERS]; //!< Contains the values for each timer.\r
\r
// timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
//#pragma vector = TIM0_OVF_vect\r
*/ \r
unsigned char Time_Left(unsigned char timer)\r
{\r
- if(timeval[timer] > 0) {\r
+ unsigned long tval;\r
+ unsigned char sreg_saved;\r
+\r
+ sreg_saved = SREG;\r
+ cli();\r
+ tval = timeval[timer];\r
+ SREG = sreg_saved;\r
+\r
+ if( tval > 0 ) {\r
return(TRUE);\r
} else {\r
return(FALSE);\r
// timeval[i] += 4000 * (unsigned long)sec;\r
// timeval[i] += 4 * (unsigned long)ms;\r
\r
- timeval[timer] = 60000 * (unsigned long)min;\r
- timeval[timer] += 1000 * (unsigned long)sec;\r
- timeval[timer] += 1 * (unsigned long)ms;\r
+ unsigned long tval;\r
+ unsigned char sreg_saved;\r
+ \r
+\r
+ tval = 60000 * (unsigned long)min;\r
+ tval += 1000 * (unsigned long)sec;\r
+ tval += 1 * (unsigned long)ms;\r
+\r
+ sreg_saved = SREG;\r
+ cli();\r
+ timeval[timer] = tval;\r
+ SREG = sreg_saved;\r
}\r
\r
\r
void Time_Init(void)\r
{\r
unsigned char i;\r
+ unsigned char sreg_saved;\r
\r
+ sreg_saved = SREG;\r
+ cli();\r
for (i = 0; i<<TIMERS; i++) {\r
timeval[i] = 0;\r
}\r
+ SREG = sreg_saved;\r
\r
// OCR0A = 0; // Doesn't matter, will run in normal mode.\r
\r
// TIMSK |= (1<<TOIE0); // Overflow interrupt enabled.\r
\r
TIMSK |= (1<<OCIE0A); // Timer 0, Compare match A interrupt enabled.\r
-\r
- // Enable interrupts, just in case they weren't already.\r
- sei(); \r
}\r
//******************************************************************************\r
// Globals\r
//******************************************************************************\r
-extern unsigned long timeval[]; // Needed for SPI transfer.\r
+extern volatile unsigned long timeval[]; // Needed for SPI transfer.\r
\r
\r
//******************************************************************************\r