diff --git a/conf/Makefile.stm32 b/conf/Makefile.stm32
index 7b4fc7af48..4a7b2b27b8 100644
--- a/conf/Makefile.stm32
+++ b/conf/Makefile.stm32
@@ -73,6 +73,10 @@ endif
LIBOPENCM3_LIB=$(shell if [ -e "$(GCC_LIB_DIR)/libopencm3_stm32f1.a" ]; then echo "opencm3_stm32f1"; else echo "opencm3_stm32"; fi)
LIBOPENCM3_DEFS=$(shell if [ -e "$(GCC_LIB_DIR)/libopencm3_stm32f1.a" ]; then echo "-DSTM32F1"; fi)
+ifndef $(PYTHON)
+PYTHON = $(shell which python)
+endif
+
#first try to find OpenOCD in the path
OOCD = $(shell which openocd)
#if OpenOCD could not be found in the path, try the toolchain dir
@@ -100,6 +104,12 @@ else
OOCD_BOARD = $($(TARGET).OOCD_BOARD)
endif
+ifndef NO_LUFTBOOT
+OOCD_START_SECTOR = 4
+else
+OOCD_START_SECTOR = 0
+endif
+
# input files
SRCS = $($(TARGET).srcs)
#ASRC =
@@ -252,12 +262,16 @@ $(AOBJ) : $(OBJDIR)/%.o : %.S
$(Q)test -d $(dir $@) || mkdir -p $(dir $@)
$(Q)$(CC) -c $(AFLAGS) $< -o $@
-ifeq ($(FLASH_MODE),SERIAL)
+ifeq ($(FLASH_MODE),DFU)
+upload: $(OBJDIR)/$(TARGET).bin
+ @echo "Using stm32 mem dfu loader"
+ $(PYTHON) $(PAPARAZZI_SRC)/sw/tools/dfu/stm32_mem.py $^
+else ifeq ($(FLASH_MODE),SERIAL)
upload: $(OBJDIR)/$(TARGET).bin
$(LOADER) -p /dev/ttyUSB0 -b 115200 -e -w -v $^
else ifeq ($(FLASH_MODE),JTAG)
ifeq ($(BMP_PORT),)
-upload: $(OBJDIR)/$(TARGET).elf
+upload: $(OBJDIR)/$(TARGET).hex
@echo "Using OOCD = $(OOCD)"
@echo " OOCD\t$<"
$(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
@@ -265,7 +279,7 @@ upload: $(OBJDIR)/$(TARGET).elf
-c init \
-c "reset halt" \
-c "reset init" \
- -c "stm32f1x mass_erase 0" \
+ -c "flash erase_sector 0 $(OOCD_START_SECTOR) last" \
-c "flash write_image $<" \
-c reset \
-c shutdown
diff --git a/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_fw.xml b/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_fw.xml
index 0769b226a4..ad55ce5bc2 100644
--- a/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_fw.xml
+++ b/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_fw.xml
@@ -9,13 +9,13 @@
-->
-
-
+
+
-
+
-
+
@@ -23,30 +23,30 @@
-
+
-
+
-
+
-
+
-
+
@@ -54,18 +54,18 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -162,31 +162,31 @@
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
+
diff --git a/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_rc.xml b/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_rc.xml
index c27f0e6d59..495b646eff 100644
--- a/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_rc.xml
+++ b/conf/airframes/TestHardware/LisaL_v1.1_aspirin_v1.5_overo_rc.xml
@@ -8,32 +8,32 @@
GPS connected to UART1 (Since this is inside in a metal box it won't ever get a solution)
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_fw.xml b/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_fw.xml
index 3486e98270..d5e3f0200c 100644
--- a/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_fw.xml
+++ b/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_fw.xml
@@ -9,41 +9,41 @@
-->
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -51,10 +51,10 @@
-
+
-
+
diff --git a/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_rc.xml b/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_rc.xml
index 3d0592f223..3651be6689 100644
--- a/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_rc.xml
+++ b/conf/airframes/TestHardware/LisaL_v1.1_b2_v1.2_rc.xml
@@ -10,294 +10,286 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/fraser_lisa_m_rotorcraft.xml b/conf/airframes/fraser_lisa_m_rotorcraft.xml
index cbde578834..1e50b49d2a 100644
--- a/conf/airframes/fraser_lisa_m_rotorcraft.xml
+++ b/conf/airframes/fraser_lisa_m_rotorcraft.xml
@@ -60,6 +60,9 @@
+
+
+
@@ -229,6 +232,9 @@
diff --git a/conf/airframes/logomatic.xml b/conf/airframes/logomatic.xml
index d6a36666ef..18e41ef4d8 100644
--- a/conf/airframes/logomatic.xml
+++ b/conf/airframes/logomatic.xml
@@ -4,7 +4,7 @@
Sparkfun Logomatic V26 data logger
http://www.sparkfun.com/products/10216
-
+
P1-P8 can be used as ADC_0-ADC_7
P1 as PPM_IN
P2 as SERV_CLK
diff --git a/conf/boards/lisa_m_1.0.makefile b/conf/boards/lisa_m_1.0.makefile
index b2e64f84cb..7fe5ba466e 100644
--- a/conf/boards/lisa_m_1.0.makefile
+++ b/conf/boards/lisa_m_1.0.makefile
@@ -8,6 +8,7 @@
BOARD=lisa_m
BOARD_VERSION=1.0
BOARD_CFG=\"boards/$(BOARD)_$(BOARD_VERSION).h\"
+NO_LUFTBOOT=1
ARCH=stm32
$(TARGET).ARCHDIR = $(ARCH)
diff --git a/conf/boards/lisa_m_2.0.makefile b/conf/boards/lisa_m_2.0.makefile
index dceee9636e..6afbe0d536 100644
--- a/conf/boards/lisa_m_2.0.makefile
+++ b/conf/boards/lisa_m_2.0.makefile
@@ -18,10 +18,15 @@ $(TARGET).OOCD_INTERFACE=flossjtag
# -----------------------------------------------------------------------
ifndef FLASH_MODE
-FLASH_MODE = JTAG
+FLASH_MODE = DFU
+#FLASH_MODE = JTAG
#FLASH_MODE = SERIAL
endif
+ifndef NO_LUFTBOOT
+$(TARGET).LDSCRIPT = $(SRC_ARCH)/lisa_m_2.0_luftboot.ld
+endif
+
#
#
# some default values shared between different firmwares
diff --git a/conf/modules/bat_checker.xml b/conf/modules/bat_checker.xml
index 74160f19e9..b4b7aa8104 100644
--- a/conf/modules/bat_checker.xml
+++ b/conf/modules/bat_checker.xml
@@ -14,7 +14,6 @@
-
diff --git a/sw/airborne/arch/stm32/lisa_m_2.0_luftboot.ld b/sw/airborne/arch/stm32/lisa_m_2.0_luftboot.ld
new file mode 100644
index 0000000000..b8645c4f56
--- /dev/null
+++ b/sw/airborne/arch/stm32/lisa_m_2.0_luftboot.ld
@@ -0,0 +1,207 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 Antoine Drouin
+ *
+ * This file is part of Paparazzi.
+ *
+ * Paparazzi 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, or (at your option)
+ * any later version.
+ *
+ * Paparazzi 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 Paparazzi; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* This is the linker script for lisa/m 2.0 with luftboot */
+/* Lisa/M 2.0 uses the STM32F105RCT6. */
+/* 64KB RAM and 256KB Flash */
+
+/* Memory Spaces Definitions */
+MEMORY
+{
+ RAM (xrw): ORIGIN = 0x20000000, LENGTH = 64K
+
+ /* first four pages (8k) are reserved for luftboot */
+ /* last page (2k) flash for persistent settings */
+ FLASH (rx) : ORIGIN = 0x8002000, LENGTH = 246K
+ FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
+}
+
+ENTRY(reset_handler_stage1);
+
+/* User mode stack top */
+_estack = 0x20010000;
+
+/* Stack size and address definitions */
+__Stack_Size = 0x1000 ;
+
+PROVIDE ( _Stack_Size = __Stack_Size ) ;
+
+__Stack_Init = _estack - __Stack_Size ;
+
+PROVIDE ( _Stack_Init = __Stack_Init ) ;
+
+/* Enforce a linker error if there is not enough space left in ram for the stack */
+_Minimum_Stack_Size = 0x800 ;
+
+/* Check valid alignment for VTOR */
+ASSERT(ORIGIN(FLASH) == ALIGN(ORIGIN(FLASH), 0x80), "Start of memory region flash not aligned for startup vector table");
+
+/* Sections Definitions */
+
+SECTIONS
+{
+ /* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
+ .isr_vector :
+ {
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+ . = ALIGN(4);
+ } >FLASH
+
+ /* for some STRx devices, the beginning of the startup code is stored in the .flashtext section, which goes to FLASH */
+ .flashtext :
+ {
+ . = ALIGN(4);
+ *(.flashtext) /* Startup code */
+ . = ALIGN(4);
+ } >FLASH
+
+
+ /* the program code is stored in the .text section, which goes to Flash */
+ .text :
+ {
+ . = ALIGN(4);
+
+ *(.text) /* remaining code */
+ *(.text.*) /* remaining code */
+ *(.rodata) /* read-only data (constants) */
+ *(.rodata*)
+ *(.glue_7)
+ *(.glue_7t)
+
+ . = ALIGN(4);
+ _etext = .;
+ /* This is used by the startup in order to initialize the .data secion */
+ _sidata = _etext;
+ } >FLASH
+
+
+
+ /* This is the initialized data section
+ The program executes knowing that the data is in the RAM
+ but the loader puts the initial values in the FLASH (inidata).
+ It is one task of the startup to copy the initial values from FLASH to RAM. */
+ .data : AT ( _sidata )
+ {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .data secion */
+ _sdata = . ;
+
+ *(.data)
+ *(.data.*)
+
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .data secion */
+ _edata = . ;
+ } >RAM
+
+
+
+ /* This is the uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _sbss = .;
+
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ /* *(.bss) */
+ *(COMMON)
+
+ . = ALIGN(4);
+ /* This is used by the startup in order to initialize the .bss secion */
+ _ebss = . ;
+ } >RAM
+
+ PROVIDE ( end = _ebss );
+ PROVIDE ( _end = _ebss );
+
+ /* This is the user stack section
+ This is just to check that there is enough RAM left for the User mode stack
+ It should generate an error if it's full.
+ */
+ ._usrstack :
+ {
+ . = ALIGN(4);
+ _susrstack = . ;
+ . = . + _Minimum_Stack_Size ;
+ . = ALIGN(4);
+ _eusrstack = . ;
+ } >RAM
+
+ .b1text :
+ {
+ *(.b1text) /* remaining code */
+ *(.b1rodata) /* read-only data (constants) */
+ *(.b1rodata*)
+ } >FLASHB1
+
+ __exidx_start = .;
+ .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
+ __exidx_end = .;
+
+ /* after that it's only debugging information. */
+
+ /* remove the debugging information from the standard libraries */
+ /DISCARD/ :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0.*/
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+}
diff --git a/sw/airborne/arch/stm32/mcu_arch.c b/sw/airborne/arch/stm32/mcu_arch.c
index 08e34bdf70..0561c0bb27 100644
--- a/sw/airborne/arch/stm32/mcu_arch.c
+++ b/sw/airborne/arch/stm32/mcu_arch.c
@@ -43,7 +43,8 @@
void mcu_arch_init(void) {
#if USE_OPENCM3
rcc_clock_setup_in_hse_12mhz_out_72mhz();
- NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
+ /* Don't mess around with this as the address is set by luftboot. Otherwise the default should be ok. */
+ /*NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);*/
return;
#else // !USE_OPENCM3
#ifdef HSE_TYPE_EXT_CLK
@@ -88,8 +89,9 @@ void mcu_arch_init(void) {
#pragma message "Using normal system clock setup."
SystemInit();
#endif /* HSE_TYPE_EXT_CLK */
- /* Set the Vector Table base location at 0x08000000 */
- NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
+ /* Set the Vector Table base location at 0x08000000 */
+ /* Don't mess around with this as the address is set by luftboot. Otherwise the default should be ok. */
+ /*NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);*/
#ifdef STM32_FORCE_ALL_CLOCK_ON
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
diff --git a/sw/airborne/arch/stm32/subsystems/imu/imu_aspirin2_arch.c b/sw/airborne/arch/stm32/subsystems/imu/imu_aspirin2_arch.c
index d7bc7268e3..ca55e514a8 100644
--- a/sw/airborne/arch/stm32/subsystems/imu/imu_aspirin2_arch.c
+++ b/sw/airborne/arch/stm32/subsystems/imu/imu_aspirin2_arch.c
@@ -44,8 +44,8 @@ void imu_aspirin2_arch_init(void) {
SPI_InitTypeDef SPI_InitStructure;
// Set "mag ss" and "mag reset" as floating inputs ------------------------
- // "mag ss" (PC12) is shorted to I2C2 SDA
- // "mag reset" (PC13) is shorted to I2C2 SCL
+ // "mag ss" (PC12) is shorted to I2C2 SDA
+ // "mag reset" (PC13) is shorted to I2C2 SCL
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
@@ -80,7 +80,7 @@ void imu_aspirin2_arch_init(void) {
// Gyro data ready
void exti15_10_irq_handler(void) {
- // clear EXTI
+ // clear EXTI
if(EXTI_GetITStatus(EXTI_Line14) != RESET)
EXTI_ClearITPendingBit(EXTI_Line14);
diff --git a/sw/airborne/modules/bat_checker/bat_checker.c b/sw/airborne/modules/bat_checker/bat_checker.c
index 3b9dd7e52e..fc58a622af 100644
--- a/sw/airborne/modules/bat_checker/bat_checker.c
+++ b/sw/airborne/modules/bat_checker/bat_checker.c
@@ -1,6 +1,4 @@
/*
- * $Id$
- *
* Copyright (C) 2012 Thomas Kolb
*
* This file is part of paparazzi.
@@ -19,11 +17,11 @@
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
- *
*/
#include "bat_checker.h"
#include "generated/airframe.h"
+#include "generated/modules.h"
#include "subsystems/electrical.h"
#include "led.h"
@@ -40,7 +38,7 @@
#endif
#ifndef BAT_CHECKER_DELAY
-#warning BAT_CHECKER_DELAY is undefined. Falling back to 5 seconds.
+#pragma message "BAT_CHECKER_DELAY is undefined. Falling back to 5 seconds."
#define BAT_CHECKER_DELAY 5
#endif
@@ -50,8 +48,6 @@
// at this level, the buzzer will be activated permanently
#define WARN_BAT_LEVEL2 (CRITIC_BAT_LEVEL*10)
-#pragma message "Battery checker included!"
-
void init_bat_checker(void) {
LED_INIT(BAT_CHECKER_LED);
LED_OFF(BAT_CHECKER_LED);
@@ -63,7 +59,7 @@ void bat_checker_periodic(void) {
if(bat_low_counter)
bat_low_counter--;
} else {
- bat_low_counter = BAT_CHECKER_DELAY * bat_checker_periodic_FREQ;
+ bat_low_counter = BAT_CHECKER_DELAY * BAT_CHECKER_PERIODIC_FREQ;
}
if(!bat_low_counter) {
diff --git a/sw/airborne/modules/bat_checker/bat_checker.h b/sw/airborne/modules/bat_checker/bat_checker.h
index ac3d2b80f0..77c07fe41d 100644
--- a/sw/airborne/modules/bat_checker/bat_checker.h
+++ b/sw/airborne/modules/bat_checker/bat_checker.h
@@ -1,6 +1,4 @@
/*
- * $Id$
- *
* Copyright (C) 2012 Thomas Kolb
*
* This file is part of paparazzi.
@@ -19,7 +17,6 @@
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
- *
*/
#ifndef BAT_CHECKER_H
diff --git a/sw/airborne/subsystems/imu/imu_aspirin2.h b/sw/airborne/subsystems/imu/imu_aspirin2.h
index 99d8e2d972..08b0c818be 100644
--- a/sw/airborne/subsystems/imu/imu_aspirin2.h
+++ b/sw/airborne/subsystems/imu/imu_aspirin2.h
@@ -194,6 +194,7 @@ static inline void imu_aspirin2_event(void (* _gyro_handler)(void), void (* _acc
_gyro_handler();
_accel_handler();
+ _mag_handler();
}
// imu_aspirin2_arch_int_enable();
diff --git a/sw/include/std.h b/sw/include/std.h
index 3def069a3e..e99084da02 100644
--- a/sw/include/std.h
+++ b/sw/include/std.h
@@ -86,7 +86,9 @@ typedef uint8_t unit_t;
#define Min(x,y) (x < y ? x : y)
#define Max(x,y) (x > y ? x : y)
+#ifndef ABS
#define ABS(val) ((val) < 0 ? -(val) : (val))
+#endif
#define Bound(_x, _min, _max) { if (_x > _max) _x = _max; else if (_x < _min) _x = _min; }
#define BoundAbs(_x, _max) Bound(_x, -(_max), (_max))
diff --git a/sw/tools/dfu/dfu.py b/sw/tools/dfu/dfu.py
new file mode 100644
index 0000000000..1b479a3e2d
--- /dev/null
+++ b/sw/tools/dfu/dfu.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+#
+# dfu.py: Access USB DFU class devices
+# Copyright (C) 2009 Black Sphere Technologies
+# Copyright (C) 2012 Transition Robotics Inc.
+# Written by Gareth McMullin
+# Modified by Piotr Esden-Tempski
+#
+# 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 3 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, see .
+
+
+import usb
+
+DFU_DETACH_TIMEOUT = 1000
+
+# DFU Requests
+DFU_DETACH = 0x00
+DFU_DNLOAD = 0x01
+DFU_UPLOAD = 0x02
+DFU_GETSTATUS = 0x03
+DFU_CLRSTATUS = 0x04
+DFU_GETSTATE = 0x05
+DFU_ABORT = 0x06
+
+# DFU States
+STATE_APP_IDLE = 0x00
+STATE_APP_DETACH = 0x01
+STATE_DFU_IDLE = 0x02
+STATE_DFU_DOWNLOAD_SYNC = 0x03
+STATE_DFU_DOWNLOAD_BUSY = 0x04
+STATE_DFU_DOWNLOAD_IDLE = 0x05
+STATE_DFU_MANIFEST_SYNC = 0x06
+STATE_DFU_MANIFEST = 0x07
+STATE_DFU_MANIFEST_WAIT_RESET = 0x08
+STATE_DFU_UPLOAD_IDLE = 0x09
+STATE_DFU_ERROR = 0x0a
+DFU_STATUS_OK = 0x00
+
+# DFU Status cides
+DFU_STATUS_ERROR_TARGET = 0x01
+DFU_STATUS_ERROR_FILE = 0x02
+DFU_STATUS_ERROR_WRITE = 0x03
+DFU_STATUS_ERROR_ERASE = 0x04
+DFU_STATUS_ERROR_CHECK_ERASED = 0x05
+DFU_STATUS_ERROR_PROG = 0x06
+DFU_STATUS_ERROR_VERIFY = 0x07
+DFU_STATUS_ERROR_ADDRESS = 0x08
+DFU_STATUS_ERROR_NOTDONE = 0x09
+DFU_STATUS_ERROR_FIRMWARE = 0x0a
+DFU_STATUS_ERROR_VENDOR = 0x0b
+DFU_STATUS_ERROR_USBR = 0x0c
+DFU_STATUS_ERROR_POR = 0x0d
+DFU_STATUS_ERROR_UNKNOWN = 0x0e
+DFU_STATUS_ERROR_STALLEDPKT = 0x0f
+
+class dfu_status(object):
+ def __init__(self, buf):
+ self.bStatus = buf[0]
+ self.bwPollTimeout = buf[1] + (buf[2]<<8) + (buf[3]<<16)
+ self.bState = buf[4]
+ self.iString = buf[5]
+
+
+class dfu_device(object):
+ def __init__(self, dev, conf, iface):
+ self.dev = dev
+ self.conf = conf
+ self.iface = iface
+ self.handle = self.dev.open()
+ try:
+ self.handle.setConfiguration(conf)
+ except: pass
+ self.handle.claimInterface(iface.interfaceNumber)
+ if type(self.iface) is usb.Interface:
+ self.index = self.iface.interfaceNumber
+ else: self.index = self.iface
+
+ def detach(self, wTimeout=255):
+ self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
+ usb.RECIP_INTERFACE, DFU_DETACH,
+ None, value=wTimeout, index=self.index)
+
+ def download(self, wBlockNum, data):
+ self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
+ usb.RECIP_INTERFACE, DFU_DNLOAD,
+ data, value=wBlockNum, index=self.index)
+
+ def upload(self, wBlockNum, length):
+ return self.handle.controlMsg(usb.ENDPOINT_IN |
+ usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_UPLOAD,
+ length, value=wBlockNum, index=self.index)
+
+ def get_status(self):
+ buf = self.handle.controlMsg(usb.ENDPOINT_IN |
+ usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_GETSTATUS,
+ 6, index=self.index)
+ return dfu_status(buf)
+
+ def clear_status(self):
+ self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
+ usb.RECIP_INTERFACE, DFU_CLRSTATUS,
+ "", index=0)
+
+ def get_state(self):
+ buf = self.handle.controlMsg(usb.ENDPOINT_IN |
+ usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_GETSTATE,
+ 1, index=self.index)
+ return buf[0]
+
+ def abort(self):
+ self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
+ usb.RECIP_INTERFACE, DFU_ABORT,
+ None, index=self.index)
+
+
+ def make_idle(self):
+ retries = 3
+ while retries:
+ try:
+ status = self.get_status()
+ except:
+ self.clear_status()
+ continue
+
+ retries -= 1
+
+ if status.bState == STATE_DFU_IDLE:
+ return True
+
+ if ((status.bState == STATE_DFU_DOWNLOAD_SYNC) or
+ (status.bState == STATE_DFU_DOWNLOAD_IDLE) or
+ (status.bState == STATE_DFU_MANIFEST_SYNC) or
+ (status.bState == STATE_DFU_UPLOAD_IDLE) or
+ (status.bState == STATE_DFU_DOWNLOAD_BUSY) or
+ (status.bState == STATE_DFU_MANIFEST)):
+ self.abort()
+ continue
+
+ if status.bState == STATE_DFU_ERROR:
+ self.clear_status()
+ continue
+
+ if status.bState == STATE_APP_IDLE:
+ self.detach(DFU_DETACH_TIMEOUT)
+ continue
+
+ if ((status.bState == STATE_APP_DETACH) or
+ (status.bState == STATE_DFU_MANIFEST_WAIT_RESET)):
+ usb.reset(self.handle)
+ return False
+
+ raise Exception
+
+def finddevs():
+ devs = []
+ for bus in usb.busses():
+ for dev in bus.devices:
+ for conf in dev.configurations:
+ for ifaces in conf.interfaces:
+ for iface in ifaces:
+ if ((iface.interfaceClass == 0xFE) and
+ (iface.interfaceSubClass == 0x01)):
+ devs.append((dev, conf, iface))
+ return devs
+
+
+if __name__ == "__main__":
+ devs = finddevs()
+ if not devs:
+ print "No devices found!"
+ exit(-1)
+
+ for dfu in devs:
+ handle = dfu[0].open()
+ try:
+ man = handle.getString(dfu[0].iManufacturer, 30)
+ product = handle.getString(dfu[0].iProduct, 30)
+ serial = handle.getString(dfu[0].iSerialNumber, 40)
+ except:
+ print "Could not access descriptions strings of a DFU device. Maybe the OS driver is claiming it?"
+ continue
+
+ print "Device %s: ID %04x:%04x %s - %s - %s" % (dfu[0].filename,
+ dfu[0].idVendor, dfu[0].idProduct, man, product, serial)
+ print "%r, %r" % (dfu[1], dfu[2])
+ print "Finished scanning for devices."
+
+
+
diff --git a/sw/tools/dfu/stm32_mem.py b/sw/tools/dfu/stm32_mem.py
new file mode 100755
index 0000000000..f48480d5fe
--- /dev/null
+++ b/sw/tools/dfu/stm32_mem.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+#
+# stm32_mem.py: STM32 memory access using USB DFU class
+# Copyright (C) 2011 Black Sphere Technologies
+# Written by Gareth McMullin
+#
+# 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 3 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, see .
+
+from time import sleep
+import struct
+from sys import stdout, argv
+
+import usb
+import dfu
+
+APP_ADDRESS = 0x08002000
+SECTOR_SIZE = 2048
+
+CMD_GETCOMMANDS = 0x00
+CMD_SETADDRESSPOINTER = 0x21
+CMD_ERASE = 0x41
+
+def stm32_erase(dev, addr):
+ erase_cmd = struct.pack(""
+ print
+
+ devs = dfu.finddevs()
+ if not devs:
+ print "No devices found!"
+ exit(-1)
+
+ for dev in devs:
+ dfudev = dfu.dfu_device(*dev)
+ try:
+ man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30)
+ product = dfudev.handle.getString(dfudev.dev.iProduct, 30)
+ serial = dfudev.handle.getString(dfudev.dev.iSerialNumber, 40)
+ except:
+ print "Could not access the description strings of a DFU device. Maybe the OS driver is claiming it?"
+ continue
+ if man == "Black Sphere Technologies": break
+ if man == "Transition Robotics Inc.": break
+ if man == "STMicroelectronics": break
+
+ print "Device %s: ID %04x:%04x %s - %s - %s" % (dfudev.dev.filename,
+ dfudev.dev.idVendor, dfudev.dev.idProduct, man, product, serial)
+
+ try:
+ state = dfudev.get_state()
+ except:
+ print "Failed to read device state! Assuming APP_IDLE"
+ state = dfu.STATE_APP_IDLE
+ if state == dfu.STATE_APP_IDLE:
+ dfudev.detach()
+ print "Run again to upgrade firmware."
+ exit(0)
+
+ dfudev.make_idle()
+
+ try:
+ bin = open(argv[1], "rb").read()
+ except:
+ print "Could not open binary file."
+ raise
+
+ addr = APP_ADDRESS
+ while bin:
+ print ("Programming memory at 0x%08X\r" % addr),
+ stdout.flush()
+ stm32_erase(dfudev, addr)
+ stm32_write(dfudev, bin[:SECTOR_SIZE])
+
+ bin = bin[SECTOR_SIZE:]
+ addr += SECTOR_SIZE
+
+ stm32_manifest(dfudev)
+
+ print "\nAll operations complete!\n"
diff --git a/sw/tools/gen_modules.ml b/sw/tools/gen_modules.ml
index 921952fa80..4512322f2e 100644
--- a/sw/tools/gen_modules.ml
+++ b/sw/tools/gen_modules.ml
@@ -64,6 +64,41 @@ let get_status_shortname = fun f ->
let func = (Xml.attrib f "fun") in
String.sub func 0 (try String.index func '(' with _ -> (String.length func))
+let get_period_and_freq = fun f max_freq ->
+ let period = try Some (float_of_string (Xml.attrib f "period")) with _ -> None
+ and freq = try Some (float_of_string (Xml.attrib f "freq")) with _ -> None in
+ match period, freq with
+ | None, None -> (1. /. max_freq, max_freq)
+ | Some _p, None -> (_p, 1. /. _p)
+ | None, Some _f -> (1. /. _f, _f)
+ | Some _p, Some _ ->
+ fprintf stderr "Warning: both period and freq are defined but only period is used for function %s\n" (ExtXml.attrib f "fun");
+ (_p, 1. /. _p)
+
+(* Extract function name and return in capital letters *)
+let get_cap_name = fun f ->
+ let name = Str.full_split (Str.regexp "[()]") f in
+ match name with
+ | [Str.Text t]
+ | [Str.Text t; Str.Delim "("; Str.Delim ")"]
+ | [Str.Text t; Str.Delim "("; Str.Text _ ; Str.Delim ")"] -> String.uppercase t
+ | _ -> failwith "Gen_modules: not a valid function name"
+
+let print_function_freq = fun modules ->
+ let max_freq = float !freq in
+ nl ();
+ List.iter (fun m ->
+ List.iter (fun i ->
+ match Xml.tag i with
+ "periodic" ->
+ let fname = get_cap_name (Xml.attrib i "fun") in
+ let p, f = get_period_and_freq i max_freq in
+ lprintf out_h "#define %s_PERIOD %f\n" fname p;
+ lprintf out_h "#define %s_FREQ %f\n" fname f;
+ | _ -> ())
+ (Xml.children m))
+ modules
+
let is_status_lock = fun p ->
let mode = ExtXml.attrib_or_default p "autorun" "LOCK" in
mode = "LOCK"
@@ -115,19 +150,13 @@ let print_periodic_functions = fun modules ->
let periodic = List.filter (fun i -> (String.compare (Xml.tag i) "periodic") == 0) (Xml.children m) in
let module_name = ExtXml.attrib m "name" in
List.map (fun x ->
- try
- let p = float_of_string (Xml.attrib x "period") in
- let _ = try let _ = Xml.attrib x "freq" in fprintf stderr "Warning: both period and freq are defined but only period is used for function %s\n" (ExtXml.attrib x "fun") with _ -> () in
- if p < min_period || p > max_period then
- fprintf stderr "Warning: period is bound between %.3fs and %.3fs for function %s\n%!" min_period max_period (ExtXml.attrib x "fun");
- ((x, module_name), min 65535 (max 1 (int_of_float (p *. float_of_int !freq))))
- with _ ->
- let f = float_of_string (ExtXml.attrib_or_default x "freq" (string_of_float max_freq)) in
- if f < min_freq || f > max_freq then
- fprintf stderr "Warning: frequency is bound between %fHz and %.1fHz for function %s\n%!" min_freq max_freq (ExtXml.attrib x "fun");
- ((x, module_name), min 65535 (max 1 (int_of_float (float_of_int !freq /. f))))
- )
- periodic) modules) in
+ let p, _ = get_period_and_freq x max_freq in
+ if p < min_period || p > max_period then
+ fprintf stderr "Warning: period is bound between %.3fs and %.3fs (%fHz and %.1fHz) for function %s\n%!"
+ min_period max_period max_freq min_freq (ExtXml.attrib x "fun");
+ ((x, module_name), min 65535 (max 1 (int_of_float (p *. float_of_int !freq))))
+ ) periodic)
+ modules) in
let modulos = GC.singletonize (List.map snd functions_modulo) in
(** Print modulos *)
List.iter (fun modulo ->
@@ -244,6 +273,7 @@ let print_datalink_functions = fun modules ->
let parse_modules modules =
print_headers modules;
+ print_function_freq modules;
print_status modules;
nl ();
fprintf out_h "#ifdef MODULES_C\n";