Skip to content

Commit

Permalink
Merge pull request #89 from Gregwar/bootloader-option
Browse files Browse the repository at this point in the history
Adding BOOTLOADER option to support Robotis bootloader different ROM
  • Loading branch information
Marti Bolivar committed Apr 30, 2014
2 parents 621ff1a + fed549d commit f4d4fe2
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 1 deletion.
16 changes: 15 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 \
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08003000, LENGTH = 108K
}
5 changes: 5 additions & 0 deletions support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-jtag.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
}
5 changes: 5 additions & 0 deletions support/ld/stm32/mem/sram_20k_flash_128k_robotis/mem-ram.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
}
5 changes: 5 additions & 0 deletions support/make/board-includes/cm900.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions support/make/board-includes/opencm904.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
94 changes: 94 additions & 0 deletions support/scripts/robotis-loader.py
Original file line number Diff line number Diff line change
@@ -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)
4 changes: 4 additions & 0 deletions wirish/boards.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__;

Expand Down
26 changes: 26 additions & 0 deletions wirish/usb_serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down

0 comments on commit f4d4fe2

Please sign in to comment.