cancel
Showing results for 
Search instead for 
Did you mean: 

STM32MP1 FreeRTOS debug issue

romain2
Associate III

Hi,

We are currently using the STM32MP1-DK1 board.

We have tried several examples but we are facing some issues with the one using FreeRTOS (FreeRTOS_ThreadCreation) :

We have no issues running the program on the M4 both in Engineering mode and Production mode.

When we are debugging the program and stepping instruction by instruction, the debugging process is lost at a time during the execution.

In Engineering mode :

We can execute the program and and we can insert breakpoint wherever we want. But, after the instruction msr msp, r0 in the function prvPortStartFirstTask in the file port.c has been executing, if we stop the program execution by inserting a breakpoint, the debugging process is lost with the error :

Examination failed, GDB will be halted. Polling again in 6300ms

Polling target stm32mp15x.cpu0 failed, trying to reexamine

In Production mode :

We can execute the program and and we can insert breakpoint wherever we want. But, after the instruction bx r14 in the function vPortSVCHandler in the file port.c

has been executing, if we stop the program execution by inserting a breakpoint, the debuging process is lost with the error (in the linux console):

dwc2 49000000.usb-otg : dwc2_hsotg_ep_stop_xfr: timeout DIEPINT.NAKEFF

dwc2 49000000.usb-otg : dwc2_hsotg_ep_stop_xfr: timeout DOEPCTL.EPDisable

dwc2 49000000.usb-otg : dwc2_flush_tx_fifo : HANG ! AHB Idle GRSCTL

dwc2 49000000.usb-otg : dwc2_hsotg_ep_stop_xfr: timeout GINTSTS.GOUTNAKEFF

dwc2 49000000.usb-otg : dwc2_hsotg_ep_stop_xfr: timeout DOEPCTL.EPDisable

dwc2 49000000.usb-otg : dwc2_hsotg_ep_stop_xfr: timeout DIEPINT.NAKEFF

If we don’t stop the execution after executing these instructions, we can see with the LED that the program is executing without error and the tasks are correctly scheduling.

The same error will appears if we break the execution flow after theses instructions has been executed.

The program is compiled with the size optimization (-Os). When compiling without optimization (-Oo), the issue no longer appears and it is possible to debug the entire execution and include breakpoint whenever/wherever we want without having issues, both in Production mode and Engineering mode.

The behavior is the same when using the STM32MP1-DK2 board.

We don’t see what is the issue here and how changing the optimization from –Os to –Oo could impact the behavior of the program.

Do you have any idea of the root cause of the issue ?

Thanks,

Regards,

Romain

4 REPLIES 4
OlivierK
ST Employee

​Hello Romain,

I experience the same in my freeRTOS project. I suppose it is in the nature of any code compiler tool that the code execution will differ according to compiler optimization settings.

The compiler reorganizes instructions and the debugger cannot always identify the source code that corresponds to a set of instructions. Therefore I would live with -Oo for debug as long as the code behave as expected in run and release mode.

Regards,

Olivier

AntonioST
ST Employee

Hello Romain,

what you have found is really interesting.

GDB tries to identify the current status of the program in execution and does it by reading the CPU registers and the content of the stack.

In prvPortStartFirstTask the instruction "msr msp, r0" changes the value of the stack pointer in order to prepare the execution of the first thread of FreeRTOS.

By changing the stack pointer, the execution context is partially modified but it is not in the final "stable" state yet.

GDB still try to read the stack content at the new address, finds garbage values that "could" be the address of the caller function, and ask OpenOCD to read the memory at that address. These "random" reads from GDB are really dangerous.

When I tried to replicate this use case, GDB asked OpenOCD to read at one address that belongs to the DDR (DDR is not enabled in Engineering Mode) and the internal bus freezes waiting for DDR to provide the value. After that, OpenOCD fails to check the status of the CPUs.

On my side, this simple patch seams working and prevents GDB to issue the random read. Would you mind checking it too?

File: Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c

@@ -269,6 +269,9 @@ static void prvPortStartFirstTask( void )

                                       " ldr r0, [r0]                 \n"

                                       " ldr r0, [r0]                 \n"

                                       " msr msp, r0                  \n" /* Set the msp back to the start of the stack. */

+#ifdef __GCC_HAVE_DWARF2_CFI_ASM

+                                      " .cfi_undefined 14 \n"

+#endif

                                       " mov r0, #0                   \n" /* Clear the bit that indicates the FPU is in use, see comment above. */

                                       " msr control, r0              \n"

                                       " cpsie i                              \n" /* Globally enable interrupts. */

I did not succeed to replicate the second issue in Production Mode with vPortSVCHandler, but I expect being similar to the first issue. In your case the "random" read from GDB impacts the functionality of the USB OTG device.

Antonio

Hi Antonio,

Thank you for your answer.

If we apply your patch we can go some steps further but we still have some issues.

Now the behavior is the same in Production mode and in Engineering mode :

We can now step until the start of the first task (LED_Thread1 here).

Once we have reached the first instruction of the first task to be executed, the debugger is lost with the same error than the one in the previous task.

Regards,

Romain

AntonioST
ST Employee

Hello Romain,

I still failed to replicate the issue, so I'm only guessing what could be the reason of it.

Would you mind testing this additional patch? To be applied together with the previous one on the same file.

@@ -101,6 +101,26 @@ occurred while the SysTick counter is stopped during tickless idle

 calculations. */

 #define portMISSED_COUNTS_FACTOR                      ( 45UL )

+static void prvTaskExitError( void );

+void wrapperTaskExitError( void ) __attribute__ (( naked ));

+void wrapperTaskExitError( void )

+{

+      __asm volatile (

+#ifdef __GCC_HAVE_DWARF2_CFI_ASM

+              ".cfi_undefined 14 \n"

+#endif

+              "nop \n"

+              "nop \n"

+              "nop \n"

+              "nop \n"

+              "bl %0 \n"

+              ".L0: \n"

+              "b .L0 \n"

+              :: "i"(prvTaskExitError)

+      );

+}

+#define configTASK_RETURN_ADDRESS (((StackType_t) wrapperTaskExitError) + 4)

+

 /* Let the user override the pre-loading of the initial LR with the address of

 prvTaskExitError() in case it messes up unwinding of the stack in the

 debugger. */