Recent

Author Topic: Compiler bug on arm embedded: How to identify, how to report?  (Read 6358 times)

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Hi,

lately I did some tests with arm embedded, compiling for the microcontroller STM32F103C8 (Cortex M3). Building the cross compiler worked fine, I got LEDs flashing toggled by a timer interrupt, the serial port is sending data and a 1602 text display also works.

The first error, where I blame the compiler: After some code changes (I ported my first program version using the firmware lib [from here: http://www.j-software.dk/stm32f103.php] to direct register calls) in the ISR of the timer interrupt the program crashed when the timer interrupt was enabled the first time. Even having an empty ISR resulted in a crash. But including a random procedure call (e.g. serial port or delay) helped to prevent the crash. Probably the whole ISR was optimized away by the compiler. Changing the optimization level from -O3 to -O0 helped to solve that problem.

The second error: I tried to port some c-code using an I2C interface to connect to a sensor. In the initialisation phase I call an init procedure of the sensor unit. After including this procedure call the program seems to crash directly at startup. Means only having this procedure call corrupts the complete code, even if its never reached. If I comment out the init call, then the programm starts normally with flashing LED, some delays and status messages via the serial port, everything before the code reaches the position of the init call. But if the init call is there, then no LED will light up and no single byte of a status is transfered through the serial port, that means the code is corrupted from the very beginning. Again when I add a random procedure call within the I2C-init-procedure, for example sending a status message through the serial port, then the program will start corectly and reach the initialisation code. Removing such call than the programm again won't startup at all. Changing compiler optimisation settings didn't help in this case.

My question is now, how can I identify such problems so that I can report them. Obviously its a very target specific problem and it arises in the larger context of the program.

I have a debugger connected to the microcontroller, so I could check on which address the programm got stuck, but with the bare address I have no idea in which pascal line this is. For the first issue I'd like to know if the ISR-Procedure is even linked by the linker (it exists as assembler code), but there is no hint in the binary about the procedures or anything. Debug symbols or procedure names are always stripped away, no matter if I change the compiler settings (e.g. -Xs).

Sure I can provide the code to anyone who could try to help, but I don't want to publish it here because the code is still a bit messy. Attached the timer unit for the timer interrupt as reference / example.

Thanks for any suggestions!

mse

  • Sr. Member
  • ****
  • Posts: 286
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #1 on: June 25, 2017, 11:26:01 am »
I have a debugger connected to the microcontroller, so I could check on which address the programm got stuck, but with the bare address I have no idea in which pascal line this is.
I use MSEide to do source level debugging of M3 chips of Silicon Labs (EM32 Tiny Gecko). In order to debug the chip is connected with a demo board from Energy Micro which has a Segger J-Link debugger chip with an USB port for connection to the development PC. On PC there runs an instance of a gdb-server proxy. MSEide connects the gdb-server for debugging. I use gcc as compiler but I assume it should work with FPC too.
Maybe a similar environment can be setup with ST-chips too?
« Last Edit: June 25, 2017, 11:28:00 am by mse »

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #2 on: June 25, 2017, 11:48:15 am »
Hello mse,

like you have the segger J-link, I have a ST-Link, also connected to the computer with USB . It provides debugging via JTAG and SWD, so from hardware side it should be no problem. But from software side I have no idea how to do the setup. I read some articles (e.g. http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips), also on the internet about gdb etc., but still I have no clue. Do you or anyone else know where to read about some details?

"GDB server proxy" may be a good keyword. I checked in my Em::blocks installation, there is a STLinkGDB.exe with description "STLINK GDB Server (EmBlocks Mar 18 2014 11:17:29)", promising?

Regards

mse

  • Sr. Member
  • ****
  • Posts: 286
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #3 on: June 25, 2017, 12:51:00 pm »
"GDB server proxy" may be a good keyword. I checked in my Em::blocks installation, there is a STLinkGDB.exe with description "STLINK GDB Server (EmBlocks Mar 18 2014 11:17:29)", promising?
Yes! For a first step I would try to run the server and to connect the server with a commandline gdb. I can't help much because I work on Linux and I don't know the ST-environment. I can connect the J-Link server in gdb with
Code: Text  [Select][+][-]
  1. target remote localhost:2331
  2.  

Laksen

  • Hero Member
  • *****
  • Posts: 724
    • J-Software
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #4 on: June 25, 2017, 03:20:20 pm »
The first error, where I blame the compiler: After some code changes (I ported my first program version using the firmware lib [from here: http://www.j-software.dk/stm32f103.php] to direct register calls) in the ISR of the timer interrupt the program crashed when the timer interrupt was enabled the first time. Even having an empty ISR resulted in a crash. But including a random procedure call (e.g. serial port or delay) helped to prevent the crash. Probably the whole ISR was optimized away by the compiler. Changing the optimization level from -O3 to -O0 helped to solve that problem.
You might have triggered a bug which is in the stack frame optimization code. Do you have a small piece of code where you see this in?

Quote
My question is now, how can I identify such problems so that I can report them. Obviously its a very target specific problem and it arises in the larger context of the program.
Debugging or tracing would be the smart way of doing it. What could happen is that one of the exceptions are triggered, which will jump to the default ISR handler. This is just an infinite loop. It would be wise to override those so you can write debug info for those cases. You can compile the RTL with debug info when you build a crosscompiler. That might show some line info. You can do that with CROSSOPT="-g"

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #5 on: June 25, 2017, 04:07:33 pm »
@mse: The connection with the command line worked with port 4242:
Code: Pascal  [Select][+][-]
  1. target remote localhost:4242

@Laksen:
Attached the minimum project which shows the error. The timer-ISR is in file uTimer.pas. If you uncomment the "UART.SendString" line than the program will work as expected. Also if instead optimization is reduced to -O0 or -O1.

What could happen is that one of the exceptions are triggered, which will jump to the default ISR handler. This is just an infinite loop. It would be wise to override those so you can write debug info for those cases.
OK, I can assign handlers for the complete interrupt vector. Problem is that no hardware is initialised in case the second error occurs, so I really need the debugger.

Quote
You can compile the RTL with debug info when you build a crosscompiler. That might show some line info. You can do that with CROSSOPT="-g"
I'll try that.
Edit: Tried with with CROSSOPT="-g", but its the same. In the .bin and .hex ther is no procedure name or anything which could give a hint about the position in the source.
« Last Edit: June 25, 2017, 04:27:01 pm by kupferstecher »

mse

  • Sr. Member
  • ****
  • Posts: 286
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #6 on: June 25, 2017, 04:31:04 pm »
@mse: The connection with the command line worked with port 4242:
My MSEide 'Project'-'Options'-'Debugger' setup is attached.
"startgdbserver_mcu" is a script which starts the gdb server.
'After connect gdb script' ("start.gdb") is
Code: Text  [Select][+][-]
  1. monitor speed 4000
  2. monitor endian little
  3. monitor flash download = 1
  4. monitor flash device = EFM32TG210F32
  5. monitor reset 0
  6.  
You probably need to adapt it.
« Last Edit: June 26, 2017, 06:41:00 am by mse »

Laksen

  • Hero Member
  • *****
  • Posts: 724
    • J-Software
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #7 on: June 26, 2017, 10:11:35 am »
Attached the minimum project which shows the error. The timer-ISR is in file uTimer.pas. If you uncomment the "UART.SendString" line than the program will work as expected. Also if instead optimization is reduced to -O0 or -O1.
Try to update to newest trunk r36597. I just fixed at least one bug. It was generating an exit instruction that didn't trigger an exception return. BTW you don't have to specify the interrupt procedure directive. It doesn't do anything on ARM.

Quote
I'll try that.
Edit: Tried with with CROSSOPT="-g", but its the same. In the .bin and .hex ther is no procedure name or anything which could give a hint about the position in the source.
.bin and .hex doesn't include debug info at all. You will need to debug the .elf instead.
The debug format should match what you are using when compiling your project. So you could try -gw2 or -gw3, but it has to be the same both places.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #8 on: June 26, 2017, 06:11:22 pm »
@mse: Thanks! I'll have a try.

@Laksen
Try to update to newest trunk r36597.
While building the crosscompiler (trunk r36597) I get the following error:
Code: Diff  [Select][+][-]
  1. C:\Programme\fpccross\arm-embedded\fpc\rtl\units\arm-embedded\fgl.s:237: Error:
  2. selected processor does not support Thumb mode `mlas r1,r5,r0,r1'
  3. fgl.pp(1969) Error: Error while assembling exitcode 1
  4. fgl.pp(1969) Fatal: There were 2 errors compiling module, stopping
  5. Fatal: Compilation aborted
  6. make[4]: *** [fgl.ppu] Error 1
  7. make[4]: Leaving directory `C:/Programme/fpccross/arm-embedded/fpc/rtl/embedded'
  8.  
  9. make[3]: *** [embedded_all] Error 2
  10. make[3]: Leaving directory `C:/Programme/fpccross/arm-embedded/fpc/rtl'
  11. make[2]: *** [rtl_all] Error 2
  12. make[2]: Leaving directory `C:/Programme/fpccross/arm-embedded/fpc'
  13. make[1]: *** [build-stamp.arm-embedded] Error 2
  14. make[1]: Leaving directory `C:/Programme/fpccross/arm-embedded/fpc'
  15. make: *** [crossall] Error 2
  16.  
Subarch is armv7m.
I use the following batch-file for building, checked with older fpc version, there it works:
Code: Diff  [Select][+][-]
  1.     REM **Installed compiler directory
  2.  SET FPC_PATH=C:\Programme\lazarus\fpc\3.0.0\bin\i386-win32
  3.      
  4.     REM The compiler itself
  5.  SET PPCBIN=%FPC_PATH%\fpc.exe
  6.      
  7.     REM Folder where the generated cross compiler and run-time libs are going to be saved
  8.  SET INSTALL_PATH=C:\Programme\fpccross\arm-embedded\compiler
  9.      
  10.     REM We need the path to arm-embedded-* files
  11.  SET NDK_BIN=C:\Programme\fpccross\arm-embedded\binutils
  12.      
  13.     REM Make all the binary files that we need accessible
  14.  SET PATH=%FPC_PATH%;%NDK_BIN%;%PATH%
  15.      
  16.     REM Use the correct SUBARCH here
  17.     REM for STM32F1 use armv7m
  18.     REM Start the process
  19.  
  20.  cd fpc
  21.  
  22.  make clean crossall crossinstall FPC=%PPCBIN% OS_TARGET=embedded CPU_TARGET=arm SUBARCH=armv7m INSTALL_PREFIX=%INSTALL_PATH% CROSSBINDIR=%GNU_BIN_PATH% CROSSOPT="-O3 -XX -CX" BINUTILSPREFIX=arm-embedded-
  23.  
  24.  cd ..



Quote
BTW you don't have to specify the interrupt procedure directive. It doesn't do anything on ARM.
Good to know  :)

Quote
.bin and .hex doesn't include debug info at all. You will need to debug the .elf instead.
The debug format should match what you are using when compiling your project. So you could try -gw2 or -gw3, but it has to be the same both places.
The debugger I don't understand yet. What do you mean by "be the same both places."?


Laksen

  • Hero Member
  • *****
  • Posts: 724
    • J-Software
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #9 on: June 26, 2017, 08:20:52 pm »
Try to update to newest trunk r36597.
While building the crosscompiler (trunk r36597) I get the following error:
Should be fixed now

Quote
Quote
.bin and .hex doesn't include debug info at all. You will need to debug the .elf instead.
The debug format should match what you are using when compiling your project. So you could try -gw2 or -gw3, but it has to be the same both places.
The debugger I don't understand yet. What do you mean by "be the same both places."?
It has to be the same both when you build the compiler as when you build your project.

In the bat file you use to compile with you have to change the CROSSOPT="-O3 -XX -CX" to be CROSSOPT="-O3 -XX -CX -gw2" for example.
And then in your project you should specify the same. You might have debug info enabled already, in that case select dwarf2 info.

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Compiler bug on arm embedded: How to identify, how to report?
« Reply #10 on: June 27, 2017, 10:40:06 am »
Hello Laksen,

I just tested and the first problem is solved. :) Very nice!

About using the debugger I have to do some trials first.

The second issue still exists, attached the code where the program doesn't even start if a certain procedure is called ('BMP180.Init' in Line 75 of 'test.lpr'). That it doesn't start I can see by a LED which should be on for one second before 'BMP180.Init' is called.
'BMP180.Init' calls 'I2C.Init' (both uBMP180.pas).
If 'I2C.Init' is commented out, then the program will start normally.
Alternatively if the UART call in 'I2C.Init' is not commented out in line 129 of 'uBMP180.pas', then the program will also start normally. I marked all three lines with '//!!!' so its easier to find.

Regards

 

TinyPortal © 2005-2018