2020-12-21 08:20 AM
A STM32F746 on a custom board powered by the step-down regulator TPS62082 by TI doesn't start in about 90% of cases.
I flashed (which always works fine) a simple test program, which flashes two LEDs alternately:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1) {
LED1; // LED1 on, GPIOx->BSRR = ...;
LED20; // LED2 off, GPIOx->BSRR = ...;
HAL_Delay(1000);
LED10; // LED1 off
LED2; // LED2 on
HAL_Delay(1000);
}
}
The STM32 runs at 200 MHz, using HSI and LSI. In about 10% of cases after power on, the LEDs light up. The other 90%, both LEDs remain dark. If the LEDs remain dark, a manual reset by pulling NRST low always starts the STM32.
The first idea was that there is a power issue, but I set the Brown Out Reset level in the option bytes to around 3V. Looking at Vin (3) and Vout (1) of the regulator, voltage seems to be fine. (2) is the output of a GPIO output which was initialized to HIGH in MX_GPIO_Init() -- but it remains LOW, which means the program is not executed.
The duration until the voltage has risen to 3.3V is more than 1ms, but according to the datasheet the rise time doesn't matter (if it's not too short).
Looking at the NRST pin (with only a 10K pullup attached, but no flasher device), this is curve (3) while (1) is Vout, i.e., Vdd of the STM32.
The increased BOD level seems to work; the STM32 starts working after the voltage is stable.
Thus, the voltage doesn't seem to play a role in the STM32 not starting up. What else could prevent a startup?
Solved! Go to Solution.
2020-12-22 03:45 AM
> PC = 1FF01752
That's bootloader.
> I think we crossed that bridge already.
Obviously, not quite.
JW
2020-12-21 08:26 AM
Is BOOT0 pulled low?
2020-12-21 08:40 AM
I think we crossed that bridge already.
Probably is starting
Get the Error_Handler() and HardFault_Handler() properly instrumented so you can see if it dies there.
Get code in the Reset_Handler to set some GPIOs or squawk a couple of bytes to a UART using the HSI the chip starts with.
2020-12-21 11:35 PM
The problem with that is that the debugger doesn't even reach the main() breakpoint. That implies that an error handler (if that is the issue) is hit before peripherals are initialized, thus lighting LEDs via GPIO doesn't work.
So far I couldn't think of anything that would signal the outer world that an error handler was hit -- without using the debugger.
2020-12-21 11:50 PM
2020-12-22 12:02 AM
As said, I'm using HSI and LSI, and that is what's configured in CubeMX.
I don't have a capacitor for NRST (I missed it), but then should its effect not be similar to raising the BOD level? If you look at the last graph, you see that NRST goes HIGH well after the voltage is stable. If I'm not mistaken, that's the entire point of the NRST capacitor (together with the resistor, an RC delay element).
2020-12-22 01:25 AM
You initialize GPIO using simpler self contained code fragments. Similarly UART.
Not without some effort, but seem to be in a position where that's necessary to see what's happening without a debugger and from outside the box.
2020-12-22 02:21 AM
I did use Jlink Commander to connect to the STM32 with much more control than the debugger.
Anyway, here is the output when I connected to the STM32 which did not start. The MCU was running, so I had to halt it, which printed out the registers.
J-Link>halt
PC = 1FF01752, CycleCnt = 13E4E3F9
R0 = 40004800, R1 = 40003000, R2 = 0000AAAA, R3 = 006210DF
R4 = 00000000, R5 = 0000AAAA, R6 = 40003000, R7 = 00000000
R8 = 00000000, R9 = 00000000, R10= 00000000, R11= 00000000
R12= 00800100
SP(R13)= 20003AF8, MSP= 20003AF8, PSP= 00000000, R14(LR) = 1FF0160F
XPSR = 21000000: APSR = nzCvq, EPSR = 01000000, IPSR = 000 (NoException)
CFBP = 00000001, CONTROL = 00, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 01
FPS0 = 00000000, FPS1 = 00000000, FPS2 = 00000000, FPS3 = 00000000
FPS4 = 00000000, FPS5 = 00000000, FPS6 = 00000000, FPS7 = 00000000
FPS8 = 00000000, FPS9 = 00000000, FPS10= 00000000, FPS11= 00000000
FPS12= 00000000, FPS13= 00000000, FPS14= 00000000, FPS15= FFFFFFFF
FPS16= 00000000, FPS17= 00000000, FPS18= 00000000, FPS19= 00000000
FPS20= 00000000, FPS21= 00000000, FPS22= 00000000, FPS23= 00000000
FPS24= 00000000, FPS25= 00000000, FPS26= 00000000, FPS27= 00000000
FPS28= 00000000, FPS29= 00000000, FPS30= 00000000, FPS31= FFFFFFFF
FPSCR= 00000000
Notice that strange address in PC, which corresponds to a reserved area in memory. Also, the SP should grow from 0x2001 0000 downwards.
I then reset the MCU, and looked at the registers again.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>regs
PC = 002106C4, CycleCnt = 00000000
R0 = 00000000, R1 = 00000000, R2 = 00000000, R3 = 00000000
R4 = 00000000, R5 = 00000000, R6 = 00000000, R7 = 00000000
R8 = 00000000, R9 = 00000000, R10= 00000000, R11= 00000000
R12= 00000000
SP(R13)= 20010000, MSP= 20010000, PSP= 00000000, R14(LR) = FFFFFFFF
XPSR = 01000000: APSR = nzcvq, EPSR = 01000000, IPSR = 000 (NoException)
CFBP = 00000000, CONTROL = 00, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 00
FPS0 = 00000000, FPS1 = 00000000, FPS2 = 00000000, FPS3 = 00000000
FPS4 = 00000000, FPS5 = 00000000, FPS6 = 00000000, FPS7 = 00000000
FPS8 = 00000000, FPS9 = 00000000, FPS10= 00000000, FPS11= 00000000
FPS12= 00000000, FPS13= 00000000, FPS14= 00000000, FPS15= FFFFFFFF
FPS16= 00000000, FPS17= 00000000, FPS18= 00000000, FPS19= 00000000
FPS20= 00000000, FPS21= 00000000, FPS22= 00000000, FPS23= 00000000
FPS24= 00000000, FPS25= 00000000, FPS26= 00000000, FPS27= 00000000
FPS28= 00000000, FPS29= 00000000, FPS30= 00000000, FPS31= FFFFFFFF
FPSCR= 00000000
That looks much better, in fact, comparing it to the list file:
002106c4 <Reset_Handler>:
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
2106c4: f8df d034 ldr.w sp, [pc, #52] ; 2106fc <LoopFillZerobss+0x14>
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
2106c8: 2100 movs r1, #0
b LoopCopyDataInit
2106ca: e003 b.n 2106d4 <LoopCopyDataInit>
the PC is exactly where it should. Single stepping also showed it would enter main() and the LED blink loop therein.
Contrast this with the non-starting MCU. After halting it, I'm also able to single step, but it seems the MCU is stuck in a random(?), short loop:
1FF01752: 9B 06 LSLS R3, R3, #26
J-Link>s
1FF01754: FB D5 BPL #-0x0A
J-Link>s
1FF0174E: 0A 60 STR R2, [R1]
J-Link>s
1FF01750: C3 69 LDR R3, [R0, #+0x1C]
J-Link>s
1FF01752: 9B 06 LSLS R3, R3, #26
J-Link>s
1FF01754: FB D5 BPL #-0x0A
[...]
How the MCU got to address 0x1FF01752, I have no idea, and I also don't know how I could find out.
2020-12-22 03:45 AM
> PC = 1FF01752
That's bootloader.
> I think we crossed that bridge already.
Obviously, not quite.
JW
2020-12-22 04:00 AM
At first, I did connect BOOT0 incorrectly, but I fixed it with a wire on my board. I did measure the fixed BOOT0 pin, and it is LOW now. Also, in about 5-10% of cases, the STM32 starts normal.
And if I switch to a power plug (the board has two power sources), the start rate is above 90%.
What other causes could start the bootloader?