Skip to content

Commit 76a9690

Browse files
committed
Segger RTT: update to latest version V786h
Main features: * Zero-init RTT control block before init in case it's not in BSS * Improved initialization and write functions Different use case for Zephyr applications in init function added. Fixes #53544. Signed-off-by: Giancarlo Stasi <[email protected]>
1 parent e2ff220 commit 76a9690

File tree

1 file changed

+76
-40
lines changed

1 file changed

+76
-40
lines changed

SEGGER/SEGGER_RTT.c

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
* The Embedded Experts *
44
**********************************************************************
55
* *
6-
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
6+
* (c) 1995 - 2019 SEGGER Microcontroller GmbH *
77
* *
88
* www.segger.com Support: [email protected] *
99
* *
1010
**********************************************************************
1111
* *
12-
* SEGGER SystemView * Real-time application analysis *
12+
* SEGGER RTT * Real Time Transfer for embedded targets *
1313
* *
1414
**********************************************************************
1515
* *
1616
* All rights reserved. *
1717
* *
1818
* SEGGER strongly recommends to not make any changes *
1919
* to or modify the source code of this software in order to stay *
20-
* compatible with the SystemView and RTT protocol, and J-Link. *
20+
* compatible with the RTT protocol and J-Link. *
2121
* *
2222
* Redistribution and use in source and binary forms, with or *
2323
* without modification, are permitted provided that the following *
@@ -41,16 +41,12 @@
4141
* DAMAGE. *
4242
* *
4343
**********************************************************************
44-
* *
45-
* SystemView version: 3.30 *
46-
* *
47-
**********************************************************************
4844
---------------------------END-OF-HEADER------------------------------
4945
File : SEGGER_RTT.c
5046
Purpose : Implementation of SEGGER real-time transfer (RTT) which
5147
allows real-time communication on targets which support
5248
debugger memory accesses while the CPU is running.
53-
Revision: $Rev: 22333 $
49+
Revision: $Rev: 29687 $
5450
5551
Additional information:
5652
Type "int" is assumed to be 32-bits in size
@@ -168,17 +164,17 @@ Additional information:
168164
#endif
169165

170166
#ifndef MIN
171-
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
167+
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
172168
#endif
173169

174170
#ifndef MAX
175-
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
171+
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
176172
#endif
177173
//
178174
// For some environments, NULL may not be defined until certain headers are included
179175
//
180176
#ifndef NULL
181-
#define NULL 0
177+
#define NULL 0
182178
#endif
183179

184180
/*********************************************************************
@@ -192,7 +188,7 @@ Additional information:
192188
#endif
193189

194190
#if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT
195-
#if (defined __GNUC__)
191+
#if ((defined __GNUC__) || (defined __clang__))
196192
#define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment)))
197193
#elif (defined __ICCARM__) || (defined __ICCRX__)
198194
#define PRAGMA(A) _Pragma(#A)
@@ -208,7 +204,7 @@ Additional information:
208204
#endif
209205

210206
#if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION)
211-
#if (defined __GNUC__)
207+
#if ((defined __GNUC__) || (defined __clang__))
212208
#define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var
213209
#elif (defined __ICCARM__) || (defined __ICCRX__)
214210
#define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \
@@ -254,7 +250,7 @@ Additional information:
254250
**********************************************************************
255251
*/
256252

257-
static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
253+
static const unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
258254

259255
/*********************************************************************
260256
*
@@ -266,9 +262,26 @@ static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7'
266262
//
267263
// RTT Control Block and allocate buffers for channel 0
268264
//
269-
SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
270-
SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)]));
271-
SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)]));
265+
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
266+
#if ((defined __GNUC__) || (defined __clang__))
267+
SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
268+
static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
269+
static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE)));
270+
#elif (defined __ICCARM__)
271+
#pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
272+
SEGGER_RTT_CB _SEGGER_RTT;
273+
#pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
274+
static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)];
275+
#pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE
276+
static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)];
277+
#else
278+
#error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned"
279+
#endif
280+
#else
281+
SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT));
282+
SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP]));
283+
SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));
284+
#endif
272285

273286
static unsigned char _ActiveTerminal;
274287

@@ -285,25 +298,29 @@ static unsigned char _ActiveTerminal;
285298
*
286299
* Function description
287300
* Initializes the control block an buffers.
288-
* May only be called via INIT() to avoid overriding settings.
289301
*
302+
* Notes
303+
* (1) May only be called via INIT() to avoid overriding settings.
304+
* The only exception is SEGGER_RTT_Init(), to make an intentional override possible.
290305
*/
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-
}
306+
#define INIT() \
307+
do { \
308+
volatile SEGGER_RTT_CB* pRTTCBInit; \
309+
pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \
310+
if (pRTTCBInit->acID[0] != 'S') { \
311+
_DoInit(); \
312+
} \
313+
} while (0)
300314

301315
static void _DoInit(void) {
302316
volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block
317+
static const char _aInitStr[] = "\0\0\0\0\0\0TTR REGGES"; // Init complete ID string to make sure that things also work if RTT is linked to a no-init memory area
318+
unsigned i;
303319
//
304320
// Initialize control block
305321
//
306322
p = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access control block uncached so that nothing in the cache ever becomes dirty and all changes are visible in HW directly
323+
memset((SEGGER_RTT_CB*)p, 0, sizeof(_SEGGER_RTT)); // Make sure that the RTT CB is always zero initialized.
307324
p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS;
308325
p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS;
309326
//
@@ -326,15 +343,14 @@ static void _DoInit(void) {
326343
p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT;
327344
//
328345
// Finish initialization of the control block.
329-
// Copy Id string in three steps to make sure "SEGGER RTT" is not found
330-
// in initializer memory (usually flash) by J-Link
331-
//
332-
STRCPY((char*)&p->acID[7], "RTT");
333-
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
334-
STRCPY((char*)&p->acID[0], "SEGGER");
335-
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
336-
p->acID[6] = ' ';
337-
RTT__DMB(); // Force order of memory accessed inside core for cores that allow to change the order
346+
// Copy Id string backwards to make sure that "SEGGER RTT" is not found in initializer memory (usually flash),
347+
// as this would cause J-Link to "find" the control block at a wrong address.
348+
//
349+
RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses
350+
for (i = 0; i < sizeof(_aInitStr) - 1; ++i) {
351+
p->acID[i] = _aInitStr[sizeof(_aInitStr) - 2 - i]; // Skip terminating \0 at the end of the array
352+
}
353+
RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses
338354
}
339355

340356
/*********************************************************************
@@ -938,11 +954,10 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
938954
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
939955
RdOff = pRing->RdOff;
940956
WrOff = pRing->WrOff;
957+
pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
941958
if (RdOff <= WrOff) { // Case 1), 2) or 3)
942959
Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
943960
if (Avail >= NumBytes) { // Case 1)?
944-
CopyStraight:
945-
pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
946961
memcpy((void*)pDst, pData, NumBytes);
947962
RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
948963
pRing->WrOff = WrOff + NumBytes;
@@ -951,7 +966,6 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
951966
Avail += RdOff; // Space incl. wrap-around
952967
if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit)
953968
Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer
954-
pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF;
955969
memcpy((void*)pDst, pData, Rem); // Copy 1st chunk
956970
NumBytes -= Rem;
957971
//
@@ -971,7 +985,10 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
971985
} else { // Potential case 4)
972986
Avail = RdOff - WrOff - 1u;
973987
if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit)
974-
goto CopyStraight;
988+
memcpy((void*)pDst, pData, NumBytes);
989+
RTT__DMB(); // Force data write to be complete before writing the <WrOff>, in case CPU is allowed to change the order of memory accesses
990+
pRing->WrOff = WrOff + NumBytes;
991+
return 1;
975992
}
976993
}
977994
return 0; // No space in buffer
@@ -1541,6 +1558,7 @@ unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) {
15411558
* pBuffer Pointer to a buffer to be used.
15421559
* BufferSize Size of the buffer.
15431560
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1561+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
15441562
*
15451563
* Return value
15461564
* >= 0 - O.K. Buffer Index
@@ -1589,6 +1607,7 @@ int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned Buffer
15891607
* pBuffer Pointer to a buffer to be used.
15901608
* BufferSize Size of the buffer.
15911609
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1610+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
15921611
*
15931612
* Return value
15941613
* >= 0 - O.K. Buffer Index
@@ -1638,6 +1657,7 @@ int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSi
16381657
* pBuffer Pointer to a buffer to be used.
16391658
* BufferSize Size of the buffer.
16401659
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1660+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
16411661
*
16421662
* Return value
16431663
* >= 0 - O.K.
@@ -1689,6 +1709,7 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
16891709
* pBuffer Pointer to a buffer to be used.
16901710
* BufferSize Size of the buffer.
16911711
* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message).
1712+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
16921713
*
16931714
* Return value
16941715
* >= 0 O.K.
@@ -1807,6 +1828,7 @@ int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
18071828
* Parameters
18081829
* BufferIndex Index of the buffer.
18091830
* Flags Flags to set for the buffer.
1831+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
18101832
*
18111833
* Return value
18121834
* >= 0 O.K.
@@ -1842,6 +1864,7 @@ int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) {
18421864
* Parameters
18431865
* BufferIndex Index of the buffer to renamed.
18441866
* Flags Flags to set for the buffer.
1867+
* Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
18451868
*
18461869
* Return value
18471870
* >= 0 O.K.
@@ -1876,7 +1899,20 @@ int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) {
18761899
*
18771900
*/
18781901
void SEGGER_RTT_Init (void) {
1902+
1903+
/*
1904+
* If used by bootloader or by stand-alone application, the standard
1905+
* Segger code using _DoInit() is used. For applications started by
1906+
* bootloader, Segger recommends not calling this function, as all the
1907+
* recommended APIs use INIT(). Unfortunately Zephyr log backend uses
1908+
* SEGGER_RTT_WriteSkipNoLock() that doesn't call INT(), so we need
1909+
* this modification for a safe API usage.
1910+
*/
1911+
#if defined(CONFIG_MCUBOOT) || ! defined(CONFIG_BOOTLOADER_MCUBOOT)
18791912
_DoInit();
1913+
#else
1914+
INIT();
1915+
#endif
18801916
}
18811917

18821918
/*********************************************************************

0 commit comments

Comments
 (0)