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>
39 #define echo(c) do {} while(0)
41 #define echo(c) uart_send(c)
100 #define UCSZx0 UCSZ30
101 #define UCSZx1 UCSZ31
107 static char uart_recv(void)
109 while ( !(UCSRxA & (1<<RXCx)) ) ;
113 static void uart_send(char c)
115 while ( !( UCSRxA & (1<<UDREx)) ) ;
119 static void uart_puts(const char *buf)
125 static int8_t bootloader_query_hex(uint32_t *val)
134 if (c == '\n' || c == '\r') {
138 else if (c >= '0' && c <= '9') {
142 else if (c >= 'a' && c <= 'f') {
144 tmp += (c - 'a' + 10);
146 else if (c >= 'A' && c <= 'F') {
148 tmp += (c - 'A' + 10);
156 /* launch application */
157 static void launch_app(void)
159 uart_puts("Boot...");
161 MCUCR = (0 << IVSEL);
165 static void disp_digit(uint8_t x)
174 static void disp_hex8(uint8_t x)
180 static void disp_hex16(uint16_t x)
186 static void disp_hex32(uint32_t x)
192 static void crc_app(void)
194 uint32_t start_addr, addr, size;
196 uint16_t crc = 0xffff;
199 uart_puts("addr?\r\n");
200 if (bootloader_query_hex(&start_addr))
202 if (start_addr > FLASHEND)
204 uart_puts("size?\r\n");
205 if (bootloader_query_hex(&size))
207 if (start_addr + size > FLASHEND)
209 for (addr=start_addr; addr<start_addr+size; addr++) {
211 /* ignore the 2nd page, it contains microb infos */
212 if (addr >= 256 && addr < 512)
215 c = pgm_read_byte_far(addr);
216 crc = _crc_ccitt_update(crc, c);
226 static void read32(void)
228 uint32_t start_addr, val = 0;
231 uart_puts("addr?\r\n");
232 if (bootloader_query_hex(&start_addr))
234 if (start_addr > FLASHEND)
236 for (i=0; i<4; i++) {
237 c = pgm_read_byte_far(start_addr+i);
247 static void prog_page(void)
252 uint16_t crc = 0xffff;
254 uint8_t buf[SPM_PAGESIZE];
256 #define SPM_PAGEMASK ((uint32_t)SPM_PAGESIZE-1)
257 uart_puts("addr?\r\n");
258 if (bootloader_query_hex(&addr))
262 /* start_addr must be page aligned */
263 if (addr & SPM_PAGEMASK)
269 /* data is received like the .bin format (which is already in
271 for (i=0; i<SPM_PAGESIZE; i++) {
273 crc = _crc_ccitt_update(crc, c);
279 uart_puts(" (y?)\r\n");
286 boot_page_erase(addr);
287 boot_spm_busy_wait();
289 /* Set up little-endian word and fill tmp buf. */
290 for (i=0; i<SPM_PAGESIZE; i+=2) {
291 uint16_t w = buf[i] + ((uint16_t)(buf[i+1]) << 8);
292 boot_page_fill(addr + i, w);
295 boot_page_write(addr);
296 boot_spm_busy_wait();
298 /* Reenable RWW-section again. We need this if we want to jump
299 * back to the application after bootloading. */
314 UCSRxB = _BV(RXENx) | _BV(TXENx);
315 UCSRxC = _BV(UCSZx1) | _BV(UCSZx0); /* 8 bits no parity 1 stop */
316 UBRRx = 25; /* 57600 at 12 Mhz */
318 /* move interrupt vector in bootloader section */
320 MCUCR = (1 << IVSEL);
324 uart_puts("\r\ncmd> ");
327 while ( !(UCSRxA & (1<<RXCx)) ) {
329 if (i>1000000) /* wait about 1 sec */
334 uart_puts("\r\ncmd> ");
345 uart_puts("p:prog_page c:crc x:exec d:dump32");