trice icon indicating copy to clipboard operation
trice copied to clipboard

Feature: function calls instead of inline

Open KammutierSpule opened this issue 3 weeks ago • 3 comments

On fast MCUs a function call is not a concern and this will save code program size.

Would be possible to have a function for Trice calls instead of inline? Or is there something that could already work like this? (I couldn't find in the code)

KammutierSpule avatar Dec 09 '25 13:12 KammutierSpule

De-facto for example trice( "hi" ); is a function call and TRICE( "hi" ); a code insertion. It is not obvious to see but you can follow up like in this example:

Find definition of trice( brings you to line 33 in triceOn.h:

#define trice(  tid, fmt, ...) TRICE_CONCAT2(trice_,   TRICE_COUNT_ARGUMENTS(__VA_ARGS__))(tid, fmt, ##__VA_ARGS__)

This ends up in trice_2 when you have 2 arguments, what ends up in trice32_2, when TRICE_DEFAULT_PARAMETER_BIT_WIDTH == 32. In file triceOn.h line 354 we see #define trice32_2(tid, fmt, v0, v1) trice32fn_2(tid, (uint32_t)(v0), (uint32_t)(v1)) and that finally is a defined function in trice32.c line 339:

void trice32fn_2(uint16_t tid, uint32_t v0, uint32_t v1) {
	trice32m_2(tid, v0, v1);
}

trice32m_2 is a macro adding the trice code into the function body, so each trice( "hi" ) is a function call. When you follow the code of TRICE in a similar way you will see the macro invocation directly and not a function call. That is a very bit faster but includes the Trice code on each TRICE invocation, where using trice just calls the appropriate function.

Historically there where only TRICE macros (for max speed), but then I realized too much memory usage, when you have many times TRICE in the code and added trice macros, which are in fact macros, but are finally function calls.

You should be able to write trice32fn_2( id(123(, "hi %d %d", 1, 2 ); and get exactly the same code as with trice( id(123(, "hi %d %d", 1, 2 );. But the trice parser will ignore such code during ID management, I guess.

rokath avatar Dec 09 '25 20:12 rokath

Thanks for the explanation, I found I was just looking into Trice0, those are inline

#define trice( tid, fmt, ...) TRICE_CONCAT2(trice_, TRICE_COUNT_ARGUMENTS(__VA_ARGS__))(tid, fmt, ##__VA_ARGS__)

if TRICE_COUNT_ARGUMENTS is 0, then we have trice_0

but then:

#define trice_0 trice0 //!< Only the format string without parameter values.

and trice_0 is inline:

//! TRICE0 writes trice data as fast as possible in a buffer.
//! \param tid is a 16 bit Trice id in upper 2 bytes of a 32 bit value
#define TRICE0(tid, pFmt) \
	TRICE_ENTER tid;      \
	TRICE_CNTC(0);        \
	TRICE_LEAVE

TRICE_INLINE void trice0(uint16_t tid, const char* pFmt) {
	trice32m_0(tid);
	TRICE_UNUSED(pFmt)
}

TRICE_INLINE void Trice0(uint16_t tid, const char* pFmt) {
	Trice32m_0(tid);
	TRICE_UNUSED(pFmt)
}

TRICE_INLINE void TRice0(uint16_t tid, const char* pFmt) {
	TRice32m_0(tid);
	TRICE_UNUSED(pFmt)
}

It looks this is the case (when there are no arguments) that will always result on inline functions? Should it be allowed to be called as a function too?

KammutierSpule avatar Dec 10 '25 10:12 KammutierSpule

Congratulation, that's a bug! Hopefully I can fix it this week.

rokath avatar Dec 10 '25 16:12 rokath

fixed in main branch

rokath avatar Dec 11 '25 09:12 rokath