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 *
4141* DAMAGE. *
4242* *
4343**********************************************************************
44- * *
45- * SystemView version: 3.30 *
46- * *
47- **********************************************************************
4844---------------------------END-OF-HEADER------------------------------
4945File : SEGGER_RTT.c
5046Purpose : 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
5551Additional 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
273286static 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
301315static 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*/
18781901void 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