add bootloader
authorOlivier Matz <zer0@droids-corp.org>
Wed, 20 May 2015 22:09:44 +0000 (00:09 +0200)
committerOlivier Matz <zer0@droids-corp.org>
Wed, 20 May 2015 22:13:35 +0000 (00:13 +0200)
bootloader/Makefile [new file with mode: 0755]
bootloader/main.c [new file with mode: 0755]
bootloader/uart_config.h [new file with mode: 0755]

diff --git a/bootloader/Makefile b/bootloader/Makefile
new file mode 100755 (executable)
index 0000000..52543f8
--- /dev/null
@@ -0,0 +1,41 @@
+TARGET = main
+
+# repertoire des modules
+AVERSIVE_DIR ?= ../../..
+# VALUE, absolute or relative path : example ../.. #
+
+CFLAGS += -Werror
+
+# atm128 or atm1284
+# address is 0xf000 (in words)
+LDFLAGS += -Wl,--section-start=.text=1e000
+UART_NUM = 1
+
+# atm2560
+# address is 0x1f800 (in words)
+# LDFLAGS += -Wl,--section-start=.text=3f000
+# UART_NUM = 1
+
+CFLAGS += -DUART_NUM=$(UART_NUM)
+
+# List C source files here. (C dependencies are automatically generated.)
+SRC = $(TARGET).c
+
+# List Assembler source files here.
+# Make them always end in a capital .S.  Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC =
+
+########################################
+
+-include .aversive_conf
+include $(AVERSIVE_DIR)/mk/aversive_project.mk
+
+program_noerase: $(TARGET).$(FORMAT_EXTENSION) $(TARGET).eep
+       echo $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\
+       $(AVRDUDE) -D -V $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) ;\
+
diff --git a/bootloader/main.c b/bootloader/main.c
new file mode 100755 (executable)
index 0000000..cd0202e
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  Copyright Droids Corporation
+ *  Olivier Matz <zer0@droids-corp.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Revision : $Id: main.c,v 1.4 2009-05-27 20:04:06 zer0 Exp $
+ *
+ */
+
+/*
+ * A simple bootloader example.
+ */
+
+#include <aversive.h>
+#include <aversive/wait.h>
+#include <aversive/pgmspace.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <util/crc16.h>
+#include <avr/boot.h>
+
+#define NOECHO
+
+#ifdef NOECHO
+#define echo(c) do {} while(0)
+#else
+#define echo(c) uart_send(c)
+#endif
+
+#if UART_NUM == 0
+
+#define UCSRxA UCSR0A
+#define UCSRxB UCSR0B
+#define UCSRxC UCSR0C
+#define RXCx RXC0
+#define UDRx UDR0
+#define UDREx UDRE0
+#define U2Xx U2X0
+#define RXENx RXEN0
+#define TXENx TXEN0
+#define UCSZx0 UCSZ00
+#define UCSZx1 UCSZ01
+#define UBRRx UBRR0
+
+#elif  UART_NUM == 1
+
+#define UCSRxA UCSR1A
+#define UCSRxB UCSR1B
+#define UCSRxC UCSR1C
+#define RXCx RXC1
+#define UDRx UDR1
+#define UDREx UDRE1
+#define U2Xx U2X1
+#define RXENx RXEN1
+#define TXENx TXEN1
+#define UCSZx0 UCSZ10
+#define UCSZx1 UCSZ11
+#define UBRRx UBRR1
+
+#elif  UART_NUM == 2
+
+#define UCSRxA UCSR2A
+#define UCSRxB UCSR2B
+#define UCSRxC UCSR2C
+#define RXCx RXC2
+#define UDRx UDR2
+#define UDREx UDRE2
+#define U2Xx U2X2
+#define RXENx RXEN2
+#define TXENx TXEN2
+#define UCSZx0 UCSZ20
+#define UCSZx1 UCSZ21
+#define UBRRx UBRR2
+
+#elif  UART_NUM == 3
+
+#define UCSRxA UCSR3A
+#define UCSRxB UCSR3B
+#define UCSRxC UCSR3C
+#define RXCx RXC3
+#define UDRx UDR3
+#define UDREx UDRE3
+#define U2Xx U2X3
+#define RXENx RXEN3
+#define TXENx TXEN3
+#define UCSZx0 UCSZ30
+#define UCSZx1 UCSZ31
+#define UBRRx UBRR3
+
+#endif
+
+
+static char uart_recv(void)
+{
+       while ( !(UCSRxA & (1<<RXCx)) ) ;
+       return UDRx;
+}
+
+static void uart_send(char c)
+{
+       while ( !( UCSRxA & (1<<UDREx)) ) ;
+       UDRx = c;
+}
+
+static void uart_puts(const char *buf)
+{
+       while (*buf)
+               uart_send(*(buf++));
+}
+
+static int8_t bootloader_query_hex(uint32_t *val)
+{
+       uint32_t tmp = 0;
+       int c;
+
+       while (1) {
+               c = uart_recv();
+               echo(c);
+
+               if (c == '\n' || c == '\r') {
+                       *val = tmp;
+                       return 0;
+               }
+               else if (c >= '0' && c <= '9') {
+                       tmp <<= 4;
+                       tmp += (c - '0');
+               }
+               else if (c >= 'a' && c <= 'f') {
+                       tmp <<= 4;
+                       tmp += (c - 'a' + 10);
+               }
+               else if (c >= 'A' && c <= 'F') {
+                       tmp <<= 4;
+                       tmp += (c - 'A' + 10);
+               }
+               else
+                       return -1;
+       }
+       return 0;
+}
+
+/* launch application */
+static void launch_app(void)
+{
+       uart_puts("Boot...");
+       MCUCR = (1 << IVCE);
+       MCUCR = (0 << IVSEL);
+       reset();
+}
+
+static void disp_digit(uint8_t x)
+{
+       if (x < 10)
+               x += '0';
+       else
+               x += 'a' - 10 ;
+       uart_send(x);
+}
+
+static void disp_hex8(uint8_t x)
+{
+       disp_digit(x>>4);
+       disp_digit(x&0xf);
+}
+
+static void disp_hex16(uint16_t x)
+{
+       disp_hex8(x>>8);
+       disp_hex8(x);
+}
+
+static void disp_hex32(uint32_t x)
+{
+       disp_hex16(x>>16);
+       disp_hex16(x);
+}
+
+static void crc_app(void)
+{
+       uint32_t start_addr, addr, size;
+       uint8_t c;
+       uint16_t crc = 0xffff;
+       uint16_t sum = 0;
+
+       uart_puts("addr?\r\n");
+       if (bootloader_query_hex(&start_addr))
+               goto fail;
+       if (start_addr > FLASHEND)
+               goto fail;
+       uart_puts("size?\r\n");
+       if (bootloader_query_hex(&size))
+               goto fail;
+       if (start_addr + size > FLASHEND)
+               goto fail;
+       for (addr=start_addr; addr<start_addr+size; addr++) {
+#if 0
+               /* ignore the 2nd page, it contains microb infos */
+               if (addr >= 256 && addr < 512)
+                       continue;
+#endif
+               c = pgm_read_byte_far(addr);
+               crc = _crc_ccitt_update(crc, c);
+               sum += c;
+       }
+       disp_hex16(crc);
+       disp_hex16(sum);
+       return;
+ fail:
+       uart_puts("KO");
+}
+
+static void read32(void)
+{
+       uint32_t start_addr, val = 0;
+       uint8_t c, i;
+
+       uart_puts("addr?\r\n");
+       if (bootloader_query_hex(&start_addr))
+               goto fail;
+       if (start_addr > FLASHEND)
+               goto fail;
+       for (i=0; i<4; i++) {
+               c = pgm_read_byte_far(start_addr+i);
+               val <<= 8;
+               val |= c;
+       }
+       disp_hex32(val);
+       return;
+ fail:
+       uart_puts("KO");
+}
+
+static void prog_page(void)
+{
+       int c;
+       uint32_t addr;
+       uint16_t i;
+       uint16_t crc = 0xffff;
+       uint16_t sum = 0;
+       uint8_t buf[SPM_PAGESIZE];
+
+#define SPM_PAGEMASK ((uint32_t)SPM_PAGESIZE-1)
+       uart_puts("addr?\r\n");
+       if (bootloader_query_hex(&addr))
+               goto fail;
+       if (addr > FLASHEND)
+               goto fail;
+       /* start_addr must be page aligned */
+       if (addr & SPM_PAGEMASK)
+               goto fail;
+
+       uart_puts("ok\r\n");
+
+
+       /* data is received like the .bin format (which is already in
+        * little endian) */
+       for (i=0; i<SPM_PAGESIZE; i++) {
+               c = uart_recv();
+               crc = _crc_ccitt_update(crc, c);
+               sum += c;
+               buf[i] = c;
+       }
+       disp_hex16(crc);
+       disp_hex16(sum);
+       uart_puts(" (y?)\r\n");
+       c = uart_recv();
+       if (c != 'y')
+               goto fail;
+
+       /* erase page */
+       eeprom_busy_wait();
+       boot_page_erase(addr);
+       boot_spm_busy_wait();
+
+       /* Set up little-endian word and fill tmp buf. */
+       for (i=0; i<SPM_PAGESIZE; i+=2) {
+               uint16_t w = buf[i] + ((uint16_t)(buf[i+1]) << 8);
+               boot_page_fill(addr + i, w);
+       }
+
+       boot_page_write(addr);
+       boot_spm_busy_wait();
+
+       /* Reenable RWW-section again. We need this if we want to jump
+        * back to the application after bootloading. */
+       boot_rww_enable();
+
+       uart_puts("OK");
+       return;
+ fail:
+       uart_puts("KO");
+}
+
+int main(void)
+{
+       int c;
+       uint32_t i=0;
+
+       UCSRxA = _BV(U2Xx);
+       UCSRxB = _BV(RXENx) | _BV(TXENx);
+       UCSRxC = _BV(UCSZx1) | _BV(UCSZx0); /* 8 bits no parity 1 stop */
+       UBRRx = 25; /* 57600 at 12 Mhz */
+
+       /* move interrupt vector in bootloader section */
+       MCUCR = (1 << IVCE);
+       MCUCR = (1 << IVSEL);
+
+       sei();
+
+       uart_puts("\r\ncmd> ");
+
+       /* timeout */
+       while ( !(UCSRxA & (1<<RXCx)) ) {
+               i++;
+               if (i>1000000) /* wait about 1 sec */
+                       launch_app();
+       }
+
+       while (1) {
+               uart_puts("\r\ncmd> ");
+               c = uart_recv();
+               if (c == 'x')
+                       launch_app();
+               else if (c == 'c')
+                       crc_app();
+               else if (c == 'p')
+                       prog_page();
+               else if (c == 'd')
+                       read32();
+               else
+                       uart_puts("p:prog_page c:crc x:exec d:dump32");
+       }
+
+       return 0;
+}
diff --git a/bootloader/uart_config.h b/bootloader/uart_config.h
new file mode 100755 (executable)
index 0000000..bdc9fa7
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Revision : $Id: uart_config.h,v 1.3 2009-05-27 20:04:06 zer0 Exp $
+ *
+ */
+
+/* Droids-corp 2004 - Zer0
+ * config for uart module
+ */
+
+#ifndef UART_CONFIG_H
+#define UART_CONFIG_H
+
+#if UART_NUM == 0
+
+/* compile uart0 fonctions, undefine it to pass compilation */
+#define UART0_COMPILE
+
+/* enable uart0 if == 1, disable if == 0 */
+#define UART0_ENABLED  1
+
+/* enable uart0 interrupts if == 1, disable if == 0 */
+#define UART0_INTERRUPT_ENABLED  1
+
+#define UART0_BAUDRATE 57600
+
+#define UART0_USE_DOUBLE_SPEED 0
+
+#define UART0_RX_FIFO_SIZE 64
+#define UART0_TX_FIFO_SIZE 16
+
+#define UART0_NBITS 8
+#define UART0_PARITY UART_PARTITY_NONE
+#define UART0_STOP_BIT UART_STOP_BITS_1
+
+#elif UART_NUM == 1
+
+/* compile uart1 fonctions, undefine it to pass compilation */
+#define UART1_COMPILE
+
+/* enable uart1 if == 1, disable if == 0 */
+#define UART1_ENABLED  1
+
+/* enable uart1 interrupts if == 1, disable if == 0 */
+#define UART1_INTERRUPT_ENABLED  1
+
+#define UART1_BAUDRATE 57600
+
+#define UART1_USE_DOUBLE_SPEED 0
+
+#define UART1_RX_FIFO_SIZE 32
+#define UART1_TX_FIFO_SIZE 4
+
+#define UART1_NBITS 8
+#define UART1_PARITY UART_PARTITY_NONE
+#define UART1_STOP_BIT UART_STOP_BITS_1
+
+#elif UART_NUM == 2
+
+/* compile uart2 fonctions, undefine it to pass compilation */
+#define UART2_COMPILE
+
+/* enable uart2 if == 1, disable if == 0 */
+#define UART2_ENABLED  1
+
+/* enable uart2 interrupts if == 1, disable if == 0 */
+#define UART2_INTERRUPT_ENABLED  1
+
+#define UART2_BAUDRATE 57600
+
+#define UART2_USE_DOUBLE_SPEED 0
+
+#define UART2_RX_FIFO_SIZE 32
+#define UART2_TX_FIFO_SIZE 4
+
+#define UART2_NBITS 8
+#define UART2_PARITY UART_PARTITY_NONE
+#define UART2_STOP_BIT UART_STOP_BITS_1
+
+#elif UART_NUM == 3
+
+/* compile uart3 fonctions, undefine it to pass compilation */
+#define UART3_COMPILE
+
+/* enable uart3 if == 1, disable if == 0 */
+#define UART3_ENABLED  1
+
+/* enable uart3 interrupts if == 1, disable if == 0 */
+#define UART3_INTERRUPT_ENABLED  1
+
+#define UART3_BAUDRATE 57600
+
+#define UART3_USE_DOUBLE_SPEED 0
+
+#define UART3_RX_FIFO_SIZE 32
+#define UART3_TX_FIFO_SIZE 4
+
+#define UART3_NBITS 8
+#define UART3_PARITY UART_PARTITY_NONE
+#define UART3_STOP_BIT UART_STOP_BITS_1
+
+#endif /* uart num */
+
+#endif
+