mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-12-15 20:33:16 +00:00
Initial check-in for STM32 board
This commit is contained in:
1648
BootLoaders/Boards/stm32/system/support/doxygen/Doxyfile
Normal file
1648
BootLoaders/Boards/stm32/system/support/doxygen/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
# libmaple's own Evil Mangler
|
||||
#
|
||||
# Input filter hack to trick Doxygen into thinking that a series
|
||||
# header is in a separate namespace. This is necessary because Doxygen
|
||||
# doesn't know how to cope with two data structures with the same name
|
||||
# in different places in the project. (We do that all the time,
|
||||
# e.g. for foo_reg_map structs.)
|
||||
#
|
||||
# E.g., an STM32F1 header gets transformed into:
|
||||
#
|
||||
# namespace stm32f1 {
|
||||
# <contents of header>
|
||||
# }
|
||||
|
||||
BEGIN {
|
||||
# For extracting series component from header FILENAME.
|
||||
series_regex = "/stm32[flw][0-9]*/";
|
||||
# Holds header FILENAME. Cargo-culted; not sure why it's necessary.
|
||||
f = "";
|
||||
# Holds series component.
|
||||
series = "";
|
||||
}
|
||||
{
|
||||
if (f != FILENAME) {
|
||||
f = FILENAME;
|
||||
match(f, series_regex);
|
||||
series = substr(f, RSTART + 1, RLENGTH - 2);
|
||||
printf("namespace %s {\n", series);
|
||||
}
|
||||
print;
|
||||
}
|
||||
END {
|
||||
if (series != "") {
|
||||
print "}"
|
||||
}
|
||||
}
|
||||
12
BootLoaders/Boards/stm32/system/support/gdb/gpio/gpio.gdb
Normal file
12
BootLoaders/Boards/stm32/system/support/gdb/gpio/gpio.gdb
Normal file
@@ -0,0 +1,12 @@
|
||||
set print pretty on
|
||||
|
||||
print "GPIOA registers:"
|
||||
p/x *GPIOA->regs
|
||||
print "GPIOB registers:"
|
||||
p/x *GPIOB->regs
|
||||
print "GPIOC registers:"
|
||||
p/x *GPIOC->regs
|
||||
print "GPIOD registers:"
|
||||
p/x *GPIOD->regs
|
||||
print "AFIO registers:"
|
||||
p/x *(struct afio_reg_map*)0x40010000
|
||||
112
BootLoaders/Boards/stm32/system/support/gdb/i2c/test.gdb
Normal file
112
BootLoaders/Boards/stm32/system/support/gdb/i2c/test.gdb
Normal file
@@ -0,0 +1,112 @@
|
||||
define i2c_sr1_flags
|
||||
set $s = $arg0
|
||||
printf "SR1: "
|
||||
|
||||
if (($s & (1 << 15)))
|
||||
printf "SMBALERT "
|
||||
end
|
||||
|
||||
if (($s & (1 << 14)))
|
||||
printf "TIMEOUT "
|
||||
end
|
||||
|
||||
if (($s & (1 << 12)))
|
||||
printf "PECERR "
|
||||
end
|
||||
|
||||
if (($s & (1 << 11)))
|
||||
printf "OVR "
|
||||
end
|
||||
|
||||
if (($s & (1 << 10)))
|
||||
printf "AF "
|
||||
end
|
||||
|
||||
if (($s & (1 << 9)))
|
||||
printf "ARLO "
|
||||
end
|
||||
|
||||
if (($s & (1 << 8)))
|
||||
printf "BERR "
|
||||
end
|
||||
|
||||
if (($s & (1 << 7)))
|
||||
printf "TXE "
|
||||
end
|
||||
|
||||
if (($s & (1 << 6)))
|
||||
printf "RXNE "
|
||||
end
|
||||
|
||||
if (($s & (1 << 4)))
|
||||
printf "STOPF "
|
||||
end
|
||||
|
||||
if (($s & (1 << 3)))
|
||||
printf "ADD10 "
|
||||
end
|
||||
|
||||
if (($s & (1 << 2)))
|
||||
printf "BTF "
|
||||
end
|
||||
|
||||
if (($s & (1 << 1)))
|
||||
printf "ADDR "
|
||||
end
|
||||
|
||||
if (($s & (1 << 0)))
|
||||
printf "SB "
|
||||
end
|
||||
end
|
||||
|
||||
define i2c_sr2_flags
|
||||
set $s = $arg0
|
||||
printf "SR2: "
|
||||
|
||||
if (($s & (1 << 7)))
|
||||
printf "DUALF "
|
||||
end
|
||||
|
||||
if (($s & (1 << 6)))
|
||||
printf "SMBHOST "
|
||||
end
|
||||
|
||||
if (($s & (1 << 5)))
|
||||
printf "SMBDEFAULT "
|
||||
end
|
||||
|
||||
if (($s & (1 << 4)))
|
||||
printf "GENCALL "
|
||||
end
|
||||
|
||||
|
||||
if (($s & (1 << 2)))
|
||||
printf "TRA "
|
||||
end
|
||||
|
||||
if (($s & (1 << 1)))
|
||||
printf "BUSY "
|
||||
end
|
||||
|
||||
if (($s & (1 << 0)))
|
||||
printf "MSL "
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
define pbc
|
||||
set $c = crumbs
|
||||
while ($c->event)
|
||||
if ($c->event != 0)
|
||||
printf "Event: %d ", $c->event
|
||||
if ($c->event == 1)
|
||||
i2c_sr1_flags $c->sr1
|
||||
printf "\t"
|
||||
i2c_sr2_flags $c->sr2
|
||||
end
|
||||
printf "\n"
|
||||
end
|
||||
set $c = $c + 1
|
||||
end
|
||||
|
||||
|
||||
219
BootLoaders/Boards/stm32/system/support/ld/common.inc
Normal file
219
BootLoaders/Boards/stm32/system/support/ld/common.inc
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Linker script for libmaple.
|
||||
*
|
||||
* Original author "lanchon" from ST forums, with modifications by LeafLabs.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
|
||||
/*
|
||||
* Configure other libraries we want in the link.
|
||||
*
|
||||
* libgcc, libc, and libm are common across supported toolchains.
|
||||
* However, some toolchains require additional archives which aren't
|
||||
* present everywhere (e.g. ARM's gcc-arm-embedded releases).
|
||||
*
|
||||
* To hack around this, we let the build system specify additional
|
||||
* archives by putting the right extra_libs.inc (in a directory under
|
||||
* toolchains/) in our search path.
|
||||
*/
|
||||
GROUP(libgcc.a libc.a libm.a)
|
||||
INCLUDE extra_libs.inc
|
||||
|
||||
/*
|
||||
* These force the linker to search for vector table symbols.
|
||||
*
|
||||
* These symbols vary by STM32 family (and also within families).
|
||||
* It's up to the build system to configure the link's search path
|
||||
* properly for the target MCU.
|
||||
*/
|
||||
INCLUDE vector_symbols.inc
|
||||
|
||||
/* STM32 vector table. */
|
||||
EXTERN(__stm32_vector_table)
|
||||
|
||||
/* C runtime initialization function. */
|
||||
EXTERN(start_c)
|
||||
|
||||
/* main entry point */
|
||||
EXTERN(main)
|
||||
|
||||
/* Initial stack pointer value. */
|
||||
EXTERN(__msp_init)
|
||||
PROVIDE(__msp_init = ORIGIN(ram) + LENGTH(ram));
|
||||
|
||||
/* Reset vector and chip reset entry point */
|
||||
EXTERN(__start__)
|
||||
ENTRY(__start__)
|
||||
PROVIDE(__exc_reset = __start__);
|
||||
|
||||
/* Heap boundaries, for libmaple */
|
||||
EXTERN(_lm_heap_start);
|
||||
EXTERN(_lm_heap_end);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
__text_start__ = .;
|
||||
/*
|
||||
* STM32 vector table. Leave this here. Yes, really.
|
||||
*/
|
||||
*(.stm32.interrupt_vector)
|
||||
|
||||
/*
|
||||
* Program code and vague linking
|
||||
*/
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
*(.gnu.warning)
|
||||
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
|
||||
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
*(.gcc_except_table)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.init))
|
||||
|
||||
. = ALIGN(4);
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
|
||||
. = ALIGN(0x4);
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend.o(.ctors))
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
__fini_array_start = .;
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
__fini_array_end = .;
|
||||
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
} > REGION_TEXT
|
||||
|
||||
/*
|
||||
* End of text
|
||||
*/
|
||||
.text.align :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__text_end__ = .;
|
||||
} > REGION_TEXT
|
||||
|
||||
/*
|
||||
* .ARM.exidx exception unwinding; mandated by ARM's C++ ABI
|
||||
*/
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > REGION_RODATA
|
||||
__exidx_end = .;
|
||||
|
||||
/*
|
||||
* .data
|
||||
*/
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__data_start__ = .;
|
||||
|
||||
*(.got.plt) *(.got)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
|
||||
. = ALIGN(8);
|
||||
__data_end__ = .;
|
||||
} > REGION_DATA AT> REGION_RODATA
|
||||
|
||||
/*
|
||||
* Read-only data
|
||||
*/
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
/* .USER_FLASH: We allow users to allocate into Flash here */
|
||||
*(.USER_FLASH)
|
||||
/* ROM image configuration; for C startup */
|
||||
. = ALIGN(4);
|
||||
_lm_rom_img_cfgp = .;
|
||||
LONG(LOADADDR(.data));
|
||||
/*
|
||||
* Heap: Linker scripts may choose a custom heap by overriding
|
||||
* _lm_heap_start and _lm_heap_end. Otherwise, the heap is in
|
||||
* internal SRAM, beginning after .bss, and growing towards
|
||||
* the stack.
|
||||
*
|
||||
* I'm shoving these here naively; there's probably a cleaner way
|
||||
* to go about this. [mbolivar]
|
||||
*/
|
||||
_lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end;
|
||||
_lm_heap_end = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init;
|
||||
} > REGION_RODATA
|
||||
|
||||
/*
|
||||
* .bss
|
||||
*/
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__bss_start__ = .;
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
__bss_end__ = .;
|
||||
_end = __bss_end__;
|
||||
} > REGION_BSS
|
||||
|
||||
/*
|
||||
* Debugging sections
|
||||
*/
|
||||
.stab 0 (NOLOAD) : { *(.stab) }
|
||||
.stabstr 0 (NOLOAD) : { *(.stabstr) }
|
||||
/* 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) }
|
||||
|
||||
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
|
||||
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
||||
26
BootLoaders/Boards/stm32/system/support/ld/flash.ld
Normal file
26
BootLoaders/Boards/stm32/system/support/ld/flash.ld
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* libmaple linker script for "Flash" builds.
|
||||
*
|
||||
* A Flash build puts .text (and .rodata) in Flash, and
|
||||
* .data/.bss/heap (of course) in SRAM, but offsets the sections by
|
||||
* enough space to store the Maple bootloader, which lives in low
|
||||
* Flash and uses low memory.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This pulls in the appropriate MEMORY declaration from the right
|
||||
* subdirectory of stm32/mem/ (the environment must call ld with the
|
||||
* right include directory flags to make this happen). Boards can also
|
||||
* use this file to use any of libmaple's memory-related hooks (like
|
||||
* where the heap should live).
|
||||
*/
|
||||
INCLUDE mem-flash.inc
|
||||
|
||||
/* Provide memory region aliases for common.inc */
|
||||
REGION_ALIAS("REGION_TEXT", rom);
|
||||
REGION_ALIAS("REGION_DATA", ram);
|
||||
REGION_ALIAS("REGION_BSS", ram);
|
||||
REGION_ALIAS("REGION_RODATA", rom);
|
||||
|
||||
/* Let common.inc handle the real work. */
|
||||
INCLUDE common.inc
|
||||
31
BootLoaders/Boards/stm32/system/support/ld/jtag.ld
Normal file
31
BootLoaders/Boards/stm32/system/support/ld/jtag.ld
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* libmaple linker script for "JTAG" builds.
|
||||
*
|
||||
* A "JTAG" build puts .text (and .rodata) in Flash, and
|
||||
* .data/.bss/heap (of course) in SRAM, but links starting at the
|
||||
* Flash and SRAM starting addresses (0x08000000 and 0x20000000
|
||||
* respectively). This will wipe out a Maple bootloader if there's one
|
||||
* on the board, so only use this if you know what you're doing.
|
||||
*
|
||||
* Of course, a "JTAG" build is perfectly usable for upload over SWD,
|
||||
* the system memory bootloader, etc. The name is just a historical
|
||||
* artifact.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This pulls in the appropriate MEMORY declaration from the right
|
||||
* subdirectory of stm32/mem/ (the environment must call ld with the
|
||||
* right include directory flags to make this happen). Boards can also
|
||||
* use this file to use any of libmaple's memory-related hooks (like
|
||||
* where the heap should live).
|
||||
*/
|
||||
INCLUDE mem-jtag.inc
|
||||
|
||||
/* Provide memory region aliases for common.inc */
|
||||
REGION_ALIAS("REGION_TEXT", rom);
|
||||
REGION_ALIAS("REGION_DATA", ram);
|
||||
REGION_ALIAS("REGION_BSS", ram);
|
||||
REGION_ALIAS("REGION_RODATA", rom);
|
||||
|
||||
/* Let common.inc handle the real work. */
|
||||
INCLUDE common.inc
|
||||
25
BootLoaders/Boards/stm32/system/support/ld/ram.ld
Normal file
25
BootLoaders/Boards/stm32/system/support/ld/ram.ld
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* libmaple linker script for RAM builds.
|
||||
*
|
||||
* A Flash build puts .text, .rodata, and .data/.bss/heap (of course)
|
||||
* in SRAM, but offsets the sections by enough space to store the
|
||||
* Maple bootloader, which uses low memory.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This pulls in the appropriate MEMORY declaration from the right
|
||||
* subdirectory of stm32/mem/ (the environment must call ld with the
|
||||
* right include directory flags to make this happen). Boards can also
|
||||
* use this file to use any of libmaple's memory-related hooks (like
|
||||
* where the heap should live).
|
||||
*/
|
||||
INCLUDE mem-ram.inc
|
||||
|
||||
/* Provide memory region aliases for common.inc */
|
||||
REGION_ALIAS("REGION_TEXT", ram);
|
||||
REGION_ALIAS("REGION_DATA", ram);
|
||||
REGION_ALIAS("REGION_BSS", ram);
|
||||
REGION_ALIAS("REGION_RODATA", ram);
|
||||
|
||||
/* Let common.inc handle the real work. */
|
||||
INCLUDE common.inc
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Specify heap boundary addresses on the external SRAM chip */
|
||||
_lm_heap_start = 0x60000000;
|
||||
_lm_heap_end = 0x60100000;
|
||||
@@ -0,0 +1,7 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 492K
|
||||
}
|
||||
|
||||
INCLUDE maple_native_heap.inc
|
||||
@@ -0,0 +1,7 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
}
|
||||
|
||||
INCLUDE maple_native_heap.inc
|
||||
@@ -0,0 +1,7 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
|
||||
}
|
||||
|
||||
INCLUDE maple_native_heap.inc
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 108K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
|
||||
rom (rx) : ORIGIN = 0x08003000, LENGTH = 108K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 17K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 492K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000C00, LENGTH = 61K
|
||||
rom (rx) : ORIGIN = 0x08005000, LENGTH = 0K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0K
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
EXTERN(__msp_init)
|
||||
EXTERN(__exc_reset)
|
||||
EXTERN(__exc_nmi)
|
||||
EXTERN(__exc_hardfault)
|
||||
EXTERN(__exc_memmanage)
|
||||
EXTERN(__exc_busfault)
|
||||
EXTERN(__exc_usagefault)
|
||||
EXTERN(__stm32reservedexception7)
|
||||
EXTERN(__stm32reservedexception8)
|
||||
EXTERN(__stm32reservedexception9)
|
||||
EXTERN(__stm32reservedexception10)
|
||||
EXTERN(__exc_svc)
|
||||
EXTERN(__exc_debug_monitor)
|
||||
EXTERN(__stm32reservedexception13)
|
||||
EXTERN(__exc_pendsv)
|
||||
EXTERN(__exc_systick)
|
||||
|
||||
EXTERN(__irq_wwdg)
|
||||
EXTERN(__irq_pvd)
|
||||
EXTERN(__irq_tamper)
|
||||
EXTERN(__irq_rtc)
|
||||
EXTERN(__irq_flash)
|
||||
EXTERN(__irq_rcc)
|
||||
EXTERN(__irq_exti0)
|
||||
EXTERN(__irq_exti1)
|
||||
EXTERN(__irq_exti2)
|
||||
EXTERN(__irq_exti3)
|
||||
EXTERN(__irq_exti4)
|
||||
EXTERN(__irq_dma1_channel1)
|
||||
EXTERN(__irq_dma1_channel2)
|
||||
EXTERN(__irq_dma1_channel3)
|
||||
EXTERN(__irq_dma1_channel4)
|
||||
EXTERN(__irq_dma1_channel5)
|
||||
EXTERN(__irq_dma1_channel6)
|
||||
EXTERN(__irq_dma1_channel7)
|
||||
EXTERN(__irq_adc)
|
||||
EXTERN(__irq_usb_hp_can_tx)
|
||||
EXTERN(__irq_usb_lp_can_rx0)
|
||||
EXTERN(__irq_can_rx1)
|
||||
EXTERN(__irq_can_sce)
|
||||
EXTERN(__irq_exti9_5)
|
||||
EXTERN(__irq_tim1_brk)
|
||||
EXTERN(__irq_tim1_up)
|
||||
EXTERN(__irq_tim1_trg_com)
|
||||
EXTERN(__irq_tim1_cc)
|
||||
EXTERN(__irq_tim2)
|
||||
EXTERN(__irq_tim3)
|
||||
EXTERN(__irq_tim4)
|
||||
EXTERN(__irq_i2c1_ev)
|
||||
EXTERN(__irq_i2c1_er)
|
||||
EXTERN(__irq_i2c2_ev)
|
||||
EXTERN(__irq_i2c2_er)
|
||||
EXTERN(__irq_spi1)
|
||||
EXTERN(__irq_spi2)
|
||||
EXTERN(__irq_usart1)
|
||||
EXTERN(__irq_usart2)
|
||||
EXTERN(__irq_usart3)
|
||||
EXTERN(__irq_exti15_10)
|
||||
EXTERN(__irq_rtcalarm)
|
||||
EXTERN(__irq_usbwakeup)
|
||||
|
||||
EXTERN(__irq_tim8_brk)
|
||||
EXTERN(__irq_tim8_up)
|
||||
EXTERN(__irq_tim8_trg_com)
|
||||
EXTERN(__irq_tim8_cc)
|
||||
EXTERN(__irq_adc3)
|
||||
EXTERN(__irq_fsmc)
|
||||
EXTERN(__irq_sdio)
|
||||
EXTERN(__irq_tim5)
|
||||
EXTERN(__irq_spi3)
|
||||
EXTERN(__irq_uart4)
|
||||
EXTERN(__irq_uart5)
|
||||
EXTERN(__irq_tim6)
|
||||
EXTERN(__irq_tim7)
|
||||
EXTERN(__irq_dma2_channel1)
|
||||
EXTERN(__irq_dma2_channel2)
|
||||
EXTERN(__irq_dma2_channel3)
|
||||
EXTERN(__irq_dma2_channel4_5)
|
||||
@@ -0,0 +1,78 @@
|
||||
EXTERN(__msp_init)
|
||||
EXTERN(__exc_reset)
|
||||
EXTERN(__exc_nmi)
|
||||
EXTERN(__exc_hardfault)
|
||||
EXTERN(__exc_memmanage)
|
||||
EXTERN(__exc_busfault)
|
||||
EXTERN(__exc_usagefault)
|
||||
EXTERN(__stm32reservedexception7)
|
||||
EXTERN(__stm32reservedexception8)
|
||||
EXTERN(__stm32reservedexception9)
|
||||
EXTERN(__stm32reservedexception10)
|
||||
EXTERN(__exc_svc)
|
||||
EXTERN(__exc_debug_monitor)
|
||||
EXTERN(__stm32reservedexception13)
|
||||
EXTERN(__exc_pendsv)
|
||||
EXTERN(__exc_systick)
|
||||
|
||||
EXTERN(__irq_wwdg)
|
||||
EXTERN(__irq_pvd)
|
||||
EXTERN(__irq_tamper)
|
||||
EXTERN(__irq_rtc)
|
||||
EXTERN(__irq_flash)
|
||||
EXTERN(__irq_rcc)
|
||||
EXTERN(__irq_exti0)
|
||||
EXTERN(__irq_exti1)
|
||||
EXTERN(__irq_exti2)
|
||||
EXTERN(__irq_exti3)
|
||||
EXTERN(__irq_exti4)
|
||||
EXTERN(__irq_dma1_channel1)
|
||||
EXTERN(__irq_dma1_channel2)
|
||||
EXTERN(__irq_dma1_channel3)
|
||||
EXTERN(__irq_dma1_channel4)
|
||||
EXTERN(__irq_dma1_channel5)
|
||||
EXTERN(__irq_dma1_channel6)
|
||||
EXTERN(__irq_dma1_channel7)
|
||||
EXTERN(__irq_adc1)
|
||||
EXTERN(__stm32reservedexception14)
|
||||
EXTERN(__stm32reservedexception15)
|
||||
EXTERN(__stm32reservedexception16)
|
||||
EXTERN(__stm32reservedexception17)
|
||||
EXTERN(__irq_exti9_5)
|
||||
EXTERN(__irq_tim1_brk)
|
||||
EXTERN(__irq_tim1_up)
|
||||
EXTERN(__irq_tim1_trg_com)
|
||||
EXTERN(__irq_tim1_cc)
|
||||
EXTERN(__irq_tim2)
|
||||
EXTERN(__irq_tim3)
|
||||
EXTERN(__irq_tim4)
|
||||
EXTERN(__irq_i2c1_ev)
|
||||
EXTERN(__irq_i2c1_er)
|
||||
EXTERN(__irq_i2c2_ev)
|
||||
EXTERN(__irq_i2c2_er)
|
||||
EXTERN(__irq_spi1)
|
||||
EXTERN(__irq_spi2)
|
||||
EXTERN(__irq_usart1)
|
||||
EXTERN(__irq_usart2)
|
||||
EXTERN(__irq_usart3)
|
||||
EXTERN(__irq_exti15_10)
|
||||
EXTERN(__irq_rtcalarm)
|
||||
EXTERN(__irq_cec)
|
||||
EXTERN(__irq_tim12)
|
||||
EXTERN(__irq_tim13)
|
||||
EXTERN(__irq_tim14)
|
||||
EXTERN(__stm32reservedexception18)
|
||||
EXTERN(__stm32reservedexception19)
|
||||
EXTERN(__irq_fsmc)
|
||||
EXTERN(__stm32reservedexception20)
|
||||
EXTERN(__irq_tim5)
|
||||
EXTERN(__irq_spi3)
|
||||
EXTERN(__irq_uart4)
|
||||
EXTERN(__irq_uart5)
|
||||
EXTERN(__irq_tim6)
|
||||
EXTERN(__irq_tim7)
|
||||
EXTERN(__irq_dma2_channel1)
|
||||
EXTERN(__irq_dma2_channel2)
|
||||
EXTERN(__irq_dma2_channel3)
|
||||
EXTERN(__irq_dma2_channel4_5)
|
||||
EXTERN(__irq_dma2_channel5) /* on remap only */
|
||||
@@ -0,0 +1,98 @@
|
||||
EXTERN(__msp_init)
|
||||
EXTERN(__exc_reset)
|
||||
EXTERN(__exc_nmi)
|
||||
EXTERN(__exc_hardfault)
|
||||
EXTERN(__exc_memmanage)
|
||||
EXTERN(__exc_busfault)
|
||||
EXTERN(__exc_usagefault)
|
||||
EXTERN(__stm32reservedexception7)
|
||||
EXTERN(__stm32reservedexception8)
|
||||
EXTERN(__stm32reservedexception9)
|
||||
EXTERN(__stm32reservedexception10)
|
||||
EXTERN(__exc_svc)
|
||||
EXTERN(__exc_debug_monitor)
|
||||
EXTERN(__stm32reservedexception13)
|
||||
EXTERN(__exc_pendsv)
|
||||
EXTERN(__exc_systick)
|
||||
|
||||
EXTERN(__irq_wwdg)
|
||||
EXTERN(__irq_pvd)
|
||||
EXTERN(__irq_tamp_stamp)
|
||||
EXTERN(__irq_rtc_wkup)
|
||||
EXTERN(__irq_flash)
|
||||
EXTERN(__irq_rcc)
|
||||
EXTERN(__irq_exti0)
|
||||
EXTERN(__irq_exti1)
|
||||
EXTERN(__irq_exti2)
|
||||
EXTERN(__irq_exti3)
|
||||
EXTERN(__irq_exti4)
|
||||
EXTERN(__irq_dma1_stream0)
|
||||
EXTERN(__irq_dma1_stream1)
|
||||
EXTERN(__irq_dma1_stream2)
|
||||
EXTERN(__irq_dma1_stream3)
|
||||
EXTERN(__irq_dma1_stream4)
|
||||
EXTERN(__irq_dma1_stream5)
|
||||
EXTERN(__irq_dma1_stream6)
|
||||
EXTERN(__irq_adc)
|
||||
EXTERN(__irq_can1_tx)
|
||||
EXTERN(__irq_can1_rx0)
|
||||
EXTERN(__irq_can1_rx1)
|
||||
EXTERN(__irq_can1_sce)
|
||||
EXTERN(__irq_exti9_5)
|
||||
EXTERN(__irq_tim1_brk_tim9)
|
||||
EXTERN(__irq_tim1_up_tim10)
|
||||
EXTERN(__irq_tim1_trg_com_tim11)
|
||||
EXTERN(__irq_tim1_cc)
|
||||
EXTERN(__irq_tim2)
|
||||
EXTERN(__irq_tim3)
|
||||
EXTERN(__irq_tim4)
|
||||
EXTERN(__irq_i2c1_ev)
|
||||
EXTERN(__irq_i2c1_er)
|
||||
EXTERN(__irq_i2c2_ev)
|
||||
EXTERN(__irq_i2c2_er)
|
||||
EXTERN(__irq_spi1)
|
||||
EXTERN(__irq_spi2)
|
||||
EXTERN(__irq_usart1)
|
||||
EXTERN(__irq_usart2)
|
||||
EXTERN(__irq_usart3)
|
||||
EXTERN(__irq_exti15_10)
|
||||
EXTERN(__irq_rtc_alarm)
|
||||
EXTERN(__irq_otg_fs_wkup)
|
||||
EXTERN(__irq_tim8_brk_tim12)
|
||||
EXTERN(__irq_tim8_up_tim13)
|
||||
EXTERN(__irq_tim8_trg_com_tim14)
|
||||
EXTERN(__irq_tim8_cc)
|
||||
EXTERN(__irq_dma1_stream7)
|
||||
EXTERN(__irq_fsmc)
|
||||
EXTERN(__irq_sdio)
|
||||
EXTERN(__irq_tim5)
|
||||
EXTERN(__irq_spi3)
|
||||
EXTERN(__irq_uart4)
|
||||
EXTERN(__irq_uart5)
|
||||
EXTERN(__irq_tim6_dac)
|
||||
EXTERN(__irq_tim7)
|
||||
EXTERN(__irq_dma2_stream0)
|
||||
EXTERN(__irq_dma2_stream1)
|
||||
EXTERN(__irq_dma2_stream2)
|
||||
EXTERN(__irq_dma2_stream3)
|
||||
EXTERN(__irq_dma2_stream4)
|
||||
EXTERN(__irq_eth)
|
||||
EXTERN(__irq_eth_wkup)
|
||||
EXTERN(__irq_can2_tx)
|
||||
EXTERN(__irq_can2_rx0)
|
||||
EXTERN(__irq_can2_rx1)
|
||||
EXTERN(__irq_can2_sce)
|
||||
EXTERN(__irq_otg_fs)
|
||||
EXTERN(__irq_dma2_stream5)
|
||||
EXTERN(__irq_dma2_stream6)
|
||||
EXTERN(__irq_dma2_stream7)
|
||||
EXTERN(__irq_usart6)
|
||||
EXTERN(__irq_i2c3_ev)
|
||||
EXTERN(__irq_i2c3_er)
|
||||
EXTERN(__irq_otg_hs_ep1_out)
|
||||
EXTERN(__irq_otg_hs_ep1_in)
|
||||
EXTERN(__irq_otg_hs_wkup)
|
||||
EXTERN(__irq_otg_hs)
|
||||
EXTERN(__irq_dcmi)
|
||||
EXTERN(__irq_cryp)
|
||||
EXTERN(__irq_hash_rng)
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Extra archives needed by ARM's GCC ARM Embedded arm-none-eabi-
|
||||
* releases (https://launchpad.net/gcc-arm-embedded/).
|
||||
*/
|
||||
|
||||
/* This is for the provided newlib. */
|
||||
GROUP(libnosys.a)
|
||||
@@ -0,0 +1,7 @@
|
||||
MCU := STM32F100RB
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOC
|
||||
ERROR_LED_PIN := 9
|
||||
MCU_SERIES := stm32f1
|
||||
MCU_F1_LINE := value
|
||||
LD_MEM_DIR := sram_8k_flash_128k
|
||||
@@ -0,0 +1,15 @@
|
||||
MCU := STM32F103C8
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOB
|
||||
ERROR_LED_PIN := 2
|
||||
MCU_SERIES := stm32f1
|
||||
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
|
||||
@@ -0,0 +1,10 @@
|
||||
MCU := STM32F103RB
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOA
|
||||
ERROR_LED_PIN := 5
|
||||
MCU_SERIES := stm32f1
|
||||
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!
|
||||
LD_MEM_DIR := sram_20k_flash_128k
|
||||
@@ -0,0 +1,7 @@
|
||||
MCU := STM32F103RE
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOA
|
||||
ERROR_LED_PIN := 5
|
||||
MCU_SERIES := stm32f1
|
||||
MCU_F1_LINE := performance
|
||||
LD_MEM_DIR := sram_64k_flash_512k
|
||||
@@ -0,0 +1,7 @@
|
||||
MCU := STM32F103CB
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOB
|
||||
ERROR_LED_PIN := 1
|
||||
MCU_SERIES := stm32f1
|
||||
MCU_F1_LINE := performance
|
||||
LD_MEM_DIR := sram_20k_flash_128k
|
||||
@@ -0,0 +1,7 @@
|
||||
MCU := STM32F103ZE
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOC
|
||||
ERROR_LED_PIN := 15
|
||||
MCU_SERIES := stm32f1
|
||||
MCU_F1_LINE := performance
|
||||
LD_MEM_DIR := maple_native # The SRAM chip makes this board special
|
||||
@@ -0,0 +1,7 @@
|
||||
MCU := STM32F103RB
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOC
|
||||
ERROR_LED_PIN := 12
|
||||
MCU_SERIES := stm32f1
|
||||
MCU_F1_LINE := performance
|
||||
LD_MEM_DIR := sram_20k_flash_128k
|
||||
@@ -0,0 +1,15 @@
|
||||
MCU := STM32F103CB
|
||||
PRODUCT_ID := 0003
|
||||
ERROR_LED_PORT := GPIOB
|
||||
ERROR_LED_PIN := 9
|
||||
MCU_SERIES := stm32f1
|
||||
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
|
||||
@@ -0,0 +1,5 @@
|
||||
MCU := STM32F207IG
|
||||
ERROR_LED_PORT := GPIOG
|
||||
ERROR_LED_PIN := 6
|
||||
MCU_SERIES := stm32f2
|
||||
LD_MEM_DIR := sram_112k_flash_1024k
|
||||
59
BootLoaders/Boards/stm32/system/support/make/build-rules.mk
Normal file
59
BootLoaders/Boards/stm32/system/support/make/build-rules.mk
Normal file
@@ -0,0 +1,59 @@
|
||||
# Useful tools
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
CXX := $(CROSS_COMPILE)g++
|
||||
LD := $(CROSS_COMPILE)ld -v
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
AS := $(CROSS_COMPILE)gcc
|
||||
OBJCOPY := $(CROSS_COMPILE)objcopy
|
||||
DISAS := $(CROSS_COMPILE)objdump
|
||||
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||
SIZE := $(CROSS_COMPILE)size
|
||||
DFU ?= dfu-util
|
||||
|
||||
# Suppress annoying output unless V is set
|
||||
ifndef V
|
||||
SILENT_CC = @echo ' [CC] ' $(@:$(BUILD_PATH)/%.o=%.c);
|
||||
SILENT_AS = @echo ' [AS] ' $(@:$(BUILD_PATH)/%.o=%.S);
|
||||
SILENT_CXX = @echo ' [CXX] ' $(@:$(BUILD_PATH)/%.o=%.cpp);
|
||||
SILENT_LD = @echo ' [LD] ' $(@F);
|
||||
SILENT_AR = @echo ' [AR] '
|
||||
SILENT_OBJCOPY = @echo ' [OBJCOPY] ' $(@F);
|
||||
SILENT_DISAS = @echo ' [DISAS] ' $(@:$(BUILD_PATH)/%.bin=%).disas;
|
||||
SILENT_OBJDUMP = @echo ' [OBJDUMP] ' $(OBJDUMP);
|
||||
endif
|
||||
|
||||
# Extra build configuration
|
||||
|
||||
BUILDDIRS :=
|
||||
TGT_BIN :=
|
||||
|
||||
CFLAGS = $(GLOBAL_CFLAGS) $(TGT_CFLAGS)
|
||||
CXXFLAGS = $(GLOBAL_CXXFLAGS) $(TGT_CXXFLAGS)
|
||||
ASFLAGS = $(GLOBAL_ASFLAGS) $(TGT_ASFLAGS)
|
||||
|
||||
# Hacks to determine extra libraries we need to link against based on
|
||||
# the toolchain. The default specifies no extra libraries, but it can
|
||||
# be overridden.
|
||||
LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/generic
|
||||
ifneq ($(findstring ARM/embedded,$(shell $(CC) --version)),)
|
||||
# GCC ARM Embedded, https://launchpad.net/gcc-arm-embedded/
|
||||
LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/gcc-arm-embedded
|
||||
endif
|
||||
ifneq ($(findstring Linaro GCC,$(shell $(CC) --version)),)
|
||||
# Summon/Linaro GCC ARM Embedded, https://github.com/esden/summon-arm-toolchain
|
||||
LD_TOOLCHAIN_PATH := $(LDDIR)/toolchains/gcc-arm-embedded
|
||||
endif
|
||||
# Add toolchain directory to LD search path
|
||||
TOOLCHAIN_LDFLAGS := -L $(LD_TOOLCHAIN_PATH)
|
||||
|
||||
# General directory independent build rules, generate dependency information
|
||||
$(BUILD_PATH)/%.o: %.c
|
||||
$(SILENT_CC) $(CC) $(CFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $<
|
||||
|
||||
$(BUILD_PATH)/%.o: %.cpp
|
||||
$(SILENT_CXX) $(CXX) $(CFLAGS) $(CXXFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $<
|
||||
|
||||
$(BUILD_PATH)/%.o: %.S
|
||||
$(SILENT_AS) $(AS) $(ASFLAGS) -MMD -MP -MF $(@:%.o=%.d) -MT $@ -o $@ -c $<
|
||||
@@ -0,0 +1,5 @@
|
||||
define LIBMAPLE_MODULE_template
|
||||
dir := $(1)
|
||||
include $$(dir)/rules.mk
|
||||
endef
|
||||
|
||||
18
BootLoaders/Boards/stm32/system/support/make/footer.mk
Normal file
18
BootLoaders/Boards/stm32/system/support/make/footer.mk
Normal file
@@ -0,0 +1,18 @@
|
||||
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
|
||||
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
|
||||
cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%)
|
||||
|
||||
OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \
|
||||
$(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \
|
||||
$(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o)
|
||||
DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
|
||||
|
||||
$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
|
||||
$(OBJS_$(d)): TGT_CXXFLAGS := $(CXXFLAGS_$(d))
|
||||
$(OBJS_$(d)): TGT_ASFLAGS := $(ASFLAGS_$(d))
|
||||
|
||||
TGT_BIN += $(OBJS_$(d))
|
||||
|
||||
-include $(DEPS_$(d))
|
||||
d := $(dirstack_$(sp))
|
||||
sp := $(basename $(sp))
|
||||
4
BootLoaders/Boards/stm32/system/support/make/header.mk
Normal file
4
BootLoaders/Boards/stm32/system/support/make/header.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
sp := $(sp).x
|
||||
dirstack_$(sp) := $(d)
|
||||
d := $(dir)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)
|
||||
@@ -0,0 +1,54 @@
|
||||
# TARGET_FLAGS are to be passed while compiling, assembling, linking.
|
||||
TARGET_FLAGS :=
|
||||
# TARGET_LDFLAGS go to the linker
|
||||
TARGET_LDFLAGS :=
|
||||
|
||||
# Configuration derived from $(MEMORY_TARGET)
|
||||
|
||||
LD_SCRIPT_PATH := $(LDDIR)/$(MEMORY_TARGET).ld
|
||||
|
||||
ifeq ($(MEMORY_TARGET), ram)
|
||||
VECT_BASE_ADDR := VECT_TAB_RAM
|
||||
endif
|
||||
ifeq ($(MEMORY_TARGET), flash)
|
||||
VECT_BASE_ADDR := VECT_TAB_FLASH
|
||||
endif
|
||||
ifeq ($(MEMORY_TARGET), jtag)
|
||||
VECT_BASE_ADDR := VECT_TAB_BASE
|
||||
endif
|
||||
|
||||
# Pull in the board configuration file here, so it can override the
|
||||
# above.
|
||||
|
||||
include $(BOARD_INCLUDE_DIR)/$(BOARD).mk
|
||||
|
||||
# Configuration derived from $(BOARD).mk
|
||||
|
||||
LD_SERIES_PATH := $(LDDIR)/stm32/series/$(MCU_SERIES)
|
||||
LD_MEM_PATH := $(LDDIR)/stm32/mem/$(LD_MEM_DIR)
|
||||
ifeq ($(MCU_SERIES), stm32f1)
|
||||
# Due to the Balkanization on F1, we need to specify the line when
|
||||
# making linker decisions.
|
||||
LD_SERIES_PATH := $(LD_SERIES_PATH)/$(MCU_F1_LINE)
|
||||
endif
|
||||
|
||||
ifeq ($(MCU_SERIES), stm32f1)
|
||||
TARGET_FLAGS += -mcpu=cortex-m3 -march=armv7-m
|
||||
endif
|
||||
ifeq ($(MCU_SERIES), stm32f2)
|
||||
TARGET_FLAGS += -mcpu=cortex-m3 -march=armv7-m
|
||||
endif
|
||||
ifeq ($(MCU_SERIES), stm32f4)
|
||||
TARGET_FLAGS += -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
endif
|
||||
|
||||
TARGET_LDFLAGS += -Xlinker -T$(LD_SCRIPT_PATH) \
|
||||
-L $(LD_SERIES_PATH) \
|
||||
-L $(LD_MEM_PATH) \
|
||||
-L $(LDDIR)
|
||||
TARGET_FLAGS += -mthumb -DBOARD_$(BOARD) -DMCU_$(MCU) \
|
||||
-DERROR_LED_PORT=$(ERROR_LED_PORT) \
|
||||
-DERROR_LED_PIN=$(ERROR_LED_PIN) \
|
||||
-D$(VECT_BASE_ADDR)
|
||||
|
||||
LIBMAPLE_MODULE_SERIES := $(LIBMAPLE_PATH)/$(MCU_SERIES)
|
||||
@@ -0,0 +1,5 @@
|
||||
ATTRS{idProduct}=="1001", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idProduct}=="1002", ATTRS{idVendor}=="0110", MODE="664", GROUP="plugdev"
|
||||
ATTRS{idProduct}=="0003", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple"
|
||||
ATTRS{idProduct}=="0004", ATTRS{idVendor}=="1eaf", MODE="664", GROUP="plugdev" SYMLINK+="maple"
|
||||
|
||||
54
BootLoaders/Boards/stm32/system/support/scripts/copy-to-ide
Normal file
54
BootLoaders/Boards/stm32/system/support/scripts/copy-to-ide
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This hack copies libmaple's source, linker scripts, and support
|
||||
# libraries into the Maple IDE repository (which is expected as its
|
||||
# first argument).
|
||||
|
||||
DEST=$1
|
||||
|
||||
DEST_CORES=$DEST/hardware/leaflabs/cores/maple
|
||||
DEST_LIBS=$DEST/libraries
|
||||
|
||||
LMAPLE_SRC="LICENSE
|
||||
./libmaple/*.h
|
||||
./libmaple/*.c
|
||||
./libmaple/*.S
|
||||
./libmaple/usb/*.h
|
||||
./libmaple/usb/*.c
|
||||
./libmaple/usb/usb_lib/*.h
|
||||
./libmaple/usb/usb_lib/*.c
|
||||
./wirish/*.h
|
||||
./wirish/main.cxx
|
||||
./wirish/*.cpp
|
||||
./wirish/comm/*.cpp
|
||||
./wirish/comm/*.h
|
||||
./wirish/boards/*.h
|
||||
./wirish/boards/*.cpp
|
||||
./support/ld/common.inc
|
||||
./support/ld/maple
|
||||
./support/ld/maple_mini
|
||||
./support/ld/maple_native
|
||||
./support/ld/maple_RET6
|
||||
./support/ld/names.inc"
|
||||
|
||||
echo "First make sure DEST exists: $DEST"
|
||||
if !(test -d $DEST)
|
||||
then
|
||||
echo "Nope! Make sure you're doing this right?"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
# source
|
||||
echo Copying libmaple source
|
||||
rm -rf $DEST_CORES/*.c $DEST_CORES/*.cpp $DEST_CORES/*.h $DEST_CORES/*.cxx $DEST_CORES/*.S
|
||||
rm -rf $DEST_CORES/*.inc $DEST_CORES/*.a $DEST_CORES/maple $DEST_CORES/maple_*
|
||||
cp -R $LMAPLE_SRC $DEST_CORES
|
||||
|
||||
echo Copying over libraries
|
||||
cp -R libraries/* $DEST_LIBS
|
||||
|
||||
# libmaple version
|
||||
echo Creating libmaple-version.txt
|
||||
git show-ref HEAD | cut -c 1-10 > $DEST/libmaple-version.txt
|
||||
|
||||
echo Done.
|
||||
145
BootLoaders/Boards/stm32/system/support/scripts/reset.py
Normal file
145
BootLoaders/Boards/stm32/system/support/scripts/reset.py
Normal file
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import serial
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import time
|
||||
from struct import pack
|
||||
|
||||
def unix_get_maple_path(file_prefix, dev_is_maple=lambda dev: True):
|
||||
"""Try to find the device file for the Maple on *nix.
|
||||
|
||||
This function works assuming that the device file globs like
|
||||
'/dev/<file_prefix>*'. The caller may pass an additional
|
||||
dev_is_maple predicate if the platform supports additional tests
|
||||
to determine if a device is a Maple.
|
||||
|
||||
If there are multiple possibilities, ask the user what to do. If
|
||||
the user chooses not to say, returns None."""
|
||||
possible_paths = [os.path.join('/dev', x) for x in os.listdir('/dev') \
|
||||
if x.startswith(file_prefix) and dev_is_maple(x)]
|
||||
return choose_path(possible_paths)
|
||||
|
||||
def linux_get_maple_path(file_prefix='ttyACM'):
|
||||
"""Specialized unix_get_maple_path() for Linux.
|
||||
|
||||
Attempts to check that a candidate device has the correct ID in
|
||||
the /sys tree when deciding if it's a Maple."""
|
||||
return unix_get_maple_path(file_prefix, linux_tty_is_maple)
|
||||
|
||||
def linux_tty_is_maple(device):
|
||||
try:
|
||||
sysfile = open("/sys/class/tty/%s/device/uevent" % device, "r")
|
||||
text = "".join(sysfile.readlines())
|
||||
return "PRODUCT=1eaf/4" in text
|
||||
except IOError: # no udev info available
|
||||
return True
|
||||
|
||||
def windows_get_maple_path():
|
||||
"""Similar to unix_get_maple_path(), but on Windows."""
|
||||
import _winreg as reg
|
||||
p = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
|
||||
k = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, p)
|
||||
possible_paths = []
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
possible_paths.append(reg.EnumValue(k, i)[1])
|
||||
i += 1
|
||||
except WindowsError:
|
||||
break
|
||||
return choose_path(possible_paths)
|
||||
|
||||
def choose_path(possible_paths):
|
||||
if len(possible_paths) == 0:
|
||||
return None
|
||||
elif len(possible_paths) == 1:
|
||||
return possible_paths[0]
|
||||
else:
|
||||
print('Found multiple candidates for the Maple device:')
|
||||
return choose_among_options(possible_paths)
|
||||
|
||||
def choose_among_options(options):
|
||||
for (i,p) in enumerate(options):
|
||||
print('\t%d. %s' % (i+1, p))
|
||||
|
||||
prompt = 'Enter a number to select one, or q to quit: '
|
||||
while True:
|
||||
resp = raw_input(prompt).strip().lower()
|
||||
if resp == 'q': sys.exit()
|
||||
|
||||
try:
|
||||
i = int(resp, 10)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
if 0 <= i-1 < len(options):
|
||||
return options[i-1]
|
||||
|
||||
prompt = 'Please enter a number from the list, or q to quit: '
|
||||
|
||||
plat_sys = platform.system()
|
||||
plat_bits = platform.architecture()[0]
|
||||
if plat_sys == 'Linux':
|
||||
maple_path = linux_get_maple_path()
|
||||
# fall back on /dev/maple if that doesn't work
|
||||
if maple_path is None:
|
||||
maple_path = '/dev/maple'
|
||||
print('Could not find Maple serial port; defaulting to /dev/maple.')
|
||||
elif plat_sys == 'Darwin':
|
||||
maple_path = unix_get_maple_path('tty.usbmodem')
|
||||
elif plat_sys == 'Windows':
|
||||
maple_path = windows_get_maple_path()
|
||||
else:
|
||||
maple_path = raw_input('Unrecognized platform. Please enter '
|
||||
"the path to the Maple's serial port device file:")
|
||||
|
||||
if maple_path is None:
|
||||
print('Could not find the Maple serial port for reset.',
|
||||
'Perhaps this is your first upload, or the board is already',
|
||||
'in bootloader mode.')
|
||||
print()
|
||||
print("If your sketch doesn't upload, try putting your Maple",
|
||||
'into bootloader mode manually by pressing the RESET button',
|
||||
'then letting it go and quickly pressing button BUT',
|
||||
'(hold for several seconds).')
|
||||
sys.exit()
|
||||
|
||||
print('Using %s as Maple serial port' % maple_path)
|
||||
|
||||
try:
|
||||
ser = serial.Serial(maple_path, baudrate=115200, xonxoff=1)
|
||||
|
||||
try:
|
||||
# try to toggle DTR/RTS (old scheme)
|
||||
ser.setRTS(0)
|
||||
time.sleep(0.01)
|
||||
ser.setDTR(0)
|
||||
time.sleep(0.01)
|
||||
ser.setDTR(1)
|
||||
time.sleep(0.01)
|
||||
ser.setDTR(0)
|
||||
|
||||
# try magic number
|
||||
ser.setRTS(1)
|
||||
time.sleep(0.01)
|
||||
ser.setDTR(1)
|
||||
time.sleep(0.01)
|
||||
ser.setDTR(0)
|
||||
time.sleep(0.01)
|
||||
ser.write("1EAF".encode("ascii"))
|
||||
ser.flush()
|
||||
|
||||
# Delay a bit before proceeding
|
||||
time.sleep(0.1)
|
||||
finally:
|
||||
# ok we're done here
|
||||
ser.close()
|
||||
|
||||
except Exception as e:
|
||||
print('Failed to open serial port %s for reset' % maple_path)
|
||||
sys.exit()
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,29 @@
|
||||
# Windows program for listing COM (serial) ports.
|
||||
#
|
||||
# enumerate_serial_ports() is by Eli Bendersky:
|
||||
#
|
||||
# http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
|
||||
|
||||
import _winreg as winreg
|
||||
import itertools
|
||||
|
||||
def enumerate_serial_ports():
|
||||
""" Uses the Win32 registry to return an
|
||||
iterator of serial (COM) ports
|
||||
existing on this computer.
|
||||
"""
|
||||
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
|
||||
try:
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
|
||||
except WindowsError:
|
||||
raise IterationError
|
||||
|
||||
for i in itertools.count():
|
||||
try:
|
||||
val = winreg.EnumValue(key, i)
|
||||
yield str(val[1])
|
||||
except EnvironmentError:
|
||||
break
|
||||
|
||||
for com in enumerate_serial_ports():
|
||||
print com
|
||||
532
BootLoaders/Boards/stm32/system/support/stm32loader.py
Normal file
532
BootLoaders/Boards/stm32/system/support/stm32loader.py
Normal file
@@ -0,0 +1,532 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: sw=4:ts=4:si:et:enc=utf-8
|
||||
|
||||
# Author: Ivan A-R <ivan@tuxotronic.org>
|
||||
# Project page: http://tuxotronic.org/wiki/projects/stm32loader
|
||||
#
|
||||
# This file is part of stm32loader.
|
||||
#
|
||||
# stm32loader 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, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# stm32loader 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 stm32loader; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys, getopt
|
||||
import serial
|
||||
import time
|
||||
import glob
|
||||
import time
|
||||
import tempfile
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
from progressbar import *
|
||||
usepbar = 1
|
||||
except:
|
||||
usepbar = 0
|
||||
|
||||
# Verbose level
|
||||
QUIET = 5
|
||||
|
||||
def mdebug(level, message):
|
||||
if QUIET >= level:
|
||||
print(message, file=sys.stderr)
|
||||
|
||||
# Takes chip IDs (obtained via Get ID command) to human-readable names
|
||||
CHIP_ID_STRS = {0x410: 'STM32F1, performance, medium-density',
|
||||
0x411: 'STM32F2',
|
||||
0x412: 'STM32F1, performance, low-density',
|
||||
0x413: 'STM32F4',
|
||||
0x414: 'STM32F1, performance, high-density',
|
||||
0x416: 'STM32L1, performance, medium-density',
|
||||
0x418: 'STM32F1, connectivity',
|
||||
0x420: 'STM32F1, value, medium-density',
|
||||
0x428: 'STM32F1, value, high-density',
|
||||
0x430: 'STM32F1, performance, XL-density'}
|
||||
|
||||
class CmdException(Exception):
|
||||
pass
|
||||
|
||||
class CommandInterface(object):
|
||||
def open(self, aport='/dev/tty.usbserial-FTD3TMCH', abaudrate=115200) :
|
||||
self.sp = serial.Serial(
|
||||
port=aport,
|
||||
baudrate=abaudrate, # baudrate
|
||||
bytesize=8, # number of databits
|
||||
parity=serial.PARITY_EVEN,
|
||||
stopbits=1,
|
||||
xonxoff=0, # enable software flow control
|
||||
rtscts=0, # disable RTS/CTS flow control
|
||||
timeout=0.5 # set a timeout value, None for waiting forever
|
||||
)
|
||||
|
||||
|
||||
def _wait_for_ack(self, info="", timeout=0):
|
||||
stop = time.time() + timeout
|
||||
got = None
|
||||
while not got:
|
||||
got = self.sp.read(1)
|
||||
if time.time() > stop:
|
||||
break
|
||||
|
||||
if not got:
|
||||
raise CmdException("No response to %s" % info)
|
||||
|
||||
# wait for ask
|
||||
ask = ord(got)
|
||||
|
||||
if ask == 0x79:
|
||||
# ACK
|
||||
return 1
|
||||
elif ask == 0x1F:
|
||||
# NACK
|
||||
raise CmdException("Chip replied with a NACK during %s" % info)
|
||||
|
||||
# Unknown response
|
||||
raise CmdException("Unrecognised response 0x%x to %s" % (ask, info))
|
||||
|
||||
def reset(self):
|
||||
self.sp.setDTR(0)
|
||||
time.sleep(0.1)
|
||||
self.sp.setDTR(1)
|
||||
time.sleep(0.5)
|
||||
|
||||
def initChip(self):
|
||||
# Set boot
|
||||
self.sp.setRTS(0)
|
||||
self.reset()
|
||||
|
||||
# Be a bit more persistent when trying to initialise the chip
|
||||
stop = time.time() + 5.0
|
||||
|
||||
while time.time() <= stop:
|
||||
self.sp.write('\x7f')
|
||||
|
||||
got = self.sp.read()
|
||||
|
||||
# The chip will ACK a sync the very first time and
|
||||
# NACK it every time afterwards
|
||||
if got and got in '\x79\x1f':
|
||||
# Synced up
|
||||
return
|
||||
|
||||
raise CmdException('No response while trying to sync')
|
||||
|
||||
def releaseChip(self):
|
||||
self.sp.setRTS(1)
|
||||
self.reset()
|
||||
|
||||
def cmdGeneric(self, cmd):
|
||||
self.sp.write(chr(cmd))
|
||||
self.sp.write(chr(cmd ^ 0xFF)) # Control byte
|
||||
return self._wait_for_ack(hex(cmd))
|
||||
|
||||
def cmdGet(self):
|
||||
if self.cmdGeneric(0x00):
|
||||
mdebug(10, "*** Get command");
|
||||
len = ord(self.sp.read())
|
||||
version = ord(self.sp.read())
|
||||
mdebug(10, " Bootloader version: "+hex(version))
|
||||
dat = map(lambda c: hex(ord(c)), self.sp.read(len))
|
||||
mdebug(10, " Available commands: "+str(dat))
|
||||
self._wait_for_ack("0x00 end")
|
||||
return version
|
||||
else:
|
||||
raise CmdException("Get (0x00) failed")
|
||||
|
||||
def cmdGetVersion(self):
|
||||
if self.cmdGeneric(0x01):
|
||||
mdebug(10, "*** GetVersion command")
|
||||
version = ord(self.sp.read())
|
||||
self.sp.read(2)
|
||||
self._wait_for_ack("0x01 end")
|
||||
mdebug(10, " Bootloader version: "+hex(version))
|
||||
return version
|
||||
else:
|
||||
raise CmdException("GetVersion (0x01) failed")
|
||||
|
||||
def cmdGetID(self):
|
||||
if self.cmdGeneric(0x02):
|
||||
mdebug(10, "*** GetID command")
|
||||
len = ord(self.sp.read())
|
||||
id = self.sp.read(len+1)
|
||||
self._wait_for_ack("0x02 end")
|
||||
return id
|
||||
else:
|
||||
raise CmdException("GetID (0x02) failed")
|
||||
|
||||
|
||||
def _encode_addr(self, addr):
|
||||
byte3 = (addr >> 0) & 0xFF
|
||||
byte2 = (addr >> 8) & 0xFF
|
||||
byte1 = (addr >> 16) & 0xFF
|
||||
byte0 = (addr >> 24) & 0xFF
|
||||
crc = byte0 ^ byte1 ^ byte2 ^ byte3
|
||||
return (chr(byte0) + chr(byte1) + chr(byte2) + chr(byte3) + chr(crc))
|
||||
|
||||
|
||||
def cmdReadMemory(self, addr, lng):
|
||||
assert(lng <= 256)
|
||||
if self.cmdGeneric(0x11):
|
||||
mdebug(10, "*** ReadMemory command")
|
||||
self.sp.write(self._encode_addr(addr))
|
||||
self._wait_for_ack("0x11 address failed")
|
||||
N = (lng - 1) & 0xFF
|
||||
crc = N ^ 0xFF
|
||||
self.sp.write(chr(N) + chr(crc))
|
||||
self._wait_for_ack("0x11 length failed")
|
||||
return map(lambda c: ord(c), self.sp.read(lng))
|
||||
else:
|
||||
raise CmdException("ReadMemory (0x11) failed")
|
||||
|
||||
|
||||
def cmdGo(self, addr):
|
||||
if self.cmdGeneric(0x21):
|
||||
mdebug(10, "*** Go command")
|
||||
self.sp.write(self._encode_addr(addr))
|
||||
self._wait_for_ack("0x21 go failed")
|
||||
else:
|
||||
raise CmdException("Go (0x21) failed")
|
||||
|
||||
|
||||
def cmdWriteMemory(self, addr, data):
|
||||
assert(len(data) <= 256)
|
||||
if self.cmdGeneric(0x31):
|
||||
mdebug(10, "*** Write memory command")
|
||||
self.sp.write(self._encode_addr(addr))
|
||||
self._wait_for_ack("0x31 address failed")
|
||||
#map(lambda c: hex(ord(c)), data)
|
||||
lng = (len(data)-1) & 0xFF
|
||||
mdebug(10, " %s bytes to write" % [lng+1]);
|
||||
self.sp.write(chr(lng)) # len really
|
||||
crc = 0xFF
|
||||
for c in data:
|
||||
crc = crc ^ c
|
||||
self.sp.write(chr(c))
|
||||
self.sp.write(chr(crc))
|
||||
self._wait_for_ack("0x31 programming failed")
|
||||
mdebug(10, " Write memory done")
|
||||
else:
|
||||
raise CmdException("Write memory (0x31) failed")
|
||||
|
||||
|
||||
def cmdEraseMemory(self, sectors = None):
|
||||
if self.cmdGeneric(0x43):
|
||||
mdebug(10, "*** Erase memory command")
|
||||
if sectors is None:
|
||||
# Global erase
|
||||
self.sp.write(chr(0xFF))
|
||||
self.sp.write(chr(0x00))
|
||||
else:
|
||||
# Sectors erase
|
||||
self.sp.write(chr((len(sectors)-1) & 0xFF))
|
||||
crc = 0xFF
|
||||
for c in sectors:
|
||||
crc = crc ^ c
|
||||
self.sp.write(chr(c))
|
||||
self.sp.write(chr(crc))
|
||||
self._wait_for_ack("0x43 erasing failed")
|
||||
mdebug(10, " Erase memory done")
|
||||
else:
|
||||
raise CmdException("Erase memory (0x43) failed")
|
||||
|
||||
|
||||
# TODO support for non-global mass erase
|
||||
GLOBAL_ERASE_TIMEOUT_SECONDS = 20 # This takes a while
|
||||
def cmdExtendedEraseMemory(self):
|
||||
if self.cmdGeneric(0x44):
|
||||
mdebug(10, "*** Extended erase memory command")
|
||||
# Global mass erase
|
||||
mdebug(5, "Global mass erase; this may take a while")
|
||||
self.sp.write(chr(0xFF))
|
||||
self.sp.write(chr(0xFF))
|
||||
# Checksum
|
||||
self.sp.write(chr(0x00))
|
||||
self._wait_for_ack("0x44 extended erase failed",
|
||||
timeout=self.GLOBAL_ERASE_TIMEOUT_SECONDS)
|
||||
mdebug(10, " Extended erase memory done")
|
||||
else:
|
||||
raise CmdException("Extended erase memory (0x44) failed")
|
||||
|
||||
|
||||
def cmdWriteProtect(self, sectors):
|
||||
if self.cmdGeneric(0x63):
|
||||
mdebug(10, "*** Write protect command")
|
||||
self.sp.write(chr((len(sectors)-1) & 0xFF))
|
||||
crc = 0xFF
|
||||
for c in sectors:
|
||||
crc = crc ^ c
|
||||
self.sp.write(chr(c))
|
||||
self.sp.write(chr(crc))
|
||||
self._wait_for_ack("0x63 write protect failed")
|
||||
mdebug(10, " Write protect done")
|
||||
else:
|
||||
raise CmdException("Write Protect memory (0x63) failed")
|
||||
|
||||
def cmdWriteUnprotect(self):
|
||||
if self.cmdGeneric(0x73):
|
||||
mdebug(10, "*** Write Unprotect command")
|
||||
self._wait_for_ack("0x73 write unprotect failed")
|
||||
self._wait_for_ack("0x73 write unprotect 2 failed")
|
||||
mdebug(10, " Write Unprotect done")
|
||||
else:
|
||||
raise CmdException("Write Unprotect (0x73) failed")
|
||||
|
||||
def cmdReadoutProtect(self):
|
||||
if self.cmdGeneric(0x82):
|
||||
mdebug(10, "*** Readout protect command")
|
||||
self._wait_for_ack("0x82 readout protect failed")
|
||||
self._wait_for_ack("0x82 readout protect 2 failed")
|
||||
mdebug(10, " Read protect done")
|
||||
else:
|
||||
raise CmdException("Readout protect (0x82) failed")
|
||||
|
||||
def cmdReadoutUnprotect(self):
|
||||
if self.cmdGeneric(0x92):
|
||||
mdebug(10, "*** Readout Unprotect command")
|
||||
self._wait_for_ack("0x92 readout unprotect failed")
|
||||
self._wait_for_ack("0x92 readout unprotect 2 failed")
|
||||
mdebug(10, " Read Unprotect done")
|
||||
else:
|
||||
raise CmdException("Readout unprotect (0x92) failed")
|
||||
|
||||
|
||||
# Complex commands section
|
||||
|
||||
def readMemory(self, addr, lng):
|
||||
data = []
|
||||
if usepbar:
|
||||
widgets = ['Reading: ', Percentage(),', ', ETA(), ' ', Bar()]
|
||||
pbar = ProgressBar(widgets=widgets,maxval=lng, term_width=79).start()
|
||||
|
||||
while lng > 256:
|
||||
if usepbar:
|
||||
pbar.update(pbar.maxval-lng)
|
||||
else:
|
||||
mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
|
||||
data = data + self.cmdReadMemory(addr, 256)
|
||||
addr = addr + 256
|
||||
lng = lng - 256
|
||||
if usepbar:
|
||||
pbar.update(pbar.maxval-lng)
|
||||
pbar.finish()
|
||||
else:
|
||||
mdebug(5, "Read %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
|
||||
data = data + self.cmdReadMemory(addr, lng)
|
||||
return data
|
||||
|
||||
def writeMemory(self, addr, data):
|
||||
lng = len(data)
|
||||
|
||||
mdebug(5, "Writing %(lng)d bytes to start address 0x%(addr)X" %
|
||||
{ 'lng': lng, 'addr': addr})
|
||||
|
||||
if usepbar:
|
||||
widgets = ['Writing: ', Percentage(),' ', ETA(), ' ', Bar()]
|
||||
pbar = ProgressBar(widgets=widgets, maxval=lng, term_width=79).start()
|
||||
|
||||
offs = 0
|
||||
while lng > 256:
|
||||
if usepbar:
|
||||
pbar.update(pbar.maxval-lng)
|
||||
else:
|
||||
mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
|
||||
self.cmdWriteMemory(addr, data[offs:offs+256])
|
||||
offs = offs + 256
|
||||
addr = addr + 256
|
||||
lng = lng - 256
|
||||
if usepbar:
|
||||
pbar.update(pbar.maxval-lng)
|
||||
pbar.finish()
|
||||
else:
|
||||
mdebug(5, "Write %(len)d bytes at 0x%(addr)X" % {'addr': addr, 'len': 256})
|
||||
self.cmdWriteMemory(addr, data[offs:offs+lng] + ([0xFF] * (256-lng)) )
|
||||
|
||||
|
||||
def usage():
|
||||
print("""Usage: %s [-hqVewvr] [-l length] [-p port] [-b baud] [-a addr] [file.bin]
|
||||
-h This help
|
||||
-q Quiet
|
||||
-V Verbose
|
||||
-e Erase
|
||||
-w Write
|
||||
-v Verify
|
||||
-r Read
|
||||
-l length Length of read
|
||||
-p port Serial port (default: first USB-like port in /dev)
|
||||
-b baud Baud speed (default: 115200)
|
||||
-a addr Target address
|
||||
|
||||
./stm32loader.py -e -w -v example/main.bin
|
||||
|
||||
""" % sys.argv[0])
|
||||
|
||||
def read(filename):
|
||||
"""Read the file to be programmed and turn it into a binary"""
|
||||
with open(filename, 'rb') as f:
|
||||
bytes = f.read()
|
||||
|
||||
if bytes.startswith('\x7FELF'):
|
||||
# Actually an ELF file. Convert to binary
|
||||
handle, path = tempfile.mkstemp(suffix='.bin', prefix='stm32loader')
|
||||
|
||||
try:
|
||||
os.close(handle)
|
||||
|
||||
# Try a couple of options for objcopy
|
||||
for name in ['arm-none-eabi-objcopy', 'arm-linux-gnueabi-objcopy']:
|
||||
try:
|
||||
code = subprocess.call([name, '-Obinary', filename, path])
|
||||
|
||||
if code == 0:
|
||||
return read(path)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
raise Exception('Error %d while converting to a binary file' % code)
|
||||
finally:
|
||||
# Remove the temporary file
|
||||
os.unlink(path)
|
||||
else:
|
||||
return [ord(x) for x in bytes]
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
conf = {
|
||||
'port': 'auto',
|
||||
'baud': 115200,
|
||||
'address': 0x08000000,
|
||||
'erase': 0,
|
||||
'write': 0,
|
||||
'verify': 0,
|
||||
'read': 0,
|
||||
'len': 1000,
|
||||
'fname':'',
|
||||
}
|
||||
|
||||
# http://www.python.org/doc/2.5.2/lib/module-getopt.html
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hqVewvrp:b:a:l:")
|
||||
except getopt.GetoptError as err:
|
||||
# print help information and exit:
|
||||
print(str(err)) # will print something like "option -a not recognized"
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
for o, a in opts:
|
||||
if o == '-V':
|
||||
QUIET = 10
|
||||
elif o == '-q':
|
||||
QUIET = 0
|
||||
elif o == '-h':
|
||||
usage()
|
||||
sys.exit(0)
|
||||
elif o == '-e':
|
||||
conf['erase'] = 1
|
||||
elif o == '-w':
|
||||
conf['write'] = 1
|
||||
elif o == '-v':
|
||||
conf['verify'] = 1
|
||||
elif o == '-r':
|
||||
conf['read'] = 1
|
||||
elif o == '-p':
|
||||
conf['port'] = a
|
||||
elif o == '-b':
|
||||
conf['baud'] = eval(a)
|
||||
elif o == '-a':
|
||||
conf['address'] = eval(a)
|
||||
elif o == '-l':
|
||||
conf['len'] = eval(a)
|
||||
else:
|
||||
assert False, "unhandled option"
|
||||
|
||||
# Try and find the port automatically
|
||||
if conf['port'] == 'auto':
|
||||
ports = []
|
||||
|
||||
# Get a list of all USB-like names in /dev
|
||||
for name in ['tty.usbserial', 'ttyUSB']:
|
||||
ports.extend(glob.glob('/dev/%s*' % name))
|
||||
|
||||
ports = sorted(ports)
|
||||
|
||||
if ports:
|
||||
# Found something - take it
|
||||
conf['port'] = ports[0]
|
||||
|
||||
cmd = CommandInterface()
|
||||
cmd.open(conf['port'], conf['baud'])
|
||||
mdebug(10, "Open port %(port)s, baud %(baud)d" % {'port':conf['port'],
|
||||
'baud':conf['baud']})
|
||||
try:
|
||||
if (conf['write'] or conf['verify']):
|
||||
mdebug(5, "Reading data from %s" % args[0])
|
||||
data = read(args[0])
|
||||
|
||||
try:
|
||||
cmd.initChip()
|
||||
except CmdException:
|
||||
print("Can't init. Ensure BOOT0=1, BOOT1=0, and reset device")
|
||||
|
||||
bootversion = cmd.cmdGet()
|
||||
|
||||
mdebug(0, "Bootloader version 0x%X" % bootversion)
|
||||
|
||||
if bootversion < 20 or bootversion >= 100:
|
||||
raise Exception('Unreasonable bootloader version %d' % bootversion)
|
||||
|
||||
chip_id = cmd.cmdGetID()
|
||||
assert len(chip_id) == 2, "Unreasonable chip id: %s" % repr(chip_id)
|
||||
chip_id_num = (ord(chip_id[0]) << 8) | ord(chip_id[1])
|
||||
chip_id_str = CHIP_ID_STRS.get(chip_id_num, None)
|
||||
|
||||
if chip_id_str is None:
|
||||
mdebug(0, 'Warning: unrecognised chip ID 0x%x' % chip_id_num)
|
||||
else:
|
||||
mdebug(0, "Chip id 0x%x, %s" % (chip_id_num, chip_id_str))
|
||||
|
||||
if conf['erase']:
|
||||
# Pre-3.0 bootloaders use the erase memory
|
||||
# command. Starting with 3.0, extended erase memory
|
||||
# replaced this command.
|
||||
if bootversion < 0x30:
|
||||
cmd.cmdEraseMemory()
|
||||
else:
|
||||
cmd.cmdExtendedEraseMemory()
|
||||
|
||||
if conf['write']:
|
||||
cmd.writeMemory(conf['address'], data)
|
||||
|
||||
if conf['verify']:
|
||||
verify = cmd.readMemory(conf['address'], len(data))
|
||||
if(data == verify):
|
||||
print("Verification OK")
|
||||
else:
|
||||
print("Verification FAILED")
|
||||
print(str(len(data)) + ' vs ' + str(len(verify)))
|
||||
for i in xrange(0, len(data)):
|
||||
if data[i] != verify[i]:
|
||||
print(hex(i) + ': ' + hex(data[i]) + ' vs ' + hex(verify[i]))
|
||||
|
||||
if not conf['write'] and conf['read']:
|
||||
rdata = cmd.readMemory(conf['address'], conf['len'])
|
||||
file(args[0], 'wb').write(''.join(map(chr,rdata)))
|
||||
|
||||
finally:
|
||||
cmd.releaseChip()
|
||||
|
||||
Reference in New Issue
Block a user