diff options
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc | 5 | ||||
-rw-r--r-- | support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc | 5 | ||||
-rw-r--r-- | support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc | 5 | ||||
-rw-r--r-- | support/make/board-includes/cm900.mk | 5 | ||||
-rw-r--r-- | support/make/board-includes/opencm904.mk | 5 | ||||
-rwxr-xr-x | support/scripts/robotis-loader.py | 94 | ||||
-rw-r--r-- | wirish/boards.cpp | 4 | ||||
-rw-r--r-- | wirish/usb_serial.cpp | 26 |
9 files changed, 164 insertions, 1 deletions
@@ -32,6 +32,12 @@ BOARD_INCLUDE_DIR := $(MAKEDIR)/board-includes BOARD ?= maple MEMORY_TARGET ?= flash +# Chooses the bootloader, available: maple and robotis +BOOTLOADER ?= maple + +# This is the serial port used by robotis bootloader +ROBOTIS_PORT ?= /dev/ttyACM0 + # $(BOARD)- and $(MEMORY_TARGET)-specific configuration include $(MAKEDIR)/target-config.mk @@ -56,7 +62,8 @@ TARGET_FLAGS += -I$(LIBMAPLE_PATH)/include/libmaple \ TARGET_FLAGS += -I$(LIBRARIES_PATH) # for internal lib. includes, e.g. <Wire/WireBase.h> GLOBAL_CFLAGS := -Os -g3 -gdwarf-2 -nostdlib \ -ffunction-sections -fdata-sections \ - -Wl,--gc-sections $(TARGET_FLAGS) + -Wl,--gc-sections $(TARGET_FLAGS) \ + -DBOOTLOADER_$(BOOTLOADER) GLOBAL_CXXFLAGS := -fno-rtti -fno-exceptions -Wall $(TARGET_FLAGS) GLOBAL_ASFLAGS := -x assembler-with-cpp $(TARGET_FLAGS) LDFLAGS = $(TARGET_LDFLAGS) $(TOOLCHAIN_LDFLAGS) -mcpu=cortex-m3 -mthumb \ @@ -101,12 +108,19 @@ include $(SRCROOT)/build-targets.mk # USB ID for DFU upload -- FIXME: do something smarter with this BOARD_USB_VENDOR_ID := 1EAF BOARD_USB_PRODUCT_ID := 0003 + +ifeq ($(BOOTLOADER),maple) UPLOAD_ram := $(SUPPORT_PATH)/scripts/reset.py && \ sleep 1 && \ $(DFU) -a0 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R UPLOAD_flash := $(SUPPORT_PATH)/scripts/reset.py && \ sleep 1 && \ $(DFU) -a1 -d $(BOARD_USB_VENDOR_ID):$(BOARD_USB_PRODUCT_ID) -D $(BUILD_PATH)/$(BOARD).bin -R +endif + +ifeq ($(BOOTLOADER),robotis) +UPLOAD_flash := $(SUPPORT_PATH)/scripts/robotis-loader.py $(ROBOTIS_PORT) $(BUILD_PATH)/$(BOARD).bin +endif # Conditionally upload to whatever the last build was install: INSTALL_TARGET = $(shell cat $(BUILD_PATH)/build-type 2>/dev/null) diff --git a/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc new file mode 100644 index 0000000..2c03ea9 --- /dev/null +++ b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-flash.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08003000, LENGTH = 108K +} diff --git a/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc new file mode 100644 index 0000000..20fbec0 --- /dev/null +++ b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K +} diff --git a/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc new file mode 100644 index 0000000..f02453b --- /dev/null +++ b/support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc @@ -0,0 +1,5 @@ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K + rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K +} diff --git a/support/make/board-includes/cm900.mk b/support/make/board-includes/cm900.mk index f9a09ac..9f70a1b 100644 --- a/support/make/board-includes/cm900.mk +++ b/support/make/board-includes/cm900.mk @@ -7,4 +7,9 @@ MCU_F1_LINE := performance # This crap is due to ld-script limitations. If you know of a better # way to go about this (like some magic ld switches to specify MEMORY # at the command line), please tell us! +ifeq ($(BOOTLOADER),maple) LD_MEM_DIR := sram_20k_flash_128k +endif +ifeq ($(BOOTLOADER),robotis) +LD_MEM_DIR := sram_20k_flash_128k_robotis +endif diff --git a/support/make/board-includes/opencm904.mk b/support/make/board-includes/opencm904.mk index f3a4aa7..64d3351 100644 --- a/support/make/board-includes/opencm904.mk +++ b/support/make/board-includes/opencm904.mk @@ -7,4 +7,9 @@ MCU_F1_LINE := performance # This crap is due to ld-script limitations. If you know of a better # way to go about this (like some magic ld switches to specify MEMORY # at the command line), please tell us! +ifeq ($(BOOTLOADER),maple) LD_MEM_DIR := sram_20k_flash_128k +endif +ifeq ($(BOOTLOADER),robotis) +LD_MEM_DIR := sram_20k_flash_128k_robotis +endif diff --git a/support/scripts/robotis-loader.py b/support/scripts/robotis-loader.py new file mode 100755 index 0000000..95d4e71 --- /dev/null +++ b/support/scripts/robotis-loader.py @@ -0,0 +1,94 @@ +#!/usr/bin/python + +# This script sends a program on a robotis board (OpenCM9.04 or CM900) +# using the robotis bootloader (used in OpenCM IDE) +# +# Usage: +# python robotis-loader.py <serial port> <binary> +# +# Example: +# python robotis-loader.py /dev/ttyACM0 firmware.bin +# +# https://github.com/Gregwar/robotis-loader + +import serial, sys, os, time + +print('~~ Robotis loader ~~') +print('') + +# Reading command line +if len(sys.argv) != 3: + exit('! Usage: robotis-loader.py <serial-port> <binary>') +pgm, port, binary = sys.argv + +# Helper to prints a progress bar +def progressBar(percent, precision=65): + threshold=precision*percent/100.0 + sys.stdout.write('[ ') + for x in xrange(0, precision): + if x < threshold: sys.stdout.write('#') + else: sys.stdout.write(' ') + sys.stdout.write(' ] ') + sys.stdout.flush() + +# Opening the firmware file +try: + stat = os.stat(binary) + size = stat.st_size + firmware = file(binary, 'rb') + print('* Opening %s, size=%d' % (binary, size)) +except: + exit('! Unable to open file %s' % binary) + +# Opening serial port +try: + s = serial.Serial(port, baudrate=115200) +except: + exit('! Unable to open serial port %s' % port) + +print('* Resetting the board') +s.setRTS(True) +s.setDTR(False) +time.sleep(0.1) +s.setRTS(False) +s.write('CM9X') +s.close() +time.sleep(1.0); + +print('* Connecting...') +s = serial.Serial(port, baudrate=115200) +s.write('AT&LD') +print('* Download signal transmitted, waiting...') + +# Entering bootloader sequence +while True: + line = s.readline().strip() + if line.endswith('Ready..'): + print('* Board ready, sending data') + cs = 0 + pos = 0 + while True: + c = firmware.read(2048) + if len(c): + pos += len(c) + sys.stdout.write("\r") + progressBar(100*float(pos)/float(size)) + s.write(c) + for k in range(0,len(c)): + cs = (cs+ord(c[k]))%256 + else: + break + print('') + s.setDTR(True) + print('* Checksum: %d' % (cs)) + s.write(chr(cs)) + print('* Firmware was sent') + else: + if line == 'Success..': + print('* Success, running the code') + print('') + s.write('AT&RST') + s.close() + exit() + else: + print('Board -> '+line) diff --git a/wirish/boards.cpp b/wirish/boards.cpp index a693fa6..77a05de 100644 --- a/wirish/boards.cpp +++ b/wirish/boards.cpp @@ -144,7 +144,11 @@ static void setup_clocks(void) { * present. If no bootloader is present, the user NVIC usually starts * at the Flash base address, 0x08000000. */ +#if defined(BOOTLOADER_maple) #define USER_ADDR_ROM 0x08005000 +#elif defined(BOOTLOADER_robotis) +#define USER_ADDR_ROM 0x08003000 +#endif #define USER_ADDR_RAM 0x20000C00 extern char __text_start__; diff --git a/wirish/usb_serial.cpp b/wirish/usb_serial.cpp index d21766f..3bb1923 100644 --- a/wirish/usb_serial.cpp +++ b/wirish/usb_serial.cpp @@ -36,6 +36,7 @@ #include <libmaple/nvic.h> #include <libmaple/usb_cdcacm.h> #include <libmaple/usb.h> +#include <libmaple/iwdg.h> #include <wirish/wirish.h> @@ -179,6 +180,7 @@ static void ifaceSetupHook(unsigned hook, void *requestvp) { return; } +#if defined(BOOTLOADER_maple) // We need to see a negative edge on DTR before we start looking // for the in-band magic reset byte sequence. uint8 dtr = usb_cdcacm_get_dtr(); @@ -196,13 +198,25 @@ static void ifaceSetupHook(unsigned hook, void *requestvp) { reset_state = dtr ? DTR_HIGH : DTR_LOW; break; } +#endif + +#if defined(BOOTLOADER_robotis) + uint8 dtr = usb_cdcacm_get_dtr(); + uint8 rts = usb_cdcacm_get_rts(); + + if (rts && !dtr) { + reset_state = DTR_NEGEDGE; + } +#endif } #define RESET_DELAY 100000 +#if defined(BOOTLOADER_maple) static void wait_reset(void) { delay_us(RESET_DELAY); nvic_sys_reset(); } +#endif #define STACK_TOP 0x20000800 #define EXC_RETURN 0xFFFFFFF9 @@ -215,7 +229,12 @@ static void rxHook(unsigned hook, void *ignored) { if (usb_cdcacm_data_available() >= 4) { // The magic reset sequence is "1EAF". +#if defined(BOOTLOADER_maple) static const uint8 magic[4] = {'1', 'E', 'A', 'F'}; +#endif +#if defined(BOOTLOADER_robotis) + static const uint8 magic[4] = {'C', 'M', '9', 'X'}; +#endif uint8 chkBuf[4]; // Peek at the waiting bytes, looking for reset sequence, @@ -227,6 +246,7 @@ static void rxHook(unsigned hook, void *ignored) { } } +#if defined(BOOTLOADER_maple) // Got the magic sequence -> reset, presumably into the bootloader. // Return address is wait_reset, but we must set the thumb bit. uintptr_t target = (uintptr_t)wait_reset | 0x1; @@ -251,6 +271,12 @@ static void rxHook(unsigned hook, void *ignored) { [exc_return] "r" (EXC_RETURN), [cpsr] "r" (DEFAULT_CPSR) : "r0", "r1", "r2"); +#endif + +#if defined(BOOTLOADER_robotis) + iwdg_init(IWDG_PRE_4, 10); +#endif + /* Can't happen. */ ASSERT_FAULT(0); } |