Skip to content

Commit 5c21108

Browse files
committed
Zero-init RTT control block fields if not in BSS, don't init it twice
If SEGGER_RTT_SECTION is defined, the RTT control block is not in BSS and zero-initialization is needed for not initialized fields. Moreover, it the control block is already initialized with the expected SEGGER ID signature, the initialization is skipped to allow seamless logging between programs that share it. Typical use case: bootloader and application. Signed-off-by: Giancarlo Stasi <[email protected]>
1 parent e2ff220 commit 5c21108

File tree

2 files changed

+87
-32
lines changed

2 files changed

+87
-32
lines changed

Config/SEGGER_RTT_Conf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ Revision: $Rev: 21386 $
9898
#define SEGGER_RTT_SECTION ".dtcm_data"
9999
#endif
100100

101+
#if defined(CONFIG_SEGGER_RTT_SECTION_FIXED_ADDR)
102+
#define SEGGER_RTT_SECTION ".rtt_buff_data"
103+
#endif
104+
101105
/*********************************************************************
102106
*
103107
* RTT memcpy configuration

SEGGER/SEGGER_RTT.c

Lines changed: 83 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,26 @@ Additional information:
167167
#endif
168168
#endif
169169

170+
#ifndef SEGGER_RTT_MEMCMP
171+
#ifdef MEMCPY
172+
#define SEGGER_RTT_MEMCMP(pDest, pSrc, NumBytes) MEMCMP((pDest), (pSrc), (NumBytes))
173+
#else
174+
#define SEGGER_RTT_MEMCMP(pDest, pSrc, NumBytes) memcmp((pDest), (pSrc), (NumBytes))
175+
#endif
176+
#endif
177+
178+
#ifndef SEGGER_RTT_MEMSET
179+
#ifdef MEMSET
180+
#define SEGGER_RTT_MEMSET(pDest, FillChar, NumBytes) MEMSET((pDest), (FillChar), (NumBytes))
181+
#else
182+
#define SEGGER_RTT_MEMSET(pDest, FillChar, NumBytes) memset((pDest), (FillChar), (NumBytes))
183+
#endif
184+
#endif
185+
186+
#ifndef ARRAY_SIZE
187+
# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
188+
#endif
189+
170190
#ifndef MIN
171191
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
172192
#endif
@@ -254,7 +274,12 @@ Additional information:
254274
**********************************************************************
255275
*/
256276

257-
static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
277+
static const unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
278+
279+
static const char _rttCtrBlkSign2[] = "RTT";
280+
static const char _rttCtrBlkSign1[] = "SEGGER";
281+
#define SIZEOF_RTT_CTRL_BLK_SIGN2 (ARRAY_SIZE(_rttCtrBlkSign2) - 1)
282+
#define SIZEOF_RTT_CTRL_BLK_SIGN1 (ARRAY_SIZE(_rttCtrBlkSign1) - 1)
258283

259284
/*********************************************************************
260285
*
@@ -285,19 +310,9 @@ static unsigned char _ActiveTerminal;
285310
*
286311
* Function description
287312
* Initializes the control block an buffers.
288-
* May only be called via INIT() to avoid overriding settings.
313+
* May only be called via Init() to avoid overriding settings.
289314
*
290315
*/
291-
#define INIT() { \
292-
volatile SEGGER_RTT_CB* pRTTCBInit; \
293-
pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \
294-
do { \
295-
if (pRTTCBInit->acID[0] == '\0') { \
296-
_DoInit(); \
297-
} \
298-
} while (0); \
299-
}
300-
301316
static void _DoInit(void) {
302317
volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block
303318
//
@@ -329,12 +344,48 @@ static void _DoInit(void) {
329344
// Copy Id string in three steps to make sure "SEGGER RTT" is not found
330345
// in initializer memory (usually flash) by J-Link
331346
//
332-
STRCPY((char*)&p->acID[7], "RTT");
347+
STRCPY((char*)&p->acID[SIZEOF_RTT_CTRL_BLK_SIGN1 + 1], _rttCtrBlkSign2);
333348
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
334-
STRCPY((char*)&p->acID[0], "SEGGER");
349+
STRCPY((char*)&p->acID[0], _rttCtrBlkSign1);
335350
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
336351
p->acID[6] = ' ';
337352
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
353+
#if defined(SEGGER_RTT_SECTION) // Control block not in .bss section: needs explicit zero-initializations
354+
// RTT Viewer checks even trailing null bytes to be initialized
355+
for (unsigned int i = SIZEOF_RTT_CTRL_BLK_SIGN1 + 1 + SIZEOF_RTT_CTRL_BLK_SIGN2; i < ARRAY_SIZE(p->acID); ++i)
356+
{
357+
p->acID[i] = '\0';
358+
}
359+
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
360+
// Initialize other up buffers
361+
for (unsigned int i = 1; i < ARRAY_SIZE(p->aUp); ++i)
362+
{
363+
SEGGER_RTT_MEMSET((SEGGER_RTT_BUFFER_UP*)&p->aUp[i], 0, sizeof(p->aUp[i]));
364+
}
365+
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
366+
// Initialize other down buffers
367+
for (unsigned int i = 1; i < ARRAY_SIZE(p->aDown); ++i)
368+
{
369+
SEGGER_RTT_MEMSET((SEGGER_RTT_BUFFER_DOWN*)&p->aDown[i], 0, sizeof(p->aDown[i]));
370+
}
371+
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
372+
#endif
373+
}
374+
375+
static void Init(void) {
376+
volatile SEGGER_RTT_CB* p;
377+
p = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF);
378+
379+
/* Check the whole Id string buffer (including trailing zeros) to be the expected value.
380+
* If already initialized, the control block initialization is skipped, as it may be shared between bootloader
381+
* and application. Not used a single memcmp() to make sure "SEGGER RTT" is not found in initializer
382+
* memory (usually flash) by J-Link (as above in initializing). */
383+
if (SEGGER_RTT_MEMCMP((char*)&p->acID[0], _rttCtrBlkSign1, SIZEOF_RTT_CTRL_BLK_SIGN1) != 0 ||
384+
SEGGER_RTT_MEMCMP((char*)&p->acID[SIZEOF_RTT_CTRL_BLK_SIGN1 + 1], _rttCtrBlkSign2, SIZEOF_RTT_CTRL_BLK_SIGN2) != 0 ||
385+
p->acID[6] != ' ' || p->acID[10] != '\0' || p->acID[11] != '\0' || p->acID[12] != '\0' ||
386+
p->acID[13] != '\0' || p->acID[14] != '\0' || p->acID[15] != '\0') {
387+
_DoInit();
388+
}
338389
}
339390

340391
/*********************************************************************
@@ -564,7 +615,7 @@ unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsign
564615
SEGGER_RTT_BUFFER_UP* pRing;
565616
volatile char* pSrc;
566617

567-
INIT();
618+
Init();
568619
pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
569620
pBuffer = (unsigned char*)pData;
570621
RdOff = pRing->RdOff;
@@ -656,7 +707,7 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe
656707
SEGGER_RTT_BUFFER_DOWN* pRing;
657708
volatile char* pSrc;
658709
//
659-
INIT();
710+
Init();
660711
pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
661712
pBuffer = (unsigned char*)pData;
662713
RdOff = pRing->RdOff;
@@ -1160,7 +1211,7 @@ unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsig
11601211
unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
11611212
unsigned Status;
11621213

1163-
INIT();
1214+
Init();
11641215
SEGGER_RTT_LOCK();
11651216
Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function
11661217
SEGGER_RTT_UNLOCK();
@@ -1189,7 +1240,7 @@ unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, u
11891240
unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
11901241
unsigned Status;
11911242

1192-
INIT();
1243+
Init();
11931244
SEGGER_RTT_LOCK();
11941245
Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function
11951246
SEGGER_RTT_UNLOCK();
@@ -1304,7 +1355,7 @@ unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) {
13041355
//
13051356
// Prepare
13061357
//
1307-
INIT();
1358+
Init();
13081359
SEGGER_RTT_LOCK();
13091360
//
13101361
// Get "to-host" ring buffer.
@@ -1363,7 +1414,7 @@ unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) {
13631414
//
13641415
// Prepare
13651416
//
1366-
INIT();
1417+
Init();
13671418
SEGGER_RTT_LOCK();
13681419
//
13691420
// Get "to-host" ring buffer.
@@ -1474,7 +1525,7 @@ int SEGGER_RTT_HasKey(void) {
14741525
unsigned RdOff;
14751526
int r;
14761527

1477-
INIT();
1528+
Init();
14781529
pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
14791530
RdOff = pRing->RdOff;
14801531
if (RdOff != pRing->WrOff) {
@@ -1550,7 +1601,7 @@ int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned Buffer
15501601
int BufferIndex;
15511602
volatile SEGGER_RTT_CB* pRTTCB;
15521603

1553-
INIT();
1604+
Init();
15541605
SEGGER_RTT_LOCK();
15551606
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
15561607
BufferIndex = 0;
@@ -1598,7 +1649,7 @@ int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSi
15981649
int BufferIndex;
15991650
volatile SEGGER_RTT_CB* pRTTCB;
16001651

1601-
INIT();
1652+
Init();
16021653
SEGGER_RTT_LOCK();
16031654
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
16041655
BufferIndex = 0;
@@ -1653,7 +1704,7 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
16531704
volatile SEGGER_RTT_CB* pRTTCB;
16541705
volatile SEGGER_RTT_BUFFER_UP* pUp;
16551706

1656-
INIT();
1707+
Init();
16571708
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
16581709
if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
16591710
SEGGER_RTT_LOCK();
@@ -1704,7 +1755,7 @@ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* p
17041755
volatile SEGGER_RTT_CB* pRTTCB;
17051756
volatile SEGGER_RTT_BUFFER_DOWN* pDown;
17061757

1707-
INIT();
1758+
Init();
17081759
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
17091760
if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
17101761
SEGGER_RTT_LOCK();
@@ -1747,7 +1798,7 @@ int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) {
17471798
volatile SEGGER_RTT_CB* pRTTCB;
17481799
volatile SEGGER_RTT_BUFFER_UP* pUp;
17491800

1750-
INIT();
1801+
Init();
17511802
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
17521803
if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
17531804
SEGGER_RTT_LOCK();
@@ -1782,7 +1833,7 @@ int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
17821833
volatile SEGGER_RTT_CB* pRTTCB;
17831834
volatile SEGGER_RTT_BUFFER_DOWN* pDown;
17841835

1785-
INIT();
1836+
Init();
17861837
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
17871838
if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
17881839
SEGGER_RTT_LOCK();
@@ -1817,7 +1868,7 @@ int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
18171868
volatile SEGGER_RTT_CB* pRTTCB;
18181869
volatile SEGGER_RTT_BUFFER_UP* pUp;
18191870

1820-
INIT();
1871+
Init();
18211872
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
18221873
if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) {
18231874
SEGGER_RTT_LOCK();
@@ -1852,7 +1903,7 @@ int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
18521903
volatile SEGGER_RTT_CB* pRTTCB;
18531904
volatile SEGGER_RTT_BUFFER_DOWN* pDown;
18541905

1855-
INIT();
1906+
Init();
18561907
pRTTCB = (volatile SEGGER_RTT_CB*)((unsigned char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access RTTCB uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
18571908
if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) {
18581909
SEGGER_RTT_LOCK();
@@ -1876,7 +1927,7 @@ int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
18761927
*
18771928
*/
18781929
void SEGGER_RTT_Init (void) {
1879-
_DoInit();
1930+
Init();
18801931
}
18811932

18821933
/*********************************************************************
@@ -1902,7 +1953,7 @@ int SEGGER_RTT_SetTerminal (unsigned char TerminalId) {
19021953
unsigned Avail;
19031954
int r;
19041955

1905-
INIT();
1956+
Init();
19061957
r = 0;
19071958
ac[0] = 0xFFu;
19081959
if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels
@@ -1951,7 +2002,7 @@ int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) {
19512002
unsigned Avail;
19522003
SEGGER_RTT_BUFFER_UP* pRing;
19532004
//
1954-
INIT();
2005+
Init();
19552006
//
19562007
// Validate terminal ID.
19572008
//

0 commit comments

Comments
 (0)