1 ###############################################################################
\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 #
\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved. #
\r
6 # Source file = C:\home\kevin\pub\src\bc100_cal\IAR\main.c #
\r
7 # Command line = C:\home\kevin\pub\src\bc100_cal\IAR\main.c #
\r
8 # --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #
\r
9 # \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #
\r
10 # g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #
\r
11 # st\ --initializers_in_flash -z2 --no_cse --no_inline #
\r
12 # --no_code_motion --no_cross_call --no_clustering #
\r
13 # --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e #
\r
14 # --require_prototypes -I "C:\Program Files\IAR #
\r
15 # Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program #
\r
16 # Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" #
\r
17 # --eeprom_size 512 #
\r
18 # List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\main.lst #
\r
19 # Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90 #
\r
22 ###############################################################################
\r
24 C:\home\kevin\pub\src\bc100_cal\IAR\main.c
\r
25 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
26 2 /*! \file *********************************************************************
\r
29 5 * Main program file
\r
31 7 * Contains the main program, which is a basic state machine.
\r
33 9 * \par Application note:
\r
34 10 * AVR458: Charging Li-Ion Batteries with BC100 \n
\r
35 11 * AVR463: Charging NiMH Batteries with BC100
\r
37 13 * \par Documentation
\r
38 14 * For comprehensive code documentation, supported compilers, compiler
\r
39 15 * settings and supported devices see readme.html
\r
42 18 * Atmel Corporation: http://www.atmel.com \n
\r
43 19 * Support email: avr@atmel.com
\r
47 23 * $Revision: 2302 $
\r
49 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $
\r
50 26 * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n
\r
51 27 ******************************************************************************/
\r
53 29 /*! \page License
\r
54 30 * Copyright (c) 2007, Atmel Corporation All rights reserved.
\r
56 32 * Redistribution and use in source and binary forms, with or without
\r
57 33 * modification, are permitted provided that the following conditions are met:
\r
59 35 * 1. Redistributions of source code must retain the above copyright notice,
\r
60 36 * this list of conditions and the following disclaimer.
\r
62 38 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
63 39 * this list of conditions and the following disclaimer in the documentation
\r
64 40 * and/or other materials provided with the distribution.
\r
66 42 * 3. The name of ATMEL may not be used to endorse or promote products derived
\r
67 43 * from this software without specific prior written permission.
\r
69 45 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
\r
70 46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
71 47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
\r
72 48 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
\r
73 49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
\r
74 50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
75 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
\r
76 52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
77 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
\r
78 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
81 57 #include <ioavr.h>
\r
82 58 #include <inavr.h>
\r
83 59 #include <stdlib.h>
\r
85 61 #include "structs.h"
\r
87 63 #include "main.h"
\r
89 65 #include "statefunc.h"
\r
90 66 #include "battery.h"
\r
91 67 #include "menu.h"
\r
94 70 #include "time.h"
\r
99 75 //******************************************************************************
\r
101 77 //******************************************************************************
\r
103 \ In segment NEAR_Z, align 1, keep-with-next
\r
104 \ 00000000 REQUIRE `?<Segment init: NEAR_Z>`
\r
105 78 unsigned char CurrentState; //!< \brief Global that indicates current state
\r
109 80 //!< Updated by main().
\r
110 81 //!< \note See menu.h for definition of states.
\r
113 84 //******************************************************************************
\r
115 86 //******************************************************************************
\r
116 87 /*! \brief Main program
\r
118 89 * The main function goes into an infinite loop, keeping track of the current
\r
119 90 * state and the next one. If the next state is different from the current, it
\r
120 91 * looks up the address to the next state function, in \ref menu_state[], and
\r
121 92 * updates \ref CurrentState. The state function is then called and will
\r
122 93 * eventually return a new state, and so the loop reiterates.
\r
124 95 * \todo The variable inp is passed to all state functions, but is not used
\r
125 96 * for anything yet. Remove?
\r
128 \ In segment CODE, align 2, keep-with-next
\r
129 98 int main( void )
\r
132 \ 00000000 .... RCALL ?PROLOGUE7_L09
\r
133 \ 00000002 REQUIRE ?Register_R4_is_cg_reg
\r
134 \ 00000002 REQUIRE ?Register_R5_is_cg_reg
\r
135 \ 00000002 REQUIRE ?Register_R6_is_cg_reg
\r
136 100 unsigned char nextstate, inp, i;
\r
137 101 unsigned char (*pStateFunc)(unsigned char); // Function pointer.
\r
139 103 // Initialize local state variables.
\r
141 \ 00000002 2466 CLR R6
\r
142 105 CurrentState = nextstate = ST_INIT;
\r
143 \ 00000004 E00A LDI R16, 10
\r
144 \ 00000006 2F90 MOV R25, R16
\r
145 \ 00000008 9300.... STS CurrentState, R16
\r
146 106 pStateFunc = NULL;
\r
147 \ 0000000C E000 LDI R16, 0
\r
148 \ 0000000E E010 LDI R17, 0
\r
149 \ 00000010 0128 MOVW R5:R4, R17:R16
\r
151 108 // Look for function associated with current state, get its address.
\r
152 109 for (i = 0; menu_state[i].state != 0; i++) {
\r
153 \ 00000012 E080 LDI R24, 0
\r
155 \ 00000014 2F48 MOV R20, R24
\r
156 \ 00000016 E050 LDI R21, 0
\r
157 \ 00000018 E003 LDI R16, 3
\r
158 \ 0000001A E010 LDI R17, 0
\r
159 \ 0000001C .... RCALL ?S_MUL_L02
\r
160 \ 0000001E .... LDI R30, LOW(menu_state)
\r
161 \ 00000020 .... LDI R31, (menu_state) >> 8
\r
162 \ 00000022 0FE0 ADD R30, R16
\r
163 \ 00000024 1FF1 ADC R31, R17
\r
164 \ 00000026 9104 LPM R16, Z
\r
165 \ 00000028 2300 TST R16
\r
166 \ 0000002A F0F1 BREQ ??main_1
\r
167 110 if (menu_state[i].state == CurrentState) {
\r
168 \ 0000002C 2F48 MOV R20, R24
\r
169 \ 0000002E E050 LDI R21, 0
\r
170 \ 00000030 E003 LDI R16, 3
\r
171 \ 00000032 E010 LDI R17, 0
\r
172 \ 00000034 .... RCALL ?S_MUL_L02
\r
173 \ 00000036 .... LDI R30, LOW(menu_state)
\r
174 \ 00000038 .... LDI R31, (menu_state) >> 8
\r
175 \ 0000003A 0FE0 ADD R30, R16
\r
176 \ 0000003C 1FF1 ADC R31, R17
\r
177 \ 0000003E 9104 LPM R16, Z
\r
178 \ 00000040 9110.... LDS R17, CurrentState
\r
179 \ 00000044 1701 CP R16, R17
\r
180 \ 00000046 F471 BRNE ??main_2
\r
181 111 pStateFunc = menu_state[i].pFunc;
\r
182 \ 00000048 .... LDI R26, LOW((menu_state + 1))
\r
183 \ 0000004A .... LDI R27, HIGH((menu_state + 1))
\r
184 \ 0000004C 2F48 MOV R20, R24
\r
185 \ 0000004E E050 LDI R21, 0
\r
186 \ 00000050 E003 LDI R16, 3
\r
187 \ 00000052 E010 LDI R17, 0
\r
188 \ 00000054 .... RCALL ?S_MUL_L02
\r
189 \ 00000056 0FA0 ADD R26, R16
\r
190 \ 00000058 1FB1 ADC R27, R17
\r
191 \ 0000005A 01FD MOVW R31:R30, R27:R26
\r
192 \ 0000005C 9105 LPM R16, Z+
\r
193 \ 0000005E 9114 LPM R17, Z
\r
194 \ 00000060 9731 SBIW R31:R30, 1
\r
195 \ 00000062 0128 MOVW R5:R4, R17:R16
\r
199 \ 00000064 9583 INC R24
\r
200 \ 00000066 CFD6 RJMP ??main_0
\r
203 116 // Run function associated with current state, get next state in return.
\r
204 117 if (pStateFunc != NULL){
\r
206 \ 00000068 E000 LDI R16, 0
\r
207 \ 0000006A E010 LDI R17, 0
\r
208 \ 0000006C 1640 CP R4, R16
\r
209 \ 0000006E 0651 CPC R5, R17
\r
210 \ 00000070 F021 BREQ ??main_3
\r
211 118 nextstate = pStateFunc(inp);
\r
212 \ 00000072 2D06 MOV R16, R6
\r
213 \ 00000074 01F2 MOVW R31:R30, R5:R4
\r
214 \ 00000076 9509 ICALL
\r
215 \ 00000078 2F90 MOV R25, R16
\r
218 121 // Look up function for next state, if it differs from the current.
\r
219 122 if (nextstate != CurrentState) {
\r
221 \ 0000007A 9100.... LDS R16, CurrentState
\r
222 \ 0000007E 1790 CP R25, R16
\r
223 \ 00000080 F399 BREQ ??main_1
\r
224 123 CurrentState = nextstate;
\r
225 \ 00000082 9390.... STS CurrentState, R25
\r
226 124 for ( i = 0; menu_state[i].state != 0; i++) {
\r
227 \ 00000086 E080 LDI R24, 0
\r
229 \ 00000088 2F48 MOV R20, R24
\r
230 \ 0000008A E050 LDI R21, 0
\r
231 \ 0000008C E003 LDI R16, 3
\r
232 \ 0000008E E010 LDI R17, 0
\r
233 \ 00000090 .... RCALL ?S_MUL_L02
\r
234 \ 00000092 .... LDI R30, LOW(menu_state)
\r
235 \ 00000094 .... LDI R31, (menu_state) >> 8
\r
236 \ 00000096 0FE0 ADD R30, R16
\r
237 \ 00000098 1FF1 ADC R31, R17
\r
238 \ 0000009A 9104 LPM R16, Z
\r
239 \ 0000009C 2300 TST R16
\r
240 \ 0000009E F321 BREQ ??main_1
\r
241 125 if (menu_state[i].state == CurrentState) {
\r
242 \ 000000A0 2F48 MOV R20, R24
\r
243 \ 000000A2 E050 LDI R21, 0
\r
244 \ 000000A4 E003 LDI R16, 3
\r
245 \ 000000A6 E010 LDI R17, 0
\r
246 \ 000000A8 .... RCALL ?S_MUL_L02
\r
247 \ 000000AA .... LDI R30, LOW(menu_state)
\r
248 \ 000000AC .... LDI R31, (menu_state) >> 8
\r
249 \ 000000AE 0FE0 ADD R30, R16
\r
250 \ 000000B0 1FF1 ADC R31, R17
\r
251 \ 000000B2 9104 LPM R16, Z
\r
252 \ 000000B4 9110.... LDS R17, CurrentState
\r
253 \ 000000B8 1701 CP R16, R17
\r
254 \ 000000BA F471 BRNE ??main_5
\r
255 126 pStateFunc = menu_state[i].pFunc;
\r
256 \ 000000BC .... LDI R26, LOW((menu_state + 1))
\r
257 \ 000000BE .... LDI R27, HIGH((menu_state + 1))
\r
258 \ 000000C0 2F48 MOV R20, R24
\r
259 \ 000000C2 E050 LDI R21, 0
\r
260 \ 000000C4 E003 LDI R16, 3
\r
261 \ 000000C6 E010 LDI R17, 0
\r
262 \ 000000C8 .... RCALL ?S_MUL_L02
\r
263 \ 000000CA 0FA0 ADD R26, R16
\r
264 \ 000000CC 1FB1 ADC R27, R17
\r
265 \ 000000CE 01FD MOVW R31:R30, R27:R26
\r
266 \ 000000D0 9105 LPM R16, Z+
\r
267 \ 000000D2 9114 LPM R17, Z
\r
268 \ 000000D4 9731 SBIW R31:R30, 1
\r
269 \ 000000D6 0128 MOVW R5:R4, R17:R16
\r
273 \ 000000D8 9583 INC R24
\r
274 \ 000000DA CFD6 RJMP ??main_4
\r
280 134 /* Doxygen documentation mainpage ********************************************/
\r
282 136 * \section intro Introduction
\r
283 137 * This documents the software for application note AVR458. This is a charger
\r
284 138 * for Li-Ion batteries, based on ATAVRBC100.
\r
286 140 * \section compinfo Compilation Info
\r
287 141 * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC
\r
288 142 * the source have to be modified.\n
\r
290 144 * To make project on IAR EWAVR:\n
\r
291 145 * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,
\r
292 146 * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,
\r
293 147 * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate
\r
294 148 * battery data if needed.\n
\r
296 150 * Use device --cpu=tiny861, enable bit definitions in I/O include files,
\r
297 151 * optimization low for debug target and high for release, output format: ubrof8
\r
298 152 * for Debug and intel_extended for Release. \n
\r
300 154 * \section deviceinfo Device Info
\r
301 155 * This application is based on the ATtiny 861, but it is possible to migrate
\r
302 156 * the design to other AVR microcontrollers, such as pin-compatible devices
\r
303 157 * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be
\r
304 158 * used, but with reduced functionality.
\r
306 160 * Required fuse bit settings:
\r
308 162 * FUSE BIT | SETTING
\r
309 163 * ----------+--------------------
\r
310 164 * CKDIV8 | 1 (unprogrammed)
\r
311 165 * CKSEL3..0 | 0010 (internal osc)
\r
315 169 * \section todo To Do-list
\r
317 171 * - Finalize master-slave communication protocol
\r
318 172 * - Implement discharge mode
\r
320 174 * \section contactinfo Contact Info
\r
321 175 * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n
\r
322 176 * For application notes visit
\r
323 177 * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n
\r
324 178 * Support mail: avr@atmel.com
\r
328 182 /*! \page misra MISRA C rule violations
\r
331 185 * <i>"All code shall conform to ISO 9899 standard C, with no extensions
\r
332 186 * permitted."</i>
\r
334 188 * Extensions are necessary because ISO C has no way of specifying that a
\r
335 189 * function should be an interrupt service routine, or that we would like data
\r
336 190 * members to be stored in f.ex. EEPROM.
\r
340 194 * <i>"Bitwise operations shall not be performed on signed integer types."</i>
\r
342 196 * The compiler assumes all the 1's we shift around to make bitmasks are signed
\r
343 197 * integers. Specifying them all to be (unsigned int), either directly or via a
\r
344 198 * definition, would fix the rule violations, but also reduce code readability.
\r
348 202 * <i>"Type casting from any type to or from pointers shall not be used."</i>
\r
350 204 * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..
\r
354 208 * <i>"In the definition of a function-like macro the whole definition, and each
\r
355 209 * instance of a parameter, shall be enclosed in parentheses."</i>
\r
357 211 * It is difficult to use parentheses with void function-like macros.
\r
360 Maximum stack usage in bytes:
\r
362 Function CSTACK RSTACK
\r
363 -------- ------ ------
\r
365 -> Indirect call 7 2
\r
368 Segment part sizes:
\r
370 Function/Label Bytes
\r
371 -------------- -----
\r
377 220 bytes in segment CODE
\r
378 6 bytes in segment INITTAB
\r
379 1 byte in segment NEAR_Z
\r
381 220 bytes of CODE memory (+ 6 bytes shared)
\r
382 1 byte of DATA memory
\r