From 410eaf6017cd7c6abba3d751eb55f3ad4ffafec6 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 14 Jun 2010 00:20:08 +0200 Subject: add bootloader --- src/bwbootloader/Makefile | 12 ++++ src/bwbootloader/avrconfig.h | 59 ++++++++++++++++++ src/bwbootloader/bwbootloader.c | 128 ++++++++++++++++++++++++++++++++++++++++ src/bwbootloader/bwbootloader.h | 44 ++++++++++++++ src/bwbootloader/prog.c | 85 ++++++++++++++++++++++++++ src/bwbootloader/prog.h | 51 ++++++++++++++++ src/bwbootloader/spacer.avr.S | 29 +++++++++ 7 files changed, 408 insertions(+) create mode 100644 src/bwbootloader/Makefile create mode 100644 src/bwbootloader/avrconfig.h create mode 100644 src/bwbootloader/bwbootloader.c create mode 100644 src/bwbootloader/bwbootloader.h create mode 100644 src/bwbootloader/prog.c create mode 100644 src/bwbootloader/prog.h create mode 100644 src/bwbootloader/spacer.avr.S diff --git a/src/bwbootloader/Makefile b/src/bwbootloader/Makefile new file mode 100644 index 0000000..2f477bb --- /dev/null +++ b/src/bwbootloader/Makefile @@ -0,0 +1,12 @@ +BASE = $b/digital/avr +AVR_PROGS = bwbootloader +bwbootloader_SOURCES = bwbootloader.c prog.c spacer.avr.S +MODULES = twi utils +CONFIGFILE = avrconfig.h +# atmega8, atmega8535, atmega128... +AVR_MCU = attiny85 +# -O2 : speed +# -Os : size +OPTIMIZE = -Os + +include $(BASE)/make/Makefile.gen diff --git a/src/bwbootloader/avrconfig.h b/src/bwbootloader/avrconfig.h new file mode 100644 index 0000000..9c378b9 --- /dev/null +++ b/src/bwbootloader/avrconfig.h @@ -0,0 +1,59 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h */ +/* binwatch - Tiny binary wristwatch. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + * }}} */ + +/* utils */ +/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800, + * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */ +#define AC_FREQ 1000000 + +/* twi - TWI module. */ +/** Driver to implement TWI: HARD, SOFT, or USI. */ +#define AC_TWI_DRIVER USI +/** Do not use interrupts. */ +#define AC_TWI_NO_INTERRUPT 1 +/** TWI frequency, should really be 100 kHz. */ +#define AC_TWI_FREQ 100000 +/** Enable slave part. */ +#define AC_TWI_SLAVE_ENABLE 1 +/** Enable master part. */ +#define AC_TWI_MASTER_ENABLE 0 +/** Use polled slave mode: received data is stored in a buffer which can be + * polled using twi_slave_poll. */ +#define AC_TWI_SLAVE_POLLED 0 +/** Slave reception callback to be defined by the user when not in polled + * mode. */ +#define AC_TWI_SLAVE_RECV bwbootloader_recv +/** Master transfer completion callback, optionally defined by the user, called + * at end of master transfer. */ +#undef AC_TWI_MASTER_DONE +/** Use internal pull up. */ +#define AC_TWI_PULL_UP 0 +/** Slave reception buffer size. */ +#define AC_TWI_SLAVE_RECV_BUFFER_SIZE (64 + 4) +/** Slave transmission buffer size. */ +#define AC_TWI_SLAVE_SEND_BUFFER_SIZE (64 + 4) + +#endif /* avrconfig_h */ diff --git a/src/bwbootloader/bwbootloader.c b/src/bwbootloader/bwbootloader.c new file mode 100644 index 0000000..b7cc283 --- /dev/null +++ b/src/bwbootloader/bwbootloader.c @@ -0,0 +1,128 @@ +/* bwbootloader.c */ +/* binwatch - Tiny binary wristwatch. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + * }}} */ +#include "common.h" +#include "modules/twi/twi.h" +#include "modules/utils/utils.h" +#include "modules/utils/byte.h" + +#include "bwbootloader.h" +#include "prog.h" + +#include + +/** Start application when 1. */ +volatile uint8_t start; + +int +main (void) +{ + twi_init (0xb8); + while (!start) + twi_update (); + /* Small delay for acknowledge. */ + utils_delay_ms (500); + twi_uninit (); + prog_start (); + return 0; +} + +void +bwbootloader_recv (const uint8_t *buffer, uint8_t size) +{ + /* Command is the first byte, it will be repeated as acknowledgement. + * Words are little endian. */ + static uint8_t rbuffer[AC_TWI_SLAVE_SEND_BUFFER_SIZE]; + if (size != 0) + { + switch (buffer[0]) + { + case BWBOOTLOADER_INFO: + /* Return informations. + * => + * - 12b: 'bwbootloader'. + * - b: page size. + * - w: flash size (minus bootloader size). */ + if (size != 1) + break; + rbuffer[0] = buffer[0]; + memcpy (&rbuffer[1], "bwbootloader", 12); + rbuffer[13] = PROG_PAGE_SIZE; + rbuffer[14] = (PROG_FLASH_SIZE - BWBOOTLOADER_SIZE) & 0xff; + rbuffer[15] = (PROG_FLASH_SIZE - BWBOOTLOADER_SIZE) >> 8; + twi_slave_update (rbuffer, 16); + return; + case BWBOOTLOADER_START: + /* Start application. */ + if (size != 1) + break; + start = 1; + twi_slave_update (buffer, 1); + return; + case BWBOOTLOADER_READ: + /* Read from flash. + * - w: address. + * - b: size. + * => + * - w: address. + * - size x b: flash content. */ + if (size != 4 || buffer[3] > AC_TWI_SLAVE_SEND_BUFFER_SIZE - 3) + break; + rbuffer[0] = buffer[0]; + rbuffer[1] = buffer[1]; + rbuffer[2] = buffer[2]; + prog_read (v8_to_v16 (buffer[2], buffer[1]), &rbuffer[3], + buffer[3]); + twi_slave_update (rbuffer, buffer[3] + 3); + return; + case BWBOOTLOADER_PAGE_WRITE: + /* Write flash page. + * - w: address. + * - b: size (must be PROG_PAGE_SIZE). + * - size x b: page content. + * => + * - w: address. */ + if (size != PROG_PAGE_SIZE + 4 || buffer[3] != PROG_PAGE_SIZE) + break; + if (!prog_page_write (v8_to_v16 (buffer[2], buffer[1]), &buffer[4])) + break; + twi_slave_update (buffer, 3); + return; + case BWBOOTLOADER_READ_FUSES: + /* Read fuse bytes. + * => + * - b: low fuses. + * - b: high fuses. + * - b: extended fuses. */ + if (size != 1) + break; + rbuffer[0] = buffer[0]; + prog_read_fuses (&rbuffer[1]); + twi_slave_update (rbuffer, 4); + return; + } + } + /* Error. */ + twi_slave_update (NULL, 0); +} + diff --git a/src/bwbootloader/bwbootloader.h b/src/bwbootloader/bwbootloader.h new file mode 100644 index 0000000..81f7796 --- /dev/null +++ b/src/bwbootloader/bwbootloader.h @@ -0,0 +1,44 @@ +#ifndef bwbootloader_h +#define bwbootloader_h +/* bwbootloader.h */ +/* binwatch - Tiny binary wristwatch. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + * }}} */ + +/** Reserved size for bootloader. */ +#define BWBOOTLOADER_SIZE 1024 + +#ifndef __ASSEMBLER__ + +/** Bootloader commands. */ +enum +{ + BWBOOTLOADER_INFO, + BWBOOTLOADER_START, + BWBOOTLOADER_READ, + BWBOOTLOADER_PAGE_WRITE, + BWBOOTLOADER_READ_FUSES, +}; + +#endif + +#endif /* bwbootloader_h */ diff --git a/src/bwbootloader/prog.c b/src/bwbootloader/prog.c new file mode 100644 index 0000000..7b7d2c1 --- /dev/null +++ b/src/bwbootloader/prog.c @@ -0,0 +1,85 @@ +/* prog.c */ +/* binwatch - Tiny binary wristwatch. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + * }}} */ +#include "common.h" + +#include "bwbootloader.h" +#include "prog.h" + +#include +#include + +void +prog_read (uint16_t address, uint8_t *buffer, uint8_t length) +{ + while (length--) + *buffer++ = pgm_read_byte (address++); +} + +uint8_t +prog_page_write (uint16_t address, const uint8_t *buffer) +{ + /* Bootloader area is protected. */ + if (address >= PROG_FLASH_SIZE - BWBOOTLOADER_SIZE) + return 0; + /* Aligned write only. */ + if (address % PROG_PAGE_SIZE != 0) + return 0; + /* No EEPROM or interrupt protection, there is none in this bootloader. */ + /* Load page buffer. */ + uint16_t w; + uint8_t i; + for (i = 0; i < PROG_PAGE_SIZE; i += 2) + { + /* Protect reset vector. */ + if (address == 0 && i == 0) + w = pgm_read_word (0); + else + w = *(const uint16_t *) (buffer + i); + boot_page_fill (address + i, w); + } + /* Erase page. */ + boot_page_erase (address); + boot_spm_busy_wait (); + /* Program page. */ + boot_page_write (address); + boot_spm_busy_wait (); + /* All done. */ + return 1; +} + +void +prog_read_fuses (uint8_t *buffer) +{ + buffer[0] = boot_lock_fuse_bits_get (GET_LOW_FUSE_BITS); + buffer[1] = boot_lock_fuse_bits_get (GET_HIGH_FUSE_BITS); + buffer[2] = boot_lock_fuse_bits_get (GET_EXTENDED_FUSE_BITS); +} + +void +prog_start (void) +{ + /* Jump after vectors. */ + ((void (*) (void)) _VECTORS_SIZE) (); +} + diff --git a/src/bwbootloader/prog.h b/src/bwbootloader/prog.h new file mode 100644 index 0000000..caf0e75 --- /dev/null +++ b/src/bwbootloader/prog.h @@ -0,0 +1,51 @@ +#ifndef prog_h +#define prog_h +/* prog.h */ +/* binwatch - Tiny binary wristwatch. {{{ + * + * Copyright (C) 2010 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://ni.fr.eu.org/ + * Email: + * }}} */ +#include "io.h" + +/** Size of the hole flash. */ +#define PROG_FLASH_SIZE (FLASHEND + 1) +/** Size of a single flash page. */ +#define PROG_PAGE_SIZE SPM_PAGESIZE +/** Number of fuse bytes. */ +#define PROG_FUSE_NB 3 + +/** Read from flash. */ +void +prog_read (uint16_t address, uint8_t *buffer, uint8_t length); + +/** Write a full page to flash. */ +uint8_t +prog_page_write (uint16_t address, const uint8_t *buffer); + +/** Read lfuse, hfuse and efuse. */ +void +prog_read_fuses (uint8_t *buffer); + +/** Start application, never returns. */ +void +prog_start (void); + +#endif /* prog_h */ diff --git a/src/bwbootloader/spacer.avr.S b/src/bwbootloader/spacer.avr.S new file mode 100644 index 0000000..5ff2cb7 --- /dev/null +++ b/src/bwbootloader/spacer.avr.S @@ -0,0 +1,29 @@ +; spacer.avr.S +; binwatch - Tiny binary wristwatch. {{{ +; +; Copyright (C) 2010 Nicolas Schodet +; +; 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. +; +; }}} + +; This file sole purpose is to fill memory with 0xff after the vectors so that +; the bootloader is placed in the last kilobyte. + +#include +#include "bwbootloader.h" + + .section .progmem + .skip FLASHEND + 1 - BWBOOTLOADER_SIZE - _VECTORS_SIZE, 0xff -- cgit v1.2.3