Skip to content

Switch from UART Deferred to RTT Direct #446

@initdb

Description

@initdb

Describe the bug
I migrated our trice logging from uart deferred write to rtt direct write. the trice tool cant parse some messages and discards them.

To Reproduce
Steps to reproduce the behavior:

  1. triceConfig:
//! 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() timedate_get16bittime()

//! 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() timedate_get32bittime()

//!  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 0 // must be a multiple of 4

//! 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_DEFERRED_BUFFER_SIZE needs to be capable to hold trice bursts until they are transmitted.
//! When TRICE_BUFFER == TRICE_STACK_BUFFER this value is not used.
//! When TRICE_BUFFER == TRICE_STATIC_BUFFER this value is not used.
//! When TRICE_BUFFER == TRICE_DOUBLE_BUFFER, this is the sum of both half buffers.
//! When TRICE_BUFFER == TRICE_RING_BUFFER, this is the whole buffer.
#define TRICE_DEFERRED_BUFFER_SIZE (2*(512+32)) // must be a multiple of 4

//! TRICE_MCU_IS_BIG_ENDIAN needs to be defined for TRICE64 macros on big endian MCUs for correct 64-bit values and 32-bit timestamp encoding-
//#define TRICE_MCU_IS_BIG_ENDIAN

//! 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

//! XTEA_ENCRYPT_KEY, when defined, enables XTEA TriceEncryption with the key.
//! To get your private XTEA_KEY, call just once "trice log -port ... -password YourSecret -showKey".
//! The byte sequence you see then, copy and paste it here.
//#define XTEA_ENCRYPT_KEY XTEA_KEY( ea, bb, ec, 6f, 31, 80, 4e, b9, 68, e2, fa, ea, ae, f1, 50, 54 ); //!< -password MySecret

//! XTEA_DECRYPT, when defined, enables device local decryption. Usable for checks or if you use a trice capable node to read XTEA encrypted messages.
//#define XTEA_DECRYPT

//! 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_SEGGER_RTT_32BIT_DIRECT_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(); {
//#define TRICE_ENTER_CRITICAL_SECTION {

//! 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 }

(...)
  1. trice tool call:
    trice l -p JLINK -args "-Device XXXXXXXXX -if SWD -Speed 4000 -RTTChannel 0" -pf none -logfile .\logfiles\auto
  2. the result shows some working output:
Feb 12 18:39:03.585784  JLINK:         app_threadx.c   132    0,000_000 ==================================================
Feb 12 18:39:03.585784  JLINK:         app_threadx.c   133       37_483 CYCLE: 0 not equal expected value 209 - adjusting. Now 1 CycleEvents
Feb 12 18:39:03.585784  JLINK: hardware revision:
Feb 12 18:39:03.585784  JLINK:                           0              CYCLE: 50 not equal expected value 1 - adjusting. Now 2 CycleEvents
Feb 12 18:39:03.585784  JLINK:                           0       41_368 CYCLE: 152 not equal expected value 51 - adjusting. Now 3 CycleEvents
Feb 12 18:39:03.585784  JLINK:         app_threadx.c   134       39_073 CYCLE: 0 not equal expected value 153 - adjusting. Now 4 CycleEvents

or

Feb 12 18:39:03.590431  JLINK: s.triceType = TRICE32_4 ParamSpace = 0 not matching with bitWidth  32 and paramCount 4 - ignoring package [48 16 8 0 0 0 8 0 0 0 8 0 0 0 8 0 0 0 50 149 50 149 0 0 49 0 180 197 0 0 0 0 50 5 68 69 66 85 71 0 0 0 255
 203 0 0 0 0 51 9 68 78 83 95 83 84 65 67 75 0 0 0 39 214 0 0 0 0 52 13 115 97 118 101 95 100 101 102 97 117 108 116 115 0 0 0 165 220 0 0 0 0 53 4 100 110 115 49 112 157 112 157 0 0 54 0 174 157 174 157 0 0 55 16 8 0 0 0 8 0 0 0 4 0 0 0 4 0 0 
0 50 149 50 149 0 0 56 0 180 197 0 0 0 0 57 5 68 69 66 85 71 0 0 0 255 203 0 0 0 0 58 9 68 78 83 95 83 84 65 67 75 0 0 0 39 214 0 0 0 0 59 13 115 97 118 101 95 100 101 102 97 117 108 116 115 0 0 0 165 220 0 0 0 0 60 4 100 110 115 50 112 157 112
 157 0 0 61 0 174 157 174 157 0 0 62 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 149 50 149 0 0 63 0 180 197 0 0 0 0 64 5 68 69 66 85 71 0 0 0 255 203 0 0 0 0 65 9 68 78 83 95 83 84 65 67 75 0 0 0 39 214 0 0 0 0 66 13 115 97 118 101 95 100 101 102 97 117 108 116 115 0 0 0 165 220 0 0 0 0 67 4 100 110 115 51 112 157 112 157 0 0 68 0 174 157 174 157 0 0 69 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 50 149 50 149 0 0 70 0]                                                                               
Feb 12 18:39:03.590431  JLINK: Hints:Baudrate? Encoding? Interrupt? Overflow? Parameter count? Format specifier? Password? til.json? Version?
  1. See error

Expected behavior
this is the output i receive over uart (just the logfile):

Nov 29 15:07:10.478738  COM4: �[0;1;36;109m        app_threadx.c   129 �[0m�[0;7;34;104m   0,000_000�[0m �[0m==================================================�[0m
Nov 29 15:07:10.479287  COM4: �[0;1;36;109m        app_threadx.c   130 �[0m�[0;7;34;104m       0_000�[0m �[0mhardware revision:	B2�[0m

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

Desktop (please complete the following information):

  • OS: win 11 pro
  • JLink SW + RTT sources version 7.88c
  • trice version v62.1, v62.3 and master branch show the same result

Additional context
I tried different revisions and settings. i suspected a race condition but the locking functions are present and working. the problem appeard with TRice32 and TRICE_S macros. the calls with no param seem to work more likely. also some with param work...at the moment any idea would be welcome.

Kind regards

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions