OK I realise this sounds like a dumb/noob question but please do read it through before calling me an idiot - at this stage I'll gladly take it if you can spot where I've gone wrong!
The scenario:
We have an existing working PCB design using an STM32F051K4, multiple boards have been built & programmed and all have performed as expected.
Populating a new bare PCB with just the micro, its associated smoothing/decoupling caps, and BMP/SWD (debug/ICP) header the SysTick interrupt would not fire and breakpoints set in the debugger would not trigger (setting break main
would never trigger!).
I have tried several fresh boards, micros from two different batches, getting a more skilled colleague to solder the board... and none of them work!
The complete environment:
Boards are a fairly basic PCB with STM32F051K4U6 / K6U7 (UFQFPN32 package) microprocessor plus a couple of 100n / 4u7 capacitors around the 3v3 rail.
In the test setup, the board is powered, programmed, and debugged by a Black Magic Probe (BMP) via GDB.
The firmware is based on generated code from STM32CubeMX using low-level (LL) libraries, compiled in SW4STM32, initialising only the basic system clock / systick and setting all GPIO pins to analogue (floating / High Z).
The pseudo-code of the entire thing is as follows - standard init purely as-generated by CubeMX:
LL_Init();
SystemClockConfig(); // Include SysTick IRQ
LL_SYSTICK_EnableIT(); // Enable the SysTick interrupt
MX_GPIO_Init();
while(1)
{
count++;
//optionally toggle a pin here to prove it's running
}
The SysTick_Handler
simply increments a global ticks
variable.
Then the main loop literally just increments a count while we wait for the SysTick that never comes.
The code compiles, and via GDB/BMP downloads and runs - in the "good" board I can set break main
and break SysTick_Handler
and both will be triggered as soon as the board is run.
In the "bad" boards the breakpoints are never tripped and the interrupt never fires (ticks remains 0) despite the main loop counting upwards (and, if I toggle a pin in main()
, I can see it toggle). However, the micro can be stopped and single-stepped and GDB reports no errors setting breakpoints. programming, etc.
I have checked the interrupt vectors in the startup code and they are as expected.
I am really stumped by this, my best-guess is there's some pin that needs to be pulled up or down or something, or perhaps some extra power rail smoothing is needed somewhere that the fully-populated board introduces, but I would NOT expect the micro/debugger to be that sensitive?
I've checked and re-checked the code, the boards, the components fitted, the soldering job, and my sanity (TBC) to no avail.
Any ideas gratefully received at this stage!
Edit to address questions in comments (in order & as I can):
@ChrisStratton:
The binary is identical every time, from the working running board I am then detaching GDB, issuing BMP "power disable", swapping boards, "power enable", scan, re-attach, load the binary, run. Not touching the IDE at all.
Hard to be 100% sure the ground pad is soldered as it's under the chip in the UFQFPN32. All power pins (2x VDD + VDDA) are connected and have smoothing caps per the datasheet.
I have not (yet) tried other interrupts as I would have to write new code to interrupt from a GPIO pin for example.
I don't have a discovery board with this micro on so can't try that.
Linker & startup are generated by CubeMX for this part and are obviously working on the "good" board with no modification.
@SamGibson:
The "bare" board is minus peripherals such as MAX232, I2C EEPROM, external voltage regulator, etc. just has the micro, debug header, and power supply caps / relevant pullups (BOOT0, NRST) fitted.
I'm not currently in a position to post photos/schematics, I will if I can.