I've seen multiple threads around the internet about the issue I'm having with no solution. So here's another thread:
I can't get the ST-Link/v2 debugger to work. When I compile the project in uVision 5 and flash a board with the STM32F070CB I'm using this all works great.
But when I try to debug the debugger doesn't go into main() in startup_stm32F070xb.s, instead it goes through all of the lines below (past main) to where the arrow is:
IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 <--- ENDP
I've tried everything, I checked all the project settings at least a 1000 times.
This is code that was generated straight from STM32CubeMX using HAL but no OS.
I can get debugging to work on the STM32F0Discovery board with the example project. But I can't get it to work when I try to create my own project on that same devkit with the exact same project settings. When I do that I have the exact same problem as described above.
__main != main()
If you step-into the "BX R0" it will take you into library/run-time code that initializes the statics used in your code, once that is done it will enter main()
The granularity of the M0 seems a bit rougher than other parts, not sure I'd lose sleep over it. Optimized C will always be difficult as there is often a many-to-one relationship between the source and output, and the output may be out of sequence.
So are you basically saying "The F0/M0 series doesn't always really work, don't worry about it and use something else instead?"
But you are aware that the external label for main() is _main (one leading underscore), while the __main in the startup file has two leading underscores and represents an initialization function within the C runtime library?
So jumping to __main doesn't take you directly to main(), but to C runtime-library code that you normally don't have the source code for and no debugging information for and that will initialize RAM, give initial values to variables and setup different library subsystems within the CRTL. So if you want the debugger to stop at main(), then you first need to set a breaking at main(). Or you have to step into __main and then step around through a potentially huge number of instructions there before you will reach main().
I think what he meant was that different architectures have different instruction sets and policy rules for the code generation. And since there isn't a 1-to-1 mapping between C and machine instructions, and there machine instructions need not be emitted in the same order than the original C statements, it can be quite hard to debug the processor. If you set a breaking on a C line, the debugger will use the debug information from the compiler to translate that into an assembler instruction address. But that assembler instruction might end up corresponding to a different source line. While the C code performs all the testing at the start of a for loop, the assembler output might have all the tests at the end of the loop and start by making a jump directly past the loop body code to reach the tests.
You might possibly know all this, but you haven't made any comments making it possible to figure out how much you know about debugging assembler instructions or the rather wicked reordering that may happen. Or the usual code that a CRTL needs to process before it's time to enter main().
Incredible. After spending about 3 days I now discovered what the problem was and it has nothing to do with project settings, debugger, debugger settings, compilation or code.
The reason I was having these problems was that the debugger couldn't locate the compiled object file(s). They were there, but the debugger couldn't see them.
Why?
Because I was working from a networked drive, which Keil can't work with well. Not sure why Keil didn't give any errors or hints towards this though?!
Solution: put everything on a local harddrive/SSD and work from there.
*bangs head on desk*
>>So are you basically saying "The F0/M0 series doesn't always really work, don't worry about it and use something else instead?"
No, I'm saying if you are stepping through assembler code to understand why your code isn't working that you need to be sufficiently familiar with the CPU, tool-chain and the debugger for it to be useful. That there isn't a one-to-one relationship between assembler and high-level source code shouldn't be surprising. Stepping through high-level source will also be non-linear in many cases.
Loading R0 with __main isn't calling anything.
>>>>>>>No, I'm saying if you are stepping through assembler code to understand why your code isn't working that you need to be sufficiently familiar with the CPU, tool-chain and the debugger for it to be useful. That there isn't a one-to-one relationship between assembler and high-level source code shouldn't be surprising. Stepping through high-level source will also be non-linear in many cases.
=========================
Ah ok, that's useful to keep in mind of course. Perhaps I wasn't clear in my explanation earlier: I wasn't trying to step through assembler code. It's just that when I set breakpoints in C code earlier it wouldn't get to the C code and instead stop at that part of the assembler code; that's all it had to show me...
Again, for people who missed it: the reason was the debugger tool couldn't see the object files (that where there) because they were on a networked drive (Windows OS). The solution was to put the whole project on the drive of the local machine.