Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trice locks up or gets stuck on first message of the application #518

Open
initdb opened this issue Jan 30, 2025 · 7 comments
Open

Trice locks up or gets stuck on first message of the application #518

initdb opened this issue Jan 30, 2025 · 7 comments
Assignees

Comments

@initdb
Copy link

initdb commented Jan 30, 2025

Describe the bug
I upgraded from 0.72.5 to 0.73.1 and now my application gets stuck on the first Trice message after TriceInit().

I marked the debugger step where it gets stuck with: =====>
I also will add the sybols tomorrow.

//main:
TriceInit();

	=====>TRice(iD(7489), "INFO: APP_THREADX - init...!\n");

// trice.h
TRICE_INLINE void TRice0(uint16_t tid, const char* pFmt) {
	=====>TRice32m_0(tid);
	TRICE_UNUSED(pFmt)
}

// libtrice.a only dissassembly i will add the symbols tomorrow
TriceNonBlockingDirectWrite:
	push {r3, r4, r5, r6, r7, lr}   
	mov r4, r0                      
	movs r0, #0                     
	mov r5, r1                      
	bl 0x801ac6c <SEGGER_RTT_GetAvailWriteSpace>
	cmp.w r0, r5, lsl #2            
	bcs.n 0x801ada6 <TriceNonBlockingDirectWrite+54>
	ldr r2, [pc, #184] @ (0x801ae3c <TriceNonBlockingDirectWrite+204>)
	ldr r4, [pc, #184] @ (0x801ae40 <TriceNonBlockingDirectWrite+208>)
	ldr r3, [r2, #0]                
	adds r3, #1                     
	str r3, [r2, #0]                
	movs r0, #0                     
	bl 0x801ac6c <SEGGER_RTT_GetAvailWriteSpace>
	rsbs r0, r0, #1024 @ 0x400      
	bmi.n 0x801ada4 <TriceNonBlockingDirectWrite+52>
	ldr r3, [r4, #0]                
	cmp r0, r3                      
	it cc                           
	movcc r0, r3                    
	str r0, [r4, #0]                
	pop {r3, r4, r5, r6, r7, pc}    
	b.n 0x801ada4 <TriceNonBlockingDirectWrite+52>
	movs r0, #0                     
	bl 0x801ac6c <SEGGER_RTT_GetAvailWriteSpace>
	lsls r6, r5, #2                 
	cmp r6, r0                      
	bhi.n 0x801ae1e <TriceNonBlockingDirectWrite+174>
	ldr r7, [pc, #144] @ (0x801ae44 <TriceNonBlockingDirectWrite+212>)
	ldrd r3, r1, [r7, #32]          
	ldr r2, [r7, #28]               
	subs r3, r3, r1                 
	cmp.w r5, r3, lsr #2            
	mov.w lr, r3, lsr #2            
	add.w r0, r2, r1                
	bcc.n 0x801ae22 <TriceNonBlockingDirectWrite+178>
	mov r1, r4                      
	cmp.w lr, #0                    
	beq.n 0x801ade4 <TriceNonBlockingDirectWrite+116>
	add.w r1, r4, lr, lsl #2        
	ldr.w r6, [r4], #4              
	adds r0, #4                     
	cmp r4, r1                      
	str.w r6, [r0, #-4]             
	bne.n 0x801add6 <TriceNonBlockingDirectWrite+102>
	sub.w r5, r5, lr                
	subs r0, r5, #1                 
	cbz r5, 0x801adfc <TriceNonBlockingDirectWrite+140>
	ldr.w r4, [r1], #4              
	subs r0, #1                     
	adds r3, r0, #1                 
	str r4, [r2, #0]                
	add.w r2, r2, #4                
	bne.n 0x801adec <TriceNonBlockingDirectWrite+124>
	dmb sy                          
	lsls r1, r5, #2                 
	movs r0, #0                     
	str r1, [r7, #36] @ 0x24        
	bl 0x801ac6c <SEGGER_RTT_GetAvailWriteSpace>
	rsbs r0, r0, #1024 @ 0x400      
	bmi.n 0x801ae20 <TriceNonBlockingDirectWrite+176>
	ldr r4, [pc, #44] @ (0x801ae40 <TriceNonBlockingDirectWrite+208>)
	ldr r3, [r4, #0]                
	cmp r0, r3                      
	it cc                           
	movcc r0, r3                    
	str r0, [r4, #0]                
	b.n 0x801ad8c <TriceNonBlockingDirectWrite+28>
	b.n 0x801ae1e <TriceNonBlockingDirectWrite+174>
	=====>b.n 0x801ae20 <TriceNonBlockingDirectWrite+176>
	add r1, r6                      
	cbz r5, 0x801ae36 <TriceNonBlockingDirectWrite+198>
	add r6, r4                      
	ldr.w r2, [r4], #4              
	adds r0, #4                     
	cmp r4, r6                      
	str.w r2, [r0, #-4]             
	bne.n 0x801ae28 <TriceNonBlockingDirectWrite+184>
	dmb sy                          
	b.n 0x801ae02 <TriceNonBlockingDirectWrite+146>
	asrs r0, r1, #4                 
	movs r0, #9                     
	asrs r4, r0, #4                 
	movs r0, #9                     
	subs r4, r3, r3                 
	movs r0, #0              

To Reproduce
triceCongig.h

extern uint32_t ms32;
#include "stm32u5xx_ll_system.h"

//! TriceStamp16 returns a 16-bit value to stamp `Id` TRICE macros. Usually it is a timestamp, but could also be a destination address or a counter for example.
//! The user has to provide this function. Defining a macro here, instead if providing `int16_t TriceStamp16( void );` has significant speed impact.
#define TriceStamp16 (SysTick->VAL) // Counts from 31999 -> 0 in each ms.

//! TriceStamp32 returns a 32-bit value to stamp `ID` TRICE macros. Usually it is a timestamp, but could also be a destination address or a counter for example.
//! The user has to provide this function. Defining a macro here, instead if providing `int32_t TriceStamp32( void );` has significant speed impact.
#define TriceStamp32 ms32           // 1ms, wraps after 2^32 ms ~= 49,7 days

//!  TRICE_BUFFER selects, where the TRICE macros accumulate the trice data during a single TRICE execution. Selectable options:
//! - TRICE_STACK_BUFFER: No additional buffer is needed, what makes sense for single task systems with direct output only.
//! - TRICE_STATIC_BUFFER: A single trice is stored in a separate static buffer, what makes sense in single- and multi-tasking systems with direct output only.
//! - TRICE_DOUBLE_BUFFER: TRICE macros write direct into a double buffer without any additional management action.
//!   This is the fastest execution option for TRICE macros but needs more RAM. Used for deferred output and optional additional direct output.
//! - TRICE_RING_BUFFER: TRICE macros write direct into a ring buffer without any additional management action.
//!   This is not the fastest execution option for TRICE macros but needs less RAM. Used for deferred output and optional additional direct output.
//! If unsure select TRICE_DOUBLE_BUFFER. The TRICE_RING_BUFFER option works, but is experimental.
#define TRICE_BUFFER TRICE_STATIC_BUFFER

//! TRICE_DIRECT_OUTPUT == 0: only deferred output, usually UART output only
//! TRICE_DIRECT_OUTPUT == 1: with direct output, usually RTT
//! Setting TRICE_BUFFER to TRICE_STACK_BUFFER or TRICE_STATIC_BUFFER demands TRICE_DIRECT_OUTPUT == 1, no deferred output at all.
//! When TRICE_BUFFER == TRICE_RING_BUFFER or TRICE_BUFFER == TRICE_DOUBLE_BUFFER for deferred output, additional direct output can be switched on here.
//! For example it is possible to have direct 32-bit wise RTT TRICE_FRAMING_NONE output and deferred UART TRICE_FRAMING_COBS output.
//! TRICE_BUFFER == TRICE_STACK_BUFFER or TRICE_BUFFER == TRICE_STATIC_BUFFER needs TRICE_DIRECT_OUTPUT == 1.
#define TRICE_DIRECT_OUTPUT 1

//! TRICE_DATA_OFFSET is the space in front of single trice data for in-buffer (T)COBS encoding.
//! - When using real big buffers, 16 may be not enough.
//! - When having only short trices but lots of trice bursts, it may make sense to reduce this value to 4.
//! - Without encoding/framing this value can be 0.
#define TRICE_DATA_OFFSET 16 // must be a multiple of 4 (default: 64)

//! TRICE_SINGLE_MAX_SIZE is used to truncate long dynamically generated strings and to detect the need of a ring buffer wrap.
//! - Be careful with this value: When using 12 64-bit values with a 32-bit stamp the trice size is 2(id) + 4(stamp) + 2(count) + 12*8(values) = 104 bytes.
//! - In direct mode, and also when you enabled TRICE_SEGGER_RTT_8BIT_DEFERRED_WRITE, this plus TRICE_DATA_OFFSET is the max allocation size on the target stack with TRICE_BUFFER == TRICE_STACK_BUFFER.
//! - When short of RAM and, for example, max 2 32-bit values with a 32-bit stamp are used, the max trice size is 2 + 4 + 2 + 2*4 = 16 bytes.
//! - You should then also disable all then forbidden trices to avoid mistakes. Example: `#define ENABLE_TRice32fn_3 0` and so on at the end of this file.
#define TRICE_SINGLE_MAX_SIZE (1*512) // must be a multiple of 4

//! TRICE_DIRECT_OUT_FRAMING defines the framing method of the binary trice data stream for direct output. Options:
//! - TRICE_FRAMING_TCOBS: Recommended for internal transfer and trice tool visualization.
//! - TRICE_FRAMING_COBS: The trice tool needs switch `-pf COBS`. Useful with XTEA or to decode the binary trice data with a user tool.
//! - TRICE_FRAMING_NONE: The trice tool needs switch `-pf none`. TRICE_FRAMING_NONE is needed for fast RTT (32-bit access), recommended.
//! - With TRICE_SEGGER_RTT_32BIT_DIRECT_WRITE == 1 or TRICE_SEGGER_RTT_8BIT_WRITE_DIRECT_WITHOUT_FRAMING == 1,
//!   the RTT data arrive unframed ignoring the TRICE_DIRECT_OUT_FRAMING setting here.
//#define TRICE_DIRECT_OUT_FRAMING TRICE_FRAMING_NONE

//! TRICE_DEFERRED_OUT_FRAMING defines the framing method of the binary trice data stream for deferred output. Options:
//! - TRICE_FRAMING_TCOBS: Recommended for UART transfer and trice tool visualization.
//! - TRICE_FRAMING_COBS: The trice tool needs switch `-pf COBS`. Useful with XTEA or to decode the binary trice date with Python or an other language.
//! - TRICE_FRAMING_NONE: The trice tool needs switch `-pf none`. This mode may be helpful if you write your own trice viewer without a decoder.
//#define TRICE_DEFERRED_OUT_FRAMING TRICE_FRAMING_NONE

//! With TRICE_DIAGNOSTICS == 0, additional trice diagnostics code is removed.
//! During developmemt TRICE_DIAGNOSTICS == 1 helps to optimize the trice buffer sizes.
//#define TRICE_DIAGNOSTICS 1

//! TRICE_SEGGER_RTT_32BIT_DIRECT_WRITE == 1 speeds up RTT transfer by using function SEGGER_Write_RTT0_NoCheck32 and needs ((TRICE_DIRECT_OUTPUT == 1).
//! - This setting results in unframed RTT trice packages and requires the `-packageFraming none` switch for the appropriate trice tool instance.
//!   This squeezes the whole TRICE macro into about 100 processor clocks leaving the data already inside the SEGGER _acUpBuffer.
//! - If you do not wish RTT, or wish RTT with framing, simply set this value to 0.
#define TRICE_DIRECT_SEGGER_RTT_32BIT_WRITE 1

//! USE_SEGGER_RTT_LOCK_UNLOCK_MACROS == 1 includes SEGGER_RTT header files even SEGGER_RTT is not used.
//#define USE_SEGGER_RTT_LOCK_UNLOCK_MACROS 1

//! TRICE_ENTER_CRITICAL_SECTION saves interrupt state and disables Interrupts.
//! If trices are used only outside critical sections or interrupts,
//! you can leave this macro empty for more speed. Use only '{' in that case.
//!#define TRICE_ENTER_CRITICAL_SECTION { SEGGER_RTT_LOCK() { //- does the job for many compilers.
//! #define TRICE_ENTER_CRITICAL_SECTION {
//! #define TRICE_ENTER_CRITICAL_SECTION { uint32_t old_mask = cm_mask_interrupts(1); { // copied from test/OpenCM3_STM32F411_Nucleo/triceConfig.h
//! #define TRICE_ENTER_CRITICAL_SECTION { uint32_t primaskstate = __get_PRIMASK(); __disable_irq(); {
#include "cmsis_gcc.h"
#define TRICE_ENTER_CRITICAL_SECTION { uint32_t primaskstate = __get_PRIMASK(); __disable_irq(); {

//! TRICE_LEAVE_CRITICAL_SECTION restores interrupt state.
//! If trices are used only outside critical sections or interrupts,
//! you can leave this macro empty for more speed. Use only '}' in that case.
//!#define TRICE_LEAVE_CRITICAL_SECTION } SEGGER_RTT_UNLOCK() } //- does the job for many compilers.
//! #define TRICE_LEAVE_CRITICAL_SECTION }
//! #define TRICE_LEAVE_CRITICAL_SECTION } cm_mask_interrupts(old_mask); } // copied from test/OpenCM3_STM32F411_Nucleo/triceConfig.h
//! #define TRICE_LEAVE_CRITICAL_SECTION } __set_PRIMASK(primaskstate); }
#define TRICE_LEAVE_CRITICAL_SECTION } __set_PRIMASK(primaskstate); }

//#define TRICE_8_BIT_SUPPORT  1
//#define TRICE_16_BIT_SUPPORT 1
//#define TRICE_32_BIT_SUPPORT 1
//#define TRICE_64_BIT_SUPPORT 1

///////////////////////////////////////////////////////////////////////////////

Expected behavior
The application should never get blocked by the trice logging output.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: ubuntu
  • compiler: arm-none-eabi-gcc
  • Version 12

Additional context
I already tried with and without the TRICE_ENTER_CRITICAL_SECTION locks, but no change of behaviour.

@initdb
Copy link
Author

initdb commented Jan 30, 2025

same config with 0.72.5 works fine.

@rokath
Copy link
Owner

rokath commented Jan 31, 2025

Am I understand you right, that the problem is inside the target code? So the problem persists, no matter you use the the trice_v0.72.5 tool or the trice_v0.73.1 tool?

I downloaded trice_linux_amd64.tar.gz v0.72.5 and v0.73.1 and compared the folders, but I could not detect any critical changes.

Due to a context timeout the v0.73.1 release occurred 3 times in GitHub and in-between I deleted the 2 additional drafts. But I assume they where identical. Maybe you compare v0.72.5 and v0.73.1 by your own too. 4 eyes are better than 2.

Could it be that you have a buffer size issue and you simply have "luck" with v0.72.5? Just for investigation you could change #define TRICE_DATA_OFFSET to 64 and #define TRICE_SINGLE_MAX_SIZE to 104 or even smaller values. A typical trice message is 4 to 16 bytes long only. The Trice static buffer needs to hold only one singe Trice message.

I would use SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() for the critical sections if you use SEGGER RTT anyway. For the investigation, do not use Trice macros inside interrupts or parallel running tasks.

One more thing: Now a newer SEGGER version is used by default. Please set #define TRICE_DIRECT_SEGGER_RTT_8BIT_WRITE 1 just for investigation. This uses the slower original SEGGER code and we can assume not to have any issue in it. With #define TRICE_DIRECT_SEGGER_RTT_32BIT_WRITE 1 a self-written 32-bit code gets active and it relies on an unchanged SEGGER code. Even I could not see any critical changes in the SEGGER update, it is better for investigation to change that back.

@initdb
Copy link
Author

initdb commented Jan 31, 2025

Am I understand you right, that the problem is inside the target code? So the problem persists, no matter you use the the
trice_v0.72.5 tool or the trice_v0.73.1 tool?

yes the tool version doesn't matter, only the difference in the target code.

I will check the other points and report as soon as i get them.

and for clarification the target is stuck in a while loop.

@rokath
Copy link
Owner

rokath commented Jan 31, 2025

Could it be, that you do not execute TriceInit() before the very first Trice macro?

//! TriceInit needs to run before the first trice macro is executed.
//! Not neseecary for all configurations.
void TriceInit(void) {
#if defined(SEGGER_RTT) && (TRICE_CGO == 0)
	// This is just to force the INIT() call inside SEGGER_RTT.c what allows to use
	// SEGGER_RTT_WriteNoLock or SEGGER_Write_RTT0_NoCheck32 instead of SEGGER_RTT_Write.
	SEGGER_RTT_Write(0, 0, 0); // lint !e534
#endif

@initdb
Copy link
Author

initdb commented Jan 31, 2025

the TriceInit(); in call is the the one before the first log message TRice(iD(7489), "INFO: APP_THREADX - init...!\n");. the log gets throw to the trice cli an printed but after this the target code is stuck in a while loop (disassemlby b.n 0x801ae20 <TriceNonBlockingDirectWrite+176>). I tried to show this with my code snipped and the debugging arrow (===>).
the system remains in a while loop (repeated branch (b) instruction) until the watchdog resets the system and the initial trice message is repeated and so on.

I would use SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() for the critical sections if you use SEGGER RTT anyway. For the
investigation, do not use Trice macros inside interrupts or parallel running tasks.

i already tried SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK(), the gcc way and now lock e.g just the { and }.

I have to check:

  • load symbols to see the c code line
  • buffer size as suggested
  • #define TRICE_DIRECT_SEGGER_RTT_8BIT_WRITE 1

@rokath
Copy link
Owner

rokath commented Jan 31, 2025

You could temporarily disable the watchdog for debugging, to find out what condition causes the endless loop.

You could #define TRICE_PROTECT 0 just for checking.

@rokath
Copy link
Owner

rokath commented Feb 11, 2025

Any results?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants