summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNicolas Schodet2013-05-01 00:34:39 +0200
committerNicolas Schodet2013-05-01 00:34:39 +0200
commit6ba10be3492959fa052eaa98b2ff0935f09b6d24 (patch)
tree259f184e27253318cedc006fa96f09b00a56e315
parent77e654cec77e28b5cead392ed34457035b5a2481 (diff)
digital/io-hub/src/bootloader: add io-hub-stm32 XMODEM bootloader
Not exactly a bootloader, but a binary image updater, which should be run by main code.
-rw-r--r--digital/io-hub/src/bootloader/Config2
-rw-r--r--digital/io-hub/src/bootloader/Makefile9
-rw-r--r--digital/io-hub/src/bootloader/bootloader.cc84
-rw-r--r--digital/io-hub/src/bootloader/self_programming.cc59
-rw-r--r--digital/io-hub/src/bootloader/self_programming.hh33
-rw-r--r--digital/io-hub/src/bootloader/stm32f4.ld6
6 files changed, 193 insertions, 0 deletions
diff --git a/digital/io-hub/src/bootloader/Config b/digital/io-hub/src/bootloader/Config
new file mode 100644
index 00000000..727498dc
--- /dev/null
+++ b/digital/io-hub/src/bootloader/Config
@@ -0,0 +1,2 @@
+[hal/uart]
+rx_buffer = 2048
diff --git a/digital/io-hub/src/bootloader/Makefile b/digital/io-hub/src/bootloader/Makefile
new file mode 100644
index 00000000..a2610723
--- /dev/null
+++ b/digital/io-hub/src/bootloader/Makefile
@@ -0,0 +1,9 @@
+BASE = ../../../ucoolib
+
+TARGETS = stm32f4
+PROGS = bootloader
+bootloader_SOURCES = bootloader.cc self_programming.cc
+
+MODULES = hal/uart utils dev/xmodem
+
+include $(BASE)/build/top.mk
diff --git a/digital/io-hub/src/bootloader/bootloader.cc b/digital/io-hub/src/bootloader/bootloader.cc
new file mode 100644
index 00000000..ca8a99c2
--- /dev/null
+++ b/digital/io-hub/src/bootloader/bootloader.cc
@@ -0,0 +1,84 @@
+// io-hub - Modular Input/Output. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT 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.
+//
+// }}}
+#include "ucoolib/hal/uart/uart.hh"
+#include "ucoolib/arch/arch.hh"
+#include "ucoolib/common.hh"
+
+#include <libopencm3/stm32/f4/rcc.h>
+#include "ucoolib/hal/gpio/gpio.hh"
+
+#include "ucoolib/dev/xmodem/xmodem.hh"
+#include "ucoolib/utils/delay.hh"
+
+#include "self_programming.hh"
+
+class BootloaderReceiver : public ucoo::XmodemReceiver
+{
+ uint32_t addr_;
+public:
+ BootloaderReceiver (uint32_t addr) : addr_ (addr) { }
+ int write (const char *buf, int count)
+ {
+ self_programming_write (addr_, buf, count);
+ addr_ += count;
+ return count;
+ }
+};
+
+int
+main (int argc, const char **argv)
+{
+ ucoo::arch_init (argc, argv);
+ // D8, D9: UART3
+ // C12, D2: UART5
+ rcc_peripheral_enable_clock (&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN);
+ rcc_peripheral_enable_clock (&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
+ gpio_mode_setup (GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12);
+ gpio_mode_setup (GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO8 | GPIO9);
+ gpio_set_af (GPIOC, GPIO_AF8, GPIO12);
+ gpio_set_af (GPIOD, GPIO_AF8, GPIO2);
+ gpio_set_af (GPIOD, GPIO_AF7, GPIO8 | GPIO9);
+ ucoo::Uart u0 (2), u1 (4);
+ u0.enable (38400, ucoo::Uart::EVEN, 1);
+ u1.enable (38400, ucoo::Uart::EVEN, 1);
+ ucoo::Uart *u[] = { &u0, &u1 };
+ const char welcome[] = "Press enter to start Xmodem receiver\n";
+ int i;
+ for (i = 0; i < (int) lengthof (u); i++)
+ {
+ u[i]->write (welcome, sizeof (welcome) - 1);
+ u[i]->block (false);
+ }
+ for (i = 0; ; i = (i + 1) % lengthof (u))
+ {
+ int c = u[i]->getc ();
+ if (c == '\n')
+ break;
+ }
+ BootloaderReceiver receiver (0x8000000);
+ ucoo::xmodem_receive (*u[i], receiver);
+ ucoo::delay (1);
+ ucoo::arch_reset ();
+}
+
diff --git a/digital/io-hub/src/bootloader/self_programming.cc b/digital/io-hub/src/bootloader/self_programming.cc
new file mode 100644
index 00000000..803e1c7a
--- /dev/null
+++ b/digital/io-hub/src/bootloader/self_programming.cc
@@ -0,0 +1,59 @@
+// io-hub - Modular Input/Output. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT 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.
+//
+// }}}
+#include "self_programming.hh"
+#include <libopencm3/stm32/f4/flash.h>
+
+static const uint32_t sector_addr[] = {
+ // 16 KB
+ 0x8000000, 0x8004000, 0x8008000, 0x800c000,
+ // 64 KB
+ 0x8010000,
+ // 128 KB.
+ 0x8020000, 0x8040000, 0x8060000, 0x8080000, 0x80a0000, 0x80c0000,
+ 0x80e0000, 0x8100000,
+};
+
+static int
+self_programming_sector (uint32_t addr)
+{
+ unsigned i;
+ for (i = 0; i < lengthof (sector_addr); i++)
+ if (addr == sector_addr[i])
+ return i;
+ return -1;
+}
+
+void
+self_programming_write (uint32_t addr, const char *buf, int count)
+{
+ int sector = self_programming_sector (addr);
+ flash_unlock ();
+ if (sector != -1)
+ flash_erase_sector (sector << 3, FLASH_CR_PROGRAM_X32);
+ for (int i = 0; i < count; i += 4)
+ flash_program_word (addr + i, *(uint32_t *) (buf + i),
+ FLASH_CR_PROGRAM_X32);
+ flash_lock ();
+}
+
diff --git a/digital/io-hub/src/bootloader/self_programming.hh b/digital/io-hub/src/bootloader/self_programming.hh
new file mode 100644
index 00000000..63a05aaf
--- /dev/null
+++ b/digital/io-hub/src/bootloader/self_programming.hh
@@ -0,0 +1,33 @@
+#ifndef self_programming_hh
+#define self_programming_hh
+// io-hub - Modular Input/Output. {{{
+//
+// Copyright (C) 2013 Nicolas Schodet
+//
+// APBTeam:
+// Web: http://apbteam.org/
+// Email: team AT apbteam DOT 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.
+//
+// }}}
+#include "ucoolib/common.hh"
+
+/// Program flash at given address. If address is a start of a page, erase
+/// first. Everything must be word aligned.
+void
+self_programming_write (uint32_t addr, const char *buf, int count);
+
+#endif // self_programming_hh
diff --git a/digital/io-hub/src/bootloader/stm32f4.ld b/digital/io-hub/src/bootloader/stm32f4.ld
new file mode 100644
index 00000000..1b84f38c
--- /dev/null
+++ b/digital/io-hub/src/bootloader/stm32f4.ld
@@ -0,0 +1,6 @@
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x080e0000, LENGTH = 128K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+INCLUDE libopencm3_stm32f4.ld