2 * Copyright Droids Corporation
3 * Olivier Matz <zer0@droids-corp.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Revision : $Id: main.c,v 1.4 2009-05-27 20:04:06 zer0 Exp $
24 * A simple bootloader example.
28 #include <aversive/wait.h>
29 #include <aversive/pgmspace.h>
33 #include <util/crc16.h>
36 #define BRAKE_DDR() do { DDRJ |= 0xF0; } while(0)
37 #define BRAKE_ON() do { PORTJ |= 0xF0; } while(0)
38 #define BRAKE_OFF() do { PORTJ &= 0x0F; } while(0)
40 #define LED1_ON() sbi(PORTJ, 2)
41 #define LED1_OFF() cbi(PORTJ, 2)
43 #define LED2_ON() sbi(PORTJ, 3)
44 #define LED2_OFF() cbi(PORTJ, 3)
50 #define echo(c) do {} while(0)
52 #define echo(c) uart_send(c)
102 #define UCSRxA UCSR3A
103 #define UCSRxB UCSR3B
104 #define UCSRxC UCSR3C
111 #define UCSZx0 UCSZ30
112 #define UCSZx1 UCSZ31
118 static char uart_recv(void)
120 while ( !(UCSRxA & (1<<RXCx)) ) ;
124 static void uart_send(char c)
126 while ( !( UCSRxA & (1<<UDREx)) ) ;
130 static void uart_puts(const char *buf)
136 static int8_t bootloader_query_hex(uint32_t *val)
145 if (c == '\n' || c == '\r') {
149 else if (c >= '0' && c <= '9') {
153 else if (c >= 'a' && c <= 'f') {
155 tmp += (c - 'a' + 10);
157 else if (c >= 'A' && c <= 'F') {
159 tmp += (c - 'A' + 10);
167 /* launch application */
168 static void launch_app(void)
170 uart_puts("Boot...");
172 MCUCR = (0 << IVSEL);
176 static void disp_digit(uint8_t x)
185 static void disp_hex8(uint8_t x)
191 static void disp_hex16(uint16_t x)
197 static void disp_hex32(uint32_t x)
203 static void crc_app(void)
205 uint32_t start_addr, addr, size;
207 uint16_t crc = 0xffff;
210 uart_puts("addr?\r\n");
211 if (bootloader_query_hex(&start_addr))
213 if (start_addr > FLASHEND)
215 uart_puts("size?\r\n");
216 if (bootloader_query_hex(&size))
218 if (start_addr + size > FLASHEND)
220 for (addr=start_addr; addr<start_addr+size; addr++) {
222 /* ignore the 2nd page, it contains microb infos */
223 if (addr >= 256 && addr < 512)
226 c = pgm_read_byte_far(addr);
227 crc = _crc_ccitt_update(crc, c);
237 static void read32(void)
239 uint32_t start_addr, val = 0;
242 uart_puts("addr?\r\n");
243 if (bootloader_query_hex(&start_addr))
245 if (start_addr > FLASHEND)
247 for (i=0; i<4; i++) {
248 c = pgm_read_byte_far(start_addr+i);
258 static void prog_page(void)
263 uint16_t crc = 0xffff;
265 uint8_t buf[SPM_PAGESIZE];
267 #define SPM_PAGEMASK ((uint32_t)SPM_PAGESIZE-1)
268 uart_puts("addr?\r\n");
269 if (bootloader_query_hex(&addr))
273 /* start_addr must be page aligned */
274 if (addr & SPM_PAGEMASK)
281 /* data is received like the .bin format (which is already in
283 for (i=0; i<SPM_PAGESIZE; i++) {
285 crc = _crc_ccitt_update(crc, c);
291 uart_puts(" (y?)\r\n");
298 boot_page_erase(addr);
299 boot_spm_busy_wait();
301 /* Set up little-endian word and fill tmp buf. */
302 for (i=0; i<SPM_PAGESIZE; i+=2) {
303 uint16_t w = buf[i] + ((uint16_t)(buf[i+1]) << 8);
304 boot_page_fill(addr + i, w);
309 boot_page_write(addr);
310 boot_spm_busy_wait();
312 /* Reenable RWW-section again. We need this if we want to jump
313 * back to the application after bootloading. */
327 /* disable all motors and switch on leds */
332 UCSRxB = _BV(RXENx) | _BV(TXENx);
333 UCSRxC = _BV(UCSZx1) | _BV(UCSZx0); /* 8 bits no parity 1 stop */
334 UBRRx = 34; /* 57600 at 16 Mhz */
336 /* move interrupt vector in bootloader section */
338 MCUCR = (1 << IVSEL);
342 uart_puts("\r\ncmd> ");
345 while ( !(UCSRxA & (1<<RXCx)) ) {
347 if (i>1000000) /* wait about 1 sec */
352 uart_puts("\r\ncmd> ");
363 uart_puts("p:prog_page c:crc x:exec d:dump32");