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.2 2009-02-20 21:10:01 zer0 Exp $
24 * A simple bootloader example.
28 #include <aversive/wait.h>
29 #include <aversive/pgmspace.h>
34 #include <util/crc16.h>
37 #if defined __AVR_ATmega128__
39 #elif defined __AVR_ATmega2560__
47 #define echo(c) do {} while(0)
49 #define echo(c) uart_send(UARTNUM, c)
52 static void bootloader_puts(const char *buf)
55 uart_send(UARTNUM, *(buf++));
58 static uint32_t bootloader_query_hex(void)
64 memset(buf, 0, sizeof(buf));
66 while ((c=uart_recv_nowait(UARTNUM)) == -1);
67 if (i >= sizeof(buf) - 1)
69 if (c == '\n' || c == '\r') {
77 return strtol(buf, NULL, 16);
80 static void launch_app(void)
82 bootloader_puts("BOOT\r\n");
89 static void disp_digit(uint8_t x)
92 uart_send(UARTNUM, '0' + x);
94 uart_send(UARTNUM, 'a' - 10 + x);
97 static void disp_hex8(uint8_t x)
103 static void disp_hex16(uint16_t x)
109 static void crc_app(void)
111 uint32_t start_addr, addr, size;
113 uint16_t crc = 0xffff;
115 bootloader_puts("start addr?\r\n");
116 start_addr = bootloader_query_hex();
117 if (start_addr > FLASHEND)
119 bootloader_puts("size?\r\n");
120 size = bootloader_query_hex();
121 if (start_addr + size > FLASHEND)
123 for (addr=start_addr; addr<start_addr+size; addr++) {
124 c = pgm_read_byte_far(addr);
125 crc = _crc_ccitt_update(crc, c);
130 bootloader_puts("KO");
133 static void prog_page(void)
138 uint16_t crc = 0xffff;
139 uint8_t buf[SPM_PAGESIZE];
141 #define SPM_PAGEMASK ((uint32_t)SPM_PAGESIZE-1)
142 bootloader_puts("addr?\r\n");
143 addr = bootloader_query_hex();
146 /* start_addr must be page aligned */
147 if (addr & SPM_PAGEMASK)
150 bootloader_puts("addr ok\r\n");
152 /* data is received like the .bin format (which is already in
154 for (i=0; i<SPM_PAGESIZE; i++) {
155 while ((c=uart_recv_nowait(UARTNUM)) == -1);
156 crc = _crc_ccitt_update(crc, c);
160 bootloader_puts(" (y to valid)\r\n");
161 while ((c=uart_recv_nowait(UARTNUM)) == -1);
167 boot_page_erase(addr);
168 boot_spm_busy_wait();
170 /* Set up little-endian word and fill tmp buf. */
171 for (i=0; i<SPM_PAGESIZE; i+=2) {
172 uint16_t w = buf[i] + ((uint16_t)(buf[i+1]) << 8);
173 boot_page_fill(addr + i, w);
176 boot_page_write(addr);
177 boot_spm_busy_wait();
179 /* Reenable RWW-section again. We need this if we want to jump
180 * back to the application after bootloading. */
183 bootloader_puts("OK");
186 bootloader_puts("KO");
195 /* move interrupt vector in bootloader section */
197 MCUCR = (1 << IVSEL);
201 bootloader_puts("\r\n");
203 bootloader_puts("cmd>");
204 while ((c=uart_recv_nowait(UARTNUM)) == -1);
212 bootloader_puts("bad cmd (p:prog_page c:crc x:exec)");
213 bootloader_puts("\r\n");