├── examples ├── HelloWorld │ └── HelloWorld.ino ├── Echo │ └── Echo.ino ├── FlagTest │ └── FlagTest.ino ├── SpeedTest │ └── SpeedTest.ino ├── StreamTest │ └── StreamTest.ino └── Color │ └── Color.ino ├── src ├── SEGGER_RTT_Peek.h ├── RTTStream.h ├── RTTStream.cpp ├── SEGGER_RTT_Peek.c ├── SEGGER_RTT_printf.c ├── SEGGER_RTT.h ├── SEGGER_RTT_Conf.h └── SEGGER_RTT.c ├── library.properties ├── LICENSE ├── README.md └── doc └── SEGGER_RTT.patch /examples/HelloWorld/HelloWorld.ino: -------------------------------------------------------------------------------- 1 | #include 2 | RTTStream rtt; 3 | void setup() 4 | { 5 | rtt.println("hello world!"); 6 | } 7 | void loop() 8 | { 9 | } 10 | -------------------------------------------------------------------------------- /src/SEGGER_RTT_Peek.h: -------------------------------------------------------------------------------- 1 | #ifndef SEGGER_RTT_PEEK_H 2 | #define SEGGER_RTT_PEEK_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | unsigned SEGGER_RTT_GetBytesInDownBuffer (unsigned BufferIndex); 8 | int SEGGER_RTT_PeekNoLock (unsigned BufferIndex); 9 | int SEGGER_RTT_Peek (unsigned BufferIndex); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /examples/Echo/Echo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Echo - RTT echo test 3 | * 4 | * This program requires a "Segger" brand debugger probe to run. 5 | */ 6 | 7 | #include 8 | RTTStream rtt; 9 | 10 | void setup() 11 | { 12 | rtt.println("rtt echo test"); 13 | rtt.println("type a character; the program will echo the next ascii character"); 14 | } 15 | 16 | void loop() 17 | { 18 | while (rtt.available()) 19 | rtt.write(rtt.read() + 1); 20 | } 21 | /* not truncated */ 22 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=RTT Stream 2 | version=1.4.1 3 | author=Koen De Vleeschauwer 4 | maintainer=Koen De Vleeschauwer 5 | sentence=Arduino library for Segger RTT Real-Time Transfer 6 | paragraph=With Segger Real-Time Transfer (RTT) an arduino arm system can do screen output on a pc, and get keyboard input from a pc. To use RTT you need a Segger JLink debugger probe. RTT only runs on systems with arm and risc-v processors, sorry. 7 | category=Communication 8 | url=https://github.com/koendv/Arduino-RTTStream 9 | architectures=*,stm32,gd32v,sam,samd,rp2040 10 | includes=RTTStream.h 11 | depends=ANSI 12 | -------------------------------------------------------------------------------- /examples/FlagTest/FlagTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * FlagTest - test RTT flags for data from host to target. 3 | * 4 | * Sample test: 5 | * - configure with rtt.blockDownBufferFull(); 6 | * - paste 1000 characters in window 7 | * - check counter increases by 1000 8 | * 9 | * This program requires a "Segger" brand debugger probe to run. 10 | */ 11 | 12 | #include 13 | 14 | RTTStream rtt; 15 | 16 | int count = 0; 17 | 18 | void setup() { 19 | // uncomment one of the following three lines: 20 | rtt.blockDownBufferFull(); 21 | //rtt.skipDownBufferFull(); 22 | //rtt.trimDownBufferFull(); 23 | 24 | rtt.println("start typing or paste text in this window"); 25 | } 26 | 27 | void loop() { 28 | if (rtt.available()) { 29 | while (rtt.available()) { 30 | rtt.write(rtt.read()); 31 | count++; 32 | } 33 | rtt.println(); 34 | rtt.print(count); 35 | rtt.print(" "); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/SpeedTest/SpeedTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * SpeedTest - RTT speed test 3 | * 4 | * This program requires a "Segger" brand debugger probe to run. 5 | */ 6 | 7 | #include 8 | #include 9 | RTTStream rtt; 10 | const int count = 5000; 11 | 12 | 13 | void setup() 14 | { 15 | rtt.println(); 16 | rtt.println("rtt speed test"); 17 | rtt.blockUpBufferFull(); 18 | 19 | unsigned long startTime = millis(); 20 | unsigned long currentTime = millis(); 21 | unsigned long overhead = currentTime - startTime; 22 | 23 | String str; 24 | for (char ch = 0; ch < 255; ch++) 25 | if (isPrintable(ch)) 26 | str += ch; 27 | 28 | startTime = millis(); 29 | for (int i = 0; i < count; i++) 30 | rtt.print(str); 31 | currentTime = millis(); 32 | unsigned long t = currentTime - startTime - overhead; 33 | long speed = count * str.length() * 1000 / t; 34 | rtt.println(); 35 | rtt.println("rtt speed test"); 36 | rtt.print("speed: "); 37 | rtt.print(speed); 38 | rtt.println(" chars/s"); 39 | } 40 | 41 | void loop() 42 | { 43 | } 44 | /* not truncated */ 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Koen De Vleeschauwer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/RTTStream.h: -------------------------------------------------------------------------------- 1 | #ifndef RTTSTREAM_H 2 | #define RTTSTREAM_H 3 | 4 | 5 | /* 6 | * Arduino stream wrapper for Segger RTT. 7 | * 2021 Koen De Vleeschauwer 8 | * No copyright asserted. 9 | */ 10 | 11 | #include 12 | 13 | class RTTStream : public Stream { 14 | public: 15 | RTTStream(); 16 | ~RTTStream(); 17 | 18 | /* mode */ 19 | void blockUpBufferFull(); /* block if buffer to host is full */ 20 | void skipUpBufferFull(); /* skip if buffer to host is full */ 21 | void trimUpBufferFull(); /* trim if buffer to host is full */ 22 | void blockDownBufferFull(); /* block if buffer from host is full */ 23 | void skipDownBufferFull(); /* skip if buffer from host is full */ 24 | void trimDownBufferFull(); /* trim if buffer from host is full */ 25 | 26 | /* echo */ 27 | void echo(); /* echo characters received from host */ 28 | void noEcho(); /* do not echo characters received from host, default */ 29 | 30 | /* reading */ 31 | virtual int available(); 32 | virtual int read(); 33 | virtual size_t readBytes(char *buffer, size_t length); 34 | virtual int peek(); 35 | 36 | /* writing */ 37 | virtual size_t write(uint8_t ch); 38 | virtual size_t write(const uint8_t *buffer, size_t size); 39 | virtual void flush(); 40 | using Print::write; 41 | int printf(const char *format, ...); 42 | 43 | /* compatibility with Serial */ 44 | void begin(unsigned long); 45 | operator bool(); 46 | 47 | private: 48 | bool echo_on = false; 49 | }; 50 | 51 | #endif 52 | /* not truncated */ -------------------------------------------------------------------------------- /examples/StreamTest/StreamTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * StreamTest - RTT stream test 3 | * 4 | * This program requires a "Segger" brand debugger probe to run. 5 | */ 6 | 7 | #include 8 | #include 9 | RTTStream rtt; 10 | 11 | void setup() { 12 | rtt.blockUpBufferFull(); 13 | rtt.setTimeout(300000); /* 5 minute timeout for entry */ 14 | rtt.echo(); /* echo each character received from the host back to the screen */ 15 | 16 | /* stream output */ 17 | rtt.println(); 18 | rtt.println("rtt stream test"); 19 | rtt.print("char: "); 20 | rtt.println('a'); 21 | rtt.print("string: "); 22 | rtt.println("the quick brown fox jumps over a lazy dog"); 23 | rtt.print("int: "); 24 | rtt.println(12345); 25 | rtt.print("float: "); 26 | rtt.println(3.1415926535); 27 | rtt.printf("printf char: %c signed int: %d unsigned int: %u\r\n", 'a', -12345, 12345); 28 | rtt.printf("printf hex int: %x string: %s pointer: %p\r\n", 0x12345, "12345", &rtt); 29 | 30 | /* stream input */ 31 | while (rtt.available()) rtt.read(); 32 | rtt.print("enter an int: "); 33 | int i = rtt.parseInt(); 34 | rtt.println(); 35 | rtt.print("value: "); 36 | rtt.println(i); 37 | while (rtt.available()) rtt.read(); 38 | rtt.print("enter a float: "); 39 | float f = rtt.parseFloat(); 40 | rtt.println(); 41 | rtt.print("value: "); 42 | rtt.println(f); 43 | while (rtt.available()) rtt.read(); 44 | rtt.print("enter a string and wait 5 seconds: "); 45 | rtt.setTimeout(5000); 46 | while (!rtt.available()) 47 | ; 48 | String s = rtt.readString(); 49 | rtt.println(); 50 | rtt.print("string: "); 51 | rtt.println(s); 52 | rtt.println("rtt stream test end"); 53 | } 54 | 55 | void loop() { 56 | } 57 | /* not truncated */ 58 | -------------------------------------------------------------------------------- /examples/Color/Color.ino: -------------------------------------------------------------------------------- 1 | /* ansi color test. 2 | * Needs ANSI library by Rob Tillaart 3 | * This program requires a "Segger" brand debugger probe to run. 4 | * Output goes to JLinkRTTClient. 5 | */ 6 | 7 | /* */ 8 | /* FILE: ansiDemo01.ino */ 9 | /* AUTHOR: Rob Tillaart */ 10 | /* VERSION: 0.1.0 */ 11 | /* PURPOSE: demo */ 12 | /* DATE: 2020-04-28 */ 13 | /* URL: https://github.com/RobTillaart/ANSI */ 14 | /* (c) : MIT */ 15 | /* */ 16 | 17 | #include "RTTStream.h" 18 | #include "ansi.h" 19 | 20 | RTTStream rtt; 21 | ANSI ansi(&rtt); 22 | 23 | void setup() 24 | { 25 | ansi.clearScreen(); 26 | ansi.bold(); 27 | ansi.println("Hello world"); 28 | ansi.blink(); 29 | ansi.println("Hello world"); 30 | ansi.underline(); 31 | ansi.println("Hello world"); 32 | ansi.low(); 33 | ansi.println("Hello world"); 34 | ansi.reverse(); 35 | ansi.println("Hello world"); 36 | ansi.normal(); 37 | ansi.println("Hello world"); 38 | delay(1000); 39 | 40 | ansi.clearScreen(); 41 | ansi.println("Hello world"); 42 | ansi.println("Hello world"); 43 | ansi.println("Hello world"); 44 | delay(1000); 45 | 46 | ansi.clearScreen(); 47 | for (int i = 1; i < 25; i++) { 48 | ansi.gotoXY(i, 2 * i); 49 | ansi.println("Hello world"); 50 | delay(100); 51 | } 52 | delay(1000); 53 | 54 | ansi.clearScreen(); 55 | /* 4 bit color test */ 56 | for (int color = 0; color < 16; ++color) { 57 | ansi.foreground(color); 58 | ansi.print("foreground"); 59 | ansi.normal(); 60 | ansi.background(color); 61 | ansi.println("background"); 62 | ansi.normal(); 63 | } 64 | 65 | delay(1000); 66 | 67 | ansi.clearScreen(); 68 | for (int color = 0; color < 16; ++color) { 69 | ansi.color(color, (color + 1) % 16); 70 | ansi.println("foreground and background"); 71 | ansi.normal(); 72 | } 73 | 74 | delay(1000); 75 | 76 | ansi.clearScreen(); 77 | /* 8 bit color test */ 78 | ansi.foreground(ansi.rgb2color(180, 0, 158)); 79 | ansi.print("foreground"); 80 | ansi.normal(); 81 | ansi.background(ansi.rgb2color(180, 0, 158)); 82 | ansi.println("background"); 83 | ansi.normal(); 84 | 85 | ansi.foreground(ansi.grey2color(64)); 86 | ansi.print("foreground"); 87 | ansi.normal(); 88 | ansi.background(ansi.grey2color(64)); 89 | ansi.println("background"); 90 | ansi.normal(); 91 | 92 | delay(1000); 93 | ansi.normal(); 94 | 95 | ansi.println("\ndone..."); 96 | } 97 | 98 | void loop() 99 | { 100 | } 101 | 102 | // -- END OF FILE -- 103 | -------------------------------------------------------------------------------- /src/RTTStream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Arduino stream wrapper for Segger RTT. 3 | * 2021 Koen De Vleeschauwer 4 | * No copyright asserted. 5 | */ 6 | 7 | #include 8 | #include 9 | #include "SEGGER_RTT_Peek.h" 10 | 11 | RTTStream::RTTStream() { 12 | SEGGER_RTT_Init(); 13 | } 14 | 15 | RTTStream::~RTTStream() { 16 | } 17 | 18 | void RTTStream::blockUpBufferFull() { 19 | SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); 20 | } 21 | 22 | void RTTStream::skipUpBufferFull() { 23 | SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); 24 | } 25 | 26 | void RTTStream::trimUpBufferFull() { 27 | SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_TRIM); 28 | } 29 | 30 | void RTTStream::blockDownBufferFull() { 31 | SEGGER_RTT_ConfigDownBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); 32 | } 33 | 34 | void RTTStream::skipDownBufferFull() { 35 | SEGGER_RTT_ConfigDownBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); 36 | } 37 | 38 | void RTTStream::trimDownBufferFull() { 39 | SEGGER_RTT_ConfigDownBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_TRIM); 40 | } 41 | 42 | void RTTStream::echo() { 43 | echo_on = true; 44 | } 45 | 46 | void RTTStream::noEcho() { 47 | echo_on = false; 48 | } 49 | 50 | int RTTStream::available() { 51 | int bytes_in_buffer = SEGGER_RTT_GetBytesInDownBuffer(0); 52 | return bytes_in_buffer; 53 | } 54 | 55 | int RTTStream::read() { 56 | int ch; 57 | int bytes_read = SEGGER_RTT_Read(0, &ch, 1); 58 | if (echo_on && bytes_read == 1) 59 | SEGGER_RTT_PutChar(0, ch); 60 | if (bytes_read == 1) 61 | return ch; 62 | return -1; 63 | }; 64 | 65 | size_t RTTStream::readBytes(char *buffer, size_t length) { 66 | int bytes_read = SEGGER_RTT_Read(0, buffer, length); 67 | if (echo_on && bytes_read > 0) 68 | SEGGER_RTT_Write(0, buffer, bytes_read); 69 | return bytes_read; 70 | }; 71 | 72 | int RTTStream::peek() { 73 | int peekch; 74 | peekch = SEGGER_RTT_Peek(0); 75 | return peekch; 76 | } 77 | 78 | size_t RTTStream::write(uint8_t ch) { 79 | int bytes_written = SEGGER_RTT_PutChar(0, ch); 80 | return bytes_written; 81 | } 82 | 83 | size_t RTTStream::write(const uint8_t *buffer, size_t size) { 84 | size_t bytes_written = SEGGER_RTT_Write(0, buffer, size); 85 | return bytes_written; 86 | } 87 | 88 | void RTTStream::flush() { 89 | while (SEGGER_RTT_GetBytesInBuffer(0) != 0) { 90 | delay(1); 91 | } 92 | } 93 | 94 | int RTTStream::printf(const char *format, ...) { 95 | int retval; 96 | va_list args; 97 | va_start(args, format); 98 | retval = SEGGER_RTT_vprintf(0, format, &args); 99 | va_end(args); 100 | return retval; 101 | } 102 | 103 | /* compatibility with Serial */ 104 | 105 | void RTTStream::begin(unsigned long baudrate) { 106 | (void)baudrate; 107 | } 108 | 109 | RTTStream::operator bool() { 110 | return true; 111 | } 112 | 113 | /* not truncated */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino RTTStream 2 | 3 | ## Description 4 | Arduino library for [Segger RTT](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) on arm and risc-v Arduinos 5 | 6 | With RTTStream an stm32duino can do screen output on a pc, and get keyboard input from a pc, without using usb or serials. Connection is using the SWD or JTAG port. 7 | 8 | To use RTTStream you need a [Segger JLink](https://www.segger.com/products/debug-probes/j-link/) debugger probe. Depending upon your needs, Open Source alternatives may also be suitable. 9 | 10 | RTTStream only runs on arduinos with arm or risc-v processors, sorry. 11 | 12 | ## Use 13 | 14 | Use RTTStream just like you would use Serial: 15 | 16 | ``` 17 | #include 18 | RTTStream rtt; 19 | void setup() { 20 | rtt.println("hello world!"); 21 | } 22 | void loop() { 23 | } 24 | ``` 25 | 26 | ## Sample RTT Session 27 | 28 | This is an example of a debugging session of a STM32F103 *Blue Pill* on linux. 29 | 30 | Connect a Segger J-Link probe to the SWD port of your arduino, and to the usb of your pc. 31 | 32 | Connections between blue pill and [J-Link](https://www.segger.com/products/debug-probes/j-link/technology/interface-description/#swd-and-swo-also-called-swv-compatibility): 33 | 34 | | Blue pill | J-Link | J-Link Pin | J-Link Mini Pin | 35 | | --------- | ------ | ---------- | --------------- | 36 | | +3.3V | VTREF | 1 | 1 | 37 | | SWDIO | SWDIO | 7 | 2 | 38 | | SWCLK | SWCLK | 9 | 4 | 39 | | GND | GND | 4 | 3 | 40 | 41 | Open a window and start the gdb server: 42 | ``` 43 | JLinkGDBServer -device STM32F103R8 -if SWD -speed 4000 44 | ``` 45 | Open another window and start the RTT terminal. This is where the messages from the arduino program will appear, and where you can type keyboard input. 46 | ``` 47 | JLinkRTTClient 48 | ``` 49 | Start the debugger, download and run your program: 50 | ``` 51 | $ arm-none-eabi-gdb 52 | (gdb) target extended-remote 127.0.0.1:2331 53 | (gdb) file StreamTest.ino.elf 54 | (gdb) load 55 | (gdb) run 56 | ``` 57 | or, abbreviated: 58 | ``` 59 | $ arm-none-eabi-gdb 60 | (gdb) tar ext :2331 61 | (gdb) fil StreamTest.ino.elf 62 | (gdb) lo 63 | (gdb) r 64 | ``` 65 | Switch to the window where *JLinkRTTClient* is running to read program messages, and to type program input: 66 | 67 | ``` 68 | rtt stream test 69 | char: a 70 | string: the quick brown fox jumps over a lazy dog 71 | int: 12345 72 | float: 3.14 73 | printf char: a signed int: -12345 unsigned int: 12345 74 | printf hex int: 12345 string: 12345 pointer: 20000090 75 | enter an int: 23456 76 | value: 23456 77 | enter a float: 2.71828 78 | value: 2.72 79 | enter a string and wait 5 seconds: qwerty 80 | string: qwerty 81 | rtt stream test end 82 | ``` 83 | 84 | ## Boards with built-in RTT 85 | 86 | RTTStream contains SEGGER RTT source files. Some Arduino boards already include SEGGER RTT as part of the board package, e.g. nrf52. 87 | 88 | To avoid duplicates, if the Arduino board package already contains the files `SEGGER_RTT.h`, `SEGGER_RTT.c` and `SEGGER_RTT_Conf.h`, please remove the files `SEGGER_RTT.h`, `SEGGER_RTT.c` and `SEGGER_RTT_Conf.h` from `libraries/RTT_Stream/src/` 89 | 90 | This way there is only one version of SEGGER RTT. 91 | 92 | ## Links 93 | - The Eclipse development environment has a [plugin](https://eclipse-embed-cdt.github.io/debug/jlink/) to automate using Segger J-Link. 94 | - Open source projects that support RTT are [OpenOCD](https://openocd.org/doc/html/General-Commands.html#Real-Time-Transfer-_0028RTT_0029), [Black Magic Probe](https://github.com/blackmagic-debug/blackmagic/blob/master/UsingRTT.md), [probe-rs](https://probe.rs/docs/tools/cargo-embed/#rtt) and others. 95 | 96 | *not truncated* 97 | -------------------------------------------------------------------------------- /src/SEGGER_RTT_Peek.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SEGGER_RTT_Peek.h" 3 | 4 | /********************************************************************* 5 | * 6 | * SEGGER_RTT_GetBytesInDownBuffer() 7 | * 8 | * Function description 9 | * Returns the number of bytes currently used in the down buffer. 10 | * 11 | * Parameters 12 | * BufferIndex Index of the down buffer. 13 | * 14 | * Return value 15 | * Number of bytes that are used in the buffer. 16 | */ 17 | unsigned SEGGER_RTT_GetBytesInDownBuffer(unsigned BufferIndex) { 18 | unsigned RdOff; 19 | unsigned WrOff; 20 | unsigned r; 21 | volatile SEGGER_RTT_CB* pRTTCB; 22 | SEGGER_RTT_BUFFER_DOWN* pRing; 23 | // 24 | // Avoid warnings regarding volatile access order. It's not a problem 25 | // in this case, but dampen compiler enthusiasm. 26 | // 27 | 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 28 | if (pRTTCB->acID[0] == '\0') { 29 | return(0); // RTT not initialized yet 30 | } 31 | 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 32 | RdOff = pRing->RdOff; 33 | WrOff = pRing->WrOff; 34 | if (RdOff <= WrOff) { 35 | r = WrOff - RdOff; 36 | } else { 37 | r = pRing->SizeOfBuffer - (WrOff - RdOff); 38 | } 39 | return r; 40 | } 41 | 42 | /********************************************************************* 43 | * 44 | * SEGGER_RTT_PeekNoLock() 45 | * 46 | * Function description 47 | * Returns character at current read position 48 | * Does not lock against interrupts and multiple access. 49 | * 50 | * Parameters 51 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 52 | * 53 | * Return value 54 | * character at current read position, 55 | * -1 if no characters in Down-buffer 56 | */ 57 | 58 | int SEGGER_RTT_PeekNoLock(unsigned BufferIndex) { 59 | int retval = -1; 60 | unsigned RdOff; 61 | unsigned WrOff; 62 | SEGGER_RTT_BUFFER_DOWN* pRing; 63 | volatile char* pSrc; 64 | volatile SEGGER_RTT_CB* pRTTCB; 65 | // 66 | 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 67 | if (pRTTCB->acID[0] == '\0') { 68 | return(-1); // RTT not initialized yet 69 | } 70 | 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 71 | RdOff = pRing->RdOff; 72 | WrOff = pRing->WrOff; 73 | 74 | // 75 | // Return character at current read position 76 | // 77 | if (RdOff == WrOff) retval = -1; 78 | else { 79 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 80 | retval = *pSrc; 81 | } 82 | // 83 | return retval; 84 | } 85 | 86 | /********************************************************************* 87 | * 88 | * SEGGER_RTT_Peek() 89 | * 90 | * Function description 91 | * Returns character at current read position 92 | * Locks against interrupts and multiple access. 93 | * 94 | * Parameters 95 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 96 | * 97 | * Return value 98 | * character at current read position, 99 | * -1 if no characters in Down-buffer 100 | */ 101 | 102 | int SEGGER_RTT_Peek(unsigned BufferIndex) { 103 | int retval = -1; 104 | SEGGER_RTT_LOCK(); 105 | retval = SEGGER_RTT_PeekNoLock(BufferIndex); 106 | SEGGER_RTT_UNLOCK(); 107 | return retval; 108 | } 109 | 110 | /*************************** End of file ****************************/ 111 | -------------------------------------------------------------------------------- /doc/SEGGER_RTT.patch: -------------------------------------------------------------------------------- 1 | diff -urN OLD/SEGGER_RTT_V782/RTT/SEGGER_RTT.c NEW/SEGGER_RTT_V782/RTT/SEGGER_RTT.c 2 | --- OLD/SEGGER_RTT_V782/RTT/SEGGER_RTT.c 2022-10-13 10:27:09.000000000 +0200 3 | +++ NEW/SEGGER_RTT_V782/RTT/SEGGER_RTT.c 2022-10-21 14:22:03.215554654 +0200 4 | @@ -2095,4 +2095,101 @@ 5 | return r; 6 | } 7 | 8 | +/********************************************************************* 9 | +* 10 | +* SEGGER_RTT_GetBytesInDownBuffer() 11 | +* 12 | +* Function description 13 | +* Returns the number of bytes currently used in the down buffer. 14 | +* 15 | +* Parameters 16 | +* BufferIndex Index of the down buffer. 17 | +* 18 | +* Return value 19 | +* Number of bytes that are used in the buffer. 20 | +*/ 21 | +unsigned SEGGER_RTT_GetBytesInDownBuffer(unsigned BufferIndex) { 22 | + unsigned RdOff; 23 | + unsigned WrOff; 24 | + unsigned r; 25 | + volatile SEGGER_RTT_CB* pRTTCB; 26 | + // 27 | + // Avoid warnings regarding volatile access order. It's not a problem 28 | + // in this case, but dampen compiler enthusiasm. 29 | + // 30 | + 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 31 | + RdOff = pRTTCB->aDown[BufferIndex].RdOff; 32 | + WrOff = pRTTCB->aDown[BufferIndex].WrOff; 33 | + if (RdOff <= WrOff) { 34 | + r = WrOff - RdOff; 35 | + } else { 36 | + r = pRTTCB->aDown[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 37 | + } 38 | + return r; 39 | +} 40 | + 41 | +/********************************************************************* 42 | +* 43 | +* SEGGER_RTT_PeekNoLock() 44 | +* 45 | +* Function description 46 | +* Returns character at current read position 47 | +* Does not lock against interrupts and multiple access. 48 | +* 49 | +* Parameters 50 | +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 51 | +* 52 | +* Return value 53 | +* character at current read position, 54 | +* -1 if no characters in Down-buffer 55 | +*/ 56 | + 57 | +int SEGGER_RTT_PeekNoLock(unsigned BufferIndex) { 58 | + int retval = -1; 59 | + unsigned RdOff; 60 | + unsigned WrOff; 61 | + SEGGER_RTT_BUFFER_DOWN* pRing; 62 | + volatile char* pSrc; 63 | + // 64 | + INIT(); 65 | + 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 66 | + RdOff = pRing->RdOff; 67 | + WrOff = pRing->WrOff; 68 | + 69 | + // 70 | + // Return character at current read position 71 | + // 72 | + if (RdOff == WrOff) retval = -1; 73 | + else { 74 | + pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 75 | + retval = *pSrc; 76 | + } 77 | + // 78 | + return retval; 79 | +} 80 | + 81 | +/********************************************************************* 82 | +* 83 | +* SEGGER_RTT_Peek() 84 | +* 85 | +* Function description 86 | +* Returns character at current read position 87 | +* Locks against interrupts and multiple access. 88 | +* 89 | +* Parameters 90 | +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 91 | +* 92 | +* Return value 93 | +* character at current read position, 94 | +* -1 if no characters in Down-buffer 95 | +*/ 96 | + 97 | +int SEGGER_RTT_Peek(unsigned BufferIndex) { 98 | + int retval = -1; 99 | + SEGGER_RTT_LOCK(); 100 | + retval = SEGGER_RTT_PeekNoLock(BufferIndex); 101 | + SEGGER_RTT_UNLOCK(); 102 | + return retval; 103 | +} 104 | + 105 | /*************************** End of file ****************************/ 106 | diff -urN OLD/SEGGER_RTT_V782/RTT/SEGGER_RTT.h NEW/SEGGER_RTT_V782/RTT/SEGGER_RTT.h 107 | --- OLD/SEGGER_RTT_V782/RTT/SEGGER_RTT.h 2022-10-13 10:27:09.000000000 +0200 108 | +++ NEW/SEGGER_RTT_V782/RTT/SEGGER_RTT.h 2022-10-21 14:22:03.215554654 +0200 109 | @@ -378,6 +378,10 @@ 110 | unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); 111 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); 112 | unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); 113 | +unsigned SEGGER_RTT_GetBytesInDownBuffer (unsigned BufferIndex); 114 | +int SEGGER_RTT_PeekNoLock (unsigned BufferIndex); 115 | +int SEGGER_RTT_Peek (unsigned BufferIndex); 116 | + 117 | // 118 | // Function macro for performance optimization 119 | // 120 | -------------------------------------------------------------------------------- /src/SEGGER_RTT_printf.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | ---------------------------END-OF-HEADER------------------------------ 45 | File : SEGGER_RTT_printf.c 46 | Purpose : Replacement for printf to write formatted data via RTT 47 | Revision: $Rev: 17697 $ 48 | ---------------------------------------------------------------------- 49 | */ 50 | #include "SEGGER_RTT.h" 51 | #include "SEGGER_RTT_Conf.h" 52 | 53 | /********************************************************************* 54 | * 55 | * Defines, configurable 56 | * 57 | ********************************************************************** 58 | */ 59 | 60 | #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 61 | #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) 62 | #endif 63 | 64 | #include 65 | #include 66 | 67 | 68 | #define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) 69 | #define FORMAT_FLAG_PAD_ZERO (1u << 1) 70 | #define FORMAT_FLAG_PRINT_SIGN (1u << 2) 71 | #define FORMAT_FLAG_ALTERNATE (1u << 3) 72 | 73 | /********************************************************************* 74 | * 75 | * Types 76 | * 77 | ********************************************************************** 78 | */ 79 | 80 | typedef struct { 81 | char* pBuffer; 82 | unsigned BufferSize; 83 | unsigned Cnt; 84 | 85 | int ReturnValue; 86 | 87 | unsigned RTTBufferIndex; 88 | } SEGGER_RTT_PRINTF_DESC; 89 | 90 | /********************************************************************* 91 | * 92 | * Function prototypes 93 | * 94 | ********************************************************************** 95 | */ 96 | 97 | /********************************************************************* 98 | * 99 | * Static code 100 | * 101 | ********************************************************************** 102 | */ 103 | /********************************************************************* 104 | * 105 | * _StoreChar 106 | */ 107 | static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { 108 | unsigned Cnt; 109 | 110 | Cnt = p->Cnt; 111 | if ((Cnt + 1u) <= p->BufferSize) { 112 | *(p->pBuffer + Cnt) = c; 113 | p->Cnt = Cnt + 1u; 114 | p->ReturnValue++; 115 | } 116 | // 117 | // Write part of string, when the buffer is full 118 | // 119 | if (p->Cnt == p->BufferSize) { 120 | if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { 121 | p->ReturnValue = -1; 122 | } else { 123 | p->Cnt = 0u; 124 | } 125 | } 126 | } 127 | 128 | /********************************************************************* 129 | * 130 | * _PrintUnsigned 131 | */ 132 | static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 133 | static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 134 | unsigned Div; 135 | unsigned Digit; 136 | unsigned Number; 137 | unsigned Width; 138 | char c; 139 | 140 | Number = v; 141 | Digit = 1u; 142 | // 143 | // Get actual field width 144 | // 145 | Width = 1u; 146 | while (Number >= Base) { 147 | Number = (Number / Base); 148 | Width++; 149 | } 150 | if (NumDigits > Width) { 151 | Width = NumDigits; 152 | } 153 | // 154 | // Print leading chars if necessary 155 | // 156 | if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { 157 | if (FieldWidth != 0u) { 158 | if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { 159 | c = '0'; 160 | } else { 161 | c = ' '; 162 | } 163 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 164 | FieldWidth--; 165 | _StoreChar(pBufferDesc, c); 166 | if (pBufferDesc->ReturnValue < 0) { 167 | break; 168 | } 169 | } 170 | } 171 | } 172 | if (pBufferDesc->ReturnValue >= 0) { 173 | // 174 | // Compute Digit. 175 | // Loop until Digit has the value of the highest digit required. 176 | // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. 177 | // 178 | while (1) { 179 | if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) 180 | NumDigits--; 181 | } else { 182 | Div = v / Digit; 183 | if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done 184 | break; 185 | } 186 | } 187 | Digit *= Base; 188 | } 189 | // 190 | // Output digits 191 | // 192 | do { 193 | Div = v / Digit; 194 | v -= Div * Digit; 195 | _StoreChar(pBufferDesc, _aV2C[Div]); 196 | if (pBufferDesc->ReturnValue < 0) { 197 | break; 198 | } 199 | Digit /= Base; 200 | } while (Digit); 201 | // 202 | // Print trailing spaces if necessary 203 | // 204 | if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { 205 | if (FieldWidth != 0u) { 206 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 207 | FieldWidth--; 208 | _StoreChar(pBufferDesc, ' '); 209 | if (pBufferDesc->ReturnValue < 0) { 210 | break; 211 | } 212 | } 213 | } 214 | } 215 | } 216 | } 217 | 218 | /********************************************************************* 219 | * 220 | * _PrintInt 221 | */ 222 | static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 223 | unsigned Width; 224 | int Number; 225 | 226 | Number = (v < 0) ? -v : v; 227 | 228 | // 229 | // Get actual field width 230 | // 231 | Width = 1u; 232 | while (Number >= (int)Base) { 233 | Number = (Number / (int)Base); 234 | Width++; 235 | } 236 | if (NumDigits > Width) { 237 | Width = NumDigits; 238 | } 239 | if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { 240 | FieldWidth--; 241 | } 242 | 243 | // 244 | // Print leading spaces if necessary 245 | // 246 | if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { 247 | if (FieldWidth != 0u) { 248 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 249 | FieldWidth--; 250 | _StoreChar(pBufferDesc, ' '); 251 | if (pBufferDesc->ReturnValue < 0) { 252 | break; 253 | } 254 | } 255 | } 256 | } 257 | // 258 | // Print sign if necessary 259 | // 260 | if (pBufferDesc->ReturnValue >= 0) { 261 | if (v < 0) { 262 | v = -v; 263 | _StoreChar(pBufferDesc, '-'); 264 | } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { 265 | _StoreChar(pBufferDesc, '+'); 266 | } else { 267 | 268 | } 269 | if (pBufferDesc->ReturnValue >= 0) { 270 | // 271 | // Print leading zeros if necessary 272 | // 273 | if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { 274 | if (FieldWidth != 0u) { 275 | while ((FieldWidth != 0u) && (Width < FieldWidth)) { 276 | FieldWidth--; 277 | _StoreChar(pBufferDesc, '0'); 278 | if (pBufferDesc->ReturnValue < 0) { 279 | break; 280 | } 281 | } 282 | } 283 | } 284 | if (pBufferDesc->ReturnValue >= 0) { 285 | // 286 | // Print number without sign 287 | // 288 | _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); 289 | } 290 | } 291 | } 292 | } 293 | 294 | /********************************************************************* 295 | * 296 | * Public code 297 | * 298 | ********************************************************************** 299 | */ 300 | /********************************************************************* 301 | * 302 | * SEGGER_RTT_vprintf 303 | * 304 | * Function description 305 | * Stores a formatted string in SEGGER RTT control block. 306 | * This data is read by the host. 307 | * 308 | * Parameters 309 | * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 310 | * sFormat Pointer to format string 311 | * pParamList Pointer to the list of arguments for the format string 312 | * 313 | * Return values 314 | * >= 0: Number of bytes which have been stored in the "Up"-buffer. 315 | * < 0: Error 316 | */ 317 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { 318 | char c; 319 | SEGGER_RTT_PRINTF_DESC BufferDesc; 320 | int v; 321 | unsigned NumDigits; 322 | unsigned FormatFlags; 323 | unsigned FieldWidth; 324 | char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; 325 | 326 | BufferDesc.pBuffer = acBuffer; 327 | BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; 328 | BufferDesc.Cnt = 0u; 329 | BufferDesc.RTTBufferIndex = BufferIndex; 330 | BufferDesc.ReturnValue = 0; 331 | 332 | do { 333 | c = *sFormat; 334 | sFormat++; 335 | if (c == 0u) { 336 | break; 337 | } 338 | if (c == '%') { 339 | // 340 | // Filter out flags 341 | // 342 | FormatFlags = 0u; 343 | v = 1; 344 | do { 345 | c = *sFormat; 346 | switch (c) { 347 | case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; 348 | case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; 349 | case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; 350 | case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; 351 | default: v = 0; break; 352 | } 353 | } while (v); 354 | // 355 | // filter out field with 356 | // 357 | FieldWidth = 0u; 358 | do { 359 | c = *sFormat; 360 | if ((c < '0') || (c > '9')) { 361 | break; 362 | } 363 | sFormat++; 364 | FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); 365 | } while (1); 366 | 367 | // 368 | // Filter out precision (number of digits to display) 369 | // 370 | NumDigits = 0u; 371 | c = *sFormat; 372 | if (c == '.') { 373 | sFormat++; 374 | do { 375 | c = *sFormat; 376 | if ((c < '0') || (c > '9')) { 377 | break; 378 | } 379 | sFormat++; 380 | NumDigits = NumDigits * 10u + ((unsigned)c - '0'); 381 | } while (1); 382 | } 383 | // 384 | // Filter out length modifier 385 | // 386 | c = *sFormat; 387 | do { 388 | if ((c == 'l') || (c == 'h')) { 389 | sFormat++; 390 | c = *sFormat; 391 | } else { 392 | break; 393 | } 394 | } while (1); 395 | // 396 | // Handle specifiers 397 | // 398 | switch (c) { 399 | case 'c': { 400 | char c0; 401 | v = va_arg(*pParamList, int); 402 | c0 = (char)v; 403 | _StoreChar(&BufferDesc, c0); 404 | break; 405 | } 406 | case 'd': 407 | v = va_arg(*pParamList, int); 408 | _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); 409 | break; 410 | case 'u': 411 | v = va_arg(*pParamList, int); 412 | _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); 413 | break; 414 | case 'x': 415 | case 'X': 416 | v = va_arg(*pParamList, int); 417 | _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); 418 | break; 419 | case 's': 420 | { 421 | const char * s = va_arg(*pParamList, const char *); 422 | if (s == NULL) { 423 | s = "(NULL)"; // Print (NULL) instead of crashing or breaking, as it is more informative to the user. 424 | } 425 | do { 426 | c = *s; 427 | s++; 428 | if (c == '\0') { 429 | break; 430 | } 431 | _StoreChar(&BufferDesc, c); 432 | } while (BufferDesc.ReturnValue >= 0); 433 | } 434 | break; 435 | case 'p': 436 | v = va_arg(*pParamList, int); 437 | _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); 438 | break; 439 | case '%': 440 | _StoreChar(&BufferDesc, '%'); 441 | break; 442 | default: 443 | break; 444 | } 445 | sFormat++; 446 | } else { 447 | _StoreChar(&BufferDesc, c); 448 | } 449 | } while (BufferDesc.ReturnValue >= 0); 450 | 451 | if (BufferDesc.ReturnValue > 0) { 452 | // 453 | // Write remaining data, if any 454 | // 455 | if (BufferDesc.Cnt != 0u) { 456 | SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); 457 | } 458 | BufferDesc.ReturnValue += (int)BufferDesc.Cnt; 459 | } 460 | return BufferDesc.ReturnValue; 461 | } 462 | 463 | /********************************************************************* 464 | * 465 | * SEGGER_RTT_printf 466 | * 467 | * Function description 468 | * Stores a formatted string in SEGGER RTT control block. 469 | * This data is read by the host. 470 | * 471 | * Parameters 472 | * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 473 | * sFormat Pointer to format string, followed by the arguments for conversion 474 | * 475 | * Return values 476 | * >= 0: Number of bytes which have been stored in the "Up"-buffer. 477 | * < 0: Error 478 | * 479 | * Notes 480 | * (1) Conversion specifications have following syntax: 481 | * %[flags][FieldWidth][.Precision]ConversionSpecifier 482 | * (2) Supported flags: 483 | * -: Left justify within the field width 484 | * +: Always print sign extension for signed conversions 485 | * 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision 486 | * Supported conversion specifiers: 487 | * c: Print the argument as one char 488 | * d: Print the argument as a signed integer 489 | * u: Print the argument as an unsigned integer 490 | * x: Print the argument as an hexadecimal integer 491 | * s: Print the string pointed to by the argument 492 | * p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) 493 | */ 494 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { 495 | int r; 496 | va_list ParamList; 497 | 498 | va_start(ParamList, sFormat); 499 | r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); 500 | va_end(ParamList); 501 | return r; 502 | } 503 | /*************************** End of file ****************************/ 504 | -------------------------------------------------------------------------------- /src/SEGGER_RTT.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | ---------------------------END-OF-HEADER------------------------------ 45 | File : SEGGER_RTT.h 46 | Purpose : Implementation of SEGGER real-time transfer which allows 47 | real-time communication on targets which support debugger 48 | memory accesses while the CPU is running. 49 | Revision: $Rev: 25842 $ 50 | ---------------------------------------------------------------------- 51 | */ 52 | 53 | #ifndef SEGGER_RTT_H 54 | #define SEGGER_RTT_H 55 | 56 | #include "SEGGER_RTT_Conf.h" 57 | 58 | /********************************************************************* 59 | * 60 | * Defines, defaults 61 | * 62 | ********************************************************************** 63 | */ 64 | 65 | #ifndef RTT_USE_ASM 66 | // 67 | // Some cores support out-of-order memory accesses (reordering of memory accesses in the core) 68 | // For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers. 69 | // Needed for: 70 | // Cortex-M7 (ARMv7-M) 71 | // Cortex-M23 (ARM-v8M) 72 | // Cortex-M33 (ARM-v8M) 73 | // Cortex-A/R (ARM-v7A/R) 74 | // 75 | // We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support. 76 | // You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio" 77 | // 78 | #if (defined __CROSSWORKS_ARM) // Rowley Crossworks 79 | #define _CC_HAS_RTT_ASM_SUPPORT 1 80 | #if (defined __ARM_ARCH_7M__) // Cortex-M3 81 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 82 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 83 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 84 | #define _CORE_NEEDS_DMB 1 85 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 86 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 87 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 88 | #define _CORE_NEEDS_DMB 1 89 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 90 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 91 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 92 | #define _CORE_NEEDS_DMB 1 93 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 94 | #elif (defined(__ARM_ARCH_8_1M_MAIN__)) // Cortex-M85 95 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 96 | #define _CORE_NEEDS_DMB 1 97 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 98 | #else 99 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 100 | #endif 101 | #elif (defined __ARMCC_VERSION) 102 | // 103 | // ARM compiler 104 | // ARM compiler V6.0 and later is clang based. 105 | // Our ASM part is compatible to clang. 106 | // 107 | #if (__ARMCC_VERSION >= 6000000) 108 | #define _CC_HAS_RTT_ASM_SUPPORT 1 109 | #else 110 | #define _CC_HAS_RTT_ASM_SUPPORT 0 111 | #endif 112 | #if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1 113 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture 114 | #elif (defined __ARM_ARCH_7M__) // Cortex-M3 115 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 116 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 117 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 118 | #define _CORE_NEEDS_DMB 1 119 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 120 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 121 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 122 | #define _CORE_NEEDS_DMB 1 123 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 124 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 125 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 126 | #define _CORE_NEEDS_DMB 1 127 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 128 | #elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85 129 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 130 | #define _CORE_NEEDS_DMB 1 131 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 132 | #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R 133 | #define _CORE_NEEDS_DMB 1 134 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 135 | #else 136 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 137 | #endif 138 | #elif ((defined __GNUC__) || (defined __clang__)) 139 | // 140 | // GCC / Clang 141 | // 142 | #define _CC_HAS_RTT_ASM_SUPPORT 1 143 | // ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__ 144 | #if (defined __ARM_ARCH_7M__) // Cortex-M3 145 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 146 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 147 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 148 | #define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here... 149 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 150 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 151 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 152 | #define _CORE_NEEDS_DMB 1 153 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 154 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 155 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 156 | #define _CORE_NEEDS_DMB 1 157 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 158 | #elif (defined __ARM_ARCH_8_1M_MAIN__) // Cortex-M85 159 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 160 | #define _CORE_NEEDS_DMB 1 161 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 162 | #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R 163 | #define _CORE_NEEDS_DMB 1 164 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 165 | #else 166 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 167 | #endif 168 | #elif ((defined __IASMARM__) || (defined __ICCARM__)) 169 | // 170 | // IAR assembler/compiler 171 | // 172 | #define _CC_HAS_RTT_ASM_SUPPORT 1 173 | #if (__VER__ < 6300000) 174 | #define VOLATILE 175 | #else 176 | #define VOLATILE volatile 177 | #endif 178 | #if (defined __ARM7M__) // Needed for old versions that do not know the define yet 179 | #if (__CORE__ == __ARM7M__) // Cortex-M3 180 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 181 | #endif 182 | #endif 183 | #if (defined __ARM7EM__) 184 | #if (__CORE__ == __ARM7EM__) // Cortex-M4/M7 185 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 186 | #define _CORE_NEEDS_DMB 1 187 | #define RTT__DMB() asm VOLATILE ("DMB"); 188 | #endif 189 | #endif 190 | #if (defined __ARM8M_BASELINE__) 191 | #if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23 192 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 193 | #define _CORE_NEEDS_DMB 1 194 | #define RTT__DMB() asm VOLATILE ("DMB"); 195 | #endif 196 | #endif 197 | #if (defined __ARM8M_MAINLINE__) 198 | #if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33 199 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 200 | #define _CORE_NEEDS_DMB 1 201 | #define RTT__DMB() asm VOLATILE ("DMB"); 202 | #endif 203 | #endif 204 | #if (defined __ARM8EM_MAINLINE__) 205 | #if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-??? 206 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 207 | #define _CORE_NEEDS_DMB 1 208 | #define RTT__DMB() asm VOLATILE ("DMB"); 209 | #endif 210 | #endif 211 | #if (defined __ARM7A__) 212 | #if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A 213 | #define _CORE_NEEDS_DMB 1 214 | #define RTT__DMB() asm VOLATILE ("DMB"); 215 | #endif 216 | #endif 217 | #if (defined __ARM7R__) 218 | #if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R 219 | #define _CORE_NEEDS_DMB 1 220 | #define RTT__DMB() asm VOLATILE ("DMB"); 221 | #endif 222 | #endif 223 | // TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A 224 | // TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R 225 | #else 226 | // 227 | // Other compilers 228 | // 229 | #define _CC_HAS_RTT_ASM_SUPPORT 0 230 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 231 | #endif 232 | // 233 | // If IDE and core support the ASM version, enable ASM version by default 234 | // 235 | #ifndef _CORE_HAS_RTT_ASM_SUPPORT 236 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores 237 | #endif 238 | #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) 239 | #define RTT_USE_ASM (1) 240 | #else 241 | #define RTT_USE_ASM (0) 242 | #endif 243 | #endif 244 | 245 | #ifndef _CORE_NEEDS_DMB 246 | #define _CORE_NEEDS_DMB 0 247 | #endif 248 | 249 | #ifndef RTT__DMB 250 | #if _CORE_NEEDS_DMB 251 | #error "Don't know how to place inline assembly for DMB" 252 | #else 253 | #define RTT__DMB() 254 | #endif 255 | #endif 256 | 257 | #ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE 258 | #define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here 259 | #endif 260 | 261 | #ifndef SEGGER_RTT_UNCACHED_OFF 262 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 263 | #error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 264 | #else 265 | #define SEGGER_RTT_UNCACHED_OFF (0) 266 | #endif 267 | #endif 268 | #if RTT_USE_ASM 269 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 270 | #error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 271 | #endif 272 | #endif 273 | 274 | #ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file 275 | #include 276 | #include 277 | #include 278 | 279 | /********************************************************************* 280 | * 281 | * Defines, fixed 282 | * 283 | ********************************************************************** 284 | */ 285 | 286 | // 287 | // Determine how much we must pad the control block to make it a multiple of a cache line in size 288 | // Assuming: U8 = 1B 289 | // U16 = 2B 290 | // U32 = 4B 291 | // U8/U16/U32* = 4B 292 | // 293 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache 294 | #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE) 295 | #else 296 | #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes) 297 | #endif 298 | #define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24)) 299 | #define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE) 300 | 301 | /********************************************************************* 302 | * 303 | * Types 304 | * 305 | ********************************************************************** 306 | */ 307 | 308 | // 309 | // Description for a circular buffer (also called "ring buffer") 310 | // which is used as up-buffer (T->H) 311 | // 312 | typedef struct { 313 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 314 | char* pBuffer; // Pointer to start of buffer 315 | unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. 316 | unsigned WrOff; // Position of next item to be written by either target. 317 | volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. 318 | unsigned Flags; // Contains configuration flags. 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. 319 | } SEGGER_RTT_BUFFER_UP; 320 | 321 | // 322 | // Description for a circular buffer (also called "ring buffer") 323 | // which is used as down-buffer (H->T) 324 | // 325 | typedef struct { 326 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 327 | char* pBuffer; // Pointer to start of buffer 328 | unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. 329 | volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. 330 | unsigned RdOff; // Position of next item to be read by target (down-buffer). 331 | unsigned Flags; // Contains configuration flags. 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. 332 | } SEGGER_RTT_BUFFER_DOWN; 333 | 334 | // 335 | // RTT control block which describes the number of buffers available 336 | // as well as the configuration for each buffer 337 | // 338 | // 339 | typedef struct { 340 | char acID[16]; // Initialized to "SEGGER RTT" 341 | int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) 342 | int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) 343 | SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host 344 | SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target 345 | #if SEGGER_RTT__CB_PADDING 346 | unsigned char aDummy[SEGGER_RTT__CB_PADDING]; 347 | #endif 348 | } SEGGER_RTT_CB; 349 | 350 | /********************************************************************* 351 | * 352 | * Global data 353 | * 354 | ********************************************************************** 355 | */ 356 | extern SEGGER_RTT_CB _SEGGER_RTT; 357 | 358 | /********************************************************************* 359 | * 360 | * RTT API functions 361 | * 362 | ********************************************************************** 363 | */ 364 | #ifdef __cplusplus 365 | extern "C" { 366 | #endif 367 | int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 368 | int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 369 | int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 370 | int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 371 | int SEGGER_RTT_GetKey (void); 372 | unsigned SEGGER_RTT_HasData (unsigned BufferIndex); 373 | int SEGGER_RTT_HasKey (void); 374 | unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); 375 | void SEGGER_RTT_Init (void); 376 | unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 377 | unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 378 | int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); 379 | int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); 380 | int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); 381 | int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); 382 | int SEGGER_RTT_WaitKey (void); 383 | unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 384 | unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 385 | unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 386 | unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 387 | unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); 388 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 389 | unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); 390 | unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); 391 | unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); 392 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); 393 | unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); 394 | // 395 | // Function macro for performance optimization 396 | // 397 | #define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) 398 | 399 | #if RTT_USE_ASM 400 | #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock 401 | #endif 402 | 403 | /********************************************************************* 404 | * 405 | * RTT transfer functions to send RTT data via other channels. 406 | * 407 | ********************************************************************** 408 | */ 409 | unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 410 | unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 411 | unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 412 | unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 413 | 414 | #define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 415 | 416 | /********************************************************************* 417 | * 418 | * RTT "Terminal" API functions 419 | * 420 | ********************************************************************** 421 | */ 422 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId); 423 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); 424 | 425 | /********************************************************************* 426 | * 427 | * RTT printf functions (require SEGGER_RTT_printf.c) 428 | * 429 | ********************************************************************** 430 | */ 431 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 432 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); 433 | 434 | #ifdef __cplusplus 435 | } 436 | #endif 437 | 438 | #endif // ifndef(SEGGER_RTT_ASM) 439 | 440 | // 441 | // For some environments, NULL may not be defined until certain headers are included 442 | // 443 | #ifndef NULL 444 | #define NULL ((void*)0) 445 | #endif 446 | 447 | /********************************************************************* 448 | * 449 | * Defines 450 | * 451 | ********************************************************************** 452 | */ 453 | 454 | // 455 | // Operating modes. Define behavior if buffer is full (not enough space for entire message) 456 | // 457 | #define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) 458 | #define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. 459 | #define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. 460 | #define SEGGER_RTT_MODE_MASK (3) 461 | 462 | // 463 | // Control sequences, based on ANSI. 464 | // Can be used to control color, and clear the screen 465 | // 466 | #define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors 467 | #define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left 468 | 469 | #define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" 470 | #define RTT_CTRL_TEXT_RED "\x1B[2;31m" 471 | #define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" 472 | #define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" 473 | #define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" 474 | #define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" 475 | #define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" 476 | #define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" 477 | 478 | #define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" 479 | #define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" 480 | #define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" 481 | #define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" 482 | #define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" 483 | #define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" 484 | #define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" 485 | #define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" 486 | 487 | #define RTT_CTRL_BG_BLACK "\x1B[24;40m" 488 | #define RTT_CTRL_BG_RED "\x1B[24;41m" 489 | #define RTT_CTRL_BG_GREEN "\x1B[24;42m" 490 | #define RTT_CTRL_BG_YELLOW "\x1B[24;43m" 491 | #define RTT_CTRL_BG_BLUE "\x1B[24;44m" 492 | #define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" 493 | #define RTT_CTRL_BG_CYAN "\x1B[24;46m" 494 | #define RTT_CTRL_BG_WHITE "\x1B[24;47m" 495 | 496 | #define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" 497 | #define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" 498 | #define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" 499 | #define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" 500 | #define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" 501 | #define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" 502 | #define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" 503 | #define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" 504 | 505 | 506 | #endif 507 | 508 | /*************************** End of file ****************************/ 509 | -------------------------------------------------------------------------------- /src/SEGGER_RTT_Conf.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2020 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | ---------------------------END-OF-HEADER------------------------------ 45 | File : SEGGER_RTT_Conf.h 46 | Purpose : Implementation of SEGGER real-time transfer (RTT) which 47 | allows real-time communication on targets which support 48 | debugger memory accesses while the CPU is running. 49 | Revision: $Rev: 24316 $ 50 | 51 | */ 52 | 53 | #ifndef SEGGER_RTT_CONF_H 54 | #define SEGGER_RTT_CONF_H 55 | 56 | #ifdef __IAR_SYSTEMS_ICC__ 57 | #include 58 | #endif 59 | 60 | /********************************************************************* 61 | * 62 | * Defines, configurable 63 | * 64 | ********************************************************************** 65 | */ 66 | 67 | // 68 | // Take in and set to correct values for Cortex-A systems with CPU cache 69 | // 70 | //#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system 71 | //#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached 72 | // 73 | // Most common case: 74 | // Up-channel 0: RTT 75 | // Up-channel 1: SystemView 76 | // 77 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 78 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3) 79 | #endif 80 | // 81 | // Most common case: 82 | // Down-channel 0: RTT 83 | // Down-channel 1: SystemView 84 | // 85 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 86 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3) 87 | #endif 88 | 89 | #ifndef BUFFER_SIZE_UP 90 | #define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) 91 | #endif 92 | 93 | #ifndef BUFFER_SIZE_DOWN 94 | #define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) 95 | #endif 96 | 97 | #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 98 | #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) 99 | #endif 100 | 101 | #ifndef SEGGER_RTT_MODE_DEFAULT 102 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) 103 | #endif 104 | 105 | /********************************************************************* 106 | * 107 | * RTT memcpy configuration 108 | * 109 | * memcpy() is good for large amounts of data, 110 | * but the overhead is big for small amounts, which are usually stored via RTT. 111 | * With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead. 112 | * 113 | * SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions. 114 | * This is may be required with memory access restrictions, 115 | * such as on Cortex-A devices with MMU. 116 | */ 117 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 118 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop 119 | #endif 120 | // 121 | // Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets 122 | // 123 | //#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__)) 124 | // #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes)) 125 | //#endif 126 | 127 | // 128 | // Target is not allowed to perform other RTT operations while string still has not been stored completely. 129 | // Otherwise we would probably end up with a mixed string in the buffer. 130 | // If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. 131 | // 132 | // SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4. 133 | // Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches. 134 | // When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly. 135 | // (Higher priority = lower priority number) 136 | // Default value for embOS: 128u 137 | // Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 138 | // In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC 139 | // or define SEGGER_RTT_LOCK() to completely disable interrupts. 140 | // 141 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 142 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20) 143 | #endif 144 | 145 | /********************************************************************* 146 | * 147 | * RTT lock configuration for SEGGER Embedded Studio, 148 | * Rowley CrossStudio and GCC 149 | */ 150 | #if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32)) 151 | #if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__)) 152 | #define SEGGER_RTT_LOCK() { \ 153 | unsigned int _SEGGER_RTT__LockState; \ 154 | __asm volatile ("mrs %0, primask \n\t" \ 155 | "movs r1, #1 \n\t" \ 156 | "msr primask, r1 \n\t" \ 157 | : "=r" (_SEGGER_RTT__LockState) \ 158 | : \ 159 | : "r1", "cc" \ 160 | ); 161 | 162 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \ 163 | : \ 164 | : "r" (_SEGGER_RTT__LockState) \ 165 | : \ 166 | ); \ 167 | } 168 | #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__)) 169 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 170 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 171 | #endif 172 | #define SEGGER_RTT_LOCK() { \ 173 | unsigned int _SEGGER_RTT__LockState; \ 174 | __asm volatile ("mrs %0, basepri \n\t" \ 175 | "mov r1, %1 \n\t" \ 176 | "msr basepri, r1 \n\t" \ 177 | : "=r" (_SEGGER_RTT__LockState) \ 178 | : "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \ 179 | : "r1", "cc" \ 180 | ); 181 | 182 | #define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \ 183 | : \ 184 | : "r" (_SEGGER_RTT__LockState) \ 185 | : \ 186 | ); \ 187 | } 188 | 189 | #elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)) 190 | #define SEGGER_RTT_LOCK() { \ 191 | unsigned int _SEGGER_RTT__LockState; \ 192 | __asm volatile ("mrs r1, CPSR \n\t" \ 193 | "mov %0, r1 \n\t" \ 194 | "orr r1, r1, #0xC0 \n\t" \ 195 | "msr CPSR_c, r1 \n\t" \ 196 | : "=r" (_SEGGER_RTT__LockState) \ 197 | : \ 198 | : "r1", "cc" \ 199 | ); 200 | 201 | #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ 202 | "mrs r1, CPSR \n\t" \ 203 | "bic r1, r1, #0xC0 \n\t" \ 204 | "and r0, r0, #0xC0 \n\t" \ 205 | "orr r1, r1, r0 \n\t" \ 206 | "msr CPSR_c, r1 \n\t" \ 207 | : \ 208 | : "r" (_SEGGER_RTT__LockState) \ 209 | : "r0", "r1", "cc" \ 210 | ); \ 211 | } 212 | #elif defined(__riscv) || defined(__riscv_xlen) 213 | #define SEGGER_RTT_LOCK() { \ 214 | unsigned int _SEGGER_RTT__LockState; \ 215 | __asm volatile ("csrr %0, mstatus \n\t" \ 216 | "csrci mstatus, 8 \n\t" \ 217 | "andi %0, %0, 8 \n\t" \ 218 | : "=r" (_SEGGER_RTT__LockState) \ 219 | : \ 220 | : \ 221 | ); 222 | 223 | #define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \ 224 | "or %0, %0, a1 \n\t" \ 225 | "csrs mstatus, %0 \n\t" \ 226 | : \ 227 | : "r" (_SEGGER_RTT__LockState) \ 228 | : "a1" \ 229 | ); \ 230 | } 231 | #else 232 | #define SEGGER_RTT_LOCK() 233 | #define SEGGER_RTT_UNLOCK() 234 | #endif 235 | #endif 236 | 237 | /********************************************************************* 238 | * 239 | * RTT lock configuration for IAR EWARM 240 | */ 241 | #ifdef __ICCARM__ 242 | #if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \ 243 | (defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__)) 244 | #define SEGGER_RTT_LOCK() { \ 245 | unsigned int _SEGGER_RTT__LockState; \ 246 | _SEGGER_RTT__LockState = __get_PRIMASK(); \ 247 | __set_PRIMASK(1); 248 | 249 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ 250 | } 251 | #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \ 252 | (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \ 253 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \ 254 | (defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) 255 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 256 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 257 | #endif 258 | #define SEGGER_RTT_LOCK() { \ 259 | unsigned int _SEGGER_RTT__LockState; \ 260 | _SEGGER_RTT__LockState = __get_BASEPRI(); \ 261 | __set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 262 | 263 | #define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \ 264 | } 265 | #elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \ 266 | (defined (__ARM7R__) && (__CORE__ == __ARM7R__)) 267 | #define SEGGER_RTT_LOCK() { \ 268 | unsigned int _SEGGER_RTT__LockState; \ 269 | __asm volatile ("mrs r1, CPSR \n\t" \ 270 | "mov %0, r1 \n\t" \ 271 | "orr r1, r1, #0xC0 \n\t" \ 272 | "msr CPSR_c, r1 \n\t" \ 273 | : "=r" (_SEGGER_RTT__LockState) \ 274 | : \ 275 | : "r1", "cc" \ 276 | ); 277 | 278 | #define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \ 279 | "mrs r1, CPSR \n\t" \ 280 | "bic r1, r1, #0xC0 \n\t" \ 281 | "and r0, r0, #0xC0 \n\t" \ 282 | "orr r1, r1, r0 \n\t" \ 283 | "msr CPSR_c, r1 \n\t" \ 284 | : \ 285 | : "r" (_SEGGER_RTT__LockState) \ 286 | : "r0", "r1", "cc" \ 287 | ); \ 288 | } 289 | #endif 290 | #endif 291 | 292 | /********************************************************************* 293 | * 294 | * RTT lock configuration for IAR RX 295 | */ 296 | #ifdef __ICCRX__ 297 | #define SEGGER_RTT_LOCK() { \ 298 | unsigned long _SEGGER_RTT__LockState; \ 299 | _SEGGER_RTT__LockState = __get_interrupt_state(); \ 300 | __disable_interrupt(); 301 | 302 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ 303 | } 304 | #endif 305 | 306 | /********************************************************************* 307 | * 308 | * RTT lock configuration for IAR RL78 309 | */ 310 | #ifdef __ICCRL78__ 311 | #define SEGGER_RTT_LOCK() { \ 312 | __istate_t _SEGGER_RTT__LockState; \ 313 | _SEGGER_RTT__LockState = __get_interrupt_state(); \ 314 | __disable_interrupt(); 315 | 316 | #define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \ 317 | } 318 | #endif 319 | 320 | /********************************************************************* 321 | * 322 | * RTT lock configuration for KEIL ARM 323 | */ 324 | #ifdef __CC_ARM 325 | #if (defined __TARGET_ARCH_6S_M) 326 | #define SEGGER_RTT_LOCK() { \ 327 | unsigned int _SEGGER_RTT__LockState; \ 328 | register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \ 329 | _SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \ 330 | _SEGGER_RTT__PRIMASK = 1u; \ 331 | __schedule_barrier(); 332 | 333 | #define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \ 334 | __schedule_barrier(); \ 335 | } 336 | #elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) 337 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 338 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 339 | #endif 340 | #define SEGGER_RTT_LOCK() { \ 341 | unsigned int _SEGGER_RTT__LockState; \ 342 | register unsigned char BASEPRI __asm( "basepri"); \ 343 | _SEGGER_RTT__LockState = BASEPRI; \ 344 | BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \ 345 | __schedule_barrier(); 346 | 347 | #define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \ 348 | __schedule_barrier(); \ 349 | } 350 | #endif 351 | #endif 352 | 353 | /********************************************************************* 354 | * 355 | * RTT lock configuration for TI ARM 356 | */ 357 | #ifdef __TI_ARM__ 358 | #if defined (__TI_ARM_V6M0__) 359 | #define SEGGER_RTT_LOCK() { \ 360 | unsigned int _SEGGER_RTT__LockState; \ 361 | _SEGGER_RTT__LockState = __get_PRIMASK(); \ 362 | __set_PRIMASK(1); 363 | 364 | #define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \ 365 | } 366 | #elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__)) 367 | #ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY 368 | #define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) 369 | #endif 370 | #define SEGGER_RTT_LOCK() { \ 371 | unsigned int _SEGGER_RTT__LockState; \ 372 | _SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY); 373 | 374 | #define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \ 375 | } 376 | #endif 377 | #endif 378 | 379 | /********************************************************************* 380 | * 381 | * RTT lock configuration for CCRX 382 | */ 383 | #ifdef __RX 384 | #include 385 | #define SEGGER_RTT_LOCK() { \ 386 | unsigned long _SEGGER_RTT__LockState; \ 387 | _SEGGER_RTT__LockState = get_psw() & 0x010000; \ 388 | clrpsw_i(); 389 | 390 | #define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \ 391 | } 392 | #endif 393 | 394 | /********************************************************************* 395 | * 396 | * RTT lock configuration for embOS Simulation on Windows 397 | * (Can also be used for generic RTT locking with embOS) 398 | */ 399 | #if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS) 400 | 401 | void OS_SIM_EnterCriticalSection(void); 402 | void OS_SIM_LeaveCriticalSection(void); 403 | 404 | #define SEGGER_RTT_LOCK() { \ 405 | OS_SIM_EnterCriticalSection(); 406 | 407 | #define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \ 408 | } 409 | #endif 410 | 411 | /********************************************************************* 412 | * 413 | * RTT lock configuration fallback 414 | */ 415 | #ifndef SEGGER_RTT_LOCK 416 | #define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts) 417 | #endif 418 | 419 | #ifndef SEGGER_RTT_UNLOCK 420 | #define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state) 421 | #endif 422 | 423 | #endif 424 | /*************************** End of file ****************************/ 425 | -------------------------------------------------------------------------------- /src/SEGGER_RTT.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * SEGGER Microcontroller GmbH * 3 | * The Embedded Experts * 4 | ********************************************************************** 5 | * * 6 | * (c) 1995 - 2019 SEGGER Microcontroller GmbH * 7 | * * 8 | * www.segger.com Support: support@segger.com * 9 | * * 10 | ********************************************************************** 11 | * * 12 | * SEGGER RTT * Real Time Transfer for embedded targets * 13 | * * 14 | ********************************************************************** 15 | * * 16 | * All rights reserved. * 17 | * * 18 | * SEGGER strongly recommends to not make any changes * 19 | * to or modify the source code of this software in order to stay * 20 | * compatible with the RTT protocol and J-Link. * 21 | * * 22 | * Redistribution and use in source and binary forms, with or * 23 | * without modification, are permitted provided that the following * 24 | * condition is met: * 25 | * * 26 | * o Redistributions of source code must retain the above copyright * 27 | * notice, this condition and the following disclaimer. * 28 | * * 29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 30 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 31 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 33 | * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 34 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 36 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 37 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 38 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 40 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 41 | * DAMAGE. * 42 | * * 43 | ********************************************************************** 44 | ---------------------------END-OF-HEADER------------------------------ 45 | File : SEGGER_RTT.c 46 | Purpose : Implementation of SEGGER real-time transfer (RTT) which 47 | allows real-time communication on targets which support 48 | debugger memory accesses while the CPU is running. 49 | Revision: $Rev: 29668 $ 50 | 51 | Additional information: 52 | Type "int" is assumed to be 32-bits in size 53 | H->T Host to target communication 54 | T->H Target to host communication 55 | 56 | RTT channel 0 is always present and reserved for Terminal usage. 57 | Name is fixed to "Terminal" 58 | 59 | Effective buffer size: SizeOfBuffer - 1 60 | 61 | WrOff == RdOff: Buffer is empty 62 | WrOff == (RdOff - 1): Buffer is full 63 | WrOff > RdOff: Free space includes wrap-around 64 | WrOff < RdOff: Used space includes wrap-around 65 | (WrOff == (SizeOfBuffer - 1)) && (RdOff == 0): 66 | Buffer full and wrap-around after next byte 67 | 68 | 69 | ---------------------------------------------------------------------- 70 | */ 71 | 72 | #include "SEGGER_RTT.h" 73 | 74 | #include // for memcpy 75 | 76 | /********************************************************************* 77 | * 78 | * Configuration, default values 79 | * 80 | ********************************************************************** 81 | */ 82 | 83 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 84 | #ifdef SEGGER_RTT_CB_ALIGN 85 | #error "Custom SEGGER_RTT_CB_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 86 | #endif 87 | #ifdef SEGGER_RTT_BUFFER_ALIGN 88 | #error "Custom SEGGER_RTT_BUFFER_ALIGN() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 89 | #endif 90 | #ifdef SEGGER_RTT_PUT_CB_SECTION 91 | #error "Custom SEGGER_RTT_PUT_CB_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 92 | #endif 93 | #ifdef SEGGER_RTT_PUT_BUFFER_SECTION 94 | #error "Custom SEGGER_RTT_PUT_BUFFER_SECTION() is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 95 | #endif 96 | #ifdef SEGGER_RTT_BUFFER_ALIGNMENT 97 | #error "Custom SEGGER_RTT_BUFFER_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 98 | #endif 99 | #ifdef SEGGER_RTT_ALIGNMENT 100 | #error "Custom SEGGER_RTT_ALIGNMENT is not supported for SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 101 | #endif 102 | #endif 103 | 104 | #ifndef BUFFER_SIZE_UP 105 | #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host 106 | #endif 107 | 108 | #ifndef BUFFER_SIZE_DOWN 109 | #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) 110 | #endif 111 | 112 | #ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS 113 | #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target 114 | #endif 115 | 116 | #ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 117 | #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target 118 | #endif 119 | 120 | #ifndef SEGGER_RTT_BUFFER_SECTION 121 | #if defined(SEGGER_RTT_SECTION) 122 | #define SEGGER_RTT_BUFFER_SECTION SEGGER_RTT_SECTION 123 | #endif 124 | #endif 125 | 126 | #ifndef SEGGER_RTT_ALIGNMENT 127 | #define SEGGER_RTT_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 128 | #endif 129 | 130 | #ifndef SEGGER_RTT_BUFFER_ALIGNMENT 131 | #define SEGGER_RTT_BUFFER_ALIGNMENT SEGGER_RTT_CPU_CACHE_LINE_SIZE 132 | #endif 133 | 134 | #ifndef SEGGER_RTT_MODE_DEFAULT 135 | #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP 136 | #endif 137 | 138 | #ifndef SEGGER_RTT_LOCK 139 | #define SEGGER_RTT_LOCK() 140 | #endif 141 | 142 | #ifndef SEGGER_RTT_UNLOCK 143 | #define SEGGER_RTT_UNLOCK() 144 | #endif 145 | 146 | #ifndef STRLEN 147 | #define STRLEN(a) strlen((a)) 148 | #endif 149 | 150 | #ifndef STRCPY 151 | #define STRCPY(pDest, pSrc) strcpy((pDest), (pSrc)) 152 | #endif 153 | 154 | #ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP 155 | #define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 156 | #endif 157 | 158 | #ifndef SEGGER_RTT_MEMCPY 159 | #ifdef MEMCPY 160 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) MEMCPY((pDest), (pSrc), (NumBytes)) 161 | #else 162 | #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) 163 | #endif 164 | #endif 165 | 166 | #ifndef MIN 167 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 168 | #endif 169 | 170 | #ifndef MAX 171 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 172 | #endif 173 | 174 | /********************************************************************* 175 | * 176 | * Defines, fixed 177 | * 178 | ********************************************************************** 179 | */ 180 | #if (defined __ICCARM__) || (defined __ICCRX__) 181 | #define RTT_PRAGMA(P) _Pragma(#P) 182 | #endif 183 | 184 | #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 185 | #if ((defined __GNUC__) || (defined __clang__)) 186 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 187 | #elif (defined __ICCARM__) || (defined __ICCRX__) 188 | #define PRAGMA(A) _Pragma(#A) 189 | #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 190 | Var 191 | #elif (defined __CC_ARM) 192 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 193 | #else 194 | #error "Alignment not supported for this compiler." 195 | #endif 196 | #else 197 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var 198 | #endif 199 | 200 | #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 201 | #if ((defined __GNUC__) || (defined __clang__)) 202 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 203 | #elif (defined __ICCARM__) || (defined __ICCRX__) 204 | #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 205 | Var 206 | #elif (defined __CC_ARM) 207 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 208 | #else 209 | #error "Section placement not supported for this compiler." 210 | #endif 211 | #else 212 | #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 213 | #endif 214 | 215 | #if SEGGER_RTT_ALIGNMENT 216 | #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 217 | #else 218 | #define SEGGER_RTT_CB_ALIGN(Var) Var 219 | #endif 220 | 221 | #if SEGGER_RTT_BUFFER_ALIGNMENT 222 | #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 223 | #else 224 | #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 225 | #endif 226 | 227 | 228 | #if defined(SEGGER_RTT_SECTION) 229 | #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 230 | #else 231 | #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 232 | #endif 233 | 234 | #if defined(SEGGER_RTT_BUFFER_SECTION) 235 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 236 | #else 237 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 238 | #endif 239 | 240 | /********************************************************************* 241 | * 242 | * Static const data 243 | * 244 | ********************************************************************** 245 | */ 246 | 247 | static const unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 248 | 249 | /********************************************************************* 250 | * 251 | * Static data 252 | * 253 | ********************************************************************** 254 | */ 255 | 256 | // 257 | // RTT Control Block and allocate buffers for channel 0 258 | // 259 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 260 | #if ((defined __GNUC__) || (defined __clang__)) 261 | SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 262 | static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 263 | static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 264 | #elif (defined __ICCARM__) 265 | #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 266 | SEGGER_RTT_CB _SEGGER_RTT; 267 | #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 268 | static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)]; 269 | #pragma data_alignment=SEGGER_RTT_CPU_CACHE_LINE_SIZE 270 | static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)]; 271 | #else 272 | #error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned" 273 | #endif 274 | #else 275 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); 276 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); 277 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); 278 | #endif 279 | 280 | static unsigned char _ActiveTerminal; 281 | 282 | /********************************************************************* 283 | * 284 | * Static functions 285 | * 286 | ********************************************************************** 287 | */ 288 | 289 | /********************************************************************* 290 | * 291 | * _DoInit() 292 | * 293 | * Function description 294 | * Initializes the control block an buffers. 295 | * 296 | * Notes 297 | * (1) May only be called via INIT() to avoid overriding settings. 298 | * The only exception is SEGGER_RTT_Init(), to make an intentional override possible. 299 | */ 300 | #define INIT() \ 301 | do { \ 302 | volatile SEGGER_RTT_CB* pRTTCBInit; \ 303 | pRTTCBInit = (volatile SEGGER_RTT_CB*)((uintptr_t)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \ 304 | if (pRTTCBInit->acID[0] != 'S') { \ 305 | _DoInit(); \ 306 | } \ 307 | } while (0) 308 | 309 | static void _DoInit(void) { 310 | volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block 311 | 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 312 | unsigned i; 313 | // 314 | // Initialize control block 315 | // 316 | p = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 317 | memset((SEGGER_RTT_CB*)p, 0, sizeof(_SEGGER_RTT)); // Make sure that the RTT CB is always zero initialized. 318 | p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; 319 | p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; 320 | // 321 | // Initialize up buffer 0 322 | // 323 | p->aUp[0].sName = "Terminal"; 324 | p->aUp[0].pBuffer = _acUpBuffer; 325 | p->aUp[0].SizeOfBuffer = BUFFER_SIZE_UP; 326 | p->aUp[0].RdOff = 0u; 327 | p->aUp[0].WrOff = 0u; 328 | p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; 329 | // 330 | // Initialize down buffer 0 331 | // 332 | p->aDown[0].sName = "Terminal"; 333 | p->aDown[0].pBuffer = _acDownBuffer; 334 | p->aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN; 335 | p->aDown[0].RdOff = 0u; 336 | p->aDown[0].WrOff = 0u; 337 | p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; 338 | // 339 | // Finish initialization of the control block. 340 | // Copy Id string backwards to make sure that "SEGGER RTT" is not found in initializer memory (usually flash), 341 | // as this would cause J-Link to "find" the control block at a wrong address. 342 | // 343 | RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 344 | for (i = 0; i < sizeof(_aInitStr) - 1; ++i) { 345 | p->acID[i] = _aInitStr[sizeof(_aInitStr) - 2 - i]; // Skip terminating \0 at the end of the array 346 | } 347 | RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 348 | } 349 | 350 | /********************************************************************* 351 | * 352 | * _WriteBlocking() 353 | * 354 | * Function description 355 | * Stores a specified number of characters in SEGGER RTT ring buffer 356 | * and updates the associated write pointer which is periodically 357 | * read by the host. 358 | * The caller is responsible for managing the write chunk sizes as 359 | * _WriteBlocking() will block until all data has been posted successfully. 360 | * 361 | * Parameters 362 | * pRing Ring buffer to post to. 363 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 364 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 365 | * 366 | * Return value 367 | * >= 0 - Number of bytes written into buffer. 368 | */ 369 | static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { 370 | unsigned NumBytesToWrite; 371 | unsigned NumBytesWritten; 372 | unsigned RdOff; 373 | unsigned WrOff; 374 | volatile char* pDst; 375 | // 376 | // Write data to buffer and handle wrap-around if necessary 377 | // 378 | NumBytesWritten = 0u; 379 | WrOff = pRing->WrOff; 380 | do { 381 | RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime 382 | if (RdOff > WrOff) { 383 | NumBytesToWrite = RdOff - WrOff - 1u; 384 | } else { 385 | NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); 386 | } 387 | NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around 388 | NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); 389 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 390 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 391 | NumBytesWritten += NumBytesToWrite; 392 | NumBytes -= NumBytesToWrite; 393 | WrOff += NumBytesToWrite; 394 | while (NumBytesToWrite--) { 395 | *pDst++ = *pBuffer++; 396 | }; 397 | #else 398 | SEGGER_RTT_MEMCPY((void*)pDst, pBuffer, NumBytesToWrite); 399 | NumBytesWritten += NumBytesToWrite; 400 | pBuffer += NumBytesToWrite; 401 | NumBytes -= NumBytesToWrite; 402 | WrOff += NumBytesToWrite; 403 | #endif 404 | if (WrOff == pRing->SizeOfBuffer) { 405 | WrOff = 0u; 406 | } 407 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 408 | pRing->WrOff = WrOff; 409 | } while (NumBytes); 410 | return NumBytesWritten; 411 | } 412 | 413 | /********************************************************************* 414 | * 415 | * _WriteNoCheck() 416 | * 417 | * Function description 418 | * Stores a specified number of characters in SEGGER RTT ring buffer 419 | * and updates the associated write pointer which is periodically 420 | * read by the host. 421 | * It is callers responsibility to make sure data actually fits in buffer. 422 | * 423 | * Parameters 424 | * pRing Ring buffer to post to. 425 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 426 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 427 | * 428 | * Notes 429 | * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking 430 | */ 431 | static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { 432 | unsigned NumBytesAtOnce; 433 | unsigned WrOff; 434 | unsigned Rem; 435 | volatile char* pDst; 436 | 437 | WrOff = pRing->WrOff; 438 | Rem = pRing->SizeOfBuffer - WrOff; 439 | if (Rem > NumBytes) { 440 | // 441 | // All data fits before wrap around 442 | // 443 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 444 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 445 | WrOff += NumBytes; 446 | while (NumBytes--) { 447 | *pDst++ = *pData++; 448 | }; 449 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 450 | pRing->WrOff = WrOff; 451 | #else 452 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 453 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 454 | pRing->WrOff = WrOff + NumBytes; 455 | #endif 456 | } else { 457 | // 458 | // We reach the end of the buffer, so need to wrap around 459 | // 460 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 461 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 462 | NumBytesAtOnce = Rem; 463 | while (NumBytesAtOnce--) { 464 | *pDst++ = *pData++; 465 | }; 466 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 467 | NumBytesAtOnce = NumBytes - Rem; 468 | while (NumBytesAtOnce--) { 469 | *pDst++ = *pData++; 470 | }; 471 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 472 | pRing->WrOff = NumBytes - Rem; 473 | #else 474 | NumBytesAtOnce = Rem; 475 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 476 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytesAtOnce); 477 | NumBytesAtOnce = NumBytes - Rem; 478 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 479 | SEGGER_RTT_MEMCPY((void*)pDst, pData + Rem, NumBytesAtOnce); 480 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 481 | pRing->WrOff = NumBytesAtOnce; 482 | #endif 483 | } 484 | } 485 | 486 | /********************************************************************* 487 | * 488 | * _PostTerminalSwitch() 489 | * 490 | * Function description 491 | * Switch terminal to the given terminal ID. It is the caller's 492 | * responsibility to ensure the terminal ID is correct and there is 493 | * enough space in the buffer for this to complete successfully. 494 | * 495 | * Parameters 496 | * pRing Ring buffer to post to. 497 | * TerminalId Terminal ID to switch to. 498 | */ 499 | static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { 500 | unsigned char ac[2]; 501 | 502 | ac[0] = 0xFFu; 503 | ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit 504 | _WriteBlocking(pRing, (const char*)ac, 2u); 505 | } 506 | 507 | /********************************************************************* 508 | * 509 | * _GetAvailWriteSpace() 510 | * 511 | * Function description 512 | * Returns the number of bytes that can be written to the ring 513 | * buffer without blocking. 514 | * 515 | * Parameters 516 | * pRing Ring buffer to check. 517 | * 518 | * Return value 519 | * Number of bytes that are free in the buffer. 520 | */ 521 | static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { 522 | unsigned RdOff; 523 | unsigned WrOff; 524 | unsigned r; 525 | // 526 | // Avoid warnings regarding volatile access order. It's not a problem 527 | // in this case, but dampen compiler enthusiasm. 528 | // 529 | RdOff = pRing->RdOff; 530 | WrOff = pRing->WrOff; 531 | if (RdOff <= WrOff) { 532 | r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; 533 | } else { 534 | r = RdOff - WrOff - 1u; 535 | } 536 | return r; 537 | } 538 | 539 | /********************************************************************* 540 | * 541 | * Public code 542 | * 543 | ********************************************************************** 544 | */ 545 | 546 | /********************************************************************* 547 | * 548 | * SEGGER_RTT_ReadUpBufferNoLock() 549 | * 550 | * Function description 551 | * Reads characters from SEGGER real-time-terminal control block 552 | * which have been previously stored by the application. 553 | * Do not lock against interrupts and multiple access. 554 | * Used to do the same operation that J-Link does, to transfer 555 | * RTT data via other channels, such as TCP/IP or UART. 556 | * 557 | * Parameters 558 | * BufferIndex Index of Up-buffer to be used. 559 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 560 | * BufferSize Size of the target application buffer. 561 | * 562 | * Return value 563 | * Number of bytes that have been read. 564 | * 565 | * Additional information 566 | * This function must not be called when J-Link might also do RTT. 567 | */ 568 | unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 569 | unsigned NumBytesRem; 570 | unsigned NumBytesRead; 571 | unsigned RdOff; 572 | unsigned WrOff; 573 | unsigned char* pBuffer; 574 | SEGGER_RTT_BUFFER_UP* pRing; 575 | volatile char* pSrc; 576 | 577 | INIT(); 578 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 579 | pBuffer = (unsigned char*)pData; 580 | RdOff = pRing->RdOff; 581 | WrOff = pRing->WrOff; 582 | NumBytesRead = 0u; 583 | // 584 | // Read from current read position to wrap-around of buffer, first 585 | // 586 | if (RdOff > WrOff) { 587 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 588 | NumBytesRem = MIN(NumBytesRem, BufferSize); 589 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 590 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 591 | NumBytesRead += NumBytesRem; 592 | BufferSize -= NumBytesRem; 593 | RdOff += NumBytesRem; 594 | while (NumBytesRem--) { 595 | *pBuffer++ = *pSrc++; 596 | }; 597 | #else 598 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 599 | NumBytesRead += NumBytesRem; 600 | pBuffer += NumBytesRem; 601 | BufferSize -= NumBytesRem; 602 | RdOff += NumBytesRem; 603 | #endif 604 | // 605 | // Handle wrap-around of buffer 606 | // 607 | if (RdOff == pRing->SizeOfBuffer) { 608 | RdOff = 0u; 609 | } 610 | } 611 | // 612 | // Read remaining items of buffer 613 | // 614 | NumBytesRem = WrOff - RdOff; 615 | NumBytesRem = MIN(NumBytesRem, BufferSize); 616 | if (NumBytesRem > 0u) { 617 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 618 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 619 | NumBytesRead += NumBytesRem; 620 | BufferSize -= NumBytesRem; 621 | RdOff += NumBytesRem; 622 | while (NumBytesRem--) { 623 | *pBuffer++ = *pSrc++; 624 | }; 625 | #else 626 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 627 | NumBytesRead += NumBytesRem; 628 | pBuffer += NumBytesRem; 629 | BufferSize -= NumBytesRem; 630 | RdOff += NumBytesRem; 631 | #endif 632 | } 633 | // 634 | // Update read offset of buffer 635 | // 636 | if (NumBytesRead) { 637 | pRing->RdOff = RdOff; 638 | } 639 | // 640 | return NumBytesRead; 641 | } 642 | 643 | /********************************************************************* 644 | * 645 | * SEGGER_RTT_ReadNoLock() 646 | * 647 | * Function description 648 | * Reads characters from SEGGER real-time-terminal control block 649 | * which have been previously stored by the host. 650 | * Do not lock against interrupts and multiple access. 651 | * 652 | * Parameters 653 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 654 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 655 | * BufferSize Size of the target application buffer. 656 | * 657 | * Return value 658 | * Number of bytes that have been read. 659 | */ 660 | unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 661 | unsigned NumBytesRem; 662 | unsigned NumBytesRead; 663 | unsigned RdOff; 664 | unsigned WrOff; 665 | unsigned char* pBuffer; 666 | SEGGER_RTT_BUFFER_DOWN* pRing; 667 | volatile char* pSrc; 668 | // 669 | INIT(); 670 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_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 671 | pBuffer = (unsigned char*)pData; 672 | RdOff = pRing->RdOff; 673 | WrOff = pRing->WrOff; 674 | NumBytesRead = 0u; 675 | // 676 | // Read from current read position to wrap-around of buffer, first 677 | // 678 | if (RdOff > WrOff) { 679 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 680 | NumBytesRem = MIN(NumBytesRem, BufferSize); 681 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 682 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 683 | NumBytesRead += NumBytesRem; 684 | BufferSize -= NumBytesRem; 685 | RdOff += NumBytesRem; 686 | while (NumBytesRem--) { 687 | *pBuffer++ = *pSrc++; 688 | }; 689 | #else 690 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 691 | NumBytesRead += NumBytesRem; 692 | pBuffer += NumBytesRem; 693 | BufferSize -= NumBytesRem; 694 | RdOff += NumBytesRem; 695 | #endif 696 | // 697 | // Handle wrap-around of buffer 698 | // 699 | if (RdOff == pRing->SizeOfBuffer) { 700 | RdOff = 0u; 701 | } 702 | } 703 | // 704 | // Read remaining items of buffer 705 | // 706 | NumBytesRem = WrOff - RdOff; 707 | NumBytesRem = MIN(NumBytesRem, BufferSize); 708 | if (NumBytesRem > 0u) { 709 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 710 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 711 | NumBytesRead += NumBytesRem; 712 | BufferSize -= NumBytesRem; 713 | RdOff += NumBytesRem; 714 | while (NumBytesRem--) { 715 | *pBuffer++ = *pSrc++; 716 | }; 717 | #else 718 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 719 | NumBytesRead += NumBytesRem; 720 | pBuffer += NumBytesRem; 721 | BufferSize -= NumBytesRem; 722 | RdOff += NumBytesRem; 723 | #endif 724 | } 725 | if (NumBytesRead) { 726 | pRing->RdOff = RdOff; 727 | } 728 | // 729 | return NumBytesRead; 730 | } 731 | 732 | /********************************************************************* 733 | * 734 | * SEGGER_RTT_ReadUpBuffer 735 | * 736 | * Function description 737 | * Reads characters from SEGGER real-time-terminal control block 738 | * which have been previously stored by the application. 739 | * Used to do the same operation that J-Link does, to transfer 740 | * RTT data via other channels, such as TCP/IP or UART. 741 | * 742 | * Parameters 743 | * BufferIndex Index of Up-buffer to be used. 744 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 745 | * BufferSize Size of the target application buffer. 746 | * 747 | * Return value 748 | * Number of bytes that have been read. 749 | * 750 | * Additional information 751 | * This function must not be called when J-Link might also do RTT. 752 | * This function locks against all other RTT operations. I.e. during 753 | * the read operation, writing is also locked. 754 | * If only one consumer reads from the up buffer, 755 | * call sEGGER_RTT_ReadUpBufferNoLock() instead. 756 | */ 757 | unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 758 | unsigned NumBytesRead; 759 | 760 | SEGGER_RTT_LOCK(); 761 | // 762 | // Call the non-locking read function 763 | // 764 | NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); 765 | // 766 | // Finish up. 767 | // 768 | SEGGER_RTT_UNLOCK(); 769 | // 770 | return NumBytesRead; 771 | } 772 | 773 | /********************************************************************* 774 | * 775 | * SEGGER_RTT_Read 776 | * 777 | * Function description 778 | * Reads characters from SEGGER real-time-terminal control block 779 | * which have been previously stored by the host. 780 | * 781 | * Parameters 782 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 783 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 784 | * BufferSize Size of the target application buffer. 785 | * 786 | * Return value 787 | * Number of bytes that have been read. 788 | */ 789 | unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 790 | unsigned NumBytesRead; 791 | 792 | SEGGER_RTT_LOCK(); 793 | // 794 | // Call the non-locking read function 795 | // 796 | NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); 797 | // 798 | // Finish up. 799 | // 800 | SEGGER_RTT_UNLOCK(); 801 | // 802 | return NumBytesRead; 803 | } 804 | 805 | /********************************************************************* 806 | * 807 | * SEGGER_RTT_WriteWithOverwriteNoLock 808 | * 809 | * Function description 810 | * Stores a specified number of characters in SEGGER RTT 811 | * control block. 812 | * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 813 | * and overwrites data if the data does not fit into the buffer. 814 | * 815 | * Parameters 816 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 817 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 818 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 819 | * 820 | * Notes 821 | * (1) If there is not enough space in the "Up"-buffer, data is overwritten. 822 | * (2) For performance reasons this function does not call Init() 823 | * and may only be called after RTT has been initialized. 824 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 825 | * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 826 | * connection reads RTT data. 827 | */ 828 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 829 | const char* pData; 830 | SEGGER_RTT_BUFFER_UP* pRing; 831 | unsigned Avail; 832 | volatile char* pDst; 833 | // 834 | // Get "to-host" ring buffer and copy some elements into local variables. 835 | // 836 | pData = (const char *)pBuffer; 837 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 838 | // 839 | // Check if we will overwrite data and need to adjust the RdOff. 840 | // 841 | if (pRing->WrOff == pRing->RdOff) { 842 | Avail = pRing->SizeOfBuffer - 1u; 843 | } else if ( pRing->WrOff < pRing->RdOff) { 844 | Avail = pRing->RdOff - pRing->WrOff - 1u; 845 | } else { 846 | Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; 847 | } 848 | if (NumBytes > Avail) { 849 | pRing->RdOff += (NumBytes - Avail); 850 | while (pRing->RdOff >= pRing->SizeOfBuffer) { 851 | pRing->RdOff -= pRing->SizeOfBuffer; 852 | } 853 | } 854 | // 855 | // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds 856 | // 857 | Avail = pRing->SizeOfBuffer - pRing->WrOff; 858 | do { 859 | if (Avail > NumBytes) { 860 | // 861 | // Last round 862 | // 863 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 864 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 865 | Avail = NumBytes; 866 | while (NumBytes--) { 867 | *pDst++ = *pData++; 868 | }; 869 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 870 | pRing->WrOff += Avail; 871 | #else 872 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 873 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 874 | pRing->WrOff += NumBytes; 875 | #endif 876 | break; 877 | } else { 878 | // 879 | // Wrap-around necessary, write until wrap-around and reset WrOff 880 | // 881 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 882 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 883 | NumBytes -= Avail; 884 | while (Avail--) { 885 | *pDst++ = *pData++; 886 | }; 887 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 888 | pRing->WrOff = 0; 889 | #else 890 | SEGGER_RTT_MEMCPY((void*)pDst, pData, Avail); 891 | pData += Avail; 892 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 893 | pRing->WrOff = 0; 894 | NumBytes -= Avail; 895 | #endif 896 | Avail = (pRing->SizeOfBuffer - 1); 897 | } 898 | } while (NumBytes); 899 | } 900 | 901 | /********************************************************************* 902 | * 903 | * SEGGER_RTT_WriteSkipNoLock 904 | * 905 | * Function description 906 | * Stores a specified number of characters in SEGGER RTT 907 | * control block which is then read by the host. 908 | * SEGGER_RTT_WriteSkipNoLock does not lock the application and 909 | * skips all data, if the data does not fit into the buffer. 910 | * 911 | * Parameters 912 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 913 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 914 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 915 | * MUST be > 0!!! 916 | * This is done for performance reasons, so no initial check has do be done. 917 | * 918 | * Return value 919 | * 1: Data has been copied 920 | * 0: No space, data has not been copied 921 | * 922 | * Notes 923 | * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 924 | * (2) For performance reasons this function does not call Init() 925 | * and may only be called after RTT has been initialized. 926 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 927 | */ 928 | #if (RTT_USE_ASM == 0) 929 | unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 930 | const char* pData; 931 | SEGGER_RTT_BUFFER_UP* pRing; 932 | unsigned Avail; 933 | unsigned RdOff; 934 | unsigned WrOff; 935 | unsigned Rem; 936 | volatile char* pDst; 937 | // 938 | // Cases: 939 | // 1) RdOff <= WrOff => Space until wrap-around is sufficient 940 | // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 941 | // 3) RdOff < WrOff => No space in buf 942 | // 4) RdOff > WrOff => Space is sufficient 943 | // 5) RdOff > WrOff => No space in buf 944 | // 945 | // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 946 | // 947 | pData = (const char *)pBuffer; 948 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 949 | RdOff = pRing->RdOff; 950 | WrOff = pRing->WrOff; 951 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 952 | if (RdOff <= WrOff) { // Case 1), 2) or 3) 953 | Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 954 | if (Avail >= NumBytes) { // Case 1)? 955 | memcpy((void*)pDst, pData, NumBytes); 956 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 957 | pRing->WrOff = WrOff + NumBytes; 958 | return 1; 959 | } 960 | Avail += RdOff; // Space incl. wrap-around 961 | if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) 962 | Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 963 | memcpy((void*)pDst, pData, Rem); // Copy 1st chunk 964 | NumBytes -= Rem; 965 | // 966 | // Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used 967 | // But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element 968 | // In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks 969 | // Therefore, check if 2nd memcpy is necessary at all 970 | // 971 | if (NumBytes) { 972 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 973 | memcpy((void*)pDst, pData + Rem, NumBytes); 974 | } 975 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 976 | pRing->WrOff = NumBytes; 977 | return 1; 978 | } 979 | } else { // Potential case 4) 980 | Avail = RdOff - WrOff - 1u; 981 | if (Avail >= NumBytes) { // Case 4)? => If not, we have case 5) (does not fit) 982 | memcpy((void*)pDst, pData, NumBytes); 983 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 984 | pRing->WrOff = WrOff + NumBytes; 985 | return 1; 986 | } 987 | } 988 | return 0; // No space in buffer 989 | } 990 | #endif 991 | 992 | /********************************************************************* 993 | * 994 | * SEGGER_RTT_WriteDownBufferNoLock 995 | * 996 | * Function description 997 | * Stores a specified number of characters in SEGGER RTT 998 | * control block inside a buffer. 999 | * SEGGER_RTT_WriteDownBufferNoLock does not lock the application. 1000 | * Used to do the same operation that J-Link does, to transfer 1001 | * RTT data from other channels, such as TCP/IP or UART. 1002 | * 1003 | * Parameters 1004 | * BufferIndex Index of "Down"-buffer to be used. 1005 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1006 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1007 | * 1008 | * Return value 1009 | * Number of bytes which have been stored in the "Down"-buffer. 1010 | * 1011 | * Notes 1012 | * (1) Data is stored according to buffer flags. 1013 | * (2) For performance reasons this function does not call Init() 1014 | * and may only be called after RTT has been initialized. 1015 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1016 | * 1017 | * Additional information 1018 | * This function must not be called when J-Link might also do RTT. 1019 | */ 1020 | unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1021 | unsigned Status; 1022 | unsigned Avail; 1023 | const char* pData; 1024 | SEGGER_RTT_BUFFER_UP* pRing; 1025 | // 1026 | // Get "to-target" ring buffer. 1027 | // It is save to cast that to a "to-host" buffer. Up and Down buffer differ in volatility of offsets that might be modified by J-Link. 1028 | // 1029 | pData = (const char *)pBuffer; 1030 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1031 | // 1032 | // How we output depends upon the mode... 1033 | // 1034 | switch (pRing->Flags) { 1035 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1036 | // 1037 | // If we are in skip mode and there is no space for the whole 1038 | // of this output, don't bother. 1039 | // 1040 | Avail = _GetAvailWriteSpace(pRing); 1041 | if (Avail < NumBytes) { 1042 | Status = 0u; 1043 | } else { 1044 | Status = NumBytes; 1045 | _WriteNoCheck(pRing, pData, NumBytes); 1046 | } 1047 | break; 1048 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1049 | // 1050 | // If we are in trim mode, trim to what we can output without blocking. 1051 | // 1052 | Avail = _GetAvailWriteSpace(pRing); 1053 | Status = Avail < NumBytes ? Avail : NumBytes; 1054 | _WriteNoCheck(pRing, pData, Status); 1055 | break; 1056 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1057 | // 1058 | // If we are in blocking mode, output everything. 1059 | // 1060 | Status = _WriteBlocking(pRing, pData, NumBytes); 1061 | break; 1062 | default: 1063 | Status = 0u; 1064 | break; 1065 | } 1066 | // 1067 | // Finish up. 1068 | // 1069 | return Status; 1070 | } 1071 | 1072 | /********************************************************************* 1073 | * 1074 | * SEGGER_RTT_WriteNoLock 1075 | * 1076 | * Function description 1077 | * Stores a specified number of characters in SEGGER RTT 1078 | * control block which is then read by the host. 1079 | * SEGGER_RTT_WriteNoLock does not lock the application. 1080 | * 1081 | * Parameters 1082 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1083 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1084 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1085 | * 1086 | * Return value 1087 | * Number of bytes which have been stored in the "Up"-buffer. 1088 | * 1089 | * Notes 1090 | * (1) Data is stored according to buffer flags. 1091 | * (2) For performance reasons this function does not call Init() 1092 | * and may only be called after RTT has been initialized. 1093 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1094 | */ 1095 | unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1096 | unsigned Status; 1097 | unsigned Avail; 1098 | const char* pData; 1099 | SEGGER_RTT_BUFFER_UP* pRing; 1100 | // 1101 | // Get "to-host" ring buffer. 1102 | // 1103 | pData = (const char *)pBuffer; 1104 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1105 | // 1106 | // How we output depends upon the mode... 1107 | // 1108 | switch (pRing->Flags) { 1109 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1110 | // 1111 | // If we are in skip mode and there is no space for the whole 1112 | // of this output, don't bother. 1113 | // 1114 | Avail = _GetAvailWriteSpace(pRing); 1115 | if (Avail < NumBytes) { 1116 | Status = 0u; 1117 | } else { 1118 | Status = NumBytes; 1119 | _WriteNoCheck(pRing, pData, NumBytes); 1120 | } 1121 | break; 1122 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1123 | // 1124 | // If we are in trim mode, trim to what we can output without blocking. 1125 | // 1126 | Avail = _GetAvailWriteSpace(pRing); 1127 | Status = Avail < NumBytes ? Avail : NumBytes; 1128 | _WriteNoCheck(pRing, pData, Status); 1129 | break; 1130 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1131 | // 1132 | // If we are in blocking mode, output everything. 1133 | // 1134 | Status = _WriteBlocking(pRing, pData, NumBytes); 1135 | break; 1136 | default: 1137 | Status = 0u; 1138 | break; 1139 | } 1140 | // 1141 | // Finish up. 1142 | // 1143 | return Status; 1144 | } 1145 | 1146 | /********************************************************************* 1147 | * 1148 | * SEGGER_RTT_WriteDownBuffer 1149 | * 1150 | * Function description 1151 | * Stores a specified number of characters in SEGGER RTT control block in a buffer. 1152 | * 1153 | * Parameters 1154 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1155 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1156 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1157 | * 1158 | * Return value 1159 | * Number of bytes which have been stored in the "Down"-buffer. 1160 | * 1161 | * Notes 1162 | * (1) Data is stored according to buffer flags. 1163 | * 1164 | * Additional information 1165 | * This function must not be called when J-Link might also do RTT. 1166 | * This function locks against all other RTT operations. I.e. during 1167 | * the write operation, writing from the application is also locked. 1168 | * If only one consumer writes to the down buffer, 1169 | * call SEGGER_RTT_WriteDownBufferNoLock() instead. 1170 | */ 1171 | unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1172 | unsigned Status; 1173 | 1174 | INIT(); 1175 | SEGGER_RTT_LOCK(); 1176 | Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1177 | SEGGER_RTT_UNLOCK(); 1178 | return Status; 1179 | } 1180 | 1181 | /********************************************************************* 1182 | * 1183 | * SEGGER_RTT_Write 1184 | * 1185 | * Function description 1186 | * Stores a specified number of characters in SEGGER RTT 1187 | * control block which is then read by the host. 1188 | * 1189 | * Parameters 1190 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1191 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1192 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1193 | * 1194 | * Return value 1195 | * Number of bytes which have been stored in the "Up"-buffer. 1196 | * 1197 | * Notes 1198 | * (1) Data is stored according to buffer flags. 1199 | */ 1200 | unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1201 | unsigned Status; 1202 | 1203 | INIT(); 1204 | SEGGER_RTT_LOCK(); 1205 | Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1206 | SEGGER_RTT_UNLOCK(); 1207 | return Status; 1208 | } 1209 | 1210 | /********************************************************************* 1211 | * 1212 | * SEGGER_RTT_WriteString 1213 | * 1214 | * Function description 1215 | * Stores string in SEGGER RTT control block. 1216 | * This data is read by the host. 1217 | * 1218 | * Parameters 1219 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1220 | * s Pointer to string. 1221 | * 1222 | * Return value 1223 | * Number of bytes which have been stored in the "Up"-buffer. 1224 | * 1225 | * Notes 1226 | * (1) Data is stored according to buffer flags. 1227 | * (2) String passed to this function has to be \0 terminated 1228 | * (3) \0 termination character is *not* stored in RTT buffer 1229 | */ 1230 | unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1231 | unsigned Len; 1232 | 1233 | Len = STRLEN(s); 1234 | return SEGGER_RTT_Write(BufferIndex, s, Len); 1235 | } 1236 | 1237 | /********************************************************************* 1238 | * 1239 | * SEGGER_RTT_PutCharSkipNoLock 1240 | * 1241 | * Function description 1242 | * Stores a single character/byte in SEGGER RTT buffer. 1243 | * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1244 | * skips the byte, if it does not fit into the buffer. 1245 | * 1246 | * Parameters 1247 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1248 | * c Byte to be stored. 1249 | * 1250 | * Return value 1251 | * Number of bytes which have been stored in the "Up"-buffer. 1252 | * 1253 | * Notes 1254 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1255 | * (2) For performance reasons this function does not call Init() 1256 | * and may only be called after RTT has been initialized. 1257 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1258 | */ 1259 | 1260 | unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1261 | SEGGER_RTT_BUFFER_UP* pRing; 1262 | unsigned WrOff; 1263 | unsigned Status; 1264 | volatile char* pDst; 1265 | // 1266 | // Get "to-host" ring buffer. 1267 | // 1268 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1269 | // 1270 | // Get write position and handle wrap-around if necessary 1271 | // 1272 | WrOff = pRing->WrOff + 1; 1273 | if (WrOff == pRing->SizeOfBuffer) { 1274 | WrOff = 0; 1275 | } 1276 | // 1277 | // Output byte if free space is available 1278 | // 1279 | if (WrOff != pRing->RdOff) { 1280 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1281 | *pDst = c; 1282 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1283 | pRing->WrOff = WrOff; 1284 | Status = 1; 1285 | } else { 1286 | Status = 0; 1287 | } 1288 | // 1289 | return Status; 1290 | } 1291 | 1292 | /********************************************************************* 1293 | * 1294 | * SEGGER_RTT_PutCharSkip 1295 | * 1296 | * Function description 1297 | * Stores a single character/byte in SEGGER RTT buffer. 1298 | * 1299 | * Parameters 1300 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1301 | * c Byte to be stored. 1302 | * 1303 | * Return value 1304 | * Number of bytes which have been stored in the "Up"-buffer. 1305 | * 1306 | * Notes 1307 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1308 | */ 1309 | 1310 | unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1311 | SEGGER_RTT_BUFFER_UP* pRing; 1312 | unsigned WrOff; 1313 | unsigned Status; 1314 | volatile char* pDst; 1315 | // 1316 | // Prepare 1317 | // 1318 | INIT(); 1319 | SEGGER_RTT_LOCK(); 1320 | // 1321 | // Get "to-host" ring buffer. 1322 | // 1323 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1324 | // 1325 | // Get write position and handle wrap-around if necessary 1326 | // 1327 | WrOff = pRing->WrOff + 1; 1328 | if (WrOff == pRing->SizeOfBuffer) { 1329 | WrOff = 0; 1330 | } 1331 | // 1332 | // Output byte if free space is available 1333 | // 1334 | if (WrOff != pRing->RdOff) { 1335 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1336 | *pDst = c; 1337 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1338 | pRing->WrOff = WrOff; 1339 | Status = 1; 1340 | } else { 1341 | Status = 0; 1342 | } 1343 | // 1344 | // Finish up. 1345 | // 1346 | SEGGER_RTT_UNLOCK(); 1347 | // 1348 | return Status; 1349 | } 1350 | 1351 | /********************************************************************* 1352 | * 1353 | * SEGGER_RTT_PutChar 1354 | * 1355 | * Function description 1356 | * Stores a single character/byte in SEGGER RTT buffer. 1357 | * 1358 | * Parameters 1359 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1360 | * c Byte to be stored. 1361 | * 1362 | * Return value 1363 | * Number of bytes which have been stored in the "Up"-buffer. 1364 | * 1365 | * Notes 1366 | * (1) Data is stored according to buffer flags. 1367 | */ 1368 | 1369 | unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1370 | SEGGER_RTT_BUFFER_UP* pRing; 1371 | unsigned WrOff; 1372 | unsigned Status; 1373 | volatile char* pDst; 1374 | // 1375 | // Prepare 1376 | // 1377 | INIT(); 1378 | SEGGER_RTT_LOCK(); 1379 | // 1380 | // Get "to-host" ring buffer. 1381 | // 1382 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1383 | // 1384 | // Get write position and handle wrap-around if necessary 1385 | // 1386 | WrOff = pRing->WrOff + 1; 1387 | if (WrOff == pRing->SizeOfBuffer) { 1388 | WrOff = 0; 1389 | } 1390 | // 1391 | // Wait for free space if mode is set to blocking 1392 | // 1393 | if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1394 | while (WrOff == pRing->RdOff) { 1395 | ; 1396 | } 1397 | } 1398 | // 1399 | // Output byte if free space is available 1400 | // 1401 | if (WrOff != pRing->RdOff) { 1402 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1403 | *pDst = c; 1404 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1405 | pRing->WrOff = WrOff; 1406 | Status = 1; 1407 | } else { 1408 | Status = 0; 1409 | } 1410 | // 1411 | // Finish up. 1412 | // 1413 | SEGGER_RTT_UNLOCK(); 1414 | return Status; 1415 | } 1416 | 1417 | /********************************************************************* 1418 | * 1419 | * SEGGER_RTT_GetKey 1420 | * 1421 | * Function description 1422 | * Reads one character from the SEGGER RTT buffer. 1423 | * Host has previously stored data there. 1424 | * 1425 | * Return value 1426 | * < 0 - No character available (buffer empty). 1427 | * >= 0 - Character which has been read. (Possible values: 0 - 255) 1428 | * 1429 | * Notes 1430 | * (1) This function is only specified for accesses to RTT buffer 0. 1431 | */ 1432 | int SEGGER_RTT_GetKey(void) { 1433 | char c; 1434 | int r; 1435 | 1436 | r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1437 | if (r == 1) { 1438 | r = (int)(unsigned char)c; 1439 | } else { 1440 | r = -1; 1441 | } 1442 | return r; 1443 | } 1444 | 1445 | /********************************************************************* 1446 | * 1447 | * SEGGER_RTT_WaitKey 1448 | * 1449 | * Function description 1450 | * Waits until at least one character is avaible in the SEGGER RTT buffer. 1451 | * Once a character is available, it is read and this function returns. 1452 | * 1453 | * Return value 1454 | * >=0 - Character which has been read. 1455 | * 1456 | * Notes 1457 | * (1) This function is only specified for accesses to RTT buffer 0 1458 | * (2) This function is blocking if no character is present in RTT buffer 1459 | */ 1460 | int SEGGER_RTT_WaitKey(void) { 1461 | int r; 1462 | 1463 | do { 1464 | r = SEGGER_RTT_GetKey(); 1465 | } while (r < 0); 1466 | return r; 1467 | } 1468 | 1469 | /********************************************************************* 1470 | * 1471 | * SEGGER_RTT_HasKey 1472 | * 1473 | * Function description 1474 | * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1475 | * 1476 | * Return value 1477 | * == 0 - No characters are available to read. 1478 | * == 1 - At least one character is available. 1479 | * 1480 | * Notes 1481 | * (1) This function is only specified for accesses to RTT buffer 0 1482 | */ 1483 | int SEGGER_RTT_HasKey(void) { 1484 | SEGGER_RTT_BUFFER_DOWN* pRing; 1485 | unsigned RdOff; 1486 | int r; 1487 | 1488 | INIT(); 1489 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_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 1490 | RdOff = pRing->RdOff; 1491 | if (RdOff != pRing->WrOff) { 1492 | r = 1; 1493 | } else { 1494 | r = 0; 1495 | } 1496 | return r; 1497 | } 1498 | 1499 | /********************************************************************* 1500 | * 1501 | * SEGGER_RTT_HasData 1502 | * 1503 | * Function description 1504 | * Check if there is data from the host in the given buffer. 1505 | * 1506 | * Return value: 1507 | * ==0: No data 1508 | * !=0: Data in buffer 1509 | * 1510 | */ 1511 | unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1512 | SEGGER_RTT_BUFFER_DOWN* pRing; 1513 | unsigned v; 1514 | 1515 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((uintptr_t)&_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 1516 | v = pRing->WrOff; 1517 | return v - pRing->RdOff; 1518 | } 1519 | 1520 | /********************************************************************* 1521 | * 1522 | * SEGGER_RTT_HasDataUp 1523 | * 1524 | * Function description 1525 | * Check if there is data remaining to be sent in the given buffer. 1526 | * 1527 | * Return value: 1528 | * ==0: No data 1529 | * !=0: Data in buffer 1530 | * 1531 | */ 1532 | unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { 1533 | SEGGER_RTT_BUFFER_UP* pRing; 1534 | unsigned v; 1535 | 1536 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 1537 | v = pRing->RdOff; 1538 | return pRing->WrOff - v; 1539 | } 1540 | 1541 | /********************************************************************* 1542 | * 1543 | * SEGGER_RTT_AllocDownBuffer 1544 | * 1545 | * Function description 1546 | * Run-time configuration of the next down-buffer (H->T). 1547 | * The next buffer, which is not used yet is configured. 1548 | * This includes: Buffer address, size, name, flags, ... 1549 | * 1550 | * Parameters 1551 | * sName Pointer to a constant name string. 1552 | * pBuffer Pointer to a buffer to be used. 1553 | * BufferSize Size of the buffer. 1554 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1555 | * 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. 1556 | * 1557 | * Return value 1558 | * >= 0 - O.K. Buffer Index 1559 | * < 0 - Error 1560 | */ 1561 | int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1562 | int BufferIndex; 1563 | volatile SEGGER_RTT_CB* pRTTCB; 1564 | 1565 | INIT(); 1566 | SEGGER_RTT_LOCK(); 1567 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1568 | BufferIndex = 0; 1569 | do { 1570 | if (pRTTCB->aDown[BufferIndex].pBuffer == NULL) { 1571 | break; 1572 | } 1573 | BufferIndex++; 1574 | } while (BufferIndex < pRTTCB->MaxNumDownBuffers); 1575 | if (BufferIndex < pRTTCB->MaxNumDownBuffers) { 1576 | pRTTCB->aDown[BufferIndex].sName = sName; 1577 | pRTTCB->aDown[BufferIndex].pBuffer = (char*)pBuffer; 1578 | pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize; 1579 | pRTTCB->aDown[BufferIndex].RdOff = 0u; 1580 | pRTTCB->aDown[BufferIndex].WrOff = 0u; 1581 | pRTTCB->aDown[BufferIndex].Flags = Flags; 1582 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1583 | } else { 1584 | BufferIndex = -1; 1585 | } 1586 | SEGGER_RTT_UNLOCK(); 1587 | return BufferIndex; 1588 | } 1589 | 1590 | /********************************************************************* 1591 | * 1592 | * SEGGER_RTT_AllocUpBuffer 1593 | * 1594 | * Function description 1595 | * Run-time configuration of the next up-buffer (T->H). 1596 | * The next buffer, which is not used yet is configured. 1597 | * This includes: Buffer address, size, name, flags, ... 1598 | * 1599 | * Parameters 1600 | * sName Pointer to a constant name string. 1601 | * pBuffer Pointer to a buffer to be used. 1602 | * BufferSize Size of the buffer. 1603 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1604 | * 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. 1605 | * 1606 | * Return value 1607 | * >= 0 - O.K. Buffer Index 1608 | * < 0 - Error 1609 | */ 1610 | int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1611 | int BufferIndex; 1612 | volatile SEGGER_RTT_CB* pRTTCB; 1613 | 1614 | INIT(); 1615 | SEGGER_RTT_LOCK(); 1616 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1617 | BufferIndex = 0; 1618 | do { 1619 | if (pRTTCB->aUp[BufferIndex].pBuffer == NULL) { 1620 | break; 1621 | } 1622 | BufferIndex++; 1623 | } while (BufferIndex < pRTTCB->MaxNumUpBuffers); 1624 | if (BufferIndex < pRTTCB->MaxNumUpBuffers) { 1625 | pRTTCB->aUp[BufferIndex].sName = sName; 1626 | pRTTCB->aUp[BufferIndex].pBuffer = (char*)pBuffer; 1627 | pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize; 1628 | pRTTCB->aUp[BufferIndex].RdOff = 0u; 1629 | pRTTCB->aUp[BufferIndex].WrOff = 0u; 1630 | pRTTCB->aUp[BufferIndex].Flags = Flags; 1631 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1632 | } else { 1633 | BufferIndex = -1; 1634 | } 1635 | SEGGER_RTT_UNLOCK(); 1636 | return BufferIndex; 1637 | } 1638 | 1639 | /********************************************************************* 1640 | * 1641 | * SEGGER_RTT_ConfigUpBuffer 1642 | * 1643 | * Function description 1644 | * Run-time configuration of a specific up-buffer (T->H). 1645 | * Buffer to be configured is specified by index. 1646 | * This includes: Buffer address, size, name, flags, ... 1647 | * 1648 | * Parameters 1649 | * BufferIndex Index of the buffer to configure. 1650 | * sName Pointer to a constant name string. 1651 | * pBuffer Pointer to a buffer to be used. 1652 | * BufferSize Size of the buffer. 1653 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1654 | * 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. 1655 | * 1656 | * Return value 1657 | * >= 0 - O.K. 1658 | * < 0 - Error 1659 | * 1660 | * Additional information 1661 | * Buffer 0 is configured on compile-time. 1662 | * May only be called once per buffer. 1663 | * Buffer name and flags can be reconfigured using the appropriate functions. 1664 | */ 1665 | int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1666 | int r; 1667 | volatile SEGGER_RTT_CB* pRTTCB; 1668 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1669 | 1670 | INIT(); 1671 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1672 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1673 | SEGGER_RTT_LOCK(); 1674 | pUp = &pRTTCB->aUp[BufferIndex]; 1675 | if (BufferIndex) { 1676 | pUp->sName = sName; 1677 | pUp->pBuffer = (char*)pBuffer; 1678 | pUp->SizeOfBuffer = BufferSize; 1679 | pUp->RdOff = 0u; 1680 | pUp->WrOff = 0u; 1681 | } 1682 | pUp->Flags = Flags; 1683 | SEGGER_RTT_UNLOCK(); 1684 | r = 0; 1685 | } else { 1686 | r = -1; 1687 | } 1688 | return r; 1689 | } 1690 | 1691 | /********************************************************************* 1692 | * 1693 | * SEGGER_RTT_ConfigDownBuffer 1694 | * 1695 | * Function description 1696 | * Run-time configuration of a specific down-buffer (H->T). 1697 | * Buffer to be configured is specified by index. 1698 | * This includes: Buffer address, size, name, flags, ... 1699 | * 1700 | * Parameters 1701 | * BufferIndex Index of the buffer to configure. 1702 | * sName Pointer to a constant name string. 1703 | * pBuffer Pointer to a buffer to be used. 1704 | * BufferSize Size of the buffer. 1705 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1706 | * 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. 1707 | * 1708 | * Return value 1709 | * >= 0 O.K. 1710 | * < 0 Error 1711 | * 1712 | * Additional information 1713 | * Buffer 0 is configured on compile-time. 1714 | * May only be called once per buffer. 1715 | * Buffer name and flags can be reconfigured using the appropriate functions. 1716 | */ 1717 | int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1718 | int r; 1719 | volatile SEGGER_RTT_CB* pRTTCB; 1720 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1721 | 1722 | INIT(); 1723 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1724 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1725 | SEGGER_RTT_LOCK(); 1726 | pDown = &pRTTCB->aDown[BufferIndex]; 1727 | if (BufferIndex) { 1728 | pDown->sName = sName; 1729 | pDown->pBuffer = (char*)pBuffer; 1730 | pDown->SizeOfBuffer = BufferSize; 1731 | pDown->RdOff = 0u; 1732 | pDown->WrOff = 0u; 1733 | } 1734 | pDown->Flags = Flags; 1735 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1736 | SEGGER_RTT_UNLOCK(); 1737 | r = 0; 1738 | } else { 1739 | r = -1; 1740 | } 1741 | return r; 1742 | } 1743 | 1744 | /********************************************************************* 1745 | * 1746 | * SEGGER_RTT_SetNameUpBuffer 1747 | * 1748 | * Function description 1749 | * Run-time configuration of a specific up-buffer name (T->H). 1750 | * Buffer to be configured is specified by index. 1751 | * 1752 | * Parameters 1753 | * BufferIndex Index of the buffer to renamed. 1754 | * sName Pointer to a constant name string. 1755 | * 1756 | * Return value 1757 | * >= 0 O.K. 1758 | * < 0 Error 1759 | */ 1760 | int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1761 | int r; 1762 | volatile SEGGER_RTT_CB* pRTTCB; 1763 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1764 | 1765 | INIT(); 1766 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1767 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1768 | SEGGER_RTT_LOCK(); 1769 | pUp = &pRTTCB->aUp[BufferIndex]; 1770 | pUp->sName = sName; 1771 | SEGGER_RTT_UNLOCK(); 1772 | r = 0; 1773 | } else { 1774 | r = -1; 1775 | } 1776 | return r; 1777 | } 1778 | 1779 | /********************************************************************* 1780 | * 1781 | * SEGGER_RTT_SetNameDownBuffer 1782 | * 1783 | * Function description 1784 | * Run-time configuration of a specific Down-buffer name (T->H). 1785 | * Buffer to be configured is specified by index. 1786 | * 1787 | * Parameters 1788 | * BufferIndex Index of the buffer to renamed. 1789 | * sName Pointer to a constant name string. 1790 | * 1791 | * Return value 1792 | * >= 0 O.K. 1793 | * < 0 Error 1794 | */ 1795 | int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1796 | int r; 1797 | volatile SEGGER_RTT_CB* pRTTCB; 1798 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1799 | 1800 | INIT(); 1801 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1802 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1803 | SEGGER_RTT_LOCK(); 1804 | pDown = &pRTTCB->aDown[BufferIndex]; 1805 | pDown->sName = sName; 1806 | SEGGER_RTT_UNLOCK(); 1807 | r = 0; 1808 | } else { 1809 | r = -1; 1810 | } 1811 | return r; 1812 | } 1813 | 1814 | /********************************************************************* 1815 | * 1816 | * SEGGER_RTT_SetFlagsUpBuffer 1817 | * 1818 | * Function description 1819 | * Run-time configuration of specific up-buffer flags (T->H). 1820 | * Buffer to be configured is specified by index. 1821 | * 1822 | * Parameters 1823 | * BufferIndex Index of the buffer. 1824 | * Flags Flags to set for the buffer. 1825 | * 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. 1826 | * 1827 | * Return value 1828 | * >= 0 O.K. 1829 | * < 0 Error 1830 | */ 1831 | int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1832 | int r; 1833 | volatile SEGGER_RTT_CB* pRTTCB; 1834 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1835 | 1836 | INIT(); 1837 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1838 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1839 | SEGGER_RTT_LOCK(); 1840 | pUp = &pRTTCB->aUp[BufferIndex]; 1841 | pUp->Flags = Flags; 1842 | SEGGER_RTT_UNLOCK(); 1843 | r = 0; 1844 | } else { 1845 | r = -1; 1846 | } 1847 | return r; 1848 | } 1849 | 1850 | /********************************************************************* 1851 | * 1852 | * SEGGER_RTT_SetFlagsDownBuffer 1853 | * 1854 | * Function description 1855 | * Run-time configuration of specific Down-buffer flags (T->H). 1856 | * Buffer to be configured is specified by index. 1857 | * 1858 | * Parameters 1859 | * BufferIndex Index of the buffer to renamed. 1860 | * Flags Flags to set for the buffer. 1861 | * 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. 1862 | * 1863 | * Return value 1864 | * >= 0 O.K. 1865 | * < 0 Error 1866 | */ 1867 | int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1868 | int r; 1869 | volatile SEGGER_RTT_CB* pRTTCB; 1870 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1871 | 1872 | INIT(); 1873 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 1874 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1875 | SEGGER_RTT_LOCK(); 1876 | pDown = &pRTTCB->aDown[BufferIndex]; 1877 | pDown->Flags = Flags; 1878 | SEGGER_RTT_UNLOCK(); 1879 | r = 0; 1880 | } else { 1881 | r = -1; 1882 | } 1883 | return r; 1884 | } 1885 | 1886 | /********************************************************************* 1887 | * 1888 | * SEGGER_RTT_Init 1889 | * 1890 | * Function description 1891 | * Initializes the RTT Control Block. 1892 | * Should be used in RAM targets, at start of the application. 1893 | * 1894 | */ 1895 | void SEGGER_RTT_Init (void) { 1896 | _DoInit(); 1897 | } 1898 | 1899 | /********************************************************************* 1900 | * 1901 | * SEGGER_RTT_SetTerminal 1902 | * 1903 | * Function description 1904 | * Sets the terminal to be used for output on channel 0. 1905 | * 1906 | * Parameters 1907 | * TerminalId Index of the terminal. 1908 | * 1909 | * Return value 1910 | * >= 0 O.K. 1911 | * < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) 1912 | * 1913 | * Notes 1914 | * (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1915 | */ 1916 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { 1917 | unsigned char ac[2]; 1918 | SEGGER_RTT_BUFFER_UP* pRing; 1919 | unsigned Avail; 1920 | int r; 1921 | 1922 | INIT(); 1923 | r = 0; 1924 | ac[0] = 0xFFu; 1925 | if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels 1926 | ac[1] = _aTerminalId[TerminalId]; 1927 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[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 1928 | SEGGER_RTT_LOCK(); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing 1929 | if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1930 | _ActiveTerminal = TerminalId; 1931 | _WriteBlocking(pRing, (const char*)ac, 2u); 1932 | } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1933 | Avail = _GetAvailWriteSpace(pRing); 1934 | if (Avail >= 2) { 1935 | _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1936 | _WriteNoCheck(pRing, (const char*)ac, 2u); 1937 | } else { 1938 | r = -1; 1939 | } 1940 | } 1941 | SEGGER_RTT_UNLOCK(); 1942 | } else { 1943 | r = -1; 1944 | } 1945 | return r; 1946 | } 1947 | 1948 | /********************************************************************* 1949 | * 1950 | * SEGGER_RTT_TerminalOut 1951 | * 1952 | * Function description 1953 | * Writes a string to the given terminal 1954 | * without changing the terminal for channel 0. 1955 | * 1956 | * Parameters 1957 | * TerminalId Index of the terminal. 1958 | * s String to be printed on the terminal. 1959 | * 1960 | * Return value 1961 | * >= 0 - Number of bytes written. 1962 | * < 0 - Error. 1963 | * 1964 | */ 1965 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { 1966 | int Status; 1967 | unsigned FragLen; 1968 | unsigned Avail; 1969 | SEGGER_RTT_BUFFER_UP* pRing; 1970 | // 1971 | INIT(); 1972 | // 1973 | // Validate terminal ID. 1974 | // 1975 | if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1976 | // 1977 | // Get "to-host" ring buffer. 1978 | // 1979 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_SEGGER_RTT.aUp[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 1980 | // 1981 | // Need to be able to change terminal, write data, change back. 1982 | // Compute the fixed and variable sizes. 1983 | // 1984 | FragLen = STRLEN(s); 1985 | // 1986 | // How we output depends upon the mode... 1987 | // 1988 | SEGGER_RTT_LOCK(); 1989 | Avail = _GetAvailWriteSpace(pRing); 1990 | switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1991 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1992 | // 1993 | // If we are in skip mode and there is no space for the whole 1994 | // of this output, don't bother switching terminals at all. 1995 | // 1996 | if (Avail < (FragLen + 4u)) { 1997 | Status = 0; 1998 | } else { 1999 | _PostTerminalSwitch(pRing, TerminalId); 2000 | Status = (int)_WriteBlocking(pRing, s, FragLen); 2001 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2002 | } 2003 | break; 2004 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 2005 | // 2006 | // If we are in trim mode and there is not enough space for everything, 2007 | // trim the output but always include the terminal switch. If no room 2008 | // for terminal switch, skip that totally. 2009 | // 2010 | if (Avail < 4u) { 2011 | Status = -1; 2012 | } else { 2013 | _PostTerminalSwitch(pRing, TerminalId); 2014 | Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 2015 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2016 | } 2017 | break; 2018 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 2019 | // 2020 | // If we are in blocking mode, output everything. 2021 | // 2022 | _PostTerminalSwitch(pRing, TerminalId); 2023 | Status = (int)_WriteBlocking(pRing, s, FragLen); 2024 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2025 | break; 2026 | default: 2027 | Status = -1; 2028 | break; 2029 | } 2030 | // 2031 | // Finish up. 2032 | // 2033 | SEGGER_RTT_UNLOCK(); 2034 | } else { 2035 | Status = -1; 2036 | } 2037 | return Status; 2038 | } 2039 | 2040 | /********************************************************************* 2041 | * 2042 | * SEGGER_RTT_GetAvailWriteSpace 2043 | * 2044 | * Function description 2045 | * Returns the number of bytes available in the ring buffer. 2046 | * 2047 | * Parameters 2048 | * BufferIndex Index of the up buffer. 2049 | * 2050 | * Return value 2051 | * Number of bytes that are free in the selected up buffer. 2052 | */ 2053 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex) { 2054 | SEGGER_RTT_BUFFER_UP* pRing; 2055 | 2056 | pRing = (SEGGER_RTT_BUFFER_UP*)((uintptr_t)&_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 2057 | return _GetAvailWriteSpace(pRing); 2058 | } 2059 | 2060 | 2061 | /********************************************************************* 2062 | * 2063 | * SEGGER_RTT_GetBytesInBuffer() 2064 | * 2065 | * Function description 2066 | * Returns the number of bytes currently used in the up buffer. 2067 | * 2068 | * Parameters 2069 | * BufferIndex Index of the up buffer. 2070 | * 2071 | * Return value 2072 | * Number of bytes that are used in the buffer. 2073 | */ 2074 | unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { 2075 | unsigned RdOff; 2076 | unsigned WrOff; 2077 | unsigned r; 2078 | volatile SEGGER_RTT_CB* pRTTCB; 2079 | // 2080 | // Avoid warnings regarding volatile access order. It's not a problem 2081 | // in this case, but dampen compiler enthusiasm. 2082 | // 2083 | pRTTCB = (volatile SEGGER_RTT_CB*)((uintptr_t)&_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 2084 | RdOff = pRTTCB->aUp[BufferIndex].RdOff; 2085 | WrOff = pRTTCB->aUp[BufferIndex].WrOff; 2086 | if (RdOff <= WrOff) { 2087 | r = WrOff - RdOff; 2088 | } else { 2089 | r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 2090 | } 2091 | return r; 2092 | } 2093 | 2094 | /*************************** End of file ****************************/ 2095 | --------------------------------------------------------------------------------