Discussion:
[En-Nut-Discussion] STM32: Problems running code with an offset in flash (bootloader)
Ole Reinhardt
2016-03-02 22:53:49 UTC
Permalink
Hi all,

has anyone just compiled a program for STM32 that is not linked to the
beginning of the flash?

I need to link my program to a start address of 0x0800c000, as my system
runs a bootloader, that expects its application code at this address.

CPU: STM32F411CE

To do so, I added a local linker script that defienes a
bootloader_offset of 0xC000 and includes stm32f10x_flash.ld:


----------------------------
ENTRY(NutInit)
SEARCH_DIR(.)

"bootloader_offset" = 0xC000;

MEMORY
{
FLASH0 (rx) : ORIGIN = 0x08000000, LENGTH = 512K
SRAM0 (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

INCLUDE stm32f10x_flash.ld
----------------------------


Further I added

.bootloader (NOLOAD):
{
. = bootloader_offset;
} > FLASH0

Right at the top of stm32f10x_flash.ld (similar to stm32f10x_ram.ld)


The application is started correctly and I can output some debug
messages using the DebugPut() routine (Debug Macro). I also can register
the UART driver and output a few bytes using printf().

So far everything looks fine, but as soon as the programs gets a little
more complex it hangs / crashes. Unfortunately I don't have a JTAG
connected, so I can not evaluate any register contents.

Neither a call to NutSleep() nor to NutGetMillis() returns, but on the
other hand NutThreadYield works without any problems.

For example I can create two threads both printing characters with
DebugPut and then calling NutThreadYield. That works as expected, but as
soon as I call NutSleep() the program hangs / crashes.

I also can not print longer strings using printf(). Again the program
gets stuck, while when adding a few DebugPut() calls between several
printf() calls, the output is printed as expected.


I have the strong feeling, that the interrupt handling won't work
anymore when not linking to the flash base address (0x08000000).

a) the timer interrupt is needed for NutSleep()
b) the UART driver prints out data using an interrupt. When calling
DebugPut() in between, this routine does not wait for an interrupt, but
polls the UART status register to wait for the FIFO to get empty again.

b also explains, why printing short text using printf() works, but
longer text outputs get stuck. A longer text needs interrupt interaction
while a shorter text fits into the UART FIFO.


Does anyone of you have an idea what could cause such a behaviour?

How could the behaviour be related to either the offset where the code
is linked to or to any settings that the bootloader configures?

I'm wondering if the bootloader could have disabled all interrupts and
the STM32 startup code does not re-enable them?

I'm a little out of good ideas...


Btw: The hardware is a WifiMCU board http://www.wifimcu.com/

Best regards,

Ole Reinhardt
--
kernel concepts GmbH Tel: +49-271-771091-14
Sieghuetter Hauptweg 48 Mob: +49-177-7420433
D-57072 Siegen
http://www.embedded-it.de
http://www.kernelconcepts.de
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Uwe Bonnes
2016-03-03 09:23:22 UTC
Permalink
Ole> Hi all, has anyone just compiled a program for STM32 that is not
Ole> linked to the beginning of the flash?

Ole> I need to link my program to a start address of 0x0800c000, as my
Ole> system runs a bootloader, that expects its application code at this
Ole> address.

Ole> CPU: STM32F411CE

Ole> To do so, I added a local linker script that defienes a
Ole> bootloader_offset of 0xC000 and includes stm32f10x_flash.ld:


Ole> ---------------------------- ENTRY(NutInit) SEARCH_DIR(.)

Ole> "bootloader_offset" = 0xC000;

Ole> MEMORY { FLASH0 (rx) : ORIGIN = 0x08000000, LENGTH = 512K SRAM0
Ole> (rwx) : ORIGIN = 0x20000000, LENGTH = 128K }

Ole> INCLUDE stm32f10x_flash.ld ----------------------------


Ole> Further I added

Ole> .bootloader (NOLOAD): { . = bootloader_offset; } > FLASH0

Ole> Right at the top of stm32f10x_flash.ld (similar to
Ole> stm32f10x_ram.ld)


Ole> The application is started correctly and I can output some debug
Ole> messages using the DebugPut() routine (Debug Macro). I also can
Ole> register the UART driver and output a few bytes using printf().

Ole> So far everything looks fine, but as soon as the programs gets a
Ole> little more complex it hangs / crashes. Unfortunately I don't have
Ole> a JTAG connected, so I can not evaluate any register contents.

Ole> Neither a call to NutSleep() nor to NutGetMillis() returns, but on
Ole> the other hand NutThreadYield works without any problems.

Ole> For example I can create two threads both printing characters with
Ole> DebugPut and then calling NutThreadYield. That works as expected,
Ole> but as soon as I call NutSleep() the program hangs / crashes.

Ole> I also can not print longer strings using printf(). Again the
Ole> program gets stuck, while when adding a few DebugPut() calls
Ole> between several printf() calls, the output is printed as expected.


Ole> I have the strong feeling, that the interrupt handling won't work
Ole> anymore when not linking to the flash base address (0x08000000).

Ole> a) the timer interrupt is needed for NutSleep() b) the UART driver
Ole> prints out data using an interrupt. When calling DebugPut() in
Ole> between, this routine does not wait for an interrupt, but polls the
Ole> UART status register to wait for the FIFO to get empty again.

Ole> b also explains, why printing short text using printf() works, but
Ole> longer text outputs get stuck. A longer text needs interrupt
Ole> interaction while a shorter text fits into the UART FIFO.


Ole> Does anyone of you have an idea what could cause such a behaviour?

Ole> How could the behaviour be related to either the offset where the
Ole> code is linked to or to any settings that the bootloader
Ole> configures?

Ole> I'm wondering if the bootloader could have disabled all interrupts
Ole> and the STM32 startup code does not re-enable them?

Ole> I'm a little out of good ideas...


cmsis/cortex_init.c line 431 is in charge to remap the interrupt vectors. I
guess something goes wrong there. Without a debugger, things are hard to
debug. But the ESP board has listed "SWD debug interface". And I know you have
some ST boards with Stlink at least version 2. So you could try to set up a
SWD connection from the SWD extension connector on the Stlink board to your
ESP board with flying wires.

Otherwise check in your map file that interrupt vector remap is set up
sensible.

You could also recreate your bootloader setup on your STM board. Here
SWD connection is on the board direct, so no need for flying wires. Or
perhaps post or send me your a test example and I can test and debug on some
of my bords, as time allows.

Hope this helps
--
Uwe Bonnes ***@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Coleman Brumley
2016-03-03 16:46:09 UTC
Permalink
Post by Uwe Bonnes
cmsis/cortex_init.c line 431 is in charge to remap the interrupt vectors.
Is this also a potential issue with the AT91SAM7X? I’m working on a similar project, and I’m just wondering if this is something I need to look out for.

Regards,
Coleman


_______________________________________________
http://lists.egnite.de/mailman/listinfo/e
Ole Reinhardt
2016-03-03 23:26:07 UTC
Permalink
Hi Coleman,

for AT91SAM7X I have a working solution based on an older Nut/OS Version
(4.10 if I remember correctly). If you like I can send you some sources.
I never faced any similar problems there.

The ISR vector code works different than CM3/CM4.

Best regards,

Ole
Post by Coleman Brumley
Post by Uwe Bonnes
cmsis/cortex_init.c line 431 is in charge to remap the interrupt vectors.
Is this also a potential issue with the AT91SAM7X? I’m working on a similar project, and I’m just wondering if this is something I need to look out for.
Regards,
Coleman
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
--
kernel concepts GmbH Tel: +49-271-771091-14
Sieghuetter Hauptweg 48 Mob: +49-177-7420433
D-57072 Siegen
http://www.embedded-it.de
http://www.kernelconcepts.de
_______________________________________________
http://lists.egnite.de/mailman/li
Ole Reinhardt
2016-03-03 23:34:01 UTC
Permalink
Hi Uwe,
Post by Uwe Bonnes
cmsis/cortex_init.c line 431 is in charge to remap the interrupt vectors. I
guess something goes wrong there. Without a debugger, things are hard to
debug. But the ESP board has listed "SWD debug interface". And I know you have
some ST boards with Stlink at least version 2. So you could try to set up a
SWD connection from the SWD extension connector on the Stlink board to your
ESP board with flying wires.
I got my STLink dongle today but this made things even more strange.

If I connect the STLink with the board, the program continues running,
but the output is unreadable. Looks like the baudrate (or any clock?)
changed.

If the STlink is _not connected_ the Program hangs after a few
instructions during the first printf.

What could be the difference when the STLink is connected or not? Really
strange.

Best regards,

Ole
--
kernel concepts GmbH Tel: +49-271-771091-14
Sieghuetter Hauptweg 48 Mob: +49-177-7420433
D-57072 Siegen
http://www.embedded-it.de
http://www.kernelconcepts.de
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Uwe Bonnes
2016-03-04 09:47:20 UTC
Permalink
Post by Uwe Bonnes
cmsis/cortex_init.c line 431 is in charge to remap the interrupt
vectors. I guess something goes wrong there. Without a debugger,
things are hard to debug. But the ESP board has listed "SWD debug
interface". And I know you have some ST boards with Stlink at least
version 2. So you could try to set up a SWD connection from the SWD
extension connector on the Stlink board to your ESP board with flying
wires.
Ole> I got my STLink dongle today but this made things even more
Ole> strange.

Ole> If I connect the STLink with the board, the program continues
Ole> running, but the output is unreadable. Looks like the baudrate (or
Ole> any clock?) changed.

Ole> If the STlink is _not connected_ the Program hangs after a few
Ole> instructions during the first printf.

Ole> What could be the difference when the STLink is connected or not?
Ole> Really strange.

Request for more information:
- Is this the standalone ST-Link or a STlink from a Discovery/Nucleo board?
- Do you use the ST-Link software or OpenOCD.
- If OpenOCD is used, what version?

If OpenOCD is used, tcl/target/stm32f4x.cfg enables debugging in
low-power modes and stops the watchdog during halt. If you reset, speed is
also changed to allow faster programming.

But above the word "watchdog" may be the difference. Does the bootloader use
the watchdog? The watchdog is only stopped by a reset.

Again, a stripped down or even unchanged version of the Bootloader/Programs
under test would allow me to test.

Bye
--
Uwe Bonnes ***@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Ole Reinhardt
2016-03-04 11:35:45 UTC
Permalink
Hi Uwe,
Post by Uwe Bonnes
- Is this the standalone ST-Link or a STlink from a Discovery/Nucleo board?
No, this is a standalone STLink. I could also use the nucleo board, but
decided to bye a simple standalone clone.

It's the following module:

http://www.ebay.de/itm/ST-Link-V2-STM8-STM32-USB-Programmer-3-3V-5V-SWD-212-/221884211496

A photo of the opened device can be found here:

https://github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Programming-an-STM32F103XXX-with-a-generic-%22ST-Link-V2%22-programmer-from-Linux

It is flashed with the stlink-v2 firmware.
Post by Uwe Bonnes
- Do you use the ST-Link software or OpenOCD.
- If OpenOCD is used, what version?
OpenOCD V0.9.0

I use:

openocd -f /usr/share/openocd/scripts/interface/stlink-v2.cfg -f
/usr/share/openocd/scripts/target/stm32f4x.cfg
Post by Uwe Bonnes
If OpenOCD is used, tcl/target/stm32f4x.cfg enables debugging in
low-power modes and stops the watchdog during halt. If you reset, speed is
also changed to allow faster programming.
Ok, seems I will have to look a littel further into the openocd scripts :)
Post by Uwe Bonnes
But above the word "watchdog" may be the difference. Does the bootloader use
the watchdog? The watchdog is only stopped by a reset.
Good question. I have not yet studied the bootloader firmware sources.
Until now I only used the binary blob installed on the device as I got it.
Post by Uwe Bonnes
Again, a stripped down or even unchanged version of the Bootloader/Programs
under test would allow me to test.
I suppose the bootloader is build from these sources:

https://github.com/SmartArduino/WiFiMCU/tree/master/Bootloader

Unfortunately it heavily depends on the MICO sdk (which is included in
the GIT Tree as well). But it makes it hard to strip it down to the
basic functionality.

I'll send a anothe private mail with my test sources and the bootloader
flash dump (you should be able to run it on a nucleo board as well, if
it does not fail because of the missing dataflash or wifi module).

Best regards,

Ole
--
Embedded-IT
Alter Weg 3
57223 Kreuztal
http://www.embedded-it.de

Tel.: +49-177-7420433
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Uwe Bonnes
2016-03-04 17:34:27 UTC
Permalink
Hello,

when the bootloader starts the application, the clock tree is set up
fine. Using only GPIO toggle and NutMicroDelay, things work as expected. As
soon as interrupts get involved, HSE is switched off and instead of PLL only
HSI is used.

Watching RCC->CR and RCC->CFGR starting with main in the debugger showed no
unexpected access. I tracked the WiFiMCU bootloader down to setting the
sleepdeep bit in the system control register. When entering deep sleep with
e.g. WFI, HSE is turned off, PLL has no more input and system switches to
HSI on wakeup/

Otherwise WiFiMCU uses the same debug port, but a different clock (26 MHz vs
8 MHz). With no application loaded to 0x0800c000, I can see the bootloader
output at 115200 * 8 / 26 Baud with a Saleae Logicanalyser. For the
application, I can change the config to use 8 MHz.

Bye
--
Uwe Bonnes ***@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Ole Reinhardt
2016-03-04 20:23:02 UTC
Permalink
Hi Uwe,

great, thank you very much. You made my day.

Commenting out the "wfi" call in the idle thread does the trick.

I'll now disable the deepsleep mode bit, so I hopefulle should be able
to use the WFI call again.

best regards,

Ole
Post by Uwe Bonnes
Hello,
when the bootloader starts the application, the clock tree is set up
fine. Using only GPIO toggle and NutMicroDelay, things work as expected. As
soon as interrupts get involved, HSE is switched off and instead of PLL only
HSI is used.
Watching RCC->CR and RCC->CFGR starting with main in the debugger showed no
unexpected access. I tracked the WiFiMCU bootloader down to setting the
sleepdeep bit in the system control register. When entering deep sleep with
e.g. WFI, HSE is turned off, PLL has no more input and system switches to
HSI on wakeup/
Otherwise WiFiMCU uses the same debug port, but a different clock (26 MHz vs
8 MHz). With no application loaded to 0x0800c000, I can see the bootloader
output at 115200 * 8 / 26 Baud with a Saleae Logicanalyser. For the
application, I can change the config to use 8 MHz.
Bye
--
kernel concepts GmbH Tel: +49-271-771091-14
Sieghuetter Hauptweg 48 Mob: +49-177-7420433
D-57072 Siegen
http://www.embedded-it.de
http://www.kernelconcepts.de
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Uwe Bonnes
2016-03-04 20:33:50 UTC
Permalink
Ole> Hi Uwe, great, thank you very much. You made my day.

Ole> Commenting out the "wfi" call in the idle thread does the trick.

Ole> I'll now disable the deepsleep mode bit, so I hopefulle should be
Ole> able to use the WFI call again.

How is deepsleep handled in WiFiMCU?
--
Uwe Bonnes ***@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Ole Reinhardt
2016-03-10 22:19:21 UTC
Permalink
Hi Uwe,

with your latest changes, the WifiMCU board works fine together with
it's bootloader.

Indeed the deepsleep bit was set in the SCB->SCR.

Thanks again!

Ole
Post by Uwe Bonnes
Ole> Hi Uwe, great, thank you very much. You made my day.
Ole> Commenting out the "wfi" call in the idle thread does the trick.
Ole> I'll now disable the deepsleep mode bit, so I hopefulle should be
Ole> able to use the WFI call again.
How is deepsleep handled in WiFiMCU?
--
kernel concepts GmbH Tel: +49-271-771091-14
Sieghuetter Hauptweg 48 Mob: +49-177-7420433
D-57072 Siegen
http://www.embedded-it.de
http://www.kernelconcepts.de
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Philipp Burch
2016-03-04 17:04:00 UTC
Permalink
Hi Ole!
Post by Ole Reinhardt
Hi Uwe,
Post by Uwe Bonnes
cmsis/cortex_init.c line 431 is in charge to remap the interrupt vectors. I
guess something goes wrong there. Without a debugger, things are hard to
debug. But the ESP board has listed "SWD debug interface". And I know you have
some ST boards with Stlink at least version 2. So you could try to set up a
SWD connection from the SWD extension connector on the Stlink board to your
ESP board with flying wires.
I got my STLink dongle today but this made things even more strange.
If I connect the STLink with the board, the program continues running,
but the output is unreadable. Looks like the baudrate (or any clock?)
changed.
If the STlink is _not connected_ the Program hangs after a few
instructions during the first printf.
What could be the difference when the STLink is connected or not? Really
strange.
No idea if it is related, but some time ago, I faced such
debugger-related strange behaviour on a TIVA TM4C with a Segger J-Link.
It's a while since, but as far as I remember, I noted the following effects:

- When downloading the software, then unplug the debugger, power-cycle
the board, everything runs fine.
- When downloading the software, then power-cycle the board (with the
debugger still connected), everything runs fine.
- When downloading the software, then unplug the debugger and hard-reset
the MCU (with a pushbutton), the software crashed after some random time
with a bus fault or usage fault.
- When downloading the software, then leave the debugger connected and
reset the MCU by software or by the pushbutton, it crashed as well,
without a useful backtrace.

The crashes could usually be provoked by flooding the board with
Ethernet pings, but it still took between seconds and hours until it
actually happened.

What is really strange is the dependence on the power-cycle. I suppose
that something in the debugging interface is/was not properly reset even
by a hard-reset. Maybe there is some link to your problem.

Btw, I didn't use a bootloader or anything, just writing the image
directly into the MCU flash.

Bye,
Philipp
_______________________________________________
http://lists.egnite.de/mailman/listinfo/en-nut-discussion
Loading...