Hello community, here is the log from the commit of package stm32flash for openSUSE:Factory checked in at 2016-08-29 15:42:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/stm32flash (Old) and /work/SRC/openSUSE:Factory/.stm32flash.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "stm32flash" Changes: -------- --- /work/SRC/openSUSE:Factory/stm32flash/stm32flash.changes 2015-11-16 18:51:36.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.stm32flash.new/stm32flash.changes 2016-08-29 15:46:14.000000000 +0200 @@ -1,0 +2,19 @@ +Sat Aug 13 09:49:11 UTC 2016 - kkae...@suse.com + +- add upstream fixes + * Fix for device 0x442: System memory start address: + 0001-Fix-for-device-0x442-System-memory-start-address.patch + * dev_table: Mark 0x417, 0x429, 0x427 for no mass-erase + 0003-dev_table-Mark-0x417-0x429-0x427-for-no-mass-erase.patch + +------------------------------------------------------------------- +Sat Aug 13 09:37:54 UTC 2016 - kkae...@suse.com + +- Update to 0.5 + * support for multiple bank sizes + * improved serial port support on Windows + * improved erase functionality + * improved hex parser + * many new devices and device info corrections + +------------------------------------------------------------------- Old: ---- stm32flash-0.4.tar.gz New: ---- 0001-Fix-for-device-0x442-System-memory-start-address.patch 0003-dev_table-Mark-0x417-0x429-0x427-for-no-mass-erase.patch stm32flash-0.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ stm32flash.spec ++++++ --- /var/tmp/diff_new_pack.WFKX0O/_old 2016-08-29 15:46:17.000000000 +0200 +++ /var/tmp/diff_new_pack.WFKX0O/_new 2016-08-29 15:46:17.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package stm32flash # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,15 +17,19 @@ Name: stm32flash -Version: 0.4 +Version: 0.5 Release: 0 Summary: Flash Program for the STM32 Bootloader License: GPL-2.0+ Group: Hardware/Other -Url: https://code.google.com/p/stm32flash/ +Url: https://sourceforge.net/p/stm32flash/wiki/Home Source: %{name}-%{version}.tar.gz +# PATCH-FIX-UPSTREAM +Patch1: 0001-Fix-for-device-0x442-System-memory-start-address.patch +# PATCH-FIX-UPSTREAM +Patch2: 0003-dev_table-Mark-0x417-0x429-0x427-for-no-mass-erase.patch # PATCH-FIX-OPENSUSE stm32flash-i2c-tools-headers-clash.patch sbra...@suse.cz -- Prevent clash between i2c.h and i2c-dev.h defining the same. -Patch: stm32flash-i2c-tools-headers-clash.patch +Patch3: stm32flash-i2c-tools-headers-clash.patch BuildRequires: i2c-tools BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -50,8 +54,10 @@ %prep %setup -q -n %{name} +%patch1 -p1 +%patch2 -p1 %if 0%{?suse_version} < 1315 || 0%{?suse_version} == 1320 -%patch -p1 +%patch3 -p1 %endif %build ++++++ 0001-Fix-for-device-0x442-System-memory-start-address.patch ++++++ >From 5361ed8259c9db5cf306c7cf5194af06732cb130 Mon Sep 17 00:00:00 2001 From: Amir Hammad <amir.ham...@streamunlimited.com> Date: Fri, 11 Dec 2015 15:46:03 +0100 Subject: [PATCH 1/3] Fix for device 0x442: System memory start address RM0091(rev.8.): page 50: STM32F0xx memory boundary addresses (continued) also RM0360 (rev.3) : page 39: STM32F0x0 memory boundary addresses (continued) 0x1FFFC800 -> 0x1FFFD800 Signed-off-by: Amir Hammad <amir.ham...@streamunlimited.com> --- dev_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_table.c b/dev_table.c index f4ada72..50fb64e 100755 --- a/dev_table.c +++ b/dev_table.c @@ -59,7 +59,7 @@ const stm32_dev_t devices[] = { /* ID "name" SRAM-address-range FLASH-address-range PPS PSize Option-byte-addr-range System-mem-addr-range Flags */ /* F0 */ {0x440, "STM32F030x8/F05xxx" , 0x20000800, 0x20002000, 0x08000000, 0x08010000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFEC00, 0x1FFFF800, 0}, - {0x442, "STM32F030xC/F09xxx" , 0x20001800, 0x20008000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800, F_OBLL}, + {0x442, "STM32F030xC/F09xxx" , 0x20001800, 0x20008000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, F_OBLL}, {0x444, "STM32F03xx4/6" , 0x20000800, 0x20001000, 0x08000000, 0x08008000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFEC00, 0x1FFFF800, 0}, {0x445, "STM32F04xxx/F070x6" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800, 0}, {0x448, "STM32F070xB/F071xx/F72xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800, 0}, -- 2.9.2 ++++++ 0003-dev_table-Mark-0x417-0x429-0x427-for-no-mass-erase.patch ++++++ >From 8c4aa650bffaf98e96d1b6065ab6e76c43150d8a Mon Sep 17 00:00:00 2001 From: Tormod Volden <debian.tor...@gmail.com> Date: Fri, 6 May 2016 16:04:13 +0200 Subject: [PATCH 3/3] dev_table: Mark 0x417, 0x429, 0x427 for no mass-erase These have been reported to not support mass-erase: STM32L151xx-A -> chip ID 0x429 STM32L152RCT -> chip ID 0x427 STM32L051xx -> chip ID 0x417 Thanks to Dieter Deppenaffe for reporting. https://sourceforge.net/p/stm32flash/tickets/87/ Signed-off-by: Tormod Volden <debian.tor...@gmail.com> --- dev_table.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev_table.c b/dev_table.c index 50fb64e..7e1c53c 100755 --- a/dev_table.c +++ b/dev_table.c @@ -92,12 +92,12 @@ const stm32_dev_t devices[] = { {0x449, "STM32F74xxx/75xxx" , 0x20004000, 0x20050000, 0x08000000, 0x08100000, 1, f7 , 0x1FFF0000, 0x1FFF001F, 0x1FF00000, 0x1FF0EDC0, 0}, /* L0 */ {0x425, "STM32L031xx/041xx" , 0x20001000, 0x20002000, 0x08000000, 0x08008000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, - {0x417, "STM32L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, + {0x417, "STM32L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, F_NO_ME}, {0x447, "STM32L07xxx/08xxx" , 0x20002000, 0x20005000, 0x08000000, 0x08030000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF02000, 0}, /* L1 */ {0x416, "STM32L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, F_NO_ME}, - {0x429, "STM32L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, - {0x427, "STM32L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08040000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF02000, 0}, + {0x429, "STM32L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, F_NO_ME}, + {0x427, "STM32L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08040000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF02000, F_NO_ME}, {0x436, "STM32L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, p_256 , 0x1FF80000, 0x1FF8009F, 0x1FF00000, 0x1FF02000, 0}, {0x437, "STM32L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08080000, 16, p_256 , 0x1FF80000, 0x1FF8009F, 0x1FF00000, 0x1FF02000, F_NO_ME}, /* L4 */ -- 2.9.2 ++++++ stm32flash-0.4.tar.gz -> stm32flash-0.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/AUTHORS new/stm32flash/AUTHORS --- old/stm32flash/AUTHORS 2014-07-15 23:59:06.000000000 +0200 +++ new/stm32flash/AUTHORS 2016-02-08 18:28:56.000000000 +0100 @@ -17,3 +17,11 @@ Brian Silverman Georg Hofmann Luis Rodrigues +Jeff Epler +Alexander O. Anisimov +Seth LaForge +Johan Hellman +Matthias Weisser +Tilman Sauerbeck +Mateusz SpychaĆa +Ernst Schwab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/INSTALL new/stm32flash/INSTALL --- old/stm32flash/INSTALL 1970-01-01 01:00:00.000000000 +0100 +++ new/stm32flash/INSTALL 2016-02-09 17:16:39.000000000 +0100 @@ -0,0 +1,16 @@ + +Building stm32flash + +A set of static makefiles is provided that should work on most operating +systems with a standard build environment, for instance GNU make and gcc. + +1. Build executable + + make + +2. Install executable and manual page (optional) + + make install + + The install location base can be set with the PREFIX flag (default + is /usr/local), e.g. make install PREFIX=/opt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/Makefile new/stm32flash/Makefile --- old/stm32flash/Makefile 2014-08-09 01:08:11.000000000 +0200 +++ new/stm32flash/Makefile 2016-01-26 23:45:05.000000000 +0100 @@ -19,7 +19,7 @@ serial_platform.o: serial_posix.c serial_w32.c -parsers/parsers.a: +parsers/parsers.a: force cd parsers && $(MAKE) parsers.a stm32flash: $(OBJS) $(LIBOBJS) @@ -35,4 +35,6 @@ $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/man/man1 $(INSTALL) -m 644 stm32flash.1 $(DESTDIR)$(PREFIX)/share/man/man1 -.PHONY: all clean install +force: + +.PHONY: all clean install force diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/TODO new/stm32flash/TODO --- old/stm32flash/TODO 2014-07-15 23:59:06.000000000 +0200 +++ new/stm32flash/TODO 2015-12-04 21:30:57.000000000 +0100 @@ -1,7 +1,4 @@ -stm32: -- Add support for variable page size - AUTHORS: - Add contributors from Geoffrey's commits diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/dev_table.c new/stm32flash/dev_table.c --- old/stm32flash/dev_table.c 2014-10-03 23:35:08.000000000 +0200 +++ new/stm32flash/dev_table.c 2016-02-08 18:28:56.000000000 +0100 @@ -1,7 +1,7 @@ /* stm32flash - Open Source ST STM32 flash program for *nix Copyright (C) 2010 Geoffrey McRae <ge...@spacevs.com> - Copyright (C) 2014 Antonio Borneo <borneo.anto...@gmail.com> + Copyright (C) 2014-2015 Antonio Borneo <borneo.anto...@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,51 +20,91 @@ #include "stm32.h" +#define SZ_128 0x00000080 +#define SZ_256 0x00000100 +#define SZ_1K 0x00000400 +#define SZ_2K 0x00000800 +#define SZ_16K 0x00004000 +#define SZ_32K 0x00008000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 + +/* + * Page-size for page-by-page flash erase. + * Arrays are zero terminated; last non-zero value is automatically repeated + */ + +/* fixed size pages */ +static uint32_t p_128[] = { SZ_128, 0 }; +static uint32_t p_256[] = { SZ_256, 0 }; +static uint32_t p_1k[] = { SZ_1K, 0 }; +static uint32_t p_2k[] = { SZ_2K, 0 }; +/* F2 and F4 page size */ +static uint32_t f2f4[] = { SZ_16K, SZ_16K, SZ_16K, SZ_16K, SZ_64K, SZ_128K, 0 }; +/* F4 dual bank page size */ +static uint32_t f4db[] = { + SZ_16K, SZ_16K, SZ_16K, SZ_16K, SZ_64K, SZ_128K, SZ_128K, SZ_128K, + SZ_16K, SZ_16K, SZ_16K, SZ_16K, SZ_64K, SZ_128K, 0 +}; +/* F7 page size */ +static uint32_t f7[] = { SZ_32K, SZ_32K, SZ_32K, SZ_32K, SZ_128K, SZ_256K, 0 }; + /* * Device table, corresponds to the "Bootloader device-dependant parameters" * table in ST document AN2606. * Note that the option bytes upper range is inclusive! */ const stm32_dev_t devices[] = { + /* ID "name" SRAM-address-range FLASH-address-range PPS PSize Option-byte-addr-range System-mem-addr-range Flags */ /* F0 */ - {0x440, "STM32F051xx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, - {0x444, "STM32F030/F031" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 4, 1024, 0x1FFFF800, 0x1FFFF80B, 0x1FFFEC00, 0x1FFFF800}, - {0x445, "STM32F042xx" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800}, - {0x448, "STM32F072xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800}, + {0x440, "STM32F030x8/F05xxx" , 0x20000800, 0x20002000, 0x08000000, 0x08010000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFEC00, 0x1FFFF800, 0}, + {0x442, "STM32F030xC/F09xxx" , 0x20001800, 0x20008000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800, F_OBLL}, + {0x444, "STM32F03xx4/6" , 0x20000800, 0x20001000, 0x08000000, 0x08008000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFEC00, 0x1FFFF800, 0}, + {0x445, "STM32F04xxx/F070x6" , 0x20001800, 0x20001800, 0x08000000, 0x08008000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC400, 0x1FFFF800, 0}, + {0x448, "STM32F070xB/F071xx/F72xx" , 0x20001800, 0x20004000, 0x08000000, 0x08020000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFC800, 0x1FFFF800, 0}, /* F1 */ - {0x412, "Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x410, "Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x414, "High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x420, "Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x428, "High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x418, "Connectivity line" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800}, - {0x430, "XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800}, - /* Note that F2 and F4 devices have sectors of different page sizes - and only the first sectors (of one page size) are included here */ + {0x412, "STM32F10xxx Low-density" , 0x20000200, 0x20002800, 0x08000000, 0x08008000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x410, "STM32F10xxx Medium-density" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x414, "STM32F10xxx High-density" , 0x20000200, 0x20010000, 0x08000000, 0x08080000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x420, "STM32F10xxx Medium-density VL" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x428, "STM32F10xxx High-density VL" , 0x20000200, 0x20008000, 0x08000000, 0x08080000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x418, "STM32F105xx/F107xx" , 0x20001000, 0x20010000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFB000, 0x1FFFF800, 0}, + {0x430, "STM32F10xxx XL-density" , 0x20000800, 0x20018000, 0x08000000, 0x08100000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFE000, 0x1FFFF800, 0}, /* F2 */ - {0x411, "STM32F2xx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, + {0x411, "STM32F2xxxx" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, /* F3 */ - {0x432, "STM32F373/8" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, - {0x422, "F302xB/303xB/358" , 0x20001400, 0x20010000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, - {0x439, "STM32F302x4(6/8)" , 0x20001800, 0x20004000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, - {0x438, "F303x4/334/328" , 0x20001800, 0x20003000, 0x08000000, 0x08040000, 2, 2048, 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800}, + {0x432, "STM32F373xx/F378xx" , 0x20001400, 0x20008000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, 0}, + {0x422, "STM32F302xB(C)/F303xB(C)/F358xx" , 0x20001400, 0x2000A000, 0x08000000, 0x08040000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, 0}, + {0x439, "STM32F301xx/F302x4(6/8)/F318xx" , 0x20001800, 0x20004000, 0x08000000, 0x08010000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, 0}, + {0x438, "STM32F303x4(6/8)/F334xx/F328xx" , 0x20001800, 0x20003000, 0x08000000, 0x08010000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, 0}, + {0x446, "STM32F302xD(E)/F303xD(E)/F398xx" , 0x20001800, 0x20010000, 0x08000000, 0x08080000, 2, p_2k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFD800, 0x1FFFF800, 0}, /* F4 */ - {0x413, "STM32F40/1" , 0x20002000, 0x20020000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77DF}, - /* 0x419 is also used for STM32F429/39 but with other bootloader ID... */ - {0x419, "STM32F427/37" , 0x20002000, 0x20030000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, - {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, - {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08100000, 4, 16384, 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF77FF}, + {0x413, "STM32F40xxx/41xxx" , 0x20003000, 0x20020000, 0x08000000, 0x08100000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x419, "STM32F42xxx/43xxx" , 0x20003000, 0x20030000, 0x08000000, 0x08200000, 1, f4db , 0x1FFEC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x423, "STM32F401xB(C)" , 0x20003000, 0x20010000, 0x08000000, 0x08040000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x433, "STM32F401xD(E)" , 0x20003000, 0x20018000, 0x08000000, 0x08080000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x458, "STM32F410xx" , 0x20003000, 0x20008000, 0x08000000, 0x08020000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x431, "STM32F411xx" , 0x20003000, 0x20020000, 0x08000000, 0x08080000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x421, "STM32F446xx" , 0x20003000, 0x20020000, 0x08000000, 0x08080000, 1, f2f4 , 0x1FFFC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + {0x434, "STM32F469xx" , 0x20003000, 0x20060000, 0x08000000, 0x08200000, 1, f4db , 0x1FFEC000, 0x1FFFC00F, 0x1FFF0000, 0x1FFF7800, 0}, + /* F7 */ + {0x449, "STM32F74xxx/75xxx" , 0x20004000, 0x20050000, 0x08000000, 0x08100000, 1, f7 , 0x1FFF0000, 0x1FFF001F, 0x1FF00000, 0x1FF0EDC0, 0}, /* L0 */ - {0x417, "L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, 128, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, + {0x425, "STM32L031xx/041xx" , 0x20001000, 0x20002000, 0x08000000, 0x08008000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, + {0x417, "STM32L05xxx/06xxx" , 0x20001000, 0x20002000, 0x08000000, 0x08010000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, + {0x447, "STM32L07xxx/08xxx" , 0x20002000, 0x20005000, 0x08000000, 0x08030000, 32, p_128 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF02000, 0}, /* L1 */ - {0x416, "L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, - {0x429, "L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF01000}, - {0x427, "L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, 256, 0x1FF80000, 0x1FF8000F, 0x1FF00000, 0x1FF02000}, - {0x436, "L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, - {0x437, "L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08060000, 16, 256, 0x1ff80000, 0x1ff8000F, 0x1FF00000, 0x1FF02000}, + {0x416, "STM32L1xxx6(8/B)" , 0x20000800, 0x20004000, 0x08000000, 0x08020000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, F_NO_ME}, + {0x429, "STM32L1xxx6(8/B)A" , 0x20001000, 0x20008000, 0x08000000, 0x08020000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF01000, 0}, + {0x427, "STM32L1xxxC" , 0x20001000, 0x20008000, 0x08000000, 0x08040000, 16, p_256 , 0x1FF80000, 0x1FF8001F, 0x1FF00000, 0x1FF02000, 0}, + {0x436, "STM32L1xxxD" , 0x20001000, 0x2000C000, 0x08000000, 0x08060000, 16, p_256 , 0x1FF80000, 0x1FF8009F, 0x1FF00000, 0x1FF02000, 0}, + {0x437, "STM32L1xxxE" , 0x20001000, 0x20014000, 0x08000000, 0x08080000, 16, p_256 , 0x1FF80000, 0x1FF8009F, 0x1FF00000, 0x1FF02000, F_NO_ME}, + /* L4 */ + {0x415, "STM32L476xx/486xx" , 0x20003100, 0x20018000, 0x08000000, 0x08100000, 1, p_2k , 0x1FFF7800, 0x1FFFF80F, 0x1FFF0000, 0x1FFF7000, 0}, /* These are not (yet) in AN2606: */ - {0x641, "Medium_Density PL" , 0x20000200, 0x00005000, 0x08000000, 0x08020000, 4, 1024, 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800}, - {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 1, 1024, 0, 0, 0, 0}, - {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 1, 2048, 0, 0, 0, 0}, + {0x641, "Medium_Density PL" , 0x20000200, 0x20005000, 0x08000000, 0x08020000, 4, p_1k , 0x1FFFF800, 0x1FFFF80F, 0x1FFFF000, 0x1FFFF800, 0}, + {0x9a8, "STM32W-128K" , 0x20000200, 0x20002000, 0x08000000, 0x08020000, 4, p_1k , 0x08040800, 0x0804080F, 0x08040000, 0x08040800, 0}, + {0x9b0, "STM32W-256K" , 0x20000200, 0x20004000, 0x08000000, 0x08040000, 4, p_2k , 0x08040800, 0x0804080F, 0x08040000, 0x08040800, 0}, {0x0} }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/i2c.c new/stm32flash/i2c.c --- old/stm32flash/i2c.c 2014-09-19 00:16:02.000000000 +0200 +++ new/stm32flash/i2c.c 2015-11-28 14:37:58.000000000 +0100 @@ -32,7 +32,7 @@ #include "port.h" -#if defined(__WIN32__) || defined(__CYGWIN__) || defined(__APPLE__) +#if !defined(__linux__) static port_err_t i2c_open(struct port_interface *port, struct port_options *ops) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/init.c new/stm32flash/init.c --- old/stm32flash/init.c 2014-09-19 00:16:02.000000000 +0200 +++ new/stm32flash/init.c 2016-02-08 23:58:03.000000000 +0100 @@ -20,6 +20,7 @@ #include <ctype.h> +#include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> @@ -35,9 +36,10 @@ struct gpio_list { struct gpio_list *next; int gpio; + int input; /* 1 if direction of gpio should be changed back to input. */ + int exported; /* 0 if gpio should be unexported. */ }; - static int write_to(const char *filename, const char *value) { int fd, ret; @@ -64,15 +66,45 @@ return 0; } #else +static int read_from(const char *filename, char *buf, size_t len) +{ + int fd, ret; + ssize_t n = 0; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + return 0; + } + + do { + ret = read(fd, buf + n, len - n); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + continue; /* try again */ + fprintf(stderr, "Error reading in file \"%s\"\n", filename); + close(fd); + return 0; + } + n += ret; + } while (n < len && ret); + + close(fd); + return n; +} + static int drive_gpio(int n, int level, struct gpio_list **gpio_to_release) { char num[16]; /* sized to carry MAX_INT */ char file[48]; /* sized to carry longest filename */ + char dir; struct stat buf; struct gpio_list *new; int ret; + int exported = 1; + int input = 0; - sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + sprintf(file, "/sys/class/gpio/gpio%d/value", n); ret = stat(file, &buf); if (ret) { /* file miss, GPIO not exported yet */ @@ -85,12 +117,25 @@ fprintf(stderr, "GPIO %d not available\n", n); return 0; } + exported = 0; + } + + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + ret = stat(file, &buf); + if (!ret) + if (read_from(file, &dir, sizeof(dir))) + if (dir == 'i') + input = 1; + + if (exported == 0 || input == 1) { new = (struct gpio_list *)malloc(sizeof(struct gpio_list)); if (new == NULL) { fprintf(stderr, "Out of memory\n"); return 0; } new->gpio = n; + new->exported = exported; + new->input = input; new->next = *gpio_to_release; *gpio_to_release = new; } @@ -99,12 +144,20 @@ } #endif -static int release_gpio(int n) +static int release_gpio(int n, int input, int exported) { char num[16]; /* sized to carry MAX_INT */ + char file[48]; /* sized to carry longest filename */ sprintf(num, "%d", n); - return write_to("/sys/class/gpio/unexport", num); + if (input) { + sprintf(file, "/sys/class/gpio/gpio%d/direction", n); + write_to(file, "in"); + } + if (!exported) + write_to("/sys/class/gpio/unexport", num); + + return 1; } static int gpio_sequence(struct port_interface *port, const char *s, size_t l) @@ -163,7 +216,7 @@ } while (gpio_to_release) { - release_gpio(gpio_to_release->gpio); + release_gpio(gpio_to_release->gpio, gpio_to_release->input, gpio_to_release->exported); to_free = gpio_to_release; gpio_to_release = gpio_to_release->next; free(to_free); @@ -210,7 +263,7 @@ int init_bl_exit(stm32_t *stm, struct port_interface *port, const char *seq) { - if (seq) + if (seq && strchr(seq, ':')) return gpio_bl_exit(port, seq); if (stm32_reset_device(stm) != STM32_ERR_OK) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/main.c new/stm32flash/main.c --- old/stm32flash/main.c 2014-10-04 12:21:10.000000000 +0200 +++ new/stm32flash/main.c 2016-02-10 20:55:37.000000000 +0100 @@ -2,8 +2,8 @@ stm32flash - Open Source ST STM32 flash program for *nix Copyright 2010 Geoffrey McRae <ge...@spacevs.com> Copyright 2011 Steve Markgraf <st...@steve-m.de> - Copyright 2012 Tormod Volden <debian.tor...@gmail.com> - Copyright 2013 Antonio Borneo <borneo.anto...@gmail.com> + Copyright 2012-2016 Tormod Volden <debian.tor...@gmail.com> + Copyright 2013-2016 Antonio Borneo <borneo.anto...@gmail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -38,7 +38,7 @@ #include "parsers/binary.h" #include "parsers/hex.h" -#define VERSION "0.4" +#define VERSION "0.5" /* device globals */ stm32_t *stm = NULL; @@ -55,13 +55,19 @@ .rx_frame_max = STM32_MAX_RX_FRAME, .tx_frame_max = STM32_MAX_TX_FRAME, }; -int rd = 0; -int wr = 0; -int wu = 0; -int rp = 0; -int ur = 0; -int eraseOnly = 0; -int crc = 0; + +enum actions { + ACT_NONE, + ACT_READ, + ACT_WRITE, + ACT_WRITE_UNPROTECT, + ACT_READ_PROTECT, + ACT_READ_UNPROTECT, + ACT_ERASE_ONLY, + ACT_CRC +}; + +enum actions action = ACT_NONE; int npages = 0; int spage = 0; int no_erase = 0; @@ -81,6 +87,36 @@ int parse_options(int argc, char *argv[]); void show_help(char *name); +static const char *action2str(enum actions act) +{ + switch (act) { + case ACT_READ: + return "memory read"; + case ACT_WRITE: + return "memory write"; + case ACT_WRITE_UNPROTECT: + return "write unprotect"; + case ACT_READ_PROTECT: + return "read protect"; + case ACT_READ_UNPROTECT: + return "read unprotect"; + case ACT_ERASE_ONLY: + return "flash erase"; + case ACT_CRC: + return "memory crc"; + default: + return ""; + }; +} + +static void err_multi_action(enum actions new) +{ + fprintf(stderr, + "ERROR: Invalid options !\n" + "\tCan't execute \"%s\" and \"%s\" at the same time.\n", + action2str(action), action2str(new)); +} + static int is_addr_in_ram(uint32_t addr) { return addr >= stm->dev->ram_start && addr < stm->dev->ram_end; @@ -91,26 +127,68 @@ return addr >= stm->dev->fl_start && addr < stm->dev->fl_end; } +/* returns the page that contains address "addr" */ static int flash_addr_to_page_floor(uint32_t addr) { + int page; + uint32_t *psize; + if (!is_addr_in_flash(addr)) return 0; - return (addr - stm->dev->fl_start) / stm->dev->fl_ps; + page = 0; + addr -= stm->dev->fl_start; + psize = stm->dev->fl_ps; + + while (addr >= psize[0]) { + addr -= psize[0]; + page++; + if (psize[1]) + psize++; + } + + return page; } -static int flash_addr_to_page_ceil(uint32_t addr) +/* returns the first page whose start addr is >= "addr" */ +int flash_addr_to_page_ceil(uint32_t addr) { + int page; + uint32_t *psize; + if (!(addr >= stm->dev->fl_start && addr <= stm->dev->fl_end)) return 0; - return (addr + stm->dev->fl_ps - 1 - stm->dev->fl_start) - / stm->dev->fl_ps; + page = 0; + addr -= stm->dev->fl_start; + psize = stm->dev->fl_ps; + + while (addr >= psize[0]) { + addr -= psize[0]; + page++; + if (psize[1]) + psize++; + } + + return addr ? page + 1 : page; } +/* returns the lower address of flash page "page" */ static uint32_t flash_page_to_addr(int page) { - return stm->dev->fl_start + page * stm->dev->fl_ps; + int i; + uint32_t addr, *psize; + + addr = stm->dev->fl_start; + psize = stm->dev->fl_ps; + + for (i = 0; i < page; i++) { + addr += psize[0]; + if (psize[1]) + psize++; + } + + return addr; } int main(int argc, char* argv[]) { @@ -121,15 +199,15 @@ FILE *diag = stdout; fprintf(diag, "stm32flash " VERSION "\n\n"); - fprintf(diag, "http://stm32flash.googlecode.com/\n\n"); + fprintf(diag, "http://stm32flash.sourceforge.net/\n\n"); if (parse_options(argc, argv) != 0) goto close; - if (rd && filename[0] == '-') { + if ((action == ACT_READ) && filename[0] == '-') { diag = stderr; } - if (wr) { + if (action == ACT_WRITE) { /* first try hex */ if (!force_binary) { parser = &PARSER_HEX; @@ -194,7 +272,7 @@ } fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); - fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); + fprintf(diag, "- Flash : %dKiB (size first sector: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps[0]); fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); @@ -230,14 +308,14 @@ first_page = flash_addr_to_page_floor(start); if (!first_page && end == stm->dev->fl_end) - num_pages = 0xff; /* mass erase */ + num_pages = STM32_MASS_ERASE; else num_pages = flash_addr_to_page_ceil(end) - first_page; } else if (!spage && !npages) { start = stm->dev->fl_start; end = stm->dev->fl_end; first_page = 0; - num_pages = 0xff; /* mass erase */ + num_pages = STM32_MASS_ERASE; } else { first_page = spage; start = flash_page_to_addr(first_page); @@ -257,10 +335,10 @@ } if (!first_page && end == stm->dev->fl_end) - num_pages = 0xff; /* mass erase */ + num_pages = STM32_MASS_ERASE; } - if (rd) { + if (action == ACT_READ) { unsigned int max_len = port_opts.rx_frame_max; fprintf(diag, "Memory read\n"); @@ -300,23 +378,23 @@ fprintf(diag, "Done.\n"); ret = 0; goto close; - } else if (rp) { + } else if (action == ACT_READ_PROTECT) { fprintf(stdout, "Read-Protecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_readprot_memory(stm); fprintf(stdout, "Done.\n"); - } else if (ur) { + } else if (action == ACT_READ_UNPROTECT) { fprintf(stdout, "Read-UnProtecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_runprot_memory(stm); fprintf(stdout, "Done.\n"); - } else if (eraseOnly) { + } else if (action == ACT_ERASE_ONLY) { ret = 0; fprintf(stdout, "Erasing flash\n"); - if (num_pages != 0xff && + if (num_pages != STM32_MASS_ERASE && (start != flash_page_to_addr(first_page) || end != flash_page_to_addr(first_page + num_pages))) { fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); @@ -330,14 +408,14 @@ ret = 1; goto close; } - } else if (wu) { + } else if (action == ACT_WRITE_UNPROTECT) { fprintf(diag, "Write-unprotecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_wunprot_memory(stm); fprintf(diag, "Done.\n"); - } else if (wr) { + } else if (action == ACT_WRITE) { fprintf(diag, "Write to memory\n"); off_t offset = 0; @@ -359,7 +437,7 @@ // TODO: It is possible to write to non-page boundaries, by reading out flash // from partial pages and combining with the input data - // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { + // if ((start % stm->dev->fl_ps[i]) != 0 || (end % stm->dev->fl_ps[i]) != 0) { // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); // goto close; // } @@ -450,7 +528,7 @@ fprintf(diag, "Done.\n"); ret = 0; goto close; - } else if (crc) { + } else if (action == ACT_CRC) { uint32_t crc_val = 0; fprintf(diag, "CRC computation\n"); @@ -533,12 +611,11 @@ case 'r': case 'w': - rd = rd || c == 'r'; - wr = wr || c == 'w'; - if (rd && wr) { - fprintf(stderr, "ERROR: Invalid options, can't read & write at the same time\n"); + if (action != ACT_NONE) { + err_multi_action((c == 'r') ? ACT_READ : ACT_WRITE); return 1; } + action = (c == 'r') ? ACT_READ : ACT_WRITE; filename = optarg; if (filename[0] == '-') { force_binary = 1; @@ -558,37 +635,37 @@ no_erase = 1; break; case 'u': - wu = 1; - if (rd || wr) { - fprintf(stderr, "ERROR: Invalid options, can't write unprotect and read/write at the same time\n"); + if (action != ACT_NONE) { + err_multi_action(ACT_WRITE_UNPROTECT); return 1; } + action = ACT_WRITE_UNPROTECT; break; case 'j': - rp = 1; - if (rd || wr) { - fprintf(stderr, "ERROR: Invalid options, can't read protect and read/write at the same time\n"); + if (action != ACT_NONE) { + err_multi_action(ACT_READ_PROTECT); return 1; } + action = ACT_READ_PROTECT; break; case 'k': - ur = 1; - if (rd || wr) { - fprintf(stderr, "ERROR: Invalid options, can't read unprotect and read/write at the same time\n"); + if (action != ACT_NONE) { + err_multi_action(ACT_READ_UNPROTECT); return 1; } + action = ACT_READ_UNPROTECT; break; case 'o': - eraseOnly = 1; - if (rd || wr) { - fprintf(stderr, "ERROR: Invalid options, can't erase-only and read/write at the same time\n"); + if (action != ACT_NONE) { + err_multi_action(ACT_ERASE_ONLY); return 1; } - break; - + action = ACT_ERASE_ONLY; + break; + case 'v': verify = 1; break; @@ -644,9 +721,9 @@ if (port_opts.tx_frame_max == 0) port_opts.tx_frame_max = STM32_MAX_TX_FRAME; if (port_opts.rx_frame_max < 20 - || port_opts.tx_frame_max < 5) { + || port_opts.tx_frame_max < 6) { fprintf(stderr, "ERROR: current code cannot work with small frames.\n"); - fprintf(stderr, "min(RX) = 20, min(TX) = 5\n"); + fprintf(stderr, "min(RX) = 20, min(TX) = 6\n"); return 1; } if (port_opts.rx_frame_max > STM32_MAX_RX_FRAME) { @@ -679,7 +756,11 @@ break; case 'C': - crc = 1; + if (action != ACT_NONE) { + err_multi_action(ACT_CRC); + return 1; + } + action = ACT_CRC; break; } } @@ -699,7 +780,7 @@ return 1; } - if (!wr && verify) { + if ((action != ACT_WRITE) && verify) { fprintf(stderr, "ERROR: Invalid usage, -v is only valid when writing\n"); show_help(argv[0]); return 1; @@ -760,7 +841,7 @@ " GPIO sequence:\n" " - entry sequence: GPIO_3=low, GPIO_2=low, GPIO_2=high\n" " - exit sequence: GPIO_3=high, GPIO_2=low, GPIO_2=high\n" - " %s -i -3,-2,2:3,-2,2 /dev/ttyS0\n", + " %s -R -i -3,-2,2:3,-2,2 /dev/ttyS0\n", name, name, name, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/parsers/hex.c new/stm32flash/parsers/hex.c --- old/stm32flash/parsers/hex.c 2014-10-03 23:35:08.000000000 +0200 +++ new/stm32flash/parsers/hex.c 2016-02-08 18:12:43.000000000 +0100 @@ -32,7 +32,7 @@ typedef struct { size_t data_len, offset; uint8_t *data; - uint8_t base; + uint32_t base; } hex_t; void* hex_init() { @@ -105,7 +105,7 @@ /* extended linear address record */ case 4: - base = address; + base = 0; break; } @@ -152,12 +152,17 @@ return PARSER_ERR_OK; /* address record */ + case 4: base = base << 12; case 2: base = base << 4; - case 4: base = be_u32(base); /* Reset last_address since our base changed */ last_address = 0; - if (st->base == 0) { + /* Only assign the program's base address once, and only + * do so if we haven't seen any data records yet. + * If there are any data records before address records, + * the program's base address must be zero. + */ + if (st->base == 0 && st->data_len == 0) { st->base = base; break; } @@ -168,11 +173,11 @@ return PARSER_ERR_INVALID_FILE; } - /* if there is a gap, enlarge and fill with zeros */ + /* if there is a gap, enlarge and fill with 0xff */ unsigned int len = base - st->base; if (len > st->data_len) { st->data = realloc(st->data, len); - memset(&st->data[st->data_len], 0, len - st->data_len); + memset(&st->data[st->data_len], 0xff, len - st->data_len); st->data_len = len; } break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/serial_posix.c new/stm32flash/serial_posix.c --- old/stm32flash/serial_posix.c 2014-09-19 00:16:02.000000000 +0200 +++ new/stm32flash/serial_posix.c 2016-01-26 23:45:05.000000000 +0100 @@ -18,6 +18,7 @@ */ #include <fcntl.h> +#include <limits.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -25,6 +26,7 @@ #include <termios.h> #include <unistd.h> #include <sys/ioctl.h> +#include <stdio.h> #include "serial.h" #include "port.h" @@ -202,11 +204,7 @@ { serial_t *h; - /* 1. check device name match */ - if (strncmp(ops->device, "/dev/tty", strlen("/dev/tty"))) - return PORT_ERR_NODEV; - - /* 2. check options */ + /* 1. check options */ if (ops->baudRate == SERIAL_BAUD_INVALID) return PORT_ERR_UNKNOWN; if (serial_get_bits(ops->serial_mode) == SERIAL_BITS_INVALID) @@ -216,11 +214,15 @@ if (serial_get_stopbit(ops->serial_mode) == SERIAL_STOPBIT_INVALID) return PORT_ERR_UNKNOWN; - /* 3. open it */ + /* 2. open it */ h = serial_open(ops->device); if (h == NULL) return PORT_ERR_UNKNOWN; + /* 3. check for tty (but only warn) */ + if (!isatty(h->fd)) + fprintf(stderr, "Warning: Not a tty: %s\n", ops->device); + /* 4. set options */ if (serial_setup(h, ops->baudRate, serial_get_bits(ops->serial_mode), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/serial_w32.c new/stm32flash/serial_w32.c --- old/stm32flash/serial_w32.c 2014-10-03 23:36:32.000000000 +0200 +++ new/stm32flash/serial_w32.c 2016-02-08 18:38:49.000000000 +0100 @@ -67,6 +67,7 @@ if (h->fd == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) fprintf(stderr, "File not found: %s\n", device); + free(h); return NULL; } @@ -76,6 +77,9 @@ SetCommMask(h->fd, EV_ERR); /* Notify us of error events */ + /* DCBlength should be initialized before calling GetCommState */ + h->oldtio.DCBlength = sizeof(DCB); + h->newtio.DCBlength = sizeof(DCB); GetCommState(h->fd, &h->oldtio); /* Retrieve port parameters */ GetCommState(h->fd, &h->newtio); /* Retrieve port parameters */ @@ -161,10 +165,15 @@ /* reset the settings */ h->newtio.fOutxCtsFlow = FALSE; h->newtio.fOutxDsrFlow = FALSE; + h->newtio.fDtrControl = DTR_CONTROL_DISABLE; + h->newtio.fDsrSensitivity = FALSE; + h->newtio.fTXContinueOnXoff = FALSE; h->newtio.fOutX = FALSE; h->newtio.fInX = FALSE; - h->newtio.fNull = 0; - h->newtio.fAbortOnError = 0; + h->newtio.fErrorChar = FALSE; + h->newtio.fNull = FALSE; + h->newtio.fRtsControl = RTS_CONTROL_DISABLE; + h->newtio.fAbortOnError = FALSE; /* set the settings */ serial_flush(h); @@ -186,8 +195,7 @@ serial_t *h; /* 1. check device name match */ - if (!(strlen(ops->device) == 4 - && !strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) + if (!(!strncmp(ops->device, "COM", 3) && isdigit(ops->device[3])) && !(!strncmp(ops->device, "\\\\.\\COM", strlen("\\\\.\\COM")) && isdigit(ops->device[strlen("\\\\.\\COM")]))) return PORT_ERR_NODEV; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/stm32.c new/stm32flash/stm32.c --- old/stm32flash/stm32.c 2014-10-02 09:20:26.000000000 +0200 +++ new/stm32flash/stm32.c 2016-02-10 10:43:06.000000000 +0100 @@ -57,7 +57,7 @@ #define STM32_RESYNC_TIMEOUT 35 /* seconds */ #define STM32_MASSERASE_TIMEOUT 35 /* seconds */ -#define STM32_SECTERASE_TIMEOUT 5 /* seconds */ +#define STM32_PAGEERASE_TIMEOUT 5 /* seconds */ #define STM32_BLKWRITE_TIMEOUT 1 /* seconds */ #define STM32_WUNPROT_TIMEOUT 1 /* seconds */ #define STM32_WPROT_TIMEOUT 1 /* seconds */ @@ -95,8 +95,32 @@ static const uint32_t stm_reset_code_length = sizeof(stm_reset_code); +/* RM0360, Empty check + * On STM32F070x6 and STM32F030xC devices only, internal empty check flag is + * implemented to allow easy programming of the virgin devices by the boot loader. This flag is + * used when BOOT0 pin is defining Main Flash memory as the target boot space. When the + * flag is set, the device is considered as empty and System memory (boot loader) is selected + * instead of the Main Flash as a boot space to allow user to program the Flash memory. + * This flag is updated only during Option bytes loading: it is set when the content of the + * address 0x08000 0000 is read as 0xFFFF FFFF, otherwise it is cleared. It means a power + * on or setting of OBL_LAUNCH bit in FLASH_CR register is needed to clear this flag after + * programming of a virgin device to execute user code after System reset. + */ +static const uint8_t stm_obl_launch_code[] = { + 0x01, 0x49, // ldr r1, [pc, #4] ; (<FLASH_CR>) + 0x02, 0x4A, // ldr r2, [pc, #8] ; (<OBL_LAUNCH>) + 0x0A, 0x60, // str r2, [r1, #0] + 0xfe, 0xe7, // endless: b endless + 0x10, 0x20, 0x02, 0x40, // address: FLASH_CR = 40022010 + 0x00, 0x20, 0x00, 0x00 // value: OBL_LAUNCH = 00002000 +}; + +static const uint32_t stm_obl_launch_code_length = sizeof(stm_obl_launch_code); + extern const stm32_dev_t devices[]; +int flash_addr_to_page_ceil(uint32_t addr); + static void stm32_warn_stretching(const char *f) { fprintf(stderr, "Attention !!!\n"); @@ -540,8 +564,8 @@ } /* must be 32bit aligned */ - if (address & 0x3 || len & 0x3) { - fprintf(stderr, "Error: WRITE address and length must be 4 byte aligned\n"); + if (address & 0x3) { + fprintf(stderr, "Error: WRITE address must be 4 byte aligned\n"); return STM32_ERR_UNKNOWN; } @@ -604,7 +628,7 @@ return STM32_ERR_UNKNOWN; s_err = stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT); - if (s_err == STM32_NACK) { + if (s_err == STM32_ERR_NACK) { fprintf(stderr, "Error: Failed to WRITE UNPROTECT\n"); return STM32_ERR_UNKNOWN; } @@ -631,7 +655,7 @@ return STM32_ERR_UNKNOWN; s_err = stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT); - if (s_err == STM32_NACK) { + if (s_err == STM32_ERR_NACK) { fprintf(stderr, "Error: Failed to WRITE PROTECT\n"); return STM32_ERR_UNKNOWN; } @@ -658,7 +682,7 @@ return STM32_ERR_UNKNOWN; s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); - if (s_err == STM32_NACK) { + if (s_err == STM32_ERR_NACK) { fprintf(stderr, "Error: Failed to READOUT UNPROTECT\n"); return STM32_ERR_UNKNOWN; } @@ -685,7 +709,7 @@ return STM32_ERR_UNKNOWN; s_err = stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT); - if (s_err == STM32_NACK) { + if (s_err == STM32_ERR_NACK) { fprintf(stderr, "Error: Failed to READOUT PROTECT\n"); return STM32_ERR_UNKNOWN; } @@ -698,119 +722,68 @@ return STM32_ERR_OK; } -stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, uint8_t pages) +static stm32_err_t stm32_mass_erase(const stm32_t *stm) { struct port_interface *port = stm->port; stm32_err_t s_err; - port_err_t p_err; - - if (!pages) - return STM32_ERR_OK; - - if (stm->cmd->er == STM32_CMD_ERR) { - fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); - return STM32_ERR_NO_CMD; - } + uint8_t buf[3]; if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { - fprintf(stderr, "Can't initiate chip erase!\n"); + fprintf(stderr, "Can't initiate chip mass erase!\n"); return STM32_ERR_UNKNOWN; } - /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ - /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ - /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ - if (stm->cmd->er != STM32_CMD_ER) { - /* Not all chips using Extended Erase support mass erase */ - /* Currently known as not supporting mass erase is the Ultra Low Power STM32L15xx range */ - /* So if someone has not overridden the default, but uses one of these chips, take it out of */ - /* mass erase mode, so it will be done page by page. This maximum might not be correct either! */ - if (stm->pid == 0x416 && pages == 0xFF) - pages = 0xF8; /* works for the STM32L152RB with 128Kb flash */ - - if (pages == 0xFF) { - uint8_t buf[3]; - - /* 0xFFFF the magic number for mass erase */ - buf[0] = 0xFF; - buf[1] = 0xFF; - buf[2] = 0x00; /* checksum */ - if (port->write(port, buf, 3) != PORT_ERR_OK) { - fprintf(stderr, "Mass erase error.\n"); - return STM32_ERR_UNKNOWN; - } - s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); - if (s_err != STM32_ERR_OK) { - fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); - if (port->flags & PORT_STRETCH_W - && stm->cmd->er != STM32_CMD_EE_NS) - stm32_warn_stretching("erase"); - return STM32_ERR_UNKNOWN; - } - return STM32_ERR_OK; - } - - uint16_t pg_num; - uint8_t pg_byte; - uint8_t cs = 0; - uint8_t *buf; - int i = 0; - - buf = malloc(2 + 2 * pages + 1); - if (!buf) - return STM32_ERR_UNKNOWN; - - /* Number of pages to be erased - 1, two bytes, MSB first */ - pg_byte = (pages - 1) >> 8; - buf[i++] = pg_byte; - cs ^= pg_byte; - pg_byte = (pages - 1) & 0xFF; - buf[i++] = pg_byte; - cs ^= pg_byte; - - for (pg_num = spage; pg_num < spage + pages; pg_num++) { - pg_byte = pg_num >> 8; - cs ^= pg_byte; - buf[i++] = pg_byte; - pg_byte = pg_num & 0xFF; - cs ^= pg_byte; - buf[i++] = pg_byte; - } - buf[i++] = cs; - p_err = port->write(port, buf, i); - free(buf); - if (p_err != PORT_ERR_OK) { - fprintf(stderr, "Page-by-page erase error.\n"); - return STM32_ERR_UNKNOWN; - } - - s_err = stm32_get_ack_timeout(stm, STM32_SECTERASE_TIMEOUT); - if (s_err != STM32_ERR_OK) { - fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); - if (port->flags & PORT_STRETCH_W - && stm->cmd->er != STM32_CMD_EE_NS) - stm32_warn_stretching("erase"); - return STM32_ERR_UNKNOWN; - } - - return STM32_ERR_OK; - } - - /* And now the regular erase (0x43) for all other chips */ - if (pages == 0xFF) { + /* regular erase (0x43) */ + if (stm->cmd->er == STM32_CMD_ER) { s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT); if (s_err != STM32_ERR_OK) { if (port->flags & PORT_STRETCH_W) - stm32_warn_stretching("erase"); + stm32_warn_stretching("mass erase"); return STM32_ERR_UNKNOWN; } return STM32_ERR_OK; - } else { - uint8_t cs = 0; - uint8_t pg_num; - uint8_t *buf; - int i = 0; + } + + /* extended erase */ + buf[0] = 0xFF; /* 0xFFFF the magic number for mass erase */ + buf[1] = 0xFF; + buf[2] = 0x00; /* checksum */ + if (port->write(port, buf, 3) != PORT_ERR_OK) { + fprintf(stderr, "Mass erase error.\n"); + return STM32_ERR_UNKNOWN; + } + s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Mass erase failed. Try specifying the number of pages to be erased.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("mass erase"); + return STM32_ERR_UNKNOWN; + } + return STM32_ERR_OK; +} + +static stm32_err_t stm32_pages_erase(const stm32_t *stm, uint32_t spage, uint32_t pages) +{ + struct port_interface *port = stm->port; + stm32_err_t s_err; + port_err_t p_err; + uint32_t pg_num; + uint8_t pg_byte; + uint8_t cs = 0; + uint8_t *buf; + int i = 0; + + /* The erase command reported by the bootloader is either 0x43, 0x44 or 0x45 */ + /* 0x44 is Extended Erase, a 2 byte based protocol and needs to be handled differently. */ + /* 0x45 is clock no-stretching version of Extended Erase for I2C port. */ + if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) { + fprintf(stderr, "Can't initiate chip mass erase!\n"); + return STM32_ERR_UNKNOWN; + } + /* regular erase (0x43) */ + if (stm->cmd->er == STM32_CMD_ER) { buf = malloc(1 + pages + 1); if (!buf) return STM32_ERR_UNKNOWN; @@ -828,7 +801,7 @@ fprintf(stderr, "Erase failed.\n"); return STM32_ERR_UNKNOWN; } - s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT); + s_err = stm32_get_ack_timeout(stm, pages * STM32_PAGEERASE_TIMEOUT); if (s_err != STM32_ERR_OK) { if (port->flags & PORT_STRETCH_W) stm32_warn_stretching("erase"); @@ -836,6 +809,92 @@ } return STM32_ERR_OK; } + + /* extended erase */ + buf = malloc(2 + 2 * pages + 1); + if (!buf) + return STM32_ERR_UNKNOWN; + + /* Number of pages to be erased - 1, two bytes, MSB first */ + pg_byte = (pages - 1) >> 8; + buf[i++] = pg_byte; + cs ^= pg_byte; + pg_byte = (pages - 1) & 0xFF; + buf[i++] = pg_byte; + cs ^= pg_byte; + + for (pg_num = spage; pg_num < spage + pages; pg_num++) { + pg_byte = pg_num >> 8; + cs ^= pg_byte; + buf[i++] = pg_byte; + pg_byte = pg_num & 0xFF; + cs ^= pg_byte; + buf[i++] = pg_byte; + } + buf[i++] = cs; + p_err = port->write(port, buf, i); + free(buf); + if (p_err != PORT_ERR_OK) { + fprintf(stderr, "Page-by-page erase error.\n"); + return STM32_ERR_UNKNOWN; + } + + s_err = stm32_get_ack_timeout(stm, pages * STM32_PAGEERASE_TIMEOUT); + if (s_err != STM32_ERR_OK) { + fprintf(stderr, "Page-by-page erase failed. Check the maximum pages your device supports.\n"); + if (port->flags & PORT_STRETCH_W + && stm->cmd->er != STM32_CMD_EE_NS) + stm32_warn_stretching("erase"); + return STM32_ERR_UNKNOWN; + } + + return STM32_ERR_OK; +} + +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint32_t spage, uint32_t pages) +{ + uint32_t n; + stm32_err_t s_err; + + if (!pages || spage > STM32_MAX_PAGES || + ((pages != STM32_MASS_ERASE) && ((spage + pages) > STM32_MAX_PAGES))) + return STM32_ERR_OK; + + if (stm->cmd->er == STM32_CMD_ERR) { + fprintf(stderr, "Error: ERASE command not implemented in bootloader.\n"); + return STM32_ERR_NO_CMD; + } + + if (pages == STM32_MASS_ERASE) { + /* + * Not all chips support mass erase. + * Mass erase can be obtained executing a "readout protect" + * followed by "readout un-protect". This method is not + * suggested because can hang the target if a debug SWD/JTAG + * is connected. When the target enters in "readout + * protection" mode it will consider the debug connection as + * a tentative of intrusion and will hang. + * Erasing the flash page-by-page is the safer way to go. + */ + if (!(stm->dev->flags & F_NO_ME)) + return stm32_mass_erase(stm); + + pages = flash_addr_to_page_ceil(stm->dev->fl_end); + } + + /* + * Some device, like STM32L152, cannot erase more than 512 pages in + * one command. Split the call. + */ + while (pages) { + n = (pages <= 512) ? pages : 512; + s_err = stm32_pages_erase(stm, spage, n); + if (s_err != STM32_ERR_OK) + return s_err; + spage += n; + pages -= n; + } + return STM32_ERR_OK; } static stm32_err_t stm32_run_raw_code(const stm32_t *stm, @@ -843,7 +902,7 @@ const uint8_t *code, uint32_t code_size) { uint32_t stack_le = le_u32(0x20002000); - uint32_t code_address_le = le_u32(target_address + 8); + uint32_t code_address_le = le_u32(target_address + 8 + 1); // thumb mode address (!) uint32_t length = code_size + 8; uint8_t *mem, *pos; uint32_t address, w; @@ -910,7 +969,12 @@ { uint32_t target_address = stm->dev->ram_start; - return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); + if (stm->dev->flags & F_OBLL) { + /* set the OBL_LAUNCH bit to reset device (see RM0360, 2.5) */ + return stm32_run_raw_code(stm, target_address, stm_obl_launch_code, stm_obl_launch_code_length); + } else { + return stm32_run_raw_code(stm, target_address, stm_reset_code, stm_reset_code_length); + } } stm32_err_t stm32_crc_memory(const stm32_t *stm, uint32_t address, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/stm32.h new/stm32flash/stm32.h --- old/stm32flash/stm32.h 2014-10-02 09:20:26.000000000 +0200 +++ new/stm32flash/stm32.h 2016-02-08 18:28:56.000000000 +0100 @@ -27,6 +27,9 @@ #define STM32_MAX_RX_FRAME 256 /* cmd read memory */ #define STM32_MAX_TX_FRAME (1 + 256 + 1) /* cmd write memory */ +#define STM32_MAX_PAGES 0x0000ffff +#define STM32_MASS_ERASE 0x00100000 /* > 2 x max_pages */ + typedef enum { STM32_ERR_OK = 0, STM32_ERR_UNKNOWN, /* Generic error */ @@ -34,6 +37,11 @@ STM32_ERR_NO_CMD, /* Command not available in bootloader */ } stm32_err_t; +typedef enum { + F_NO_ME = 1 << 0, /* Mass-Erase not supported */ + F_OBLL = 1 << 1, /* OBL_LAUNCH required */ +} flags_t; + typedef struct stm32 stm32_t; typedef struct stm32_cmd stm32_cmd_t; typedef struct stm32_dev stm32_dev_t; @@ -55,9 +63,10 @@ uint32_t ram_start, ram_end; uint32_t fl_start, fl_end; uint16_t fl_pps; // pages per sector - uint16_t fl_ps; // page size + uint32_t *fl_ps; // page size uint32_t opt_start, opt_end; uint32_t mem_start, mem_end; + uint32_t flags; }; stm32_t *stm32_init(struct port_interface *port, const char init); @@ -68,8 +77,8 @@ const uint8_t data[], unsigned int len); stm32_err_t stm32_wunprot_memory(const stm32_t *stm); stm32_err_t stm32_wprot_memory(const stm32_t *stm); -stm32_err_t stm32_erase_memory(const stm32_t *stm, uint8_t spage, - uint8_t pages); +stm32_err_t stm32_erase_memory(const stm32_t *stm, uint32_t spage, + uint32_t pages); stm32_err_t stm32_go(const stm32_t *stm, uint32_t address); stm32_err_t stm32_reset_device(const stm32_t *stm); stm32_err_t stm32_readprot_memory(const stm32_t *stm); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/stm32flash/stm32flash.1 new/stm32flash/stm32flash.1 --- old/stm32flash/stm32flash.1 2014-10-03 23:35:08.000000000 +0200 +++ new/stm32flash/stm32flash.1 2016-02-10 17:57:32.000000000 +0100 @@ -1,6 +1,6 @@ -.TH STM32FLASH 1 "2013\-11\-03" STM32FLASH "User command" +.TH STM32FLASH 1 "2015\-11\-25" STM32FLASH "User command" .SH NAME -stm32flash \- flashing utility for STM32 and STM32W through UART or I2C +stm32flash \- flashing utility for STM32 through UART or I2C .SH SYNOPSIS .B stm32flash .RB [ \-cfhjkouvCR ] @@ -29,19 +29,21 @@ .RB [ \-i .IR GPIO_string ] .RI [ tty_device -.R | +| .IR i2c_device ] .SH DESCRIPTION .B stm32flash -reads or writes the flash memory of STM32 and STM32W. +reads or writes the flash memory of STM32. -It requires the STM32[W] to embed a bootloader compliant with ST -application note AN3155. +It requires the STM32 to embed a bootloader compliant with ST +application note AN3155 or AN4221. .B stm32flash uses the serial port .I tty_device -to interact with the bootloader of STM32[W]. +or the i2c port +.I i2c_device +to interact with the bootloader of STM32. .SH OPTIONS .TP @@ -55,7 +57,7 @@ Specify baud rate speed of .IR tty_device . Please notice that the ST bootloader can automatically detect the baud rate, -as explaned in chapter 2 of AN3155. +as explained in chapter 2 of AN3155. This option could be required together with option .B "\-c" or if following interaction with bootloader is expected. @@ -68,7 +70,7 @@ .I mode is a three characters long string where each character specifies, in this strict order, character size, parity and stop bits. -The only values currenly used are +The only values currently used are .I 8e1 for standard STM32 bootloader and .I 8n1 @@ -78,27 +80,27 @@ .TP .BI "\-r" " filename" -Specify to read the STM32[W] flash and write its content in +Specify to read the STM32 flash and write its content in .I filename in raw binary format (see below .BR "FORMAT CONVERSION" ). .TP .BI "\-w" " filename" -Specify to write the STM32[W] flash with the content of +Specify to write the STM32 flash with the content of .IR filename . File format can be either raw binary or intel hex (see below .BR "FORMAT CONVERSION" ). The file format is automatically detected. To by\-pass format detection and force binary mode (e.g. to -write an intel hex content in STM32[W] flash), use +write an intel hex content in STM32 flash), use .B \-f option. .TP .B \-u -Specify to disable write\-protection from STM32[W] flash. -The STM32[W] will be reset after this operation. +Specify to disable write\-protection from STM32 flash. +The STM32 will be reset after this operation. .TP .B \-j @@ -167,9 +169,9 @@ .TP .BI "\-i" " GPIO_string" -Specify the GPIO sequences on the host to force STM32[W] to enter and +Specify the GPIO sequences on the host to force STM32 to enter and exit bootloader mode. GPIO can either be real GPIO connected from host to -STM32[W] beside the UART connection, or UART's modem signals used as +STM32 beside the UART connection, or UART's modem signals used as GPIO. (See below .B BOOTLOADER GPIO SEQUENCE for the format of @@ -226,6 +228,7 @@ .P sequence = [\-]n[,sequence] .RE +.PD .P In the above sequences, negative numbers correspond to GPIO at "low" level; numbers without sign correspond to GPIO at "high" level. @@ -237,6 +240,9 @@ Note: the string "\-brk" has no effect and is ignored. .PD +.P +Note that the exit sequence is only executed if -R is specified. If -R is specified, but no exit sequence, a software-triggered reset will be performed. + .PD 0 As example, let's suppose the following connection between host and STM32: .IP \(bu 2 @@ -255,13 +261,13 @@ .I GPIO_string is "4,\-5,\-3,3". -To exit from bootloade and run the application program, the sequence is: +To exit from bootloader and run the application program, the sequence is: put GPIO_4="low"; then send reset pulse. The corresponding string for .I GPIO_string is "\-4,\-3,3". -The complete command line flag is "\-i 4,\-5,\-3,3:\-4,\-3,3". +The complete command line flag is "\-R \-i 4,\-5,\-3,3:\-4,\-3,3". STM32W uses pad PA5 to select boot mode; if during reset PA5 is "low" then STM32W will enter in bootloader mode; if PA5 is "high" it will execute the @@ -271,7 +277,7 @@ The command: .PD 0 .RS -stm32flash \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 +stm32flash \-R \-i \-3,\-2,2:3,\-2,2 /dev/ttyS0 .RE provides: .IP \(bu 2 @@ -321,7 +327,7 @@ exit sequence: RTS=high, DTR=low, DTR=high .P .RS -stm32flash \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 +stm32flash \-R \-i \-rts,\-dtr,dtr:rts,\-dtr,dtr /dev/ttyS0 .PD .RE @@ -343,7 +349,7 @@ .IR "Antonio Borneo <borneo.anto...@gmail.com>" . Please report any bugs at the project homepage -http://stm32flash.googlecode.com . +http://stm32flash.sourceforge.net . .SH SEE ALSO .BR "srec_cat" "(1)," " srec_intel" "(5)," " srec_motorola" "(5)."