Hallo zusammen, ich habe gerade ein Problem, ein "Blue Pill" Board mit dem USB Bootloader von https://github.com/rogerclarkmelbourne/STM32duino-bootloader/tree/master/binaries (generic_boot20_pc13.bin) ans laufen zu kriegen. Ich kann problemlos den Bootloader auf den Chip über mein parallel zum USB angeschlossenes USB-Serial Interface an PB9 und PB10 flashen, mit dem stm32loader.py script. Der Bootloader scheint auch aktiv zu sein anhand der LED blink codes, die er beim Betätigen der Reset Taste ausgibt. Weiterhin bin ich in der Lage über den USB Bootloader ein vorher kompiliertes Programm per dfu-util (version 0.9) raufzuladen, nur dass dieses Programm dann keinerlei Funktion zeigt. Lade ich das gleiche Programm ohne Bootloader über den stm32loader.py auf den Chip, funktioniert alles wie es soll. Ich habe ein einfaches Blinky ausprobiert. Mein Verdacht ist, dass das Programm bei Verwendung des Bootloaders evtl. an eine andere Adresse im Flash geladen werden muss, aber da bin ich mir eben nicht sicher. Leider finde ich nur Anleitungen, wie diese Arduino-GUIs zu verwenden sind, aber ich will das nur mit GCC und Makefile und den unter Linux vorhandenen Tools machen. Grüße, Martin
:
Bearbeitet durch User
Ja, der bootloader benutzt den ersten Bereich des Programmspeichers. Da wo dein programm normalerweise läuft. Du musst wissen, wo der bootloader das Programm hinpackt. Dann musst Du den Linkerscript entsprechend anpassen. Aber das ist noch nicht alles. Die Vektortable für die Interruptroutinen muss an der richtigen stelle stehen. Mit Glück passt das der Bootloader entsprechend an. Wenn Du CubeMX benutzt, gibt noch eine weitere Falle. Martin
Hallo, anbei mal mein Linker-Script (hoffe es ist auch das relevante Linker-Script, habe da nicht so die Ahnung, da bisher nur mit AVRs unterwegs gewesen). Da war das nicht so relevant.
1 | /*
|
2 | Default linker script for STM32F10x_128K_20K with GNU-ld
|
3 | Martin Thomas, 9/2009
|
4 | A heavily modified "Default linker script for STM32F10x_512K_64K"
|
5 | Copyright RAISONANCE S.A.S. 2008 found in the STM fw-library.
|
6 | (there is not much left from Raisonance's code and nearly everything
|
7 | has been modified or reordered)
|
8 | */
|
9 | |
10 | /* Program Entry, set to mark it as "used" and avoid gc */
|
11 | ENTRY(Reset_Handler) |
12 | |
13 | /* Memory Spaces Definitions */
|
14 | MEMORY
|
15 | {
|
16 | RAM (RWX) : ORIGIN = 0x20000000+0, LENGTH = 20K-0 |
17 | EXTSRAM (RWX) : ORIGIN = 0x68000000, LENGTH = 0 |
18 | FLASH (RX) : ORIGIN = 0x08000000+0, LENGTH = 128K-2K-0 |
19 | EEMUL (RWX) : ORIGIN = 0x08000000+128k-2k, LENGTH = 2k |
20 | FLASHB1 (RX) : ORIGIN = 0x00000000, LENGTH = 0 |
21 | EXTMEMB0 (RX) : ORIGIN = 0x00000000, LENGTH = 0 |
22 | EXTMEMB1 (RX) : ORIGIN = 0x00000000, LENGTH = 0 |
23 | EXTMEMB2 (RX) : ORIGIN = 0x00000000, LENGTH = 0 |
24 | EXTMEMB3 (RX) : ORIGIN = 0x00000000, LENGTH = 0 |
25 | }
|
26 | |
27 | /* higher address of the user mode stack */
|
28 | _estack = ORIGIN(RAM)+LENGTH(RAM); |
29 | |
30 | /* start of the two 1kByte pages used by EEprom emulation at end of flash */
|
31 | _seemul = ORIGIN(EEMUL); |
32 | |
33 | /* There will be a link error if there is not this amount of RAM free at the end. */
|
34 | _Minimum_Stack_Size = 0x100 ; |
35 | |
36 | /* Check valid alignment for VTOR */
|
37 | ASSERT(ORIGIN(FLASH) == ALIGN(ORIGIN(FLASH), 0x80), "Start of memory region flash not aligned for startup vector table"); |
38 | |
39 | /* Sections Definitions */
|
40 | |
41 | SECTIONS
|
42 | {
|
43 | |
44 | /* the program code is stored in the .text section, which goes to Flash */
|
45 | .text : |
46 | {
|
47 | . = ALIGN(0x80); /* PM0056, Rev.1 (4/2009), 4.3.3 */ |
48 | _isr_vectorsflash_offs = . - 0x08000000; |
49 | KEEP(*(.isr_vectorsflash)) |
50 | . = ALIGN(4); |
51 | CREATE_OBJECT_SYMBOLS
|
52 | *(.text .text.* .gnu.linkonce.t.*) |
53 | *(.plt) |
54 | *(.gnu.warning) |
55 | *(.glue_7t) *(.glue_7) *(.vfp11_veneer) |
56 | *(.ARM.extab* .gnu.linkonce.armextab.*) |
57 | *(.gcc_except_table) |
58 | } >FLASH |
59 | |
60 | .eh_frame_hdr : ALIGN (4) |
61 | {
|
62 | KEEP (*(.eh_frame_hdr)) |
63 | } >FLASH |
64 | .eh_frame : ALIGN (4) |
65 | {
|
66 | KEEP (*(.eh_frame)) |
67 | } >FLASH |
68 | |
69 | /* .ARM.exidx is sorted, so has to go in its own output section. */
|
70 | __exidx_start = .; |
71 | .ARM.exidx : |
72 | {
|
73 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) |
74 | } >FLASH |
75 | __exidx_end = .; |
76 | |
77 | .rodata : ALIGN (4) |
78 | {
|
79 | *(.rodata .rodata.* .gnu.linkonce.r.*) |
80 | |
81 | . = ALIGN(4); |
82 | KEEP(*(.init)) |
83 | |
84 | . = ALIGN(4); |
85 | __preinit_array_start = .; |
86 | KEEP (*(.preinit_array)) |
87 | __preinit_array_end = .; |
88 | |
89 | . = ALIGN(4); |
90 | __init_array_start = .; |
91 | KEEP (*(SORT(.init_array.*))) |
92 | KEEP (*(.init_array)) |
93 | __init_array_end = .; |
94 | |
95 | . = ALIGN(4); |
96 | KEEP(*(.fini)) |
97 | |
98 | . = ALIGN(4); |
99 | __fini_array_start = .; |
100 | KEEP (*(.fini_array)) |
101 | KEEP (*(SORT(.fini_array.*))) |
102 | __fini_array_end = .; |
103 | |
104 | . = ALIGN(0x4); |
105 | KEEP (*crtbegin.o(.ctors)) |
106 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) |
107 | KEEP (*(SORT(.ctors.*))) |
108 | KEEP (*crtend.o(.ctors)) |
109 | |
110 | . = ALIGN(0x4); |
111 | KEEP (*crtbegin.o(.dtors)) |
112 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) |
113 | KEEP (*(SORT(.dtors.*))) |
114 | KEEP (*crtend.o(.dtors)) |
115 | |
116 | *(.init .init.*) |
117 | *(.fini .fini.*) |
118 | |
119 | PROVIDE_HIDDEN (__preinit_array_start = .); |
120 | KEEP (*(.preinit_array)) |
121 | PROVIDE_HIDDEN (__preinit_array_end = .); |
122 | PROVIDE_HIDDEN (__init_array_start = .); |
123 | KEEP (*(SORT(.init_array.*))) |
124 | KEEP (*(.init_array)) |
125 | PROVIDE_HIDDEN (__init_array_end = .); |
126 | PROVIDE_HIDDEN (__fini_array_start = .); |
127 | KEEP (*(.fini_array)) |
128 | KEEP (*(SORT(.fini_array.*))) |
129 | PROVIDE_HIDDEN (__fini_array_end = .); |
130 | |
131 | . = ALIGN (8); |
132 | *(.rom) |
133 | *(.rom.b) |
134 | _etext = .; |
135 | /* This is used by the startup in order to initialize the .data secion */
|
136 | _sidata = _etext; |
137 | } >FLASH |
138 | |
139 | /* This is the initialized data section
|
140 | The program executes knowing that the data is in the RAM
|
141 | but the loader puts the initial values in the FLASH (inidata).
|
142 | It is one task of the startup to copy the initial values from FLASH to RAM. */
|
143 | .data : ALIGN (8) |
144 | {
|
145 | /* This is used by the startup in order to initialize the .data section */
|
146 | _sdata = . ; |
147 | |
148 | . = ALIGN(0x80); |
149 | _isr_vectorsram_offs = . - 0x20000000; |
150 | KEEP(*(.isr_vectorsram)) |
151 | |
152 | . = ALIGN(4); |
153 | KEEP(*(.jcr)) |
154 | *(.got.plt) *(.got) |
155 | *(.shdata) |
156 | *(.data .data.* .gnu.linkonce.d.*) |
157 | . = ALIGN (8); |
158 | *(.ram) |
159 | *(.ramfunc*) |
160 | . = ALIGN(4); |
161 | /* This is used by the startup in order to initialize the .data section */
|
162 | _edata = .; |
163 | } >RAM AT>FLASH |
164 | |
165 | /* This is the uninitialized data section */
|
166 | .bss (NOLOAD): |
167 | {
|
168 | . = ALIGN(4); |
169 | /* This is used by the startup in order to initialize the .bss section */
|
170 | _sbss = .; |
171 | *(.shbss) |
172 | *(.bss .bss.* .gnu.linkonce.b.*) |
173 | *(COMMON) |
174 | . = ALIGN (8); |
175 | *(.ram.b) |
176 | . = ALIGN(4); |
177 | /* This is used by the startup in order to initialize the .bss section */
|
178 | _ebss = . ; |
179 | _end = .; |
180 | __end = .; |
181 | } >RAM AT>FLASH |
182 | |
183 | |
184 | /* This is the user stack section
|
185 | This is just to check that there is enough RAM left for the User mode stack
|
186 | It should generate an error if it's full.
|
187 | */
|
188 | ._usrstack (NOLOAD): |
189 | {
|
190 | . = ALIGN(4); |
191 | _susrstack = . ; |
192 | . = . + _Minimum_Stack_Size ; |
193 | . = ALIGN(4); |
194 | _eusrstack = . ; |
195 | } >RAM |
196 | |
197 | |
198 | /* this is the FLASH Bank1 */
|
199 | /* the C or assembly source must explicitly place the code or data there
|
200 | using the "section" attribute */
|
201 | .b1text : |
202 | {
|
203 | *(.b1text) /* remaining code */ |
204 | *(.b1rodata) /* read-only data (constants) */ |
205 | *(.b1rodata*) |
206 | } >FLASHB1 |
207 | |
208 | /* this is the EXTMEM */
|
209 | /* the C or assembly source must explicitly place the code or data there
|
210 | using the "section" attribute */
|
211 | |
212 | /* EXTMEM Bank0 */
|
213 | .eb0text : |
214 | {
|
215 | *(.eb0text) /* remaining code */ |
216 | *(.eb0rodata) /* read-only data (constants) */ |
217 | *(.eb0rodata*) |
218 | } >EXTMEMB0 |
219 | |
220 | /* EXTMEM Bank1 */
|
221 | .eb1text : |
222 | {
|
223 | *(.eb1text) /* remaining code */ |
224 | *(.eb1rodata) /* read-only data (constants) */ |
225 | *(.eb1rodata*) |
226 | } >EXTMEMB1 |
227 | |
228 | /* EXTMEM Bank2 */
|
229 | .eb2text : |
230 | {
|
231 | *(.eb2text) /* remaining code */ |
232 | *(.eb2rodata) /* read-only data (constants) */ |
233 | *(.eb2rodata*) |
234 | } >EXTMEMB2 |
235 | |
236 | /* EXTMEM Bank0 */
|
237 | .eb3text : |
238 | {
|
239 | *(.eb3text) /* remaining code */ |
240 | *(.eb3rodata) /* read-only data (constants) */ |
241 | *(.eb3rodata*) |
242 | } >EXTMEMB3 |
243 | |
244 | |
245 | |
246 | /* after that it's only debugging information. */
|
247 | |
248 | /* remove the debugging information from the standard libraries */
|
249 | /* DISCARD :
|
250 | {
|
251 | libc.a ( * )
|
252 | libm.a ( * )
|
253 | libgcc.a ( * )
|
254 | }
|
255 | */
|
256 | |
257 | /* Stabs debugging sections. */
|
258 | .stab 0 : { *(.stab) } |
259 | .stabstr 0 : { *(.stabstr) } |
260 | .stab.excl 0 : { *(.stab.excl) } |
261 | .stab.exclstr 0 : { *(.stab.exclstr) } |
262 | .stab.index 0 : { *(.stab.index) } |
263 | .stab.indexstr 0 : { *(.stab.indexstr) } |
264 | .comment 0 : { *(.comment) } |
265 | /* DWARF debug sections.
|
266 | Symbols in the DWARF debugging sections are relative to the beginning
|
267 | of the section so we begin them at 0. */
|
268 | /* DWARF 1 */
|
269 | .debug 0 : { *(.debug) } |
270 | .line 0 : { *(.line) } |
271 | /* GNU DWARF 1 extensions */
|
272 | .debug_srcinfo 0 : { *(.debug_srcinfo) } |
273 | .debug_sfnames 0 : { *(.debug_sfnames) } |
274 | /* DWARF 1.1 and DWARF 2 */
|
275 | .debug_aranges 0 : { *(.debug_aranges) } |
276 | .debug_pubnames 0 : { *(.debug_pubnames) } |
277 | /* DWARF 2 */
|
278 | .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } |
279 | .debug_abbrev 0 : { *(.debug_abbrev) } |
280 | .debug_line 0 : { *(.debug_line) } |
281 | .debug_frame 0 : { *(.debug_frame) } |
282 | .debug_str 0 : { *(.debug_str) } |
283 | .debug_loc 0 : { *(.debug_loc) } |
284 | .debug_macinfo 0 : { *(.debug_macinfo) } |
285 | /* SGI/MIPS DWARF 2 extensions */
|
286 | .debug_weaknames 0 : { *(.debug_weaknames) } |
287 | .debug_funcnames 0 : { *(.debug_funcnames) } |
288 | .debug_typenames 0 : { *(.debug_typenames) } |
289 | .debug_varnames 0 : { *(.debug_varnames) } |
290 | /* DWARF 3 */
|
291 | .debug_pubtypes 0 : { *(.debug_pubtypes) } |
292 | .debug_ranges 0 : { *(.debug_ranges) } |
293 | |
294 | .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } |
295 | .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } |
296 | /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } |
297 | }
|
298 | |
299 | /* mthomas: from the STM example - moved here for now to keep it as reference, not
|
300 | used in the project (useful anyway?)*/
|
301 | |
302 | /* default stack size(s). These are used by the startup in order to allocate stacks for
|
303 | the different modes. */
|
304 | __Stack_Size = 1024 ; |
305 | |
306 | PROVIDE ( _Stack_Size = __Stack_Size ) ; |
307 | __Stack_Init = _estack - __Stack_Size ; |
308 | |
309 | /*"PROVIDE" allows to easily override these values from an object file or the commmand line.*/
|
310 | PROVIDE ( _Stack_Init = __Stack_Init ) ; |
Was müsste ich jetzt da ändern um mit dem USB-Bootloader klarzukommen? Grüße, Martin
:
Bearbeitet durch User
Wau! So ein Hammer script für das BluePill? Benutzt du die HAL-Lib?
MEMORY { RAM (RWX) : ORIGIN = 0x20000000+0, LENGTH = 20K-0 EXTSRAM (RWX) : ORIGIN = 0x68000000, LENGTH = 0 FLASH (RX) : ORIGIN = 0x08000000+0, LENGTH = 128K-2K-0 EEMUL (RWX) : ORIGIN = 0x08000000+128k-2k, LENGTH = 2k FLASHB1 (RX) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB0 (RX) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB1 (RX) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB2 (RX) : ORIGIN = 0x00000000, LENGTH = 0 EXTMEMB3 (RX) : ORIGIN = 0x00000000, LENGTH = 0 } in der Memeory Beschreibung musst Du die Zeile FLASH anpassen. Da steht ORIGIN und LENGTH 0x8000000 ist start of flash des stm, da steht jetzt Dein bootloader. Du musst die Adresse entsprechend erhöhen und die Länge kürzen.
pegel schrieb: > Wau! So ein Hammer script für das BluePill? Manche Leute haben das berühmte "Warum soll ichs mir einfach machen wenns auch kompliziert geht?" eben wirklich verinnerlicht.
Hallo, freut mich, dass ich euch mit meinem anscheinend 'overkill' Linker-Script zum Lachen bringen konnte. Ich hab das aus irgend einem Projekt übernommen und es hat funktioniert. So what? Falls jemand was geeigneteres rumliegen hat nehme ich gerne das. Aber es funktioniert leider noch nicht, daher noch einige Fragen: dfu-util -l liefert folgendes:
1 | dfu-util -l |
2 | dfu-util 0.9 |
3 | |
4 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. |
5 | Copyright 2010-2016 Tormod Volden and Stefan Schmidt |
6 | This program is Free Software and has ABSOLUTELY NO WARRANTY |
7 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ |
8 | |
9 | Found DFU: [1eaf:0003] ver=0201, devnum=98, cfg=1, intf=0, path="1-1.1", alt=2, name="STM32duino bootloader v1.0 Upload to Flash 0x8002000", serial="LLM 003" |
10 | Found DFU: [1eaf:0003] ver=0201, devnum=98, cfg=1, intf=0, path="1-1.1", alt=1, name="STM32duino bootloader v1.0 Upload to Flash 0x8005000", serial="LLM 003" |
11 | Found DFU: [1eaf:0003] ver=0201, devnum=98, cfg=1, intf=0, path="1-1.1", alt=0, name="STM32duino bootloader v1.0 ERROR. Upload to RAM not supported.", serial="LLM 003" |
Es scheint also mehrere mit alt=? auswählbare Versionen zu geben, die an verschiedene Flash-Adressen laden. Macht das nun der Bootloader von selbst oder muss es trotzdem im Linker-Script angepasst werden? Mein Aufruf von dfu-util zum Flashen sieht dann so aus:
1 | dfu-util -a 2 -D ./FLASH_RUN/project.bin |
Ausgabe ist folgende:
1 | dfu-util 0.9 |
2 | |
3 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. |
4 | Copyright 2010-2016 Tormod Volden and Stefan Schmidt |
5 | This program is Free Software and has ABSOLUTELY NO WARRANTY |
6 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ |
7 | |
8 | dfu-util: Invalid DFU suffix signature |
9 | dfu-util: A valid DFU suffix will be required in a future dfu-util release!!! |
10 | Opening DFU capable USB device... |
11 | ID 1eaf:0003 |
12 | Run-time device DFU version 0110 |
13 | Claiming USB DFU Interface... |
14 | Setting Alternate Setting #2 ... |
15 | Determining device status: state = dfuIDLE, status = 0 |
16 | dfuIDLE, continuing |
17 | DFU mode device DFU version 0110 |
18 | Device returned transfer size 1024 |
19 | Copying data from PC to DFU device |
20 | Download [=========================] 100% 4928 bytes |
21 | Download done. |
22 | state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present |
23 | Done! |
Ich habe das mit den FLASH Adressen 0x08000000, 0x08002000 und 0x08005000 im Linker-Script versucht, jedoch ohne Erfolg. Hat noch jemand eine Idee? Grüße, Martin
Hättest du meine Frage nach HAL beantwortet .... Aber auch so mein Tip. In der HAL Lib gibt es ein IAP_Binary_Template Projekt, das steht wie es gemacht wird. Wenn du an der Funktion des Boot-Ladens interessiert bist, empfehle ich dazu das IAP_Main Projekt, welches über die serielle Schnittstelle funktioniert.
Hallo pegel, ich benutze kein HAL. Den Bootloader über seriell habe ich ja schon benutzt um den USB Bootloader draufzuspielen. Der funktioniert also. Grüße, Martin
Ich meinte nicht nur das Benutzen, sondern das Erstellen und Verstehen des Bootloaders und der passenden Anwendung.
Hallo, wie du vielleicht merkst, verstehe ich das Ganze nicht wirklich. Was ich bisher dachte zu wissen: der Bootloader setzt sich an die Startadresse, an der normal das Programm startet (in diesem Fall wohl 0x08000000). Nach einem Reset wartet der Bootloader auf ein zu übertagendes Programm. Wenn er das bekommt, lädt er es in einen höheren Adressbereich (in diesem Fall z.B. 0x08002000) und führt es dann aus. Wenn ein Programm schon vorhanden ist wartet der Bootloader kurz ob er ein neues Programm empfangen soll und führt ansonsten schon das vorhandene aus. Soweit mein Verständnis. Was ich nicht weiß, ist wie ein solches Programm beschaffen sein muss, damit es über den Bootloader gestartet werden kann. Ich war der Meinung dass das halbwegs transparent abläuft, aber so scheint es nicht zu sein. Grüße, Martin
Das stimmt im Prinzip auch so. Zuerst musst du wissen an welche Adresse der Bootloader dein Programm lädt. Ein gutes Programm zur Verwaltung des Speichers ist der STM32CubeProgrammer. Der kann SWD, dfu und USB. Damit kannst du sehen wohin dein Prog geladen wird und es entsprechend anpassen. Dann aus der IAP_Binary_Template/readme.txt: To build such application, some special configuration has to be performed: 1. Set the program load address at 0x08004000, using your toolchain linker file 2. Relocate the vector table at address 0x08004000, using the "NVIC_SetVectorTable" function.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.