root / arduino-1.0 / hardware / arduino / bootloaders / stk500v2 / stk500boot.c @ 58d82c77
History | View | Annotate | Download (47.2 KB)
1 | 58d82c77 | Tom Mullins | /*****************************************************************************
|
---|---|---|---|
2 | Title: STK500v2 compatible bootloader
|
||
3 | Modified for Wiring board ATMega128-16MHz
|
||
4 | Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||
5 | File: $Id: stk500boot.c,v 1.11 2006/06/25 12:39:17 peter Exp $
|
||
6 | Compiler: avr-gcc 3.4.5 or 4.1 / avr-libc 1.4.3
|
||
7 | Hardware: All AVRs with bootloader support, tested with ATmega8
|
||
8 | License: GNU General Public License
|
||
9 | |||
10 | Modified: Worapoht Kornkaewwattanakul <dev@avride.com> http://www.avride.com
|
||
11 | Date: 17 October 2007
|
||
12 | Update: 1st, 29 Dec 2007 : Enable CMD_SPI_MULTI but ignore unused command by return 0x00 byte response..
|
||
13 | Compiler: WINAVR20060421
|
||
14 | Description: add timeout feature like previous Wiring bootloader
|
||
15 | |||
16 | DESCRIPTION:
|
||
17 | This program allows an AVR with bootloader capabilities to
|
||
18 | read/write its own Flash/EEprom. To enter Programming mode
|
||
19 | an input pin is checked. If this pin is pulled low, programming mode
|
||
20 | is entered. If not, normal execution is done from $0000
|
||
21 | "reset" vector in Application area.
|
||
22 | Size fits into a 1024 word bootloader section
|
||
23 | when compiled with avr-gcc 4.1
|
||
24 | (direct replace on Wiring Board without fuse setting changed)
|
||
25 | |||
26 | USAGE:
|
||
27 | - Set AVR MCU type and clock-frequency (F_CPU) in the Makefile.
|
||
28 | - Set baud rate below (AVRISP only works with 115200 bps)
|
||
29 | - compile/link the bootloader with the supplied Makefile
|
||
30 | - program the "Boot Flash section size" (BOOTSZ fuses),
|
||
31 | for boot-size 1024 words: program BOOTSZ01
|
||
32 | - enable the BOOT Reset Vector (program BOOTRST)
|
||
33 | - Upload the hex file to the AVR using any ISP programmer
|
||
34 | - Program Boot Lock Mode 3 (program BootLock 11 and BootLock 12 lock bits) // (leave them)
|
||
35 | - Reset your AVR while keeping PROG_PIN pulled low // (for enter bootloader by switch)
|
||
36 | - Start AVRISP Programmer (AVRStudio/Tools/Program AVR)
|
||
37 | - AVRISP will detect the bootloader
|
||
38 | - Program your application FLASH file and optional EEPROM file using AVRISP
|
||
39 | |||
40 | Note:
|
||
41 | Erasing the device without flashing, through AVRISP GUI button "Erase Device"
|
||
42 | is not implemented, due to AVRStudio limitations.
|
||
43 | Flash is always erased before programming.
|
||
44 | |||
45 | AVRdude:
|
||
46 | Please uncomment #define REMOVE_CMD_SPI_MULTI when using AVRdude.
|
||
47 | Comment #define REMOVE_PROGRAM_LOCK_BIT_SUPPORT to reduce code size
|
||
48 | Read Fuse Bits and Read/Write Lock Bits is not supported
|
||
49 | |||
50 | NOTES:
|
||
51 | Based on Atmel Application Note AVR109 - Self-programming
|
||
52 | Based on Atmel Application Note AVR068 - STK500v2 Protocol
|
||
53 | |||
54 | LICENSE:
|
||
55 | Copyright (C) 2006 Peter Fleury
|
||
56 | |||
57 | This program is free software; you can redistribute it and/or modify
|
||
58 | it under the terms of the GNU General Public License as published by
|
||
59 | the Free Software Foundation; either version 2 of the License, or
|
||
60 | any later version.
|
||
61 | |||
62 | This program is distributed in the hope that it will be useful,
|
||
63 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
64 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
65 | GNU General Public License for more details.
|
||
66 | |||
67 | *****************************************************************************/
|
||
68 | |||
69 | //************************************************************************
|
||
70 | //* Edit History
|
||
71 | //************************************************************************
|
||
72 | //* Jul 7, 2010 <MLS> = Mark Sproul msproul@skycharoit.com
|
||
73 | //* Jul 7, 2010 <MLS> Working on mega2560. No Auto-restart
|
||
74 | //* Jul 7, 2010 <MLS> Switched to 8K bytes (4K words) so that we have room for the monitor
|
||
75 | //* Jul 8, 2010 <MLS> Found older version of source that had auto restart, put that code back in
|
||
76 | //* Jul 8, 2010 <MLS> Adding monitor code
|
||
77 | //* Jul 11, 2010 <MLS> Added blinking LED while waiting for download to start
|
||
78 | //* Jul 11, 2010 <MLS> Added EEPROM test
|
||
79 | //* Jul 29, 2010 <MLS> Added recchar_timeout for timing out on bootloading
|
||
80 | //* Aug 23, 2010 <MLS> Added support for atmega2561
|
||
81 | //* Aug 26, 2010 <MLS> Removed support for BOOT_BY_SWITCH
|
||
82 | //************************************************************************
|
||
83 | |||
84 | |||
85 | |||
86 | #include <inttypes.h> |
||
87 | #include <avr/io.h> |
||
88 | #include <avr/interrupt.h> |
||
89 | #include <avr/boot.h> |
||
90 | #include <avr/pgmspace.h> |
||
91 | #include <util/delay.h> |
||
92 | #include <avr/eeprom.h> |
||
93 | #include <avr/common.h> |
||
94 | #include <stdlib.h> |
||
95 | #include "command.h" |
||
96 | |||
97 | |||
98 | #if defined(_MEGA_BOARD_) || defined(_BOARD_AMBER128_) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||
99 | #define ENABLE_MONITOR
|
||
100 | static void RunMonitor(void); |
||
101 | #endif
|
||
102 | |||
103 | //#define _DEBUG_SERIAL_
|
||
104 | //#define _DEBUG_WITH_LEDS_
|
||
105 | |||
106 | |||
107 | /*
|
||
108 | * Uncomment the following lines to save code space
|
||
109 | */
|
||
110 | //#define REMOVE_PROGRAM_LOCK_BIT_SUPPORT // disable program lock bits
|
||
111 | //#define REMOVE_BOOTLOADER_LED // no LED to show active bootloader
|
||
112 | //#define REMOVE_CMD_SPI_MULTI // disable processing of SPI_MULTI commands, Remark this line for AVRDUDE <Worapoht>
|
||
113 | //
|
||
114 | |||
115 | |||
116 | |||
117 | //************************************************************************
|
||
118 | //* LED on pin "PROGLED_PIN" on port "PROGLED_PORT"
|
||
119 | //* indicates that bootloader is active
|
||
120 | //* PG2 -> LED on Wiring board
|
||
121 | //************************************************************************
|
||
122 | #define BLINK_LED_WHILE_WAITING
|
||
123 | |||
124 | #ifdef _MEGA_BOARD_
|
||
125 | #define PROGLED_PORT PORTB
|
||
126 | #define PROGLED_DDR DDRB
|
||
127 | #define PROGLED_PIN PINB7
|
||
128 | #elif defined( _BOARD_AMBER128_ )
|
||
129 | //* this is for the amber 128 http://www.soc-robotics.com/
|
||
130 | //* onbarod led is PORTE4
|
||
131 | #define PROGLED_PORT PORTD
|
||
132 | #define PROGLED_DDR DDRD
|
||
133 | #define PROGLED_PIN PINE7
|
||
134 | #elif defined( _CEREBOTPLUS_BOARD_ )
|
||
135 | //* this is for the Cerebot 2560 board
|
||
136 | //* onbarod leds are on PORTE4-7
|
||
137 | #define PROGLED_PORT PORTE
|
||
138 | #define PROGLED_DDR DDRE
|
||
139 | #define PROGLED_PIN PINE7
|
||
140 | #elif defined( _PENGUINO_ )
|
||
141 | //* this is for the Penguino
|
||
142 | //* onbarod led is PORTE4
|
||
143 | #define PROGLED_PORT PORTC
|
||
144 | #define PROGLED_DDR DDRC
|
||
145 | #define PROGLED_PIN PINC6
|
||
146 | #elif defined( _ANDROID_2561_ ) || defined( __AVR_ATmega2561__ )
|
||
147 | //* this is for the Boston Android 2561
|
||
148 | //* onbarod led is PORTE4
|
||
149 | #define PROGLED_PORT PORTA
|
||
150 | #define PROGLED_DDR DDRA
|
||
151 | #define PROGLED_PIN PINA3
|
||
152 | #else
|
||
153 | #define PROGLED_PORT PORTG
|
||
154 | #define PROGLED_DDR DDRG
|
||
155 | #define PROGLED_PIN PING2
|
||
156 | #endif
|
||
157 | |||
158 | |||
159 | |||
160 | /*
|
||
161 | * define CPU frequency in Mhz here if not defined in Makefile
|
||
162 | */
|
||
163 | #ifndef F_CPU
|
||
164 | #define F_CPU 16000000UL |
||
165 | #endif
|
||
166 | |||
167 | /*
|
||
168 | * UART Baudrate, AVRStudio AVRISP only accepts 115200 bps
|
||
169 | */
|
||
170 | |||
171 | #ifndef BAUDRATE
|
||
172 | #define BAUDRATE 115200 |
||
173 | #endif
|
||
174 | |||
175 | /*
|
||
176 | * Enable (1) or disable (0) USART double speed operation
|
||
177 | */
|
||
178 | #ifndef UART_BAUDRATE_DOUBLE_SPEED
|
||
179 | #if defined (__AVR_ATmega32__)
|
||
180 | #define UART_BAUDRATE_DOUBLE_SPEED 0 |
||
181 | #else
|
||
182 | #define UART_BAUDRATE_DOUBLE_SPEED 1 |
||
183 | #endif
|
||
184 | #endif
|
||
185 | |||
186 | /*
|
||
187 | * HW and SW version, reported to AVRISP, must match version of AVRStudio
|
||
188 | */
|
||
189 | #define CONFIG_PARAM_BUILD_NUMBER_LOW 0 |
||
190 | #define CONFIG_PARAM_BUILD_NUMBER_HIGH 0 |
||
191 | #define CONFIG_PARAM_HW_VER 0x0F |
||
192 | #define CONFIG_PARAM_SW_MAJOR 2 |
||
193 | #define CONFIG_PARAM_SW_MINOR 0x0A |
||
194 | |||
195 | /*
|
||
196 | * Calculate the address where the bootloader starts from FLASHEND and BOOTSIZE
|
||
197 | * (adjust BOOTSIZE below and BOOTLOADER_ADDRESS in Makefile if you want to change the size of the bootloader)
|
||
198 | */
|
||
199 | //#define BOOTSIZE 1024
|
||
200 | #if FLASHEND > 0x0F000 |
||
201 | #define BOOTSIZE 8192 |
||
202 | #else
|
||
203 | #define BOOTSIZE 2048 |
||
204 | #endif
|
||
205 | |||
206 | #define APP_END (FLASHEND -(2*BOOTSIZE) + 1) |
||
207 | |||
208 | /*
|
||
209 | * Signature bytes are not available in avr-gcc io_xxx.h
|
||
210 | */
|
||
211 | #if defined (__AVR_ATmega8__)
|
||
212 | #define SIGNATURE_BYTES 0x1E9307 |
||
213 | #elif defined (__AVR_ATmega16__)
|
||
214 | #define SIGNATURE_BYTES 0x1E9403 |
||
215 | #elif defined (__AVR_ATmega32__)
|
||
216 | #define SIGNATURE_BYTES 0x1E9502 |
||
217 | #elif defined (__AVR_ATmega8515__)
|
||
218 | #define SIGNATURE_BYTES 0x1E9306 |
||
219 | #elif defined (__AVR_ATmega8535__)
|
||
220 | #define SIGNATURE_BYTES 0x1E9308 |
||
221 | #elif defined (__AVR_ATmega162__)
|
||
222 | #define SIGNATURE_BYTES 0x1E9404 |
||
223 | #elif defined (__AVR_ATmega128__)
|
||
224 | #define SIGNATURE_BYTES 0x1E9702 |
||
225 | #elif defined (__AVR_ATmega1280__)
|
||
226 | #define SIGNATURE_BYTES 0x1E9703 |
||
227 | #elif defined (__AVR_ATmega2560__)
|
||
228 | #define SIGNATURE_BYTES 0x1E9801 |
||
229 | #elif defined (__AVR_ATmega2561__)
|
||
230 | #define SIGNATURE_BYTES 0x1e9802 |
||
231 | #else
|
||
232 | #error "no signature definition for MCU available" |
||
233 | #endif
|
||
234 | |||
235 | |||
236 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
|
||
237 | || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) |
||
238 | /* ATMega8 with one USART */
|
||
239 | #define UART_BAUD_RATE_LOW UBRRL
|
||
240 | #define UART_STATUS_REG UCSRA
|
||
241 | #define UART_CONTROL_REG UCSRB
|
||
242 | #define UART_ENABLE_TRANSMITTER TXEN
|
||
243 | #define UART_ENABLE_RECEIVER RXEN
|
||
244 | #define UART_TRANSMIT_COMPLETE TXC
|
||
245 | #define UART_RECEIVE_COMPLETE RXC
|
||
246 | #define UART_DATA_REG UDR
|
||
247 | #define UART_DOUBLE_SPEED U2X
|
||
248 | |||
249 | #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__) \
|
||
250 | || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) |
||
251 | /* ATMega with two USART, use UART0 */
|
||
252 | #define UART_BAUD_RATE_LOW UBRR0L
|
||
253 | #define UART_STATUS_REG UCSR0A
|
||
254 | #define UART_CONTROL_REG UCSR0B
|
||
255 | #define UART_ENABLE_TRANSMITTER TXEN0
|
||
256 | #define UART_ENABLE_RECEIVER RXEN0
|
||
257 | #define UART_TRANSMIT_COMPLETE TXC0
|
||
258 | #define UART_RECEIVE_COMPLETE RXC0
|
||
259 | #define UART_DATA_REG UDR0
|
||
260 | #define UART_DOUBLE_SPEED U2X0
|
||
261 | #else
|
||
262 | #error "no UART definition for MCU available" |
||
263 | #endif
|
||
264 | |||
265 | |||
266 | |||
267 | /*
|
||
268 | * Macro to calculate UBBR from XTAL and baudrate
|
||
269 | */
|
||
270 | #if defined(__AVR_ATmega32__) && UART_BAUDRATE_DOUBLE_SPEED
|
||
271 | #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 4 / baudRate - 1) / 2) |
||
272 | #elif defined(__AVR_ATmega32__)
|
||
273 | #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu / 8 / baudRate - 1) / 2) |
||
274 | #elif UART_BAUDRATE_DOUBLE_SPEED
|
||
275 | #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5) |
||
276 | #else
|
||
277 | #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*16.0)-1.0+0.5) |
||
278 | #endif
|
||
279 | |||
280 | |||
281 | /*
|
||
282 | * States used in the receive state machine
|
||
283 | */
|
||
284 | #define ST_START 0 |
||
285 | #define ST_GET_SEQ_NUM 1 |
||
286 | #define ST_MSG_SIZE_1 2 |
||
287 | #define ST_MSG_SIZE_2 3 |
||
288 | #define ST_GET_TOKEN 4 |
||
289 | #define ST_GET_DATA 5 |
||
290 | #define ST_GET_CHECK 6 |
||
291 | #define ST_PROCESS 7 |
||
292 | |||
293 | /*
|
||
294 | * use 16bit address variable for ATmegas with <= 64K flash
|
||
295 | */
|
||
296 | #if defined(RAMPZ)
|
||
297 | typedef uint32_t address_t;
|
||
298 | #else
|
||
299 | typedef uint16_t address_t;
|
||
300 | #endif
|
||
301 | |||
302 | /*
|
||
303 | * function prototypes
|
||
304 | */
|
||
305 | static void sendchar(char c); |
||
306 | static unsigned char recchar(void); |
||
307 | |||
308 | /*
|
||
309 | * since this bootloader is not linked against the avr-gcc crt1 functions,
|
||
310 | * to reduce the code size, we need to provide our own initialization
|
||
311 | */
|
||
312 | void __jumpMain (void) __attribute__ ((naked)) __attribute__ ((section (".init9"))); |
||
313 | #include <avr/sfr_defs.h> |
||
314 | |||
315 | //#define SPH_REG 0x3E
|
||
316 | //#define SPL_REG 0x3D
|
||
317 | |||
318 | //*****************************************************************************
|
||
319 | void __jumpMain(void) |
||
320 | { |
||
321 | //* July 17, 2010 <MLS> Added stack pointer initialzation
|
||
322 | //* the first line did not do the job on the ATmega128
|
||
323 | |||
324 | asm volatile ( ".set __stack, %0" :: "i" (RAMEND) ); |
||
325 | |||
326 | // ldi r16,high(RAMEND)
|
||
327 | // out SPH,r16 ; Set stack pointer to top of RAM
|
||
328 | |||
329 | // asm volatile ( "ldi 16, 0x10");
|
||
330 | asm volatile ( "ldi 16, %0" :: "i" (RAMEND >> 8) ); |
||
331 | // asm volatile ( "out 0x3E,16");
|
||
332 | // asm volatile ( "out %0,16" :: "i" (SPH_REG) );
|
||
333 | asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_HI_ADDR) ); |
||
334 | |||
335 | // asm volatile ( "ldi 16, 0x00");
|
||
336 | asm volatile ( "ldi 16, %0" :: "i" (RAMEND & 0x0ff) ); |
||
337 | // asm volatile ( "out 0x3d,16");
|
||
338 | // asm volatile ( "out %0,16" :: "i" (SPL_REG) );
|
||
339 | asm volatile ( "out %0,16" :: "i" (AVR_STACK_POINTER_LO_ADDR) ); |
||
340 | |||
341 | |||
342 | |||
343 | asm volatile ( "clr __zero_reg__" ); // GCC depends on register r1 set to 0 |
||
344 | asm volatile ( "out %0, __zero_reg__" :: "I" (_SFR_IO_ADDR(SREG)) ); // set SREG to 0 |
||
345 | // asm volatile ( "rjmp main"); // jump to main()
|
||
346 | asm volatile ( "jmp main"); // jump to main() |
||
347 | } |
||
348 | |||
349 | |||
350 | //*****************************************************************************
|
||
351 | void delay_ms(unsigned int timedelay) |
||
352 | { |
||
353 | unsigned int i; |
||
354 | for (i=0;i<timedelay;i++) |
||
355 | { |
||
356 | _delay_ms(0.5); |
||
357 | } |
||
358 | } |
||
359 | |||
360 | |||
361 | //*****************************************************************************
|
||
362 | /*
|
||
363 | * send single byte to USART, wait until transmission is completed
|
||
364 | */
|
||
365 | static void sendchar(char c) |
||
366 | { |
||
367 | UART_DATA_REG = c; // prepare transmission
|
||
368 | while (!(UART_STATUS_REG & (1 << UART_TRANSMIT_COMPLETE))); // wait until byte sent |
||
369 | UART_STATUS_REG |= (1 << UART_TRANSMIT_COMPLETE); // delete TXCflag |
||
370 | } |
||
371 | |||
372 | |||
373 | //************************************************************************
|
||
374 | static int Serial_Available(void) |
||
375 | { |
||
376 | return(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE)); // wait for data |
||
377 | } |
||
378 | |||
379 | |||
380 | //*****************************************************************************
|
||
381 | /*
|
||
382 | * Read single byte from USART, block if no data available
|
||
383 | */
|
||
384 | static unsigned char recchar(void) |
||
385 | { |
||
386 | while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE))) |
||
387 | { |
||
388 | // wait for data
|
||
389 | } |
||
390 | return UART_DATA_REG;
|
||
391 | } |
||
392 | |||
393 | #define MAX_TIME_COUNT (F_CPU >> 1) |
||
394 | //*****************************************************************************
|
||
395 | static unsigned char recchar_timeout(void) |
||
396 | { |
||
397 | uint32_t count = 0;
|
||
398 | |||
399 | while (!(UART_STATUS_REG & (1 << UART_RECEIVE_COMPLETE))) |
||
400 | { |
||
401 | // wait for data
|
||
402 | count++; |
||
403 | if (count > MAX_TIME_COUNT)
|
||
404 | { |
||
405 | unsigned int data; |
||
406 | #if (FLASHEND > 0x0FFFF) |
||
407 | data = pgm_read_word_far(0); //* get the first word of the user program |
||
408 | #else
|
||
409 | data = pgm_read_word_near(0); //* get the first word of the user program |
||
410 | #endif
|
||
411 | if (data != 0xffff) //* make sure its valid before jumping to it. |
||
412 | { |
||
413 | asm volatile( |
||
414 | "clr r30 \n\t"
|
||
415 | "clr r31 \n\t"
|
||
416 | "ijmp \n\t"
|
||
417 | ); |
||
418 | } |
||
419 | count = 0;
|
||
420 | } |
||
421 | } |
||
422 | return UART_DATA_REG;
|
||
423 | } |
||
424 | |||
425 | |||
426 | |||
427 | //*****************************************************************************
|
||
428 | int main(void) |
||
429 | { |
||
430 | address_t address = 0;
|
||
431 | address_t eraseAddress = 0;
|
||
432 | unsigned char msgParseState; |
||
433 | unsigned int ii = 0; |
||
434 | unsigned char checksum = 0; |
||
435 | unsigned char seqNum = 0; |
||
436 | unsigned int msgLength = 0; |
||
437 | unsigned char msgBuffer[285]; |
||
438 | unsigned char c, *p; |
||
439 | unsigned char isLeave = 0; |
||
440 | |||
441 | unsigned long boot_timeout; |
||
442 | unsigned long boot_timer; |
||
443 | unsigned int boot_state; |
||
444 | #ifdef ENABLE_MONITOR
|
||
445 | unsigned int exPointCntr = 0; |
||
446 | #endif
|
||
447 | |||
448 | |||
449 | boot_timer = 0;
|
||
450 | boot_state = 0;
|
||
451 | |||
452 | #ifdef BLINK_LED_WHILE_WAITING
|
||
453 | boot_timeout = 20000; //* should be about 1 second |
||
454 | // boot_timeout = 170000;
|
||
455 | #else
|
||
456 | boot_timeout = 3500000; // 7 seconds , approx 2us per step when optimize "s" |
||
457 | #endif
|
||
458 | /*
|
||
459 | * Branch to bootloader or application code ?
|
||
460 | */
|
||
461 | |||
462 | #ifndef REMOVE_BOOTLOADER_LED
|
||
463 | /* PROG_PIN pulled low, indicate with LED that bootloader is active */
|
||
464 | PROGLED_DDR |= (1<<PROGLED_PIN);
|
||
465 | // PROGLED_PORT &= ~(1<<PROGLED_PIN); // active low LED ON
|
||
466 | PROGLED_PORT |= (1<<PROGLED_PIN); // active high LED ON |
||
467 | |||
468 | #ifdef _DEBUG_WITH_LEDS_
|
||
469 | for (ii=0; ii<3; ii++) |
||
470 | { |
||
471 | PROGLED_PORT &= ~(1<<PROGLED_PIN); // turn LED off |
||
472 | delay_ms(100);
|
||
473 | PROGLED_PORT |= (1<<PROGLED_PIN); // turn LED on |
||
474 | delay_ms(100);
|
||
475 | } |
||
476 | #endif
|
||
477 | |||
478 | #endif
|
||
479 | /*
|
||
480 | * Init UART
|
||
481 | * set baudrate and enable USART receiver and transmiter without interrupts
|
||
482 | */
|
||
483 | #if UART_BAUDRATE_DOUBLE_SPEED
|
||
484 | UART_STATUS_REG |= (1 <<UART_DOUBLE_SPEED);
|
||
485 | #endif
|
||
486 | UART_BAUD_RATE_LOW = UART_BAUD_SELECT(BAUDRATE,F_CPU); |
||
487 | UART_CONTROL_REG = (1 << UART_ENABLE_RECEIVER) | (1 << UART_ENABLE_TRANSMITTER); |
||
488 | |||
489 | asm volatile ("nop"); // wait until port has changed |
||
490 | |||
491 | #ifdef _DEBUG_SERIAL_
|
||
492 | // delay_ms(500);
|
||
493 | |||
494 | sendchar('s');
|
||
495 | sendchar('t');
|
||
496 | sendchar('k');
|
||
497 | // sendchar('5');
|
||
498 | // sendchar('0');
|
||
499 | // sendchar('0');
|
||
500 | sendchar('v');
|
||
501 | sendchar('2');
|
||
502 | sendchar(0x0d);
|
||
503 | sendchar(0x0a);
|
||
504 | |||
505 | delay_ms(100);
|
||
506 | #endif
|
||
507 | |||
508 | while (boot_state==0) |
||
509 | { |
||
510 | while ((!(Serial_Available())) && (boot_state == 0)) // wait for data |
||
511 | { |
||
512 | _delay_ms(0.001); |
||
513 | boot_timer++; |
||
514 | if (boot_timer > boot_timeout)
|
||
515 | { |
||
516 | boot_state = 1; // (after ++ -> boot_state=2 bootloader timeout, jump to main 0x00000 ) |
||
517 | } |
||
518 | #ifdef BLINK_LED_WHILE_WAITING
|
||
519 | if ((boot_timer % 7000) == 0) |
||
520 | { |
||
521 | //* toggle the LED
|
||
522 | PROGLED_PORT ^= (1<<PROGLED_PIN); // turn LED ON |
||
523 | } |
||
524 | #endif
|
||
525 | } |
||
526 | boot_state++; // ( if boot_state=1 bootloader received byte from UART, enter bootloader mode)
|
||
527 | } |
||
528 | |||
529 | |||
530 | if (boot_state==1) |
||
531 | { |
||
532 | //* main loop
|
||
533 | while (!isLeave)
|
||
534 | { |
||
535 | /*
|
||
536 | * Collect received bytes to a complete message
|
||
537 | */
|
||
538 | msgParseState = ST_START; |
||
539 | while ( msgParseState != ST_PROCESS )
|
||
540 | { |
||
541 | if (boot_state==1) |
||
542 | { |
||
543 | boot_state = 0;
|
||
544 | c = UART_DATA_REG; |
||
545 | } |
||
546 | else
|
||
547 | { |
||
548 | // c = recchar();
|
||
549 | c = recchar_timeout(); |
||
550 | } |
||
551 | |||
552 | #ifdef ENABLE_MONITOR
|
||
553 | if (c == '!') |
||
554 | { |
||
555 | exPointCntr++; |
||
556 | if (exPointCntr == 3) |
||
557 | { |
||
558 | RunMonitor(); |
||
559 | exPointCntr = 0; // reset back to zero so we dont get in an endless loop |
||
560 | isLeave = 1;
|
||
561 | msgParseState = 99; //* we dont want it do anything |
||
562 | break;
|
||
563 | } |
||
564 | } |
||
565 | else
|
||
566 | { |
||
567 | exPointCntr = 0;
|
||
568 | } |
||
569 | #endif
|
||
570 | |||
571 | switch (msgParseState)
|
||
572 | { |
||
573 | case ST_START:
|
||
574 | if ( c == MESSAGE_START )
|
||
575 | { |
||
576 | msgParseState = ST_GET_SEQ_NUM; |
||
577 | checksum = MESSAGE_START^0;
|
||
578 | } |
||
579 | break;
|
||
580 | |||
581 | case ST_GET_SEQ_NUM:
|
||
582 | if ( (c == 1) || (c == seqNum) ) |
||
583 | { |
||
584 | seqNum = c; |
||
585 | msgParseState = ST_MSG_SIZE_1; |
||
586 | checksum ^= c; |
||
587 | } |
||
588 | else
|
||
589 | { |
||
590 | msgParseState = ST_START; |
||
591 | } |
||
592 | break;
|
||
593 | |||
594 | case ST_MSG_SIZE_1:
|
||
595 | msgLength = c<<8;
|
||
596 | msgParseState = ST_MSG_SIZE_2; |
||
597 | checksum ^= c; |
||
598 | break;
|
||
599 | |||
600 | case ST_MSG_SIZE_2:
|
||
601 | msgLength |= c; |
||
602 | msgParseState = ST_GET_TOKEN; |
||
603 | checksum ^= c; |
||
604 | break;
|
||
605 | |||
606 | case ST_GET_TOKEN:
|
||
607 | if ( c == TOKEN )
|
||
608 | { |
||
609 | msgParseState = ST_GET_DATA; |
||
610 | checksum ^= c; |
||
611 | ii = 0;
|
||
612 | } |
||
613 | else
|
||
614 | { |
||
615 | msgParseState = ST_START; |
||
616 | } |
||
617 | break;
|
||
618 | |||
619 | case ST_GET_DATA:
|
||
620 | msgBuffer[ii++] = c; |
||
621 | checksum ^= c; |
||
622 | if (ii == msgLength )
|
||
623 | { |
||
624 | msgParseState = ST_GET_CHECK; |
||
625 | } |
||
626 | break;
|
||
627 | |||
628 | case ST_GET_CHECK:
|
||
629 | if ( c == checksum )
|
||
630 | { |
||
631 | msgParseState = ST_PROCESS; |
||
632 | } |
||
633 | else
|
||
634 | { |
||
635 | msgParseState = ST_START; |
||
636 | } |
||
637 | break;
|
||
638 | } // switch
|
||
639 | } // while(msgParseState)
|
||
640 | |||
641 | /*
|
||
642 | * Now process the STK500 commands, see Atmel Appnote AVR068
|
||
643 | */
|
||
644 | |||
645 | switch (msgBuffer[0]) |
||
646 | { |
||
647 | #ifndef REMOVE_CMD_SPI_MULTI
|
||
648 | case CMD_SPI_MULTI:
|
||
649 | { |
||
650 | unsigned char answerByte; |
||
651 | unsigned char flag=0; |
||
652 | |||
653 | if ( msgBuffer[4]== 0x30 ) |
||
654 | { |
||
655 | unsigned char signatureIndex = msgBuffer[6]; |
||
656 | |||
657 | if ( signatureIndex == 0 ) |
||
658 | answerByte = (SIGNATURE_BYTES >>16) & 0x000000FF; |
||
659 | else if ( signatureIndex == 1 ) |
||
660 | answerByte = (SIGNATURE_BYTES >> 8) & 0x000000FF; |
||
661 | else
|
||
662 | answerByte = SIGNATURE_BYTES & 0x000000FF;
|
||
663 | } |
||
664 | else if ( msgBuffer[4] & 0x50 ) |
||
665 | { |
||
666 | answerByte = 0; //read fuse/lock bits not implemented, return dummy value |
||
667 | } |
||
668 | else
|
||
669 | { |
||
670 | answerByte = 0; // for all others command are not implemented, return dummy value for AVRDUDE happy <Worapoht> |
||
671 | // flag = 1; // Remark this line for AVRDUDE <Worapoht>
|
||
672 | } |
||
673 | if ( !flag )
|
||
674 | { |
||
675 | msgLength = 7;
|
||
676 | msgBuffer[1] = STATUS_CMD_OK;
|
||
677 | msgBuffer[2] = 0; |
||
678 | msgBuffer[3] = msgBuffer[4]; |
||
679 | msgBuffer[4] = 0; |
||
680 | msgBuffer[5] = answerByte;
|
||
681 | msgBuffer[6] = STATUS_CMD_OK;
|
||
682 | } |
||
683 | } |
||
684 | break;
|
||
685 | #endif
|
||
686 | case CMD_SIGN_ON:
|
||
687 | msgLength = 11;
|
||
688 | msgBuffer[1] = STATUS_CMD_OK;
|
||
689 | msgBuffer[2] = 8; |
||
690 | msgBuffer[3] = 'A'; |
||
691 | msgBuffer[4] = 'V'; |
||
692 | msgBuffer[5] = 'R'; |
||
693 | msgBuffer[6] = 'I'; |
||
694 | msgBuffer[7] = 'S'; |
||
695 | msgBuffer[8] = 'P'; |
||
696 | msgBuffer[9] = '_'; |
||
697 | msgBuffer[10] = '2'; |
||
698 | break;
|
||
699 | |||
700 | case CMD_GET_PARAMETER:
|
||
701 | { |
||
702 | unsigned char value; |
||
703 | |||
704 | switch(msgBuffer[1]) |
||
705 | { |
||
706 | case PARAM_BUILD_NUMBER_LOW:
|
||
707 | value = CONFIG_PARAM_BUILD_NUMBER_LOW; |
||
708 | break;
|
||
709 | case PARAM_BUILD_NUMBER_HIGH:
|
||
710 | value = CONFIG_PARAM_BUILD_NUMBER_HIGH; |
||
711 | break;
|
||
712 | case PARAM_HW_VER:
|
||
713 | value = CONFIG_PARAM_HW_VER; |
||
714 | break;
|
||
715 | case PARAM_SW_MAJOR:
|
||
716 | value = CONFIG_PARAM_SW_MAJOR; |
||
717 | break;
|
||
718 | case PARAM_SW_MINOR:
|
||
719 | value = CONFIG_PARAM_SW_MINOR; |
||
720 | break;
|
||
721 | default:
|
||
722 | value = 0;
|
||
723 | break;
|
||
724 | } |
||
725 | msgLength = 3;
|
||
726 | msgBuffer[1] = STATUS_CMD_OK;
|
||
727 | msgBuffer[2] = value;
|
||
728 | } |
||
729 | break;
|
||
730 | |||
731 | case CMD_LEAVE_PROGMODE_ISP:
|
||
732 | isLeave = 1;
|
||
733 | //* fall thru
|
||
734 | |||
735 | case CMD_SET_PARAMETER:
|
||
736 | case CMD_ENTER_PROGMODE_ISP:
|
||
737 | msgLength = 2;
|
||
738 | msgBuffer[1] = STATUS_CMD_OK;
|
||
739 | break;
|
||
740 | |||
741 | case CMD_READ_SIGNATURE_ISP:
|
||
742 | { |
||
743 | unsigned char signatureIndex = msgBuffer[4]; |
||
744 | unsigned char signature; |
||
745 | |||
746 | if ( signatureIndex == 0 ) |
||
747 | signature = (SIGNATURE_BYTES >>16) & 0x000000FF; |
||
748 | else if ( signatureIndex == 1 ) |
||
749 | signature = (SIGNATURE_BYTES >> 8) & 0x000000FF; |
||
750 | else
|
||
751 | signature = SIGNATURE_BYTES & 0x000000FF;
|
||
752 | |||
753 | msgLength = 4;
|
||
754 | msgBuffer[1] = STATUS_CMD_OK;
|
||
755 | msgBuffer[2] = signature;
|
||
756 | msgBuffer[3] = STATUS_CMD_OK;
|
||
757 | } |
||
758 | break;
|
||
759 | |||
760 | case CMD_READ_LOCK_ISP:
|
||
761 | msgLength = 4;
|
||
762 | msgBuffer[1] = STATUS_CMD_OK;
|
||
763 | msgBuffer[2] = boot_lock_fuse_bits_get( GET_LOCK_BITS );
|
||
764 | msgBuffer[3] = STATUS_CMD_OK;
|
||
765 | break;
|
||
766 | |||
767 | case CMD_READ_FUSE_ISP:
|
||
768 | { |
||
769 | unsigned char fuseBits; |
||
770 | |||
771 | if ( msgBuffer[2] == 0x50 ) |
||
772 | { |
||
773 | if ( msgBuffer[3] == 0x08 ) |
||
774 | fuseBits = boot_lock_fuse_bits_get( GET_EXTENDED_FUSE_BITS ); |
||
775 | else
|
||
776 | fuseBits = boot_lock_fuse_bits_get( GET_LOW_FUSE_BITS ); |
||
777 | } |
||
778 | else
|
||
779 | { |
||
780 | fuseBits = boot_lock_fuse_bits_get( GET_HIGH_FUSE_BITS ); |
||
781 | } |
||
782 | msgLength = 4;
|
||
783 | msgBuffer[1] = STATUS_CMD_OK;
|
||
784 | msgBuffer[2] = fuseBits;
|
||
785 | msgBuffer[3] = STATUS_CMD_OK;
|
||
786 | } |
||
787 | break;
|
||
788 | |||
789 | #ifndef REMOVE_PROGRAM_LOCK_BIT_SUPPORT
|
||
790 | case CMD_PROGRAM_LOCK_ISP:
|
||
791 | { |
||
792 | unsigned char lockBits = msgBuffer[4]; |
||
793 | |||
794 | lockBits = (~lockBits) & 0x3C; // mask BLBxx bits |
||
795 | boot_lock_bits_set(lockBits); // and program it
|
||
796 | boot_spm_busy_wait(); |
||
797 | |||
798 | msgLength = 3;
|
||
799 | msgBuffer[1] = STATUS_CMD_OK;
|
||
800 | msgBuffer[2] = STATUS_CMD_OK;
|
||
801 | } |
||
802 | break;
|
||
803 | #endif
|
||
804 | case CMD_CHIP_ERASE_ISP:
|
||
805 | eraseAddress = 0;
|
||
806 | msgLength = 2;
|
||
807 | msgBuffer[1] = STATUS_CMD_OK;
|
||
808 | break;
|
||
809 | |||
810 | case CMD_LOAD_ADDRESS:
|
||
811 | #if defined(RAMPZ)
|
||
812 | address = ( ((address_t)(msgBuffer[1])<<24)|((address_t)(msgBuffer[2])<<16)|((address_t)(msgBuffer[3])<<8)|(msgBuffer[4]) )<<1; |
||
813 | #else
|
||
814 | address = ( ((msgBuffer[3])<<8)|(msgBuffer[4]) )<<1; //convert word to byte address |
||
815 | #endif
|
||
816 | msgLength = 2;
|
||
817 | msgBuffer[1] = STATUS_CMD_OK;
|
||
818 | break;
|
||
819 | |||
820 | case CMD_PROGRAM_FLASH_ISP:
|
||
821 | case CMD_PROGRAM_EEPROM_ISP:
|
||
822 | { |
||
823 | unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2]; |
||
824 | unsigned char *p = msgBuffer+10; |
||
825 | unsigned int data; |
||
826 | unsigned char highByte, lowByte; |
||
827 | address_t tempaddress = address; |
||
828 | |||
829 | |||
830 | if ( msgBuffer[0] == CMD_PROGRAM_FLASH_ISP ) |
||
831 | { |
||
832 | // erase only main section (bootloader protection)
|
||
833 | if (eraseAddress < APP_END )
|
||
834 | { |
||
835 | boot_page_erase(eraseAddress); // Perform page erase
|
||
836 | boot_spm_busy_wait(); // Wait until the memory is erased.
|
||
837 | eraseAddress += SPM_PAGESIZE; // point to next page to be erase
|
||
838 | } |
||
839 | |||
840 | /* Write FLASH */
|
||
841 | do {
|
||
842 | lowByte = *p++; |
||
843 | highByte = *p++; |
||
844 | |||
845 | data = (highByte << 8) | lowByte;
|
||
846 | boot_page_fill(address,data); |
||
847 | |||
848 | address = address + 2; // Select next word in memory |
||
849 | size -= 2; // Reduce number of bytes to write by two |
||
850 | } while (size); // Loop until all bytes written |
||
851 | |||
852 | boot_page_write(tempaddress); |
||
853 | boot_spm_busy_wait(); |
||
854 | boot_rww_enable(); // Re-enable the RWW section
|
||
855 | } |
||
856 | else
|
||
857 | { |
||
858 | #if (!defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega2561__))
|
||
859 | /* write EEPROM */
|
||
860 | do {
|
||
861 | EEARL = address; // Setup EEPROM address
|
||
862 | EEARH = (address >> 8);
|
||
863 | address++; // Select next EEPROM byte
|
||
864 | |||
865 | EEDR = *p++; // get byte from buffer
|
||
866 | EECR |= (1<<EEMWE); // Write data into EEPROM |
||
867 | EECR |= (1<<EEWE);
|
||
868 | |||
869 | while (EECR & (1<<EEWE)); // Wait for write operation to finish |
||
870 | size--; // Decrease number of bytes to write
|
||
871 | } while (size); // Loop until all bytes written |
||
872 | #endif
|
||
873 | } |
||
874 | msgLength = 2;
|
||
875 | msgBuffer[1] = STATUS_CMD_OK;
|
||
876 | } |
||
877 | break;
|
||
878 | |||
879 | case CMD_READ_FLASH_ISP:
|
||
880 | case CMD_READ_EEPROM_ISP:
|
||
881 | { |
||
882 | unsigned int size = ((msgBuffer[1])<<8) | msgBuffer[2]; |
||
883 | unsigned char *p = msgBuffer+1; |
||
884 | msgLength = size+3;
|
||
885 | |||
886 | *p++ = STATUS_CMD_OK; |
||
887 | if (msgBuffer[0] == CMD_READ_FLASH_ISP ) |
||
888 | { |
||
889 | unsigned int data; |
||
890 | |||
891 | // Read FLASH
|
||
892 | do {
|
||
893 | #if defined(RAMPZ)
|
||
894 | data = pgm_read_word_far(address); |
||
895 | #else
|
||
896 | data = pgm_read_word_near(address); |
||
897 | #endif
|
||
898 | *p++ = (unsigned char)data; //LSB |
||
899 | *p++ = (unsigned char)(data >> 8); //MSB |
||
900 | address += 2; // Select next word in memory |
||
901 | size -= 2;
|
||
902 | }while (size);
|
||
903 | } |
||
904 | else
|
||
905 | { |
||
906 | /* Read EEPROM */
|
||
907 | do {
|
||
908 | EEARL = address; // Setup EEPROM address
|
||
909 | EEARH = ((address >> 8));
|
||
910 | address++; // Select next EEPROM byte
|
||
911 | EECR |= (1<<EERE); // Read EEPROM |
||
912 | *p++ = EEDR; // Send EEPROM data
|
||
913 | size--; |
||
914 | } while (size);
|
||
915 | } |
||
916 | *p++ = STATUS_CMD_OK; |
||
917 | } |
||
918 | break;
|
||
919 | |||
920 | default:
|
||
921 | msgLength = 2;
|
||
922 | msgBuffer[1] = STATUS_CMD_FAILED;
|
||
923 | break;
|
||
924 | } |
||
925 | |||
926 | /*
|
||
927 | * Now send answer message back
|
||
928 | */
|
||
929 | sendchar(MESSAGE_START); |
||
930 | checksum = MESSAGE_START^0;
|
||
931 | |||
932 | sendchar(seqNum); |
||
933 | checksum ^= seqNum; |
||
934 | |||
935 | c = ((msgLength>>8)&0xFF); |
||
936 | sendchar(c); |
||
937 | checksum ^= c; |
||
938 | |||
939 | c = msgLength&0x00FF;
|
||
940 | sendchar(c); |
||
941 | checksum ^= c; |
||
942 | |||
943 | sendchar(TOKEN); |
||
944 | checksum ^= TOKEN; |
||
945 | |||
946 | p = msgBuffer; |
||
947 | while ( msgLength )
|
||
948 | { |
||
949 | c = *p++; |
||
950 | sendchar(c); |
||
951 | checksum ^=c; |
||
952 | msgLength--; |
||
953 | } |
||
954 | sendchar(checksum); |
||
955 | seqNum++; |
||
956 | |||
957 | #ifndef REMOVE_BOOTLOADER_LED
|
||
958 | //* <MLS> toggle the LED
|
||
959 | PROGLED_PORT ^= (1<<PROGLED_PIN); // active high LED ON |
||
960 | #endif
|
||
961 | |||
962 | } |
||
963 | } |
||
964 | |||
965 | #ifdef _DEBUG_WITH_LEDS_
|
||
966 | //* this is for debugging it can be removed
|
||
967 | for (ii=0; ii<10; ii++) |
||
968 | { |
||
969 | PROGLED_PORT &= ~(1<<PROGLED_PIN); // turn LED off |
||
970 | delay_ms(200);
|
||
971 | PROGLED_PORT |= (1<<PROGLED_PIN); // turn LED on |
||
972 | delay_ms(200);
|
||
973 | } |
||
974 | PROGLED_PORT &= ~(1<<PROGLED_PIN); // turn LED off |
||
975 | #endif
|
||
976 | |||
977 | #ifdef _DEBUG_SERIAL_
|
||
978 | sendchar('j');
|
||
979 | // sendchar('u');
|
||
980 | // sendchar('m');
|
||
981 | // sendchar('p');
|
||
982 | // sendchar(' ');
|
||
983 | // sendchar('u');
|
||
984 | // sendchar('s');
|
||
985 | // sendchar('r');
|
||
986 | sendchar(0x0d);
|
||
987 | sendchar(0x0a);
|
||
988 | |||
989 | delay_ms(100);
|
||
990 | #endif
|
||
991 | |||
992 | |||
993 | #ifndef REMOVE_BOOTLOADER_LED
|
||
994 | PROGLED_DDR &= ~(1<<PROGLED_PIN); // set to default |
||
995 | PROGLED_PORT &= ~(1<<PROGLED_PIN); // active low LED OFF |
||
996 | // PROGLED_PORT |= (1<<PROGLED_PIN); // active high LED OFf
|
||
997 | delay_ms(100); // delay after exit |
||
998 | #endif
|
||
999 | |||
1000 | |||
1001 | asm volatile ("nop"); // wait until port has changed |
||
1002 | |||
1003 | /*
|
||
1004 | * Now leave bootloader
|
||
1005 | */
|
||
1006 | |||
1007 | UART_STATUS_REG &= 0xfd;
|
||
1008 | boot_rww_enable(); // enable application section
|
||
1009 | |||
1010 | |||
1011 | asm volatile( |
||
1012 | "clr r30 \n\t"
|
||
1013 | "clr r31 \n\t"
|
||
1014 | "ijmp \n\t"
|
||
1015 | ); |
||
1016 | // asm volatile ( "push r1" "\n\t" // Jump to Reset vector in Application Section
|
||
1017 | // "push r1" "\n\t"
|
||
1018 | // "ret" "\n\t"
|
||
1019 | // ::);
|
||
1020 | |||
1021 | /*
|
||
1022 | * Never return to stop GCC to generate exit return code
|
||
1023 | * Actually we will never reach this point, but the compiler doesn't
|
||
1024 | * understand this
|
||
1025 | */
|
||
1026 | for(;;);
|
||
1027 | } |
||
1028 | |||
1029 | /*
|
||
1030 | base address = f800
|
||
1031 | |||
1032 | avrdude: Device signature = 0x1e9703
|
||
1033 | avrdude: safemode: lfuse reads as FF
|
||
1034 | avrdude: safemode: hfuse reads as DA
|
||
1035 | avrdude: safemode: efuse reads as F5
|
||
1036 | avrdude>
|
||
1037 | |||
1038 | |||
1039 | base address = f000
|
||
1040 | avrdude: Device signature = 0x1e9703
|
||
1041 | avrdude: safemode: lfuse reads as FF
|
||
1042 | avrdude: safemode: hfuse reads as D8
|
||
1043 | avrdude: safemode: efuse reads as F5
|
||
1044 | avrdude>
|
||
1045 | */
|
||
1046 | |||
1047 | //************************************************************************
|
||
1048 | #ifdef ENABLE_MONITOR
|
||
1049 | #include <math.h> |
||
1050 | |||
1051 | unsigned long gRamIndex; |
||
1052 | unsigned long gFlashIndex; |
||
1053 | unsigned long gEepromIndex; |
||
1054 | |||
1055 | |||
1056 | #define true 1 |
||
1057 | #define false 0 |
||
1058 | |||
1059 | #if defined(__AVR_ATmega128__)
|
||
1060 | #define kCPU_NAME "ATmega128" |
||
1061 | #elif defined(__AVR_ATmega1280__)
|
||
1062 | #define kCPU_NAME "ATmega1280" |
||
1063 | #elif defined(__AVR_ATmega1281__)
|
||
1064 | #define kCPU_NAME "ATmega1281" |
||
1065 | #elif defined(__AVR_ATmega2560__)
|
||
1066 | #define kCPU_NAME "ATmega2560" |
||
1067 | #elif defined(__AVR_ATmega2561__)
|
||
1068 | #define kCPU_NAME "ATmega2561" |
||
1069 | #endif
|
||
1070 | |||
1071 | #ifdef _VECTORS_SIZE
|
||
1072 | #define kInterruptVectorCount (_VECTORS_SIZE / 4) |
||
1073 | #else
|
||
1074 | #define kInterruptVectorCount 23 |
||
1075 | #endif
|
||
1076 | |||
1077 | |||
1078 | void PrintDecInt(int theNumber, int digitCnt); |
||
1079 | |||
1080 | #ifdef kCPU_NAME
|
||
1081 | prog_char gTextMsg_CPU_Name[] PROGMEM = kCPU_NAME; |
||
1082 | #else
|
||
1083 | prog_char gTextMsg_CPU_Name[] PROGMEM = "UNKNOWN";
|
||
1084 | #endif
|
||
1085 | |||
1086 | prog_char gTextMsg_Explorer[] PROGMEM = "Arduino explorer stk500V2 by MLS";
|
||
1087 | prog_char gTextMsg_Prompt[] PROGMEM = "Bootloader>";
|
||
1088 | prog_char gTextMsg_HUH[] PROGMEM = "Huh?";
|
||
1089 | prog_char gTextMsg_COMPILED_ON[] PROGMEM = "Compiled on = ";
|
||
1090 | prog_char gTextMsg_CPU_Type[] PROGMEM = "CPU Type = ";
|
||
1091 | prog_char gTextMsg_AVR_ARCH[] PROGMEM = "__AVR_ARCH__ = ";
|
||
1092 | prog_char gTextMsg_AVR_LIBC[] PROGMEM = "AVR LibC Ver = ";
|
||
1093 | prog_char gTextMsg_GCC_VERSION[] PROGMEM = "GCC Version = ";
|
||
1094 | prog_char gTextMsg_CPU_SIGNATURE[] PROGMEM = "CPU signature= ";
|
||
1095 | prog_char gTextMsg_FUSE_BYTE_LOW[] PROGMEM = "Low fuse = ";
|
||
1096 | prog_char gTextMsg_FUSE_BYTE_HIGH[] PROGMEM = "High fuse = ";
|
||
1097 | prog_char gTextMsg_FUSE_BYTE_EXT[] PROGMEM = "Ext fuse = ";
|
||
1098 | prog_char gTextMsg_FUSE_BYTE_LOCK[] PROGMEM = "Lock fuse = ";
|
||
1099 | prog_char gTextMsg_GCC_DATE_STR[] PROGMEM = __DATE__; |
||
1100 | prog_char gTextMsg_AVR_LIBC_VER_STR[] PROGMEM = __AVR_LIBC_VERSION_STRING__; |
||
1101 | prog_char gTextMsg_GCC_VERSION_STR[] PROGMEM = __VERSION__; |
||
1102 | prog_char gTextMsg_VECTOR_HEADER[] PROGMEM = "V# ADDR op code instruction addr Interrupt";
|
||
1103 | prog_char gTextMsg_noVector[] PROGMEM = "no vector";
|
||
1104 | prog_char gTextMsg_rjmp[] PROGMEM = "rjmp ";
|
||
1105 | prog_char gTextMsg_jmp[] PROGMEM = "jmp ";
|
||
1106 | prog_char gTextMsg_WHAT_PORT[] PROGMEM = "What port:";
|
||
1107 | prog_char gTextMsg_PortNotSupported[] PROGMEM = "Port not supported";
|
||
1108 | prog_char gTextMsg_MustBeLetter[] PROGMEM = "Must be a letter";
|
||
1109 | prog_char gTextMsg_SPACE[] PROGMEM = " ";
|
||
1110 | prog_char gTextMsg_WriteToEEprom[] PROGMEM = "Writting EE";
|
||
1111 | prog_char gTextMsg_ReadingEEprom[] PROGMEM = "Reading EE";
|
||
1112 | prog_char gTextMsg_EEPROMerrorCnt[] PROGMEM = "eeprom error count=";
|
||
1113 | prog_char gTextMsg_PORT[] PROGMEM = "PORT";
|
||
1114 | |||
1115 | |||
1116 | //************************************************************************
|
||
1117 | //* Help messages
|
||
1118 | prog_char gTextMsg_HELP_MSG_0[] PROGMEM = "0=Zero address ctrs";
|
||
1119 | prog_char gTextMsg_HELP_MSG_QM[] PROGMEM = "?=CPU stats";
|
||
1120 | prog_char gTextMsg_HELP_MSG_AT[] PROGMEM = "@=EEPROM test";
|
||
1121 | prog_char gTextMsg_HELP_MSG_B[] PROGMEM = "B=Blink LED";
|
||
1122 | prog_char gTextMsg_HELP_MSG_E[] PROGMEM = "E=Dump EEPROM";
|
||
1123 | prog_char gTextMsg_HELP_MSG_F[] PROGMEM = "F=Dump FLASH";
|
||
1124 | prog_char gTextMsg_HELP_MSG_H[] PROGMEM = "H=Help";
|
||
1125 | prog_char gTextMsg_HELP_MSG_L[] PROGMEM = "L=List I/O Ports";
|
||
1126 | prog_char gTextMsg_HELP_MSG_Q[] PROGMEM = "Q=Quit & jump to user pgm";
|
||
1127 | prog_char gTextMsg_HELP_MSG_R[] PROGMEM = "R=Dump RAM";
|
||
1128 | prog_char gTextMsg_HELP_MSG_V[] PROGMEM = "V=show interrupt Vectors";
|
||
1129 | prog_char gTextMsg_HELP_MSG_Y[] PROGMEM = "Y=Port blink";
|
||
1130 | |||
1131 | prog_char gTextMsg_END[] PROGMEM = "*";
|
||
1132 | |||
1133 | |||
1134 | //************************************************************************
|
||
1135 | void PrintFromPROGMEM(void *dataPtr, unsigned char offset) |
||
1136 | { |
||
1137 | uint8_t ii; |
||
1138 | char theChar;
|
||
1139 | |||
1140 | ii = offset; |
||
1141 | theChar = 1;
|
||
1142 | |||
1143 | while (theChar != 0) |
||
1144 | { |
||
1145 | theChar = pgm_read_byte_far((uint32_t)dataPtr + ii); |
||
1146 | if (theChar != 0) |
||
1147 | { |
||
1148 | sendchar(theChar); |
||
1149 | } |
||
1150 | ii++; |
||
1151 | } |
||
1152 | } |
||
1153 | |||
1154 | //************************************************************************
|
||
1155 | void PrintNewLine(void) |
||
1156 | { |
||
1157 | sendchar(0x0d);
|
||
1158 | sendchar(0x0a);
|
||
1159 | } |
||
1160 | |||
1161 | |||
1162 | //************************************************************************
|
||
1163 | void PrintFromPROGMEMln(void *dataPtr, unsigned char offset) |
||
1164 | { |
||
1165 | PrintFromPROGMEM(dataPtr, offset); |
||
1166 | |||
1167 | PrintNewLine(); |
||
1168 | } |
||
1169 | |||
1170 | |||
1171 | //************************************************************************
|
||
1172 | void PrintString(char *textString) |
||
1173 | { |
||
1174 | char theChar;
|
||
1175 | int ii;
|
||
1176 | |||
1177 | theChar = 1;
|
||
1178 | ii = 0;
|
||
1179 | while (theChar != 0) |
||
1180 | { |
||
1181 | theChar = textString[ii]; |
||
1182 | if (theChar != 0) |
||
1183 | { |
||
1184 | sendchar(theChar); |
||
1185 | } |
||
1186 | ii++; |
||
1187 | } |
||
1188 | } |
||
1189 | |||
1190 | //************************************************************************
|
||
1191 | void PrintHexByte(unsigned char theByte) |
||
1192 | { |
||
1193 | char theChar;
|
||
1194 | |||
1195 | theChar = 0x30 + ((theByte >> 4) & 0x0f); |
||
1196 | if (theChar > 0x39) |
||
1197 | { |
||
1198 | theChar += 7;
|
||
1199 | } |
||
1200 | sendchar(theChar ); |
||
1201 | |||
1202 | theChar = 0x30 + (theByte & 0x0f); |
||
1203 | if (theChar > 0x39) |
||
1204 | { |
||
1205 | theChar += 7;
|
||
1206 | } |
||
1207 | sendchar(theChar ); |
||
1208 | } |
||
1209 | |||
1210 | //************************************************************************
|
||
1211 | void PrintDecInt(int theNumber, int digitCnt) |
||
1212 | { |
||
1213 | int theChar;
|
||
1214 | int myNumber;
|
||
1215 | |||
1216 | myNumber = theNumber; |
||
1217 | |||
1218 | if ((myNumber > 100) || (digitCnt >= 3)) |
||
1219 | { |
||
1220 | theChar = 0x30 + myNumber / 100; |
||
1221 | sendchar(theChar ); |
||
1222 | } |
||
1223 | |||
1224 | if ((myNumber > 10) || (digitCnt >= 2)) |
||
1225 | { |
||
1226 | theChar = 0x30 + ((myNumber % 100) / 10 ); |
||
1227 | sendchar(theChar ); |
||
1228 | } |
||
1229 | theChar = 0x30 + (myNumber % 10); |
||
1230 | sendchar(theChar ); |
||
1231 | } |
||
1232 | |||
1233 | |||
1234 | |||
1235 | |||
1236 | //************************************************************************
|
||
1237 | static void PrintCPUstats(void) |
||
1238 | { |
||
1239 | unsigned char fuseByte; |
||
1240 | |||
1241 | PrintFromPROGMEMln(gTextMsg_Explorer, 0);
|
||
1242 | |||
1243 | PrintFromPROGMEM(gTextMsg_COMPILED_ON, 0);
|
||
1244 | PrintFromPROGMEMln(gTextMsg_GCC_DATE_STR, 0);
|
||
1245 | |||
1246 | PrintFromPROGMEM(gTextMsg_CPU_Type, 0);
|
||
1247 | PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
|
||
1248 | |||
1249 | PrintFromPROGMEM(gTextMsg_AVR_ARCH, 0);
|
||
1250 | PrintDecInt(__AVR_ARCH__, 1);
|
||
1251 | PrintNewLine(); |
||
1252 | |||
1253 | PrintFromPROGMEM(gTextMsg_GCC_VERSION, 0);
|
||
1254 | PrintFromPROGMEMln(gTextMsg_GCC_VERSION_STR, 0);
|
||
1255 | |||
1256 | //* these can be found in avr/version.h
|
||
1257 | PrintFromPROGMEM(gTextMsg_AVR_LIBC, 0);
|
||
1258 | PrintFromPROGMEMln(gTextMsg_AVR_LIBC_VER_STR, 0);
|
||
1259 | |||
1260 | #if defined(SIGNATURE_0)
|
||
1261 | PrintFromPROGMEM(gTextMsg_CPU_SIGNATURE, 0);
|
||
1262 | //* these can be found in avr/iomxxx.h
|
||
1263 | PrintHexByte(SIGNATURE_0); |
||
1264 | PrintHexByte(SIGNATURE_1); |
||
1265 | PrintHexByte(SIGNATURE_2); |
||
1266 | PrintNewLine(); |
||
1267 | #endif
|
||
1268 | |||
1269 | |||
1270 | #if defined(GET_LOW_FUSE_BITS)
|
||
1271 | //* fuse settings
|
||
1272 | PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOW, 0);
|
||
1273 | fuseByte = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS); |
||
1274 | PrintHexByte(fuseByte); |
||
1275 | PrintNewLine(); |
||
1276 | |||
1277 | PrintFromPROGMEM(gTextMsg_FUSE_BYTE_HIGH, 0);
|
||
1278 | fuseByte = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS); |
||
1279 | PrintHexByte(fuseByte); |
||
1280 | PrintNewLine(); |
||
1281 | |||
1282 | PrintFromPROGMEM(gTextMsg_FUSE_BYTE_EXT, 0);
|
||
1283 | fuseByte = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS); |
||
1284 | PrintHexByte(fuseByte); |
||
1285 | PrintNewLine(); |
||
1286 | |||
1287 | PrintFromPROGMEM(gTextMsg_FUSE_BYTE_LOCK, 0);
|
||
1288 | fuseByte = boot_lock_fuse_bits_get(GET_LOCK_BITS); |
||
1289 | PrintHexByte(fuseByte); |
||
1290 | PrintNewLine(); |
||
1291 | |||
1292 | #endif
|
||
1293 | |||
1294 | } |
||
1295 | |||
1296 | #ifndef sbi
|
||
1297 | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||
1298 | #endif
|
||
1299 | |||
1300 | //************************************************************************
|
||
1301 | int analogRead(uint8_t pin)
|
||
1302 | { |
||
1303 | uint8_t low, high; |
||
1304 | |||
1305 | // set the analog reference (high two bits of ADMUX) and select the
|
||
1306 | // channel (low 4 bits). this also sets ADLAR (left-adjust result)
|
||
1307 | // to 0 (the default).
|
||
1308 | // ADMUX = (analog_reference << 6) | (pin & 0x07);
|
||
1309 | ADMUX = (1 << 6) | (pin & 0x07); |
||
1310 | |||
1311 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||
1312 | // the MUX5 bit of ADCSRB selects whether we're reading from channels
|
||
1313 | // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
|
||
1314 | ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); |
||
1315 | #endif
|
||
1316 | |||
1317 | // without a delay, we seem to read from the wrong channel
|
||
1318 | //delay(1);
|
||
1319 | |||
1320 | // start the conversion
|
||
1321 | sbi(ADCSRA, ADSC); |
||
1322 | |||
1323 | // ADSC is cleared when the conversion finishes
|
||
1324 | while (bit_is_set(ADCSRA, ADSC));
|
||
1325 | |||
1326 | // we have to read ADCL first; doing so locks both ADCL
|
||
1327 | // and ADCH until ADCH is read. reading ADCL second would
|
||
1328 | // cause the results of each conversion to be discarded,
|
||
1329 | // as ADCL and ADCH would be locked when it completed.
|
||
1330 | low = ADCL; |
||
1331 | high = ADCH; |
||
1332 | |||
1333 | // combine the two bytes
|
||
1334 | return (high << 8) | low; |
||
1335 | } |
||
1336 | |||
1337 | //************************************************************************
|
||
1338 | static void BlinkLED(void) |
||
1339 | { |
||
1340 | PROGLED_DDR |= (1<<PROGLED_PIN);
|
||
1341 | PROGLED_PORT |= (1<<PROGLED_PIN); // active high LED ON |
||
1342 | |||
1343 | while (!Serial_Available())
|
||
1344 | { |
||
1345 | PROGLED_PORT &= ~(1<<PROGLED_PIN); // turn LED off |
||
1346 | delay_ms(100);
|
||
1347 | PROGLED_PORT |= (1<<PROGLED_PIN); // turn LED on |
||
1348 | delay_ms(100);
|
||
1349 | } |
||
1350 | recchar(); // get the char out of the buffer
|
||
1351 | } |
||
1352 | |||
1353 | enum
|
||
1354 | { |
||
1355 | kDUMP_FLASH = 0,
|
||
1356 | kDUMP_EEPROM, |
||
1357 | kDUMP_RAM |
||
1358 | }; |
||
1359 | |||
1360 | //************************************************************************
|
||
1361 | static void DumpHex(unsigned char dumpWhat, unsigned long startAddress, unsigned char numRows) |
||
1362 | { |
||
1363 | unsigned long myAddressPointer; |
||
1364 | uint8_t ii; |
||
1365 | unsigned char theValue; |
||
1366 | char asciiDump[18]; |
||
1367 | unsigned char *ramPtr; |
||
1368 | |||
1369 | |||
1370 | ramPtr = 0;
|
||
1371 | theValue = 0;
|
||
1372 | myAddressPointer = startAddress; |
||
1373 | while (numRows > 0) |
||
1374 | { |
||
1375 | if (myAddressPointer > 0x10000) |
||
1376 | { |
||
1377 | PrintHexByte((myAddressPointer >> 16) & 0x00ff); |
||
1378 | } |
||
1379 | PrintHexByte((myAddressPointer >> 8) & 0x00ff); |
||
1380 | PrintHexByte(myAddressPointer & 0x00ff);
|
||
1381 | sendchar(0x20);
|
||
1382 | sendchar('-');
|
||
1383 | sendchar(0x20);
|
||
1384 | |||
1385 | asciiDump[0] = 0; |
||
1386 | for (ii=0; ii<16; ii++) |
||
1387 | { |
||
1388 | switch(dumpWhat)
|
||
1389 | { |
||
1390 | case kDUMP_FLASH:
|
||
1391 | theValue = pgm_read_byte_far(myAddressPointer); |
||
1392 | break;
|
||
1393 | |||
1394 | case kDUMP_EEPROM:
|
||
1395 | theValue = eeprom_read_byte((void *)myAddressPointer);
|
||
1396 | break;
|
||
1397 | |||
1398 | case kDUMP_RAM:
|
||
1399 | theValue = ramPtr[myAddressPointer]; |
||
1400 | break;
|
||
1401 | |||
1402 | } |
||
1403 | PrintHexByte(theValue); |
||
1404 | sendchar(0x20);
|
||
1405 | if ((theValue >= 0x20) && (theValue < 0x7f)) |
||
1406 | { |
||
1407 | asciiDump[ii % 16] = theValue;
|
||
1408 | } |
||
1409 | else
|
||
1410 | { |
||
1411 | asciiDump[ii % 16] = '.'; |
||
1412 | } |
||
1413 | |||
1414 | myAddressPointer++; |
||
1415 | } |
||
1416 | asciiDump[16] = 0; |
||
1417 | PrintString(asciiDump); |
||
1418 | PrintNewLine(); |
||
1419 | |||
1420 | numRows--; |
||
1421 | } |
||
1422 | } |
||
1423 | |||
1424 | |||
1425 | |||
1426 | //************************************************************************
|
||
1427 | //* returns amount of extended memory
|
||
1428 | static void EEPROMtest(void) |
||
1429 | { |
||
1430 | int ii;
|
||
1431 | char theChar;
|
||
1432 | char theEEPROMchar;
|
||
1433 | int errorCount;
|
||
1434 | |||
1435 | PrintFromPROGMEMln(gTextMsg_WriteToEEprom, 0);
|
||
1436 | PrintNewLine(); |
||
1437 | ii = 0;
|
||
1438 | while (((theChar = pgm_read_byte_far(gTextMsg_Explorer + ii)) != '*') && (ii < 512)) |
||
1439 | { |
||
1440 | eeprom_write_byte((uint8_t *)ii, theChar); |
||
1441 | if (theChar == 0) |
||
1442 | { |
||
1443 | PrintFromPROGMEM(gTextMsg_SPACE, 0);
|
||
1444 | } |
||
1445 | else
|
||
1446 | { |
||
1447 | sendchar(theChar); |
||
1448 | } |
||
1449 | ii++; |
||
1450 | } |
||
1451 | |||
1452 | //* no go back through and test
|
||
1453 | PrintNewLine(); |
||
1454 | PrintNewLine(); |
||
1455 | PrintFromPROGMEMln(gTextMsg_ReadingEEprom, 0);
|
||
1456 | PrintNewLine(); |
||
1457 | errorCount = 0;
|
||
1458 | ii = 0;
|
||
1459 | while (((theChar = pgm_read_byte_far(gTextMsg_Explorer + ii)) != '*') && (ii < 512)) |
||
1460 | { |
||
1461 | theEEPROMchar = eeprom_read_byte((uint8_t *)ii); |
||
1462 | if (theEEPROMchar == 0) |
||
1463 | { |
||
1464 | PrintFromPROGMEM(gTextMsg_SPACE, 0);
|
||
1465 | } |
||
1466 | else
|
||
1467 | { |
||
1468 | sendchar(theEEPROMchar); |
||
1469 | } |
||
1470 | if (theEEPROMchar != theChar)
|
||
1471 | { |
||
1472 | errorCount++; |
||
1473 | } |
||
1474 | ii++; |
||
1475 | } |
||
1476 | PrintNewLine(); |
||
1477 | PrintNewLine(); |
||
1478 | PrintFromPROGMEM(gTextMsg_EEPROMerrorCnt, 0);
|
||
1479 | PrintDecInt(errorCount, 1);
|
||
1480 | PrintNewLine(); |
||
1481 | PrintNewLine(); |
||
1482 | |||
1483 | gEepromIndex = 0; //* set index back to zero for next eeprom dump |
||
1484 | |||
1485 | } |
||
1486 | |||
1487 | |||
1488 | |||
1489 | #if (FLASHEND > 0x08000) |
||
1490 | #include "avrinterruptnames.h" |
||
1491 | #ifndef _INTERRUPT_NAMES_DEFINED_
|
||
1492 | #warning Interrupt vectors not defined
|
||
1493 | #endif
|
||
1494 | #endif
|
||
1495 | |||
1496 | //************************************************************************
|
||
1497 | static void VectorDisplay(void) |
||
1498 | { |
||
1499 | unsigned long byte1; |
||
1500 | unsigned long byte2; |
||
1501 | unsigned long byte3; |
||
1502 | unsigned long byte4; |
||
1503 | unsigned long word1; |
||
1504 | unsigned long word2; |
||
1505 | int vectorIndex;
|
||
1506 | unsigned long myMemoryPtr; |
||
1507 | unsigned long wordMemoryAddress; |
||
1508 | unsigned long realitiveAddr; |
||
1509 | unsigned long myFullAddress; |
||
1510 | unsigned long absoluteAddr; |
||
1511 | #if defined(_INTERRUPT_NAMES_DEFINED_)
|
||
1512 | long stringPointer;
|
||
1513 | #endif
|
||
1514 | |||
1515 | myMemoryPtr = 0;
|
||
1516 | vectorIndex = 0;
|
||
1517 | PrintFromPROGMEMln(gTextMsg_CPU_Name, 0);
|
||
1518 | PrintFromPROGMEMln(gTextMsg_VECTOR_HEADER, 0);
|
||
1519 | // V# ADDR op code
|
||
1520 | // 1 - 0000 = C3 BB 00 00 rjmp 03BB >000776 RESET
|
||
1521 | while (vectorIndex < kInterruptVectorCount)
|
||
1522 | { |
||
1523 | wordMemoryAddress = myMemoryPtr / 2;
|
||
1524 | // 01 - 0000 = 12 34
|
||
1525 | PrintDecInt(vectorIndex + 1, 2); |
||
1526 | sendchar(0x20);
|
||
1527 | sendchar('-');
|
||
1528 | sendchar(0x20);
|
||
1529 | PrintHexByte((wordMemoryAddress >> 8) & 0x00ff); |
||
1530 | PrintHexByte((wordMemoryAddress) & 0x00ff);
|
||
1531 | sendchar(0x20);
|
||
1532 | sendchar('=');
|
||
1533 | sendchar(0x20);
|
||
1534 | |||
1535 | |||
1536 | //* the AVR is LITTLE ENDIAN, swap the byte order
|
||
1537 | byte1 = pgm_read_byte_far(myMemoryPtr++); |
||
1538 | byte2 = pgm_read_byte_far(myMemoryPtr++); |
||
1539 | word1 = (byte2 << 8) + byte1;
|
||
1540 | |||
1541 | byte3 = pgm_read_byte_far(myMemoryPtr++); |
||
1542 | byte4 = pgm_read_byte_far(myMemoryPtr++); |
||
1543 | word2 = (byte4 << 8) + byte3;
|
||
1544 | |||
1545 | |||
1546 | PrintHexByte(byte2); |
||
1547 | sendchar(0x20);
|
||
1548 | PrintHexByte(byte1); |
||
1549 | sendchar(0x20);
|
||
1550 | PrintHexByte(byte4); |
||
1551 | sendchar(0x20);
|
||
1552 | PrintHexByte(byte3); |
||
1553 | sendchar(0x20);
|
||
1554 | |||
1555 | if (word1 == 0xffff) |
||
1556 | { |
||
1557 | PrintFromPROGMEM(gTextMsg_noVector, 0);
|
||
1558 | } |
||
1559 | else if ((word1 & 0xc000) == 0xc000) |
||
1560 | { |
||
1561 | //* rjmp instruction
|
||
1562 | realitiveAddr = word1 & 0x3FFF;
|
||
1563 | absoluteAddr = wordMemoryAddress + realitiveAddr; //* add the offset to the current address
|
||
1564 | absoluteAddr = absoluteAddr << 1; //* multiply by 2 for byte address |
||
1565 | |||
1566 | PrintFromPROGMEM(gTextMsg_rjmp, 0);
|
||
1567 | PrintHexByte((realitiveAddr >> 8) & 0x00ff); |
||
1568 | PrintHexByte((realitiveAddr) & 0x00ff);
|
||
1569 | sendchar(0x20);
|
||
1570 | sendchar('>');
|
||
1571 | PrintHexByte((absoluteAddr >> 16) & 0x00ff); |
||
1572 | PrintHexByte((absoluteAddr >> 8) & 0x00ff); |
||
1573 | PrintHexByte((absoluteAddr) & 0x00ff);
|
||
1574 | |||
1575 | } |
||
1576 | else if ((word1 & 0xfE0E) == 0x940c) |
||
1577 | { |
||
1578 | //* jmp instruction, this is REALLY complicated, refer to the instruction manual (JMP)
|
||
1579 | myFullAddress = ((byte1 & 0x01) << 16) + |
||
1580 | ((byte1 & 0xf0) << 17) + |
||
1581 | ((byte2 & 0x01) << 21) + |
||
1582 | word2; |
||
1583 | |||
1584 | absoluteAddr = myFullAddress << 1;
|
||
1585 | |||
1586 | PrintFromPROGMEM(gTextMsg_jmp, 0);
|
||
1587 | PrintHexByte((myFullAddress >> 16) & 0x00ff); |
||
1588 | PrintHexByte((myFullAddress >> 8) & 0x00ff); |
||
1589 | PrintHexByte((myFullAddress) & 0x00ff);
|
||
1590 | sendchar(0x20);
|
||
1591 | sendchar('>');
|
||
1592 | PrintHexByte((absoluteAddr >> 16) & 0x00ff); |
||
1593 | PrintHexByte((absoluteAddr >> 8) & 0x00ff); |
||
1594 | PrintHexByte((absoluteAddr) & 0x00ff);
|
||
1595 | } |
||
1596 | |||
1597 | #if defined(_INTERRUPT_NAMES_DEFINED_)
|
||
1598 | sendchar(0x20);
|
||
1599 | stringPointer = pgm_read_word_far(&(gInterruptNameTable[vectorIndex])); |
||
1600 | PrintFromPROGMEM((char *)stringPointer, 0); |
||
1601 | #endif
|
||
1602 | PrintNewLine(); |
||
1603 | |||
1604 | vectorIndex++; |
||
1605 | } |
||
1606 | } |
||
1607 | |||
1608 | //************************************************************************
|
||
1609 | static void PrintAvailablePort(char thePortLetter) |
||
1610 | { |
||
1611 | PrintFromPROGMEM(gTextMsg_PORT, 0);
|
||
1612 | sendchar(thePortLetter); |
||
1613 | PrintNewLine(); |
||
1614 | } |
||
1615 | |||
1616 | //************************************************************************
|
||
1617 | static void ListAvailablePorts(void) |
||
1618 | { |
||
1619 | |||
1620 | #ifdef DDRA
|
||
1621 | PrintAvailablePort('A');
|
||
1622 | #endif
|
||
1623 | |||
1624 | #ifdef DDRB
|
||
1625 | PrintAvailablePort('B');
|
||
1626 | #endif
|
||
1627 | |||
1628 | #ifdef DDRC
|
||
1629 | PrintAvailablePort('C');
|
||
1630 | #endif
|
||
1631 | |||
1632 | #ifdef DDRD
|
||
1633 | PrintAvailablePort('D');
|
||
1634 | #endif
|
||
1635 | |||
1636 | #ifdef DDRE
|
||
1637 | PrintAvailablePort('E');
|
||
1638 | #endif
|
||
1639 | |||
1640 | #ifdef DDRF
|
||
1641 | PrintAvailablePort('F');
|
||
1642 | #endif
|
||
1643 | |||
1644 | #ifdef DDRG
|
||
1645 | PrintAvailablePort('G');
|
||
1646 | #endif
|
||
1647 | |||
1648 | #ifdef DDRH
|
||
1649 | PrintAvailablePort('H');
|
||
1650 | #endif
|
||
1651 | |||
1652 | #ifdef DDRI
|
||
1653 | PrintAvailablePort('I');
|
||
1654 | #endif
|
||
1655 | |||
1656 | #ifdef DDRJ
|
||
1657 | PrintAvailablePort('J');
|
||
1658 | #endif
|
||
1659 | |||
1660 | #ifdef DDRK
|
||
1661 | PrintAvailablePort('K');
|
||
1662 | #endif
|
||
1663 | |||
1664 | #ifdef DDRL
|
||
1665 | PrintAvailablePort('L');
|
||
1666 | #endif
|
||
1667 | |||
1668 | } |
||
1669 | |||
1670 | //************************************************************************
|
||
1671 | static void AVR_PortOutput(void) |
||
1672 | { |
||
1673 | char portLetter;
|
||
1674 | char getCharFlag;
|
||
1675 | |||
1676 | PrintFromPROGMEM(gTextMsg_WHAT_PORT, 0);
|
||
1677 | |||
1678 | portLetter = recchar(); |
||
1679 | portLetter = portLetter & 0x5f;
|
||
1680 | sendchar(portLetter); |
||
1681 | PrintNewLine(); |
||
1682 | |||
1683 | if ((portLetter >= 'A') && (portLetter <= 'Z')) |
||
1684 | { |
||
1685 | getCharFlag = true;
|
||
1686 | switch(portLetter)
|
||
1687 | { |
||
1688 | #ifdef DDRA
|
||
1689 | case 'A': |
||
1690 | DDRA = 0xff;
|
||
1691 | while (!Serial_Available())
|
||
1692 | { |
||
1693 | PORTA ^= 0xff;
|
||
1694 | delay_ms(200);
|
||
1695 | } |
||
1696 | PORTA = 0;
|
||
1697 | break;
|
||
1698 | #endif
|
||
1699 | |||
1700 | #ifdef DDRB
|
||
1701 | case 'B': |
||
1702 | DDRB = 0xff;
|
||
1703 | while (!Serial_Available())
|
||
1704 | { |
||
1705 | PORTB ^= 0xff;
|
||
1706 | delay_ms(200);
|
||
1707 | } |
||
1708 | PORTB = 0;
|
||
1709 | break;
|
||
1710 | #endif
|
||
1711 | |||
1712 | #ifdef DDRC
|
||
1713 | case 'C': |
||
1714 | DDRC = 0xff;
|
||
1715 | while (!Serial_Available())
|
||
1716 | { |
||
1717 | PORTC ^= 0xff;
|
||
1718 | delay_ms(200);
|
||
1719 | } |
||
1720 | PORTC = 0;
|
||
1721 | break;
|
||
1722 | #endif
|
||
1723 | |||
1724 | #ifdef DDRD
|
||
1725 | case 'D': |
||
1726 | DDRD = 0xff;
|
||
1727 | while (!Serial_Available())
|
||
1728 | { |
||
1729 | PORTD ^= 0xff;
|
||
1730 | delay_ms(200);
|
||
1731 | } |
||
1732 | PORTD = 0;
|
||
1733 | break;
|
||
1734 | #endif
|
||
1735 | |||
1736 | #ifdef DDRE
|
||
1737 | case 'E': |
||
1738 | DDRE = 0xff;
|
||
1739 | while (!Serial_Available())
|
||
1740 | { |
||
1741 | PORTE ^= 0xff;
|
||
1742 | delay_ms(200);
|
||
1743 | } |
||
1744 | PORTE = 0;
|
||
1745 | break;
|
||
1746 | #endif
|
||
1747 | |||
1748 | #ifdef DDRF
|
||
1749 | case 'F': |
||
1750 | DDRF = 0xff;
|
||
1751 | while (!Serial_Available())
|
||
1752 | { |
||
1753 | PORTF ^= 0xff;
|
||
1754 | delay_ms(200);
|
||
1755 | } |
||
1756 | PORTF = 0;
|
||
1757 | break;
|
||
1758 | #endif
|
||
1759 | |||
1760 | #ifdef DDRG
|
||
1761 | case 'G': |
||
1762 | DDRG = 0xff;
|
||
1763 | while (!Serial_Available())
|
||
1764 | { |
||
1765 | PORTG ^= 0xff;
|
||
1766 | delay_ms(200);
|
||
1767 | } |
||
1768 | PORTG = 0;
|
||
1769 | break;
|
||
1770 | #endif
|
||
1771 | |||
1772 | #ifdef DDRH
|
||
1773 | case 'H': |
||
1774 | DDRH = 0xff;
|
||
1775 | while (!Serial_Available())
|
||
1776 | { |
||
1777 | PORTH ^= 0xff;
|
||
1778 | delay_ms(200);
|
||
1779 | } |
||
1780 | PORTH = 0;
|
||
1781 | break;
|
||
1782 | #endif
|
||
1783 | |||
1784 | #ifdef DDRI
|
||
1785 | case 'I': |
||
1786 | DDRI = 0xff;
|
||
1787 | while (!Serial_Available())
|
||
1788 | { |
||
1789 | PORTI ^= 0xff;
|
||
1790 | delay_ms(200);
|
||
1791 | } |
||
1792 | PORTI = 0;
|
||
1793 | break;
|
||
1794 | #endif
|
||
1795 | |||
1796 | #ifdef DDRJ
|
||
1797 | case 'J': |
||
1798 | DDRJ = 0xff;
|
||
1799 | while (!Serial_Available())
|
||
1800 | { |
||
1801 | PORTJ ^= 0xff;
|
||
1802 | delay_ms(200);
|
||
1803 | } |
||
1804 | PORTJ = 0;
|
||
1805 | break;
|
||
1806 | #endif
|
||
1807 | |||
1808 | #ifdef DDRK
|
||
1809 | case 'K': |
||
1810 | DDRK = 0xff;
|
||
1811 | while (!Serial_Available())
|
||
1812 | { |
||
1813 | PORTK ^= 0xff;
|
||
1814 | delay_ms(200);
|
||
1815 | } |
||
1816 | PORTK = 0;
|
||
1817 | break;
|
||
1818 | #endif
|
||
1819 | |||
1820 | #ifdef DDRL
|
||
1821 | case 'L': |
||
1822 | DDRL = 0xff;
|
||
1823 | while (!Serial_Available())
|
||
1824 | { |
||
1825 | PORTL ^= 0xff;
|
||
1826 | delay_ms(200);
|
||
1827 | } |
||
1828 | PORTL = 0;
|
||
1829 | break;
|
||
1830 | #endif
|
||
1831 | |||
1832 | default:
|
||
1833 | PrintFromPROGMEMln(gTextMsg_PortNotSupported, 0);
|
||
1834 | getCharFlag = false;
|
||
1835 | break;
|
||
1836 | } |
||
1837 | if (getCharFlag)
|
||
1838 | { |
||
1839 | recchar(); |
||
1840 | } |
||
1841 | } |
||
1842 | else
|
||
1843 | { |
||
1844 | PrintFromPROGMEMln(gTextMsg_MustBeLetter, 0);
|
||
1845 | } |
||
1846 | } |
||
1847 | |||
1848 | |||
1849 | //*******************************************************************
|
||
1850 | static void PrintHelp(void) |
||
1851 | { |
||
1852 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 0);
|
||
1853 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 0);
|
||
1854 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 0);
|
||
1855 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 0);
|
||
1856 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 0);
|
||
1857 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 0);
|
||
1858 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 0);
|
||
1859 | |||
1860 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 0);
|
||
1861 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 0);
|
||
1862 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 0);
|
||
1863 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 0);
|
||
1864 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 0);
|
||
1865 | } |
||
1866 | |||
1867 | //************************************************************************
|
||
1868 | static void RunMonitor(void) |
||
1869 | { |
||
1870 | char keepGoing;
|
||
1871 | unsigned char theChar; |
||
1872 | int ii, jj;
|
||
1873 | |||
1874 | for (ii=0; ii<5; ii++) |
||
1875 | { |
||
1876 | for (jj=0; jj<25; jj++) |
||
1877 | { |
||
1878 | sendchar('!');
|
||
1879 | } |
||
1880 | PrintNewLine(); |
||
1881 | } |
||
1882 | |||
1883 | gRamIndex = 0;
|
||
1884 | gFlashIndex = 0;
|
||
1885 | gEepromIndex = 0;
|
||
1886 | |||
1887 | PrintFromPROGMEMln(gTextMsg_Explorer, 0);
|
||
1888 | |||
1889 | keepGoing = 1;
|
||
1890 | while (keepGoing)
|
||
1891 | { |
||
1892 | PrintFromPROGMEM(gTextMsg_Prompt, 0);
|
||
1893 | theChar = recchar(); |
||
1894 | if (theChar >= 0x60) |
||
1895 | { |
||
1896 | theChar = theChar & 0x5F;
|
||
1897 | } |
||
1898 | #if defined( _CEREBOTPLUS_BOARD_ )
|
||
1899 | if (theChar == 0x5F) |
||
1900 | { |
||
1901 | |||
1902 | } |
||
1903 | else
|
||
1904 | #endif
|
||
1905 | if (theChar >= 0x20) |
||
1906 | { |
||
1907 | sendchar(theChar); |
||
1908 | sendchar(0x20);
|
||
1909 | } |
||
1910 | |||
1911 | switch(theChar)
|
||
1912 | { |
||
1913 | case '0': |
||
1914 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_0, 2);
|
||
1915 | gFlashIndex = 0;
|
||
1916 | gRamIndex = 0;
|
||
1917 | gEepromIndex = 0;
|
||
1918 | break;
|
||
1919 | |||
1920 | case '?': |
||
1921 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_QM, 2);
|
||
1922 | PrintCPUstats(); |
||
1923 | break;
|
||
1924 | |||
1925 | case '@': |
||
1926 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_AT, 2);
|
||
1927 | EEPROMtest(); |
||
1928 | break;
|
||
1929 | |||
1930 | case 'B': |
||
1931 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_B, 2);
|
||
1932 | BlinkLED(); |
||
1933 | break;
|
||
1934 | |||
1935 | case 'E': |
||
1936 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_E, 2);
|
||
1937 | DumpHex(kDUMP_EEPROM, gEepromIndex, 16);
|
||
1938 | gEepromIndex += 256;
|
||
1939 | if (gEepromIndex > E2END)
|
||
1940 | { |
||
1941 | gEepromIndex = 0;
|
||
1942 | } |
||
1943 | break;
|
||
1944 | |||
1945 | case 'F': |
||
1946 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_F, 2);
|
||
1947 | DumpHex(kDUMP_FLASH, gFlashIndex, 16);
|
||
1948 | gFlashIndex += 256;
|
||
1949 | break;
|
||
1950 | |||
1951 | case 'H': |
||
1952 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_H, 2);
|
||
1953 | PrintHelp(); |
||
1954 | break;
|
||
1955 | |||
1956 | case 'L': |
||
1957 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_L, 2);
|
||
1958 | ListAvailablePorts(); |
||
1959 | break;
|
||
1960 | |||
1961 | case 'Q': |
||
1962 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_Q, 2);
|
||
1963 | keepGoing = false;
|
||
1964 | break;
|
||
1965 | |||
1966 | case 'R': |
||
1967 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_R, 2);
|
||
1968 | DumpHex(kDUMP_RAM, gRamIndex, 16);
|
||
1969 | gRamIndex += 256;
|
||
1970 | break;
|
||
1971 | |||
1972 | case 'V': |
||
1973 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_V, 2);
|
||
1974 | VectorDisplay(); |
||
1975 | break;
|
||
1976 | |||
1977 | case 'Y': |
||
1978 | PrintFromPROGMEMln(gTextMsg_HELP_MSG_Y, 2);
|
||
1979 | AVR_PortOutput(); |
||
1980 | break;
|
||
1981 | |||
1982 | #if defined( _CEREBOTPLUS_BOARD_ )
|
||
1983 | case 0x5F: |
||
1984 | //* do nothing
|
||
1985 | break;
|
||
1986 | #endif
|
||
1987 | |||
1988 | default:
|
||
1989 | PrintFromPROGMEMln(gTextMsg_HUH, 0);
|
||
1990 | break;
|
||
1991 | } |
||
1992 | } |
||
1993 | } |
||
1994 | |||
1995 | #endif
|