2019-09-25 03:45 PM
TL:DR; New to firmware development. Inherited codebase for new revision of product. Sole firmware developer. Cannot step through code. Seeking advice.
---------------------
So I am fairly new to firmware development in a new company where I inherited this codebase that is to be used for a new product. Previously, TrueStudio 9.x.y was used for the previous generation product last year.
I am the sole firmware developer in a small company. I had 2 weeks with the previous firmware engineer before they left. They did their best to transfer as much knowledge as possible, but not everything could be covered in that time-frame. My background is Cypress FX3 firmware development and kernel device drivers.
The codebase seems to have bootloader and application code mixed together. First, is this a common practice, as I see these as separate functions. The bootloader, per my understanding, is to configure the STM32 to load and run the application.
I build the application and bootloader, and when I attempt to download/debug the bootloader with a breakpoint set immediately in main,
TrueStudio 9.3.0 with an ST-Link v2 is used to connect to the custom board. I am building a debug/non-optimized code, which I download via the ST-LinkV2. The Console window output I receive starts with the below, with the crash (?) shown afterwards.
So the question I have is, of which settings do I need to be most careful? Is there something obvious I am missing due to my lack of expertise? Given that the environment is for a shipped product that did work, should I still stick with TrueStudio, or make the change to STM32CubeIDE (I did play around to it, but saw that the conversion of the project to that new IDE is nontrivial).
And is there a way to pay for support from ST, now that TrueStudio Pro is no longer available?
Thank you for reading.
Kosta
And now the initial output:
STMicroelectronics ST-LINK GDB server. Version 5.1.0
Copyright (c) 2018, STMicroelectronics. All rights reserved.
Starting server with the following options:
Persistent Mode : Disabled
Logging Level : 1
Listen Port Number : 61234
Status Refresh Delay : 15s
Verbose Mode : Disabled
SWD Debug : Enabled
Waiting for debugger connection...
Debugger connected
-------------------------------------------------------------------
STM32CubeProgrammer v1.3.0
-------------------------------------------------------------------
Log output file: C:\Users\Kosta\AppData\Local\Temp\STM32CubeProgrammer_a04312.log
ST-LINK SN : 48FF6E064967535721350887
ST-LINK FW : V2J35S7
Voltage : 3.19V
SWD freq : 4000 KHz
Connect mode: Under Reset
Reset mode : Hardware reset
Device ID : 0x434
Device name : STM32F469xx/F467xx
Device type : MCU
Device CPU : Cortex-M4
Memory Programming ...
Opening and parsing file: C:\Users\Kosta\AppData\Local\Temp\ST-LINK_GDB_server_a04312.srec
File : C:\Users\Kosta\AppData\Local\Temp\ST-LINK_GDB_server_a04312.srec
Size : 162084 Bytes
Address : 0x08040000
Erasing memory corresponding to segment 0:
Erasing internal memory sectors [6 7]
Download in Progress:
File download complete
Time elapsed during download operation: 00:00:03.894
Verifying ...
Download verified successfully
Then after a moment I get the following output in the Console window:
Program received signal
SIGINT, Interrupt.
0x08007506 in ?? ()
Stopping the session, I see the following appended to the Console window in the first section:
Debugger connection lost.
Shutting down...
2019-09-25 04:48 PM
If you have an idle loop with a __WFI (Wait For Interrupt) it will power down the debug interface.
Get a serial port working so you can understand behaviour beyond the debugger.
Check the .MAP and .LST files with respect to the failure address being reported.
>>The codebase seems to have bootloader and application code mixed together. First, is this a common practice,..
I usually keep things separate. A "workspace" might have multiple sub-projects or build options, and these might share a common/similar code base.
The main() function can be quite deep, turn off "Run to main()" options, and step from Reset_Handler on in.
SystemInit() can initialize a lot of clocks and external memory subsystems, this is usually done before the startup.s code unpacks and clears the static allocations.
2019-09-25 04:57 PM
>>And is there a way to pay for support from ST, now that TrueStudio Pro is no longer available?
Not aware they have a model for that. They keep a list of contractors/consultants.
I don't particularly care for the Atollic / TrueStudio / Eclipse / CubeIDE environments.
2019-09-25 04:59 PM
What is your preferred IDE? Given my lack of expertise, I'm a bit concerned as to switching environments, given that this environment was used successfully in the past. I'm just missing something basic. But as my knowledge grows, I'm open to change.
2019-09-25 05:16 PM
I have a preference for Keil, and when using GNU/GCC I use MAKE.
IDE's are mostly about personal preference, or business mandate, what works for me doesn't necessarily translate well to others.
Here you just sound like you're crashing early, so something in the startup code might be dumping the debug interface, either explicitly attempting to disable it, or interfering with the pins it uses, or turning off power to the interface.
Breakpointing main() is evidently too later, so you need to move earlier. I'd usually do this via code inspection and code walking, but absent that level of insight into the code, I'd step in from here the CPU starts executing.
2019-09-25 05:41 PM
Is there a way to set a breakpoint at an address? I'm able to set breakpoints at source code lines. I know how to do this in windbg, but this is a new world for me.
Setting a breakpoint in the .s file for Reset_Handler and the call to SystemInit results in basically a hang where there is what was provided in my first post up until "Download verified successfully"
Looking at the .list file I see the following around the address 8007506:
tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4U);
8007500: 683b ldr r3, [r7, #0]
8007502: 685a ldr r2, [r3, #4]
8007504: 683b ldr r3, [r7, #0]
8007506: 695b ldr r3, [r3, #20]
8007508: 011b lsls r3, r3, #4
800750a: 4313 orrs r3, r2
800750c: 68fa ldr r2, [r7, #12]
800750e: 4313 orrs r3, r2
8007510: 60fb str r3, [r7, #12]
From the .map file:
.text.Reset_Handler
0x0800907c 0x50 HALUtils\startup_stm32f479xx.o
0x0800907c Reset_Handler
2019-09-25 11:12 PM
Code starts at 0x0800'0000, so if you load code from 0x0800'4000 there's already something at that lower portion of memory, probably the bootloader, which may not pass control to the upper code's startup code and then main() as you expect. Or, your problem may be, that the bootloader is *not* there (just FFs). That might perhaps be the reason it won't get to the bootloader's main, or even its startup code or that it behaves there unexpectedly.
I loathe the eclipsoids so have no idea how is it in atollic's version of it, but in normal IDEs you set breakpoint and step through binary code in the disassembly window.
I'd also start with getting familiar with the environment, whatever it is, by writing a basic blinky; without the bootloader first, and then adding the boodloader. Small steps at a time. Trow out any ranting bean-counting superior through door or window, of your choice; firm grip on the tools is an absolute necessity.
Then, can't you start with reproducing the known working binary? You've surely shown how to achieve that by your predecessor?
And an unwanted advice, forget soon about using a different compiler setting for debugging, unless you're debugging an algorithmic problem,
JW
2019-09-26 10:26 AM
Thanks. Yes, I did note that in the .ld file for the bootloader, I have the following:
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K
}
and for the application code:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8040000, LENGTH = 512K
}
Good advice on the getting familiar. In different tools/environments, my knowledge/expertise in tools makes things quick. While the concepts translate, the rest does not. I'll ping ST about which eval or development board they'd recommend as I'm using an STM32F479NIH6.