├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── build.zig ├── ocd ├── debug.gdb ├── ocd.cfg └── ocd_rtt.cfg └── src ├── SEGGER_RTT.c ├── SEGGER_RTT.h ├── SEGGER_RTT_Conf.h ├── STM32L0x1 ├── registers.svd └── registers.zig ├── main.zig └── rtt.zig /.gitignore: -------------------------------------------------------------------------------- 1 | zig-cache 2 | zig-out 3 | .gdb_history 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libs/microzig"] 2 | path = libs/microzig 3 | url = git@github.com:ZigEmbeddedGroup/microzig.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nicolas Goy 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | BIN="zig-out/bin/sensor-firmware" 3 | 4 | .PHONY: build 5 | 6 | build: 7 | zig build -Drelease-small 8 | 9 | 10 | .PHONY: clean 11 | 12 | clean: 13 | rm -fr zig-cache 14 | rm -fr zig-out 15 | 16 | 17 | .PHONY: flash 18 | 19 | flash: build 20 | openocd -f ocd/ocd.cfg -c "program ${BIN} verify reset exit" 21 | 22 | .PHONY: run 23 | 24 | run: build 25 | multitail \ 26 | -cT ansi -l \ 27 | "bash -c 'make rtt-server || sleep 1d'" \ 28 | -cT ansi -l \ 29 | "bash -c 'make rtt-client || sleep 1d'" \ 30 | 31 | .PHONY: rtt-server 32 | 33 | rtt-server: 34 | openocd -f ocd/ocd.cfg \ 35 | -c "program ${BIN} verify reset" \ 36 | -f ocd/ocd_rtt.cfg 37 | 38 | .PHONY: rtt-client 39 | 40 | rtt-client: 41 | sleep 3 42 | nc localhost 9090 43 | 44 | 45 | .PHONY: ocd 46 | 47 | ocd: 48 | openocd -f ocd/ocd.cfg 49 | 50 | .PHONY: gdb 51 | 52 | gdb: 53 | arm-none-eabi-gdb -q -x ocd/debug.gdb ${BIN} 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Zig STM32 test 2 | 3 | This is a minimal example on how to run a zig program on a STM32 MCU with RTT 4 | for monitoring. 5 | 6 | More about this on my blog: 7 | 8 | 9 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const microzig = @import("libs/microzig/src/main.zig"); 3 | 4 | const stm32l0x1 = microzig.Chip{ 5 | .name = "STM32L011F3Px", 6 | .path = root() ++ "src/STM32L0x1/registers.zig", 7 | .cpu = microzig.cpus.cortex_m0plus, 8 | .memory_regions = &.{ 9 | .{ .kind = .flash, .offset = 0x08000000, .length = 8 * 1024 }, 10 | .{ .kind = .ram, .offset = 0x20000000, .length = 2 * 1024 }, 11 | }, 12 | }; 13 | 14 | pub fn build(b: *std.build.Builder) void { 15 | const mode = b.standardReleaseOptions(); 16 | const exe = microzig.addEmbeddedExecutable( 17 | b, 18 | "sensor-firmware", 19 | "src/main.zig", 20 | .{ .chip = stm32l0x1 }, 21 | .{}, 22 | ) catch @panic("failed to create embedded executable"); 23 | 24 | exe.addCSourceFile(root() ++ "src/SEGGER_RTT.c", &[_][]const u8{ 25 | "-std=c99", 26 | }); 27 | 28 | exe.addIncludeDir(root() ++ "src"); 29 | // This is required for RTT 30 | exe.addObjectFile("/usr/arm-none-eabi/lib/thumb/v6-m/nofp/libc.a"); 31 | exe.addSystemIncludeDir("/usr/arm-none-eabi/include/"); 32 | 33 | // This is important, without it, the linker removes the vector table 34 | exe.want_lto = false; 35 | 36 | exe.setBuildMode(mode); 37 | exe.install(); 38 | } 39 | 40 | fn root() []const u8 { 41 | return (std.fs.path.dirname(@src().file) orelse unreachable) ++ "/"; 42 | } 43 | -------------------------------------------------------------------------------- /ocd/debug.gdb: -------------------------------------------------------------------------------- 1 | target extended-remote :3333 2 | 3 | # print demangled symbols 4 | set print asm-demangle on 5 | 6 | # set backtrace limit to not have infinite backtrace loops 7 | set backtrace limit 32 8 | 9 | # detect unhandled exceptions, hard faults and panics 10 | #break DefaultHandler 11 | #break HardFault 12 | #break rust_begin_unwind 13 | # 14 | # # run the next few lines so the panic message is printed immediately 15 | # # the number needs to be adjusted for your panic handler 16 | # commands $bpnum 17 | # next 4 18 | # end 19 | 20 | # *try* to stop at the user entry point (it might be gone due to inlining) 21 | #break main 22 | 23 | #monitor arm semihosting enable 24 | 25 | #monitor reset 26 | 27 | # # send captured ITM to the file itm.fifo 28 | # # (the microcontroller SWO pin must be connected to the programmer SWO pin) 29 | # # 8000000 must match the core clock frequency 30 | # monitor tpiu config internal itm.txt uart off 8000000 31 | 32 | # # OR: make the microcontroller SWO pin output compatible with UART (8N1) 33 | # # 8000000 must match the core clock frequency 34 | # # 2000000 is the frequency of the SWO pin 35 | # monitor tpiu config external uart off 8000000 2000000 36 | 37 | # # enable ITM port 0 38 | # monitor itm port 0 on 39 | 40 | load 41 | 42 | # Run the program until main breakpoint 43 | run 44 | -------------------------------------------------------------------------------- /ocd/ocd.cfg: -------------------------------------------------------------------------------- 1 | source [find interface/jlink.cfg] 2 | 3 | transport select swd 4 | 5 | #set WORKAREASIZE 0x100 6 | #set CLOCK_FREQ 4000 7 | 8 | source [find target/stm32l0.cfg] 9 | 10 | 11 | reset_config srst_only srst_nogate connect_assert_srst 12 | 13 | #$_TARGETNAME configure -event reset-end { 14 | # echo "Remapping flash to address 0x00000000" 15 | # mww 0x40021034 0x1 16 | # mww 0x40010000 0x0 17 | #} 18 | -------------------------------------------------------------------------------- /ocd/ocd_rtt.cfg: -------------------------------------------------------------------------------- 1 | init 2 | 3 | 4 | rtt setup 0x20000000 2048 "SEGGER RTT" 5 | rtt server start 9090 0 6 | rtt start 7 | 8 | -------------------------------------------------------------------------------- /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: 25842 $ 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 | // For some environments, NULL may not be defined until certain headers are included 175 | // 176 | #ifndef NULL 177 | #define NULL 0 178 | #endif 179 | 180 | /********************************************************************* 181 | * 182 | * Defines, fixed 183 | * 184 | ********************************************************************** 185 | */ 186 | #if (defined __ICCARM__) || (defined __ICCRX__) 187 | #define RTT_PRAGMA(P) _Pragma(#P) 188 | #endif 189 | 190 | #if SEGGER_RTT_ALIGNMENT || SEGGER_RTT_BUFFER_ALIGNMENT 191 | #if ((defined __GNUC__) || (defined __clang__)) 192 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 193 | #elif (defined __ICCARM__) || (defined __ICCRX__) 194 | #define PRAGMA(A) _Pragma(#A) 195 | #define SEGGER_RTT_ALIGN(Var, Alignment) RTT_PRAGMA(data_alignment=Alignment) \ 196 | Var 197 | #elif (defined __CC_ARM) 198 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var __attribute__ ((aligned (Alignment))) 199 | #else 200 | #error "Alignment not supported for this compiler." 201 | #endif 202 | #else 203 | #define SEGGER_RTT_ALIGN(Var, Alignment) Var 204 | #endif 205 | 206 | #if defined(SEGGER_RTT_SECTION) || defined (SEGGER_RTT_BUFFER_SECTION) 207 | #if ((defined __GNUC__) || (defined __clang__)) 208 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section))) Var 209 | #elif (defined __ICCARM__) || (defined __ICCRX__) 210 | #define SEGGER_RTT_PUT_SECTION(Var, Section) RTT_PRAGMA(location=Section) \ 211 | Var 212 | #elif (defined __CC_ARM) 213 | #define SEGGER_RTT_PUT_SECTION(Var, Section) __attribute__ ((section (Section), zero_init)) Var 214 | #else 215 | #error "Section placement not supported for this compiler." 216 | #endif 217 | #else 218 | #define SEGGER_RTT_PUT_SECTION(Var, Section) Var 219 | #endif 220 | 221 | #if SEGGER_RTT_ALIGNMENT 222 | #define SEGGER_RTT_CB_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_ALIGNMENT) 223 | #else 224 | #define SEGGER_RTT_CB_ALIGN(Var) Var 225 | #endif 226 | 227 | #if SEGGER_RTT_BUFFER_ALIGNMENT 228 | #define SEGGER_RTT_BUFFER_ALIGN(Var) SEGGER_RTT_ALIGN(Var, SEGGER_RTT_BUFFER_ALIGNMENT) 229 | #else 230 | #define SEGGER_RTT_BUFFER_ALIGN(Var) Var 231 | #endif 232 | 233 | 234 | #if defined(SEGGER_RTT_SECTION) 235 | #define SEGGER_RTT_PUT_CB_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_SECTION) 236 | #else 237 | #define SEGGER_RTT_PUT_CB_SECTION(Var) Var 238 | #endif 239 | 240 | #if defined(SEGGER_RTT_BUFFER_SECTION) 241 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) SEGGER_RTT_PUT_SECTION(Var, SEGGER_RTT_BUFFER_SECTION) 242 | #else 243 | #define SEGGER_RTT_PUT_BUFFER_SECTION(Var) Var 244 | #endif 245 | 246 | /********************************************************************* 247 | * 248 | * Static const data 249 | * 250 | ********************************************************************** 251 | */ 252 | 253 | static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 254 | 255 | /********************************************************************* 256 | * 257 | * Static data 258 | * 259 | ********************************************************************** 260 | */ 261 | 262 | // 263 | // RTT Control Block and allocate buffers for channel 0 264 | // 265 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 266 | #if ((defined __GNUC__) || (defined __clang__)) 267 | SEGGER_RTT_CB _SEGGER_RTT __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 268 | static char _acUpBuffer [SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_UP)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 269 | static char _acDownBuffer[SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(BUFFER_SIZE_DOWN)] __attribute__ ((aligned (SEGGER_RTT_CPU_CACHE_LINE_SIZE))); 270 | #else 271 | #error "Don't know how to place _SEGGER_RTT, _acUpBuffer, _acDownBuffer cache-line aligned" 272 | #endif 273 | #else 274 | SEGGER_RTT_PUT_CB_SECTION(SEGGER_RTT_CB_ALIGN(SEGGER_RTT_CB _SEGGER_RTT)); 275 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer [BUFFER_SIZE_UP])); 276 | SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN])); 277 | #endif 278 | 279 | static unsigned char _ActiveTerminal; 280 | 281 | /********************************************************************* 282 | * 283 | * Static functions 284 | * 285 | ********************************************************************** 286 | */ 287 | 288 | /********************************************************************* 289 | * 290 | * _DoInit() 291 | * 292 | * Function description 293 | * Initializes the control block an buffers. 294 | * May only be called via INIT() to avoid overriding settings. 295 | * 296 | */ 297 | #define INIT() { \ 298 | volatile SEGGER_RTT_CB* pRTTCBInit; \ 299 | pRTTCBInit = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); \ 300 | do { \ 301 | if (pRTTCBInit->acID[0] == '\0') { \ 302 | _DoInit(); \ 303 | } \ 304 | } while (0); \ 305 | } 306 | 307 | static void _DoInit(void) { 308 | volatile SEGGER_RTT_CB* p; // Volatile to make sure that compiler cannot change the order of accesses to the control block 309 | 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 310 | unsigned i; 311 | // 312 | // Initialize control block 313 | // 314 | p = (volatile SEGGER_RTT_CB*)((char*)&_SEGGER_RTT + SEGGER_RTT_UNCACHED_OFF); // Access control block uncached so that nothing in the cache ever becomes dirty and all changes are visible in HW directly 315 | memset((SEGGER_RTT_CB*)p, 0, sizeof(_SEGGER_RTT)); // Make sure that the RTT CB is always zero initialized. 316 | p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; 317 | p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; 318 | // 319 | // Initialize up buffer 0 320 | // 321 | p->aUp[0].sName = "Terminal"; 322 | p->aUp[0].pBuffer = _acUpBuffer; 323 | p->aUp[0].SizeOfBuffer = BUFFER_SIZE_UP; 324 | p->aUp[0].RdOff = 0u; 325 | p->aUp[0].WrOff = 0u; 326 | p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; 327 | // 328 | // Initialize down buffer 0 329 | // 330 | p->aDown[0].sName = "Terminal"; 331 | p->aDown[0].pBuffer = _acDownBuffer; 332 | p->aDown[0].SizeOfBuffer = BUFFER_SIZE_DOWN; 333 | p->aDown[0].RdOff = 0u; 334 | p->aDown[0].WrOff = 0u; 335 | p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; 336 | // 337 | // Finish initialization of the control block. 338 | // Copy Id string backwards to make sure that "SEGGER RTT" is not found in initializer memory (usually flash), 339 | // as this would cause J-Link to "find" the control block at a wrong address. 340 | // 341 | RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 342 | for (i = 0; i < sizeof(_aInitStr) - 1; ++i) { 343 | p->acID[i] = _aInitStr[sizeof(_aInitStr) - 2 - i]; // Skip terminating \0 at the end of the array 344 | } 345 | RTT__DMB(); // Force order of memory accesses for cores that may perform out-of-order memory accesses 346 | } 347 | 348 | /********************************************************************* 349 | * 350 | * _WriteBlocking() 351 | * 352 | * Function description 353 | * Stores a specified number of characters in SEGGER RTT ring buffer 354 | * and updates the associated write pointer which is periodically 355 | * read by the host. 356 | * The caller is responsible for managing the write chunk sizes as 357 | * _WriteBlocking() will block until all data has been posted successfully. 358 | * 359 | * Parameters 360 | * pRing Ring buffer to post to. 361 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 362 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 363 | * 364 | * Return value 365 | * >= 0 - Number of bytes written into buffer. 366 | */ 367 | static unsigned _WriteBlocking(SEGGER_RTT_BUFFER_UP* pRing, const char* pBuffer, unsigned NumBytes) { 368 | unsigned NumBytesToWrite; 369 | unsigned NumBytesWritten; 370 | unsigned RdOff; 371 | unsigned WrOff; 372 | volatile char* pDst; 373 | // 374 | // Write data to buffer and handle wrap-around if necessary 375 | // 376 | NumBytesWritten = 0u; 377 | WrOff = pRing->WrOff; 378 | do { 379 | RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime 380 | if (RdOff > WrOff) { 381 | NumBytesToWrite = RdOff - WrOff - 1u; 382 | } else { 383 | NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); 384 | } 385 | NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around 386 | NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); 387 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 388 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 389 | NumBytesWritten += NumBytesToWrite; 390 | NumBytes -= NumBytesToWrite; 391 | WrOff += NumBytesToWrite; 392 | while (NumBytesToWrite--) { 393 | *pDst++ = *pBuffer++; 394 | }; 395 | #else 396 | SEGGER_RTT_MEMCPY((void*)pDst, pBuffer, NumBytesToWrite); 397 | NumBytesWritten += NumBytesToWrite; 398 | pBuffer += NumBytesToWrite; 399 | NumBytes -= NumBytesToWrite; 400 | WrOff += NumBytesToWrite; 401 | #endif 402 | if (WrOff == pRing->SizeOfBuffer) { 403 | WrOff = 0u; 404 | } 405 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 406 | pRing->WrOff = WrOff; 407 | } while (NumBytes); 408 | return NumBytesWritten; 409 | } 410 | 411 | /********************************************************************* 412 | * 413 | * _WriteNoCheck() 414 | * 415 | * Function description 416 | * Stores a specified number of characters in SEGGER RTT ring buffer 417 | * and updates the associated write pointer which is periodically 418 | * read by the host. 419 | * It is callers responsibility to make sure data actually fits in buffer. 420 | * 421 | * Parameters 422 | * pRing Ring buffer to post to. 423 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 424 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 425 | * 426 | * Notes 427 | * (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking 428 | */ 429 | static void _WriteNoCheck(SEGGER_RTT_BUFFER_UP* pRing, const char* pData, unsigned NumBytes) { 430 | unsigned NumBytesAtOnce; 431 | unsigned WrOff; 432 | unsigned Rem; 433 | volatile char* pDst; 434 | 435 | WrOff = pRing->WrOff; 436 | Rem = pRing->SizeOfBuffer - WrOff; 437 | if (Rem > NumBytes) { 438 | // 439 | // All data fits before wrap around 440 | // 441 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 442 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 443 | WrOff += NumBytes; 444 | while (NumBytes--) { 445 | *pDst++ = *pData++; 446 | }; 447 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 448 | pRing->WrOff = WrOff; 449 | #else 450 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 451 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 452 | pRing->WrOff = WrOff + NumBytes; 453 | #endif 454 | } else { 455 | // 456 | // We reach the end of the buffer, so need to wrap around 457 | // 458 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 459 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 460 | NumBytesAtOnce = Rem; 461 | while (NumBytesAtOnce--) { 462 | *pDst++ = *pData++; 463 | }; 464 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 465 | NumBytesAtOnce = NumBytes - Rem; 466 | while (NumBytesAtOnce--) { 467 | *pDst++ = *pData++; 468 | }; 469 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 470 | pRing->WrOff = NumBytes - Rem; 471 | #else 472 | NumBytesAtOnce = Rem; 473 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 474 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytesAtOnce); 475 | NumBytesAtOnce = NumBytes - Rem; 476 | pDst = pRing->pBuffer + SEGGER_RTT_UNCACHED_OFF; 477 | SEGGER_RTT_MEMCPY((void*)pDst, pData + Rem, NumBytesAtOnce); 478 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 479 | pRing->WrOff = NumBytesAtOnce; 480 | #endif 481 | } 482 | } 483 | 484 | /********************************************************************* 485 | * 486 | * _PostTerminalSwitch() 487 | * 488 | * Function description 489 | * Switch terminal to the given terminal ID. It is the caller's 490 | * responsibility to ensure the terminal ID is correct and there is 491 | * enough space in the buffer for this to complete successfully. 492 | * 493 | * Parameters 494 | * pRing Ring buffer to post to. 495 | * TerminalId Terminal ID to switch to. 496 | */ 497 | static void _PostTerminalSwitch(SEGGER_RTT_BUFFER_UP* pRing, unsigned char TerminalId) { 498 | unsigned char ac[2]; 499 | 500 | ac[0] = 0xFFu; 501 | ac[1] = _aTerminalId[TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit 502 | _WriteBlocking(pRing, (const char*)ac, 2u); 503 | } 504 | 505 | /********************************************************************* 506 | * 507 | * _GetAvailWriteSpace() 508 | * 509 | * Function description 510 | * Returns the number of bytes that can be written to the ring 511 | * buffer without blocking. 512 | * 513 | * Parameters 514 | * pRing Ring buffer to check. 515 | * 516 | * Return value 517 | * Number of bytes that are free in the buffer. 518 | */ 519 | static unsigned _GetAvailWriteSpace(SEGGER_RTT_BUFFER_UP* pRing) { 520 | unsigned RdOff; 521 | unsigned WrOff; 522 | unsigned r; 523 | // 524 | // Avoid warnings regarding volatile access order. It's not a problem 525 | // in this case, but dampen compiler enthusiasm. 526 | // 527 | RdOff = pRing->RdOff; 528 | WrOff = pRing->WrOff; 529 | if (RdOff <= WrOff) { 530 | r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; 531 | } else { 532 | r = RdOff - WrOff - 1u; 533 | } 534 | return r; 535 | } 536 | 537 | /********************************************************************* 538 | * 539 | * Public code 540 | * 541 | ********************************************************************** 542 | */ 543 | 544 | /********************************************************************* 545 | * 546 | * SEGGER_RTT_ReadUpBufferNoLock() 547 | * 548 | * Function description 549 | * Reads characters from SEGGER real-time-terminal control block 550 | * which have been previously stored by the application. 551 | * Do not lock against interrupts and multiple access. 552 | * Used to do the same operation that J-Link does, to transfer 553 | * RTT data via other channels, such as TCP/IP or UART. 554 | * 555 | * Parameters 556 | * BufferIndex Index of Up-buffer to be used. 557 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 558 | * BufferSize Size of the target application buffer. 559 | * 560 | * Return value 561 | * Number of bytes that have been read. 562 | * 563 | * Additional information 564 | * This function must not be called when J-Link might also do RTT. 565 | */ 566 | unsigned SEGGER_RTT_ReadUpBufferNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 567 | unsigned NumBytesRem; 568 | unsigned NumBytesRead; 569 | unsigned RdOff; 570 | unsigned WrOff; 571 | unsigned char* pBuffer; 572 | SEGGER_RTT_BUFFER_UP* pRing; 573 | volatile char* pSrc; 574 | 575 | INIT(); 576 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 577 | pBuffer = (unsigned char*)pData; 578 | RdOff = pRing->RdOff; 579 | WrOff = pRing->WrOff; 580 | NumBytesRead = 0u; 581 | // 582 | // Read from current read position to wrap-around of buffer, first 583 | // 584 | if (RdOff > WrOff) { 585 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 586 | NumBytesRem = MIN(NumBytesRem, BufferSize); 587 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 588 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 589 | NumBytesRead += NumBytesRem; 590 | BufferSize -= NumBytesRem; 591 | RdOff += NumBytesRem; 592 | while (NumBytesRem--) { 593 | *pBuffer++ = *pSrc++; 594 | }; 595 | #else 596 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 597 | NumBytesRead += NumBytesRem; 598 | pBuffer += NumBytesRem; 599 | BufferSize -= NumBytesRem; 600 | RdOff += NumBytesRem; 601 | #endif 602 | // 603 | // Handle wrap-around of buffer 604 | // 605 | if (RdOff == pRing->SizeOfBuffer) { 606 | RdOff = 0u; 607 | } 608 | } 609 | // 610 | // Read remaining items of buffer 611 | // 612 | NumBytesRem = WrOff - RdOff; 613 | NumBytesRem = MIN(NumBytesRem, BufferSize); 614 | if (NumBytesRem > 0u) { 615 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 616 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 617 | NumBytesRead += NumBytesRem; 618 | BufferSize -= NumBytesRem; 619 | RdOff += NumBytesRem; 620 | while (NumBytesRem--) { 621 | *pBuffer++ = *pSrc++; 622 | }; 623 | #else 624 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 625 | NumBytesRead += NumBytesRem; 626 | pBuffer += NumBytesRem; 627 | BufferSize -= NumBytesRem; 628 | RdOff += NumBytesRem; 629 | #endif 630 | } 631 | // 632 | // Update read offset of buffer 633 | // 634 | if (NumBytesRead) { 635 | pRing->RdOff = RdOff; 636 | } 637 | // 638 | return NumBytesRead; 639 | } 640 | 641 | /********************************************************************* 642 | * 643 | * SEGGER_RTT_ReadNoLock() 644 | * 645 | * Function description 646 | * Reads characters from SEGGER real-time-terminal control block 647 | * which have been previously stored by the host. 648 | * Do not lock against interrupts and multiple access. 649 | * 650 | * Parameters 651 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 652 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 653 | * BufferSize Size of the target application buffer. 654 | * 655 | * Return value 656 | * Number of bytes that have been read. 657 | */ 658 | unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { 659 | unsigned NumBytesRem; 660 | unsigned NumBytesRead; 661 | unsigned RdOff; 662 | unsigned WrOff; 663 | unsigned char* pBuffer; 664 | SEGGER_RTT_BUFFER_DOWN* pRing; 665 | volatile char* pSrc; 666 | // 667 | INIT(); 668 | 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 669 | pBuffer = (unsigned char*)pData; 670 | RdOff = pRing->RdOff; 671 | WrOff = pRing->WrOff; 672 | NumBytesRead = 0u; 673 | // 674 | // Read from current read position to wrap-around of buffer, first 675 | // 676 | if (RdOff > WrOff) { 677 | NumBytesRem = pRing->SizeOfBuffer - RdOff; 678 | NumBytesRem = MIN(NumBytesRem, BufferSize); 679 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 680 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 681 | NumBytesRead += NumBytesRem; 682 | BufferSize -= NumBytesRem; 683 | RdOff += NumBytesRem; 684 | while (NumBytesRem--) { 685 | *pBuffer++ = *pSrc++; 686 | }; 687 | #else 688 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 689 | NumBytesRead += NumBytesRem; 690 | pBuffer += NumBytesRem; 691 | BufferSize -= NumBytesRem; 692 | RdOff += NumBytesRem; 693 | #endif 694 | // 695 | // Handle wrap-around of buffer 696 | // 697 | if (RdOff == pRing->SizeOfBuffer) { 698 | RdOff = 0u; 699 | } 700 | } 701 | // 702 | // Read remaining items of buffer 703 | // 704 | NumBytesRem = WrOff - RdOff; 705 | NumBytesRem = MIN(NumBytesRem, BufferSize); 706 | if (NumBytesRem > 0u) { 707 | pSrc = (pRing->pBuffer + RdOff) + SEGGER_RTT_UNCACHED_OFF; 708 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 709 | NumBytesRead += NumBytesRem; 710 | BufferSize -= NumBytesRem; 711 | RdOff += NumBytesRem; 712 | while (NumBytesRem--) { 713 | *pBuffer++ = *pSrc++; 714 | }; 715 | #else 716 | SEGGER_RTT_MEMCPY(pBuffer, (void*)pSrc, NumBytesRem); 717 | NumBytesRead += NumBytesRem; 718 | pBuffer += NumBytesRem; 719 | BufferSize -= NumBytesRem; 720 | RdOff += NumBytesRem; 721 | #endif 722 | } 723 | if (NumBytesRead) { 724 | pRing->RdOff = RdOff; 725 | } 726 | // 727 | return NumBytesRead; 728 | } 729 | 730 | /********************************************************************* 731 | * 732 | * SEGGER_RTT_ReadUpBuffer 733 | * 734 | * Function description 735 | * Reads characters from SEGGER real-time-terminal control block 736 | * which have been previously stored by the application. 737 | * Used to do the same operation that J-Link does, to transfer 738 | * RTT data via other channels, such as TCP/IP or UART. 739 | * 740 | * Parameters 741 | * BufferIndex Index of Up-buffer to be used. 742 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-up-buffer to. 743 | * BufferSize Size of the target application buffer. 744 | * 745 | * Return value 746 | * Number of bytes that have been read. 747 | * 748 | * Additional information 749 | * This function must not be called when J-Link might also do RTT. 750 | * This function locks against all other RTT operations. I.e. during 751 | * the read operation, writing is also locked. 752 | * If only one consumer reads from the up buffer, 753 | * call sEGGER_RTT_ReadUpBufferNoLock() instead. 754 | */ 755 | unsigned SEGGER_RTT_ReadUpBuffer(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 756 | unsigned NumBytesRead; 757 | 758 | SEGGER_RTT_LOCK(); 759 | // 760 | // Call the non-locking read function 761 | // 762 | NumBytesRead = SEGGER_RTT_ReadUpBufferNoLock(BufferIndex, pBuffer, BufferSize); 763 | // 764 | // Finish up. 765 | // 766 | SEGGER_RTT_UNLOCK(); 767 | // 768 | return NumBytesRead; 769 | } 770 | 771 | /********************************************************************* 772 | * 773 | * SEGGER_RTT_Read 774 | * 775 | * Function description 776 | * Reads characters from SEGGER real-time-terminal control block 777 | * which have been previously stored by the host. 778 | * 779 | * Parameters 780 | * BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). 781 | * pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. 782 | * BufferSize Size of the target application buffer. 783 | * 784 | * Return value 785 | * Number of bytes that have been read. 786 | */ 787 | unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { 788 | unsigned NumBytesRead; 789 | 790 | SEGGER_RTT_LOCK(); 791 | // 792 | // Call the non-locking read function 793 | // 794 | NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); 795 | // 796 | // Finish up. 797 | // 798 | SEGGER_RTT_UNLOCK(); 799 | // 800 | return NumBytesRead; 801 | } 802 | 803 | /********************************************************************* 804 | * 805 | * SEGGER_RTT_WriteWithOverwriteNoLock 806 | * 807 | * Function description 808 | * Stores a specified number of characters in SEGGER RTT 809 | * control block. 810 | * SEGGER_RTT_WriteWithOverwriteNoLock does not lock the application 811 | * and overwrites data if the data does not fit into the buffer. 812 | * 813 | * Parameters 814 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 815 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 816 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 817 | * 818 | * Notes 819 | * (1) If there is not enough space in the "Up"-buffer, data is overwritten. 820 | * (2) For performance reasons this function does not call Init() 821 | * and may only be called after RTT has been initialized. 822 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 823 | * (3) Do not use SEGGER_RTT_WriteWithOverwriteNoLock if a J-Link 824 | * connection reads RTT data. 825 | */ 826 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 827 | const char* pData; 828 | SEGGER_RTT_BUFFER_UP* pRing; 829 | unsigned Avail; 830 | volatile char* pDst; 831 | // 832 | // Get "to-host" ring buffer and copy some elements into local variables. 833 | // 834 | pData = (const char *)pBuffer; 835 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 836 | // 837 | // Check if we will overwrite data and need to adjust the RdOff. 838 | // 839 | if (pRing->WrOff == pRing->RdOff) { 840 | Avail = pRing->SizeOfBuffer - 1u; 841 | } else if ( pRing->WrOff < pRing->RdOff) { 842 | Avail = pRing->RdOff - pRing->WrOff - 1u; 843 | } else { 844 | Avail = pRing->RdOff - pRing->WrOff - 1u + pRing->SizeOfBuffer; 845 | } 846 | if (NumBytes > Avail) { 847 | pRing->RdOff += (NumBytes - Avail); 848 | while (pRing->RdOff >= pRing->SizeOfBuffer) { 849 | pRing->RdOff -= pRing->SizeOfBuffer; 850 | } 851 | } 852 | // 853 | // Write all data, no need to check the RdOff, but possibly handle multiple wrap-arounds 854 | // 855 | Avail = pRing->SizeOfBuffer - pRing->WrOff; 856 | do { 857 | if (Avail > NumBytes) { 858 | // 859 | // Last round 860 | // 861 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 862 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 863 | Avail = NumBytes; 864 | while (NumBytes--) { 865 | *pDst++ = *pData++; 866 | }; 867 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 868 | pRing->WrOff += Avail; 869 | #else 870 | SEGGER_RTT_MEMCPY((void*)pDst, pData, NumBytes); 871 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 872 | pRing->WrOff += NumBytes; 873 | #endif 874 | break; 875 | } else { 876 | // 877 | // Wrap-around necessary, write until wrap-around and reset WrOff 878 | // 879 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 880 | #if SEGGER_RTT_MEMCPY_USE_BYTELOOP 881 | NumBytes -= Avail; 882 | while (Avail--) { 883 | *pDst++ = *pData++; 884 | }; 885 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 886 | pRing->WrOff = 0; 887 | #else 888 | SEGGER_RTT_MEMCPY((void*)pDst, pData, Avail); 889 | pData += Avail; 890 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 891 | pRing->WrOff = 0; 892 | NumBytes -= Avail; 893 | #endif 894 | Avail = (pRing->SizeOfBuffer - 1); 895 | } 896 | } while (NumBytes); 897 | } 898 | 899 | /********************************************************************* 900 | * 901 | * SEGGER_RTT_WriteSkipNoLock 902 | * 903 | * Function description 904 | * Stores a specified number of characters in SEGGER RTT 905 | * control block which is then read by the host. 906 | * SEGGER_RTT_WriteSkipNoLock does not lock the application and 907 | * skips all data, if the data does not fit into the buffer. 908 | * 909 | * Parameters 910 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 911 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 912 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 913 | * MUST be > 0!!! 914 | * This is done for performance reasons, so no initial check has do be done. 915 | * 916 | * Return value 917 | * 1: Data has been copied 918 | * 0: No space, data has not been copied 919 | * 920 | * Notes 921 | * (1) If there is not enough space in the "Up"-buffer, all data is dropped. 922 | * (2) For performance reasons this function does not call Init() 923 | * and may only be called after RTT has been initialized. 924 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 925 | */ 926 | #if (RTT_USE_ASM == 0) 927 | unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 928 | const char* pData; 929 | SEGGER_RTT_BUFFER_UP* pRing; 930 | unsigned Avail; 931 | unsigned RdOff; 932 | unsigned WrOff; 933 | unsigned Rem; 934 | volatile char* pDst; 935 | // 936 | // Cases: 937 | // 1) RdOff <= WrOff => Space until wrap-around is sufficient 938 | // 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks) 939 | // 3) RdOff < WrOff => No space in buf 940 | // 4) RdOff > WrOff => Space is sufficient 941 | // 5) RdOff > WrOff => No space in buf 942 | // 943 | // 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough 944 | // 945 | pData = (const char *)pBuffer; 946 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 947 | RdOff = pRing->RdOff; 948 | WrOff = pRing->WrOff; 949 | if (RdOff <= WrOff) { // Case 1), 2) or 3) 950 | Avail = pRing->SizeOfBuffer - WrOff - 1u; // Space until wrap-around (assume 1 byte not usable for case that RdOff == 0) 951 | if (Avail >= NumBytes) { // Case 1)? 952 | CopyStraight: 953 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 954 | memcpy((void*)pDst, pData, NumBytes); 955 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 956 | pRing->WrOff = WrOff + NumBytes; 957 | return 1; 958 | } 959 | Avail += RdOff; // Space incl. wrap-around 960 | if (Avail >= NumBytes) { // Case 2? => If not, we have case 3) (does not fit) 961 | Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer 962 | pDst = (pRing->pBuffer + WrOff) + SEGGER_RTT_UNCACHED_OFF; 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 | goto CopyStraight; 983 | } 984 | } 985 | return 0; // No space in buffer 986 | } 987 | #endif 988 | 989 | /********************************************************************* 990 | * 991 | * SEGGER_RTT_WriteDownBufferNoLock 992 | * 993 | * Function description 994 | * Stores a specified number of characters in SEGGER RTT 995 | * control block inside a buffer. 996 | * SEGGER_RTT_WriteDownBufferNoLock does not lock the application. 997 | * Used to do the same operation that J-Link does, to transfer 998 | * RTT data from other channels, such as TCP/IP or UART. 999 | * 1000 | * Parameters 1001 | * BufferIndex Index of "Down"-buffer to be used. 1002 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1003 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1004 | * 1005 | * Return value 1006 | * Number of bytes which have been stored in the "Down"-buffer. 1007 | * 1008 | * Notes 1009 | * (1) Data is stored according to buffer flags. 1010 | * (2) For performance reasons this function does not call Init() 1011 | * and may only be called after RTT has been initialized. 1012 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1013 | * 1014 | * Additional information 1015 | * This function must not be called when J-Link might also do RTT. 1016 | */ 1017 | unsigned SEGGER_RTT_WriteDownBufferNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1018 | unsigned Status; 1019 | unsigned Avail; 1020 | const char* pData; 1021 | SEGGER_RTT_BUFFER_UP* pRing; 1022 | // 1023 | // Get "to-target" ring buffer. 1024 | // 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. 1025 | // 1026 | pData = (const char *)pBuffer; 1027 | pRing = (SEGGER_RTT_BUFFER_UP*)((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 1028 | // 1029 | // How we output depends upon the mode... 1030 | // 1031 | switch (pRing->Flags) { 1032 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1033 | // 1034 | // If we are in skip mode and there is no space for the whole 1035 | // of this output, don't bother. 1036 | // 1037 | Avail = _GetAvailWriteSpace(pRing); 1038 | if (Avail < NumBytes) { 1039 | Status = 0u; 1040 | } else { 1041 | Status = NumBytes; 1042 | _WriteNoCheck(pRing, pData, NumBytes); 1043 | } 1044 | break; 1045 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1046 | // 1047 | // If we are in trim mode, trim to what we can output without blocking. 1048 | // 1049 | Avail = _GetAvailWriteSpace(pRing); 1050 | Status = Avail < NumBytes ? Avail : NumBytes; 1051 | _WriteNoCheck(pRing, pData, Status); 1052 | break; 1053 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1054 | // 1055 | // If we are in blocking mode, output everything. 1056 | // 1057 | Status = _WriteBlocking(pRing, pData, NumBytes); 1058 | break; 1059 | default: 1060 | Status = 0u; 1061 | break; 1062 | } 1063 | // 1064 | // Finish up. 1065 | // 1066 | return Status; 1067 | } 1068 | 1069 | /********************************************************************* 1070 | * 1071 | * SEGGER_RTT_WriteNoLock 1072 | * 1073 | * Function description 1074 | * Stores a specified number of characters in SEGGER RTT 1075 | * control block which is then read by the host. 1076 | * SEGGER_RTT_WriteNoLock does not lock the application. 1077 | * 1078 | * Parameters 1079 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1080 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1081 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1082 | * 1083 | * Return value 1084 | * Number of bytes which have been stored in the "Up"-buffer. 1085 | * 1086 | * Notes 1087 | * (1) Data is stored according to buffer flags. 1088 | * (2) For performance reasons this function does not call Init() 1089 | * and may only be called after RTT has been initialized. 1090 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1091 | */ 1092 | unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1093 | unsigned Status; 1094 | unsigned Avail; 1095 | const char* pData; 1096 | SEGGER_RTT_BUFFER_UP* pRing; 1097 | // 1098 | // Get "to-host" ring buffer. 1099 | // 1100 | pData = (const char *)pBuffer; 1101 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1102 | // 1103 | // How we output depends upon the mode... 1104 | // 1105 | switch (pRing->Flags) { 1106 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1107 | // 1108 | // If we are in skip mode and there is no space for the whole 1109 | // of this output, don't bother. 1110 | // 1111 | Avail = _GetAvailWriteSpace(pRing); 1112 | if (Avail < NumBytes) { 1113 | Status = 0u; 1114 | } else { 1115 | Status = NumBytes; 1116 | _WriteNoCheck(pRing, pData, NumBytes); 1117 | } 1118 | break; 1119 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 1120 | // 1121 | // If we are in trim mode, trim to what we can output without blocking. 1122 | // 1123 | Avail = _GetAvailWriteSpace(pRing); 1124 | Status = Avail < NumBytes ? Avail : NumBytes; 1125 | _WriteNoCheck(pRing, pData, Status); 1126 | break; 1127 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 1128 | // 1129 | // If we are in blocking mode, output everything. 1130 | // 1131 | Status = _WriteBlocking(pRing, pData, NumBytes); 1132 | break; 1133 | default: 1134 | Status = 0u; 1135 | break; 1136 | } 1137 | // 1138 | // Finish up. 1139 | // 1140 | return Status; 1141 | } 1142 | 1143 | /********************************************************************* 1144 | * 1145 | * SEGGER_RTT_WriteDownBuffer 1146 | * 1147 | * Function description 1148 | * Stores a specified number of characters in SEGGER RTT control block in a buffer. 1149 | * 1150 | * Parameters 1151 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1152 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1153 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1154 | * 1155 | * Return value 1156 | * Number of bytes which have been stored in the "Down"-buffer. 1157 | * 1158 | * Notes 1159 | * (1) Data is stored according to buffer flags. 1160 | * 1161 | * Additional information 1162 | * This function must not be called when J-Link might also do RTT. 1163 | * This function locks against all other RTT operations. I.e. during 1164 | * the write operation, writing from the application is also locked. 1165 | * If only one consumer writes to the down buffer, 1166 | * call SEGGER_RTT_WriteDownBufferNoLock() instead. 1167 | */ 1168 | unsigned SEGGER_RTT_WriteDownBuffer(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1169 | unsigned Status; 1170 | 1171 | INIT(); 1172 | SEGGER_RTT_LOCK(); 1173 | Status = SEGGER_RTT_WriteDownBufferNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1174 | SEGGER_RTT_UNLOCK(); 1175 | return Status; 1176 | } 1177 | 1178 | /********************************************************************* 1179 | * 1180 | * SEGGER_RTT_Write 1181 | * 1182 | * Function description 1183 | * Stores a specified number of characters in SEGGER RTT 1184 | * control block which is then read by the host. 1185 | * 1186 | * Parameters 1187 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1188 | * pBuffer Pointer to character array. Does not need to point to a \0 terminated string. 1189 | * NumBytes Number of bytes to be stored in the SEGGER RTT control block. 1190 | * 1191 | * Return value 1192 | * Number of bytes which have been stored in the "Up"-buffer. 1193 | * 1194 | * Notes 1195 | * (1) Data is stored according to buffer flags. 1196 | */ 1197 | unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { 1198 | unsigned Status; 1199 | 1200 | INIT(); 1201 | SEGGER_RTT_LOCK(); 1202 | Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); // Call the non-locking write function 1203 | SEGGER_RTT_UNLOCK(); 1204 | return Status; 1205 | } 1206 | 1207 | /********************************************************************* 1208 | * 1209 | * SEGGER_RTT_WriteString 1210 | * 1211 | * Function description 1212 | * Stores string in SEGGER RTT control block. 1213 | * This data is read by the host. 1214 | * 1215 | * Parameters 1216 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1217 | * s Pointer to string. 1218 | * 1219 | * Return value 1220 | * Number of bytes which have been stored in the "Up"-buffer. 1221 | * 1222 | * Notes 1223 | * (1) Data is stored according to buffer flags. 1224 | * (2) String passed to this function has to be \0 terminated 1225 | * (3) \0 termination character is *not* stored in RTT buffer 1226 | */ 1227 | unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { 1228 | unsigned Len; 1229 | 1230 | Len = STRLEN(s); 1231 | return SEGGER_RTT_Write(BufferIndex, s, Len); 1232 | } 1233 | 1234 | /********************************************************************* 1235 | * 1236 | * SEGGER_RTT_PutCharSkipNoLock 1237 | * 1238 | * Function description 1239 | * Stores a single character/byte in SEGGER RTT buffer. 1240 | * SEGGER_RTT_PutCharSkipNoLock does not lock the application and 1241 | * skips the byte, if it does not fit into the buffer. 1242 | * 1243 | * Parameters 1244 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1245 | * c Byte to be stored. 1246 | * 1247 | * Return value 1248 | * Number of bytes which have been stored in the "Up"-buffer. 1249 | * 1250 | * Notes 1251 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1252 | * (2) For performance reasons this function does not call Init() 1253 | * and may only be called after RTT has been initialized. 1254 | * Either by calling SEGGER_RTT_Init() or calling another RTT API function first. 1255 | */ 1256 | 1257 | unsigned SEGGER_RTT_PutCharSkipNoLock(unsigned BufferIndex, char c) { 1258 | SEGGER_RTT_BUFFER_UP* pRing; 1259 | unsigned WrOff; 1260 | unsigned Status; 1261 | volatile char* pDst; 1262 | // 1263 | // Get "to-host" ring buffer. 1264 | // 1265 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1266 | // 1267 | // Get write position and handle wrap-around if necessary 1268 | // 1269 | WrOff = pRing->WrOff + 1; 1270 | if (WrOff == pRing->SizeOfBuffer) { 1271 | WrOff = 0; 1272 | } 1273 | // 1274 | // Output byte if free space is available 1275 | // 1276 | if (WrOff != pRing->RdOff) { 1277 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1278 | *pDst = c; 1279 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1280 | pRing->WrOff = WrOff; 1281 | Status = 1; 1282 | } else { 1283 | Status = 0; 1284 | } 1285 | // 1286 | return Status; 1287 | } 1288 | 1289 | /********************************************************************* 1290 | * 1291 | * SEGGER_RTT_PutCharSkip 1292 | * 1293 | * Function description 1294 | * Stores a single character/byte in SEGGER RTT buffer. 1295 | * 1296 | * Parameters 1297 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1298 | * c Byte to be stored. 1299 | * 1300 | * Return value 1301 | * Number of bytes which have been stored in the "Up"-buffer. 1302 | * 1303 | * Notes 1304 | * (1) If there is not enough space in the "Up"-buffer, the character is dropped. 1305 | */ 1306 | 1307 | unsigned SEGGER_RTT_PutCharSkip(unsigned BufferIndex, char c) { 1308 | SEGGER_RTT_BUFFER_UP* pRing; 1309 | unsigned WrOff; 1310 | unsigned Status; 1311 | volatile char* pDst; 1312 | // 1313 | // Prepare 1314 | // 1315 | INIT(); 1316 | SEGGER_RTT_LOCK(); 1317 | // 1318 | // Get "to-host" ring buffer. 1319 | // 1320 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1321 | // 1322 | // Get write position and handle wrap-around if necessary 1323 | // 1324 | WrOff = pRing->WrOff + 1; 1325 | if (WrOff == pRing->SizeOfBuffer) { 1326 | WrOff = 0; 1327 | } 1328 | // 1329 | // Output byte if free space is available 1330 | // 1331 | if (WrOff != pRing->RdOff) { 1332 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1333 | *pDst = c; 1334 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1335 | pRing->WrOff = WrOff; 1336 | Status = 1; 1337 | } else { 1338 | Status = 0; 1339 | } 1340 | // 1341 | // Finish up. 1342 | // 1343 | SEGGER_RTT_UNLOCK(); 1344 | // 1345 | return Status; 1346 | } 1347 | 1348 | /********************************************************************* 1349 | * 1350 | * SEGGER_RTT_PutChar 1351 | * 1352 | * Function description 1353 | * Stores a single character/byte in SEGGER RTT buffer. 1354 | * 1355 | * Parameters 1356 | * BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). 1357 | * c Byte to be stored. 1358 | * 1359 | * Return value 1360 | * Number of bytes which have been stored in the "Up"-buffer. 1361 | * 1362 | * Notes 1363 | * (1) Data is stored according to buffer flags. 1364 | */ 1365 | 1366 | unsigned SEGGER_RTT_PutChar(unsigned BufferIndex, char c) { 1367 | SEGGER_RTT_BUFFER_UP* pRing; 1368 | unsigned WrOff; 1369 | unsigned Status; 1370 | volatile char* pDst; 1371 | // 1372 | // Prepare 1373 | // 1374 | INIT(); 1375 | SEGGER_RTT_LOCK(); 1376 | // 1377 | // Get "to-host" ring buffer. 1378 | // 1379 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1380 | // 1381 | // Get write position and handle wrap-around if necessary 1382 | // 1383 | WrOff = pRing->WrOff + 1; 1384 | if (WrOff == pRing->SizeOfBuffer) { 1385 | WrOff = 0; 1386 | } 1387 | // 1388 | // Wait for free space if mode is set to blocking 1389 | // 1390 | if (pRing->Flags == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1391 | while (WrOff == pRing->RdOff) { 1392 | ; 1393 | } 1394 | } 1395 | // 1396 | // Output byte if free space is available 1397 | // 1398 | if (WrOff != pRing->RdOff) { 1399 | pDst = (pRing->pBuffer + pRing->WrOff) + SEGGER_RTT_UNCACHED_OFF; 1400 | *pDst = c; 1401 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1402 | pRing->WrOff = WrOff; 1403 | Status = 1; 1404 | } else { 1405 | Status = 0; 1406 | } 1407 | // 1408 | // Finish up. 1409 | // 1410 | SEGGER_RTT_UNLOCK(); 1411 | return Status; 1412 | } 1413 | 1414 | /********************************************************************* 1415 | * 1416 | * SEGGER_RTT_GetKey 1417 | * 1418 | * Function description 1419 | * Reads one character from the SEGGER RTT buffer. 1420 | * Host has previously stored data there. 1421 | * 1422 | * Return value 1423 | * < 0 - No character available (buffer empty). 1424 | * >= 0 - Character which has been read. (Possible values: 0 - 255) 1425 | * 1426 | * Notes 1427 | * (1) This function is only specified for accesses to RTT buffer 0. 1428 | */ 1429 | int SEGGER_RTT_GetKey(void) { 1430 | char c; 1431 | int r; 1432 | 1433 | r = (int)SEGGER_RTT_Read(0u, &c, 1u); 1434 | if (r == 1) { 1435 | r = (int)(unsigned char)c; 1436 | } else { 1437 | r = -1; 1438 | } 1439 | return r; 1440 | } 1441 | 1442 | /********************************************************************* 1443 | * 1444 | * SEGGER_RTT_WaitKey 1445 | * 1446 | * Function description 1447 | * Waits until at least one character is avaible in the SEGGER RTT buffer. 1448 | * Once a character is available, it is read and this function returns. 1449 | * 1450 | * Return value 1451 | * >=0 - Character which has been read. 1452 | * 1453 | * Notes 1454 | * (1) This function is only specified for accesses to RTT buffer 0 1455 | * (2) This function is blocking if no character is present in RTT buffer 1456 | */ 1457 | int SEGGER_RTT_WaitKey(void) { 1458 | int r; 1459 | 1460 | do { 1461 | r = SEGGER_RTT_GetKey(); 1462 | } while (r < 0); 1463 | return r; 1464 | } 1465 | 1466 | /********************************************************************* 1467 | * 1468 | * SEGGER_RTT_HasKey 1469 | * 1470 | * Function description 1471 | * Checks if at least one character for reading is available in the SEGGER RTT buffer. 1472 | * 1473 | * Return value 1474 | * == 0 - No characters are available to read. 1475 | * == 1 - At least one character is available. 1476 | * 1477 | * Notes 1478 | * (1) This function is only specified for accesses to RTT buffer 0 1479 | */ 1480 | int SEGGER_RTT_HasKey(void) { 1481 | SEGGER_RTT_BUFFER_DOWN* pRing; 1482 | unsigned RdOff; 1483 | int r; 1484 | 1485 | INIT(); 1486 | pRing = (SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[0] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1487 | RdOff = pRing->RdOff; 1488 | if (RdOff != pRing->WrOff) { 1489 | r = 1; 1490 | } else { 1491 | r = 0; 1492 | } 1493 | return r; 1494 | } 1495 | 1496 | /********************************************************************* 1497 | * 1498 | * SEGGER_RTT_HasData 1499 | * 1500 | * Function description 1501 | * Check if there is data from the host in the given buffer. 1502 | * 1503 | * Return value: 1504 | * ==0: No data 1505 | * !=0: Data in buffer 1506 | * 1507 | */ 1508 | unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { 1509 | SEGGER_RTT_BUFFER_DOWN* pRing; 1510 | unsigned v; 1511 | 1512 | 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 1513 | v = pRing->WrOff; 1514 | return v - pRing->RdOff; 1515 | } 1516 | 1517 | /********************************************************************* 1518 | * 1519 | * SEGGER_RTT_HasDataUp 1520 | * 1521 | * Function description 1522 | * Check if there is data remaining to be sent in the given buffer. 1523 | * 1524 | * Return value: 1525 | * ==0: No data 1526 | * !=0: Data in buffer 1527 | * 1528 | */ 1529 | unsigned SEGGER_RTT_HasDataUp(unsigned BufferIndex) { 1530 | SEGGER_RTT_BUFFER_UP* pRing; 1531 | unsigned v; 1532 | 1533 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 1534 | v = pRing->RdOff; 1535 | return pRing->WrOff - v; 1536 | } 1537 | 1538 | /********************************************************************* 1539 | * 1540 | * SEGGER_RTT_AllocDownBuffer 1541 | * 1542 | * Function description 1543 | * Run-time configuration of the next down-buffer (H->T). 1544 | * The next buffer, which is not used yet is configured. 1545 | * This includes: Buffer address, size, name, flags, ... 1546 | * 1547 | * Parameters 1548 | * sName Pointer to a constant name string. 1549 | * pBuffer Pointer to a buffer to be used. 1550 | * BufferSize Size of the buffer. 1551 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1552 | * 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. 1553 | * 1554 | * Return value 1555 | * >= 0 - O.K. Buffer Index 1556 | * < 0 - Error 1557 | */ 1558 | int SEGGER_RTT_AllocDownBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1559 | int BufferIndex; 1560 | volatile SEGGER_RTT_CB* pRTTCB; 1561 | 1562 | INIT(); 1563 | SEGGER_RTT_LOCK(); 1564 | 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 1565 | BufferIndex = 0; 1566 | do { 1567 | if (pRTTCB->aDown[BufferIndex].pBuffer == NULL) { 1568 | break; 1569 | } 1570 | BufferIndex++; 1571 | } while (BufferIndex < pRTTCB->MaxNumDownBuffers); 1572 | if (BufferIndex < pRTTCB->MaxNumDownBuffers) { 1573 | pRTTCB->aDown[BufferIndex].sName = sName; 1574 | pRTTCB->aDown[BufferIndex].pBuffer = (char*)pBuffer; 1575 | pRTTCB->aDown[BufferIndex].SizeOfBuffer = BufferSize; 1576 | pRTTCB->aDown[BufferIndex].RdOff = 0u; 1577 | pRTTCB->aDown[BufferIndex].WrOff = 0u; 1578 | pRTTCB->aDown[BufferIndex].Flags = Flags; 1579 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1580 | } else { 1581 | BufferIndex = -1; 1582 | } 1583 | SEGGER_RTT_UNLOCK(); 1584 | return BufferIndex; 1585 | } 1586 | 1587 | /********************************************************************* 1588 | * 1589 | * SEGGER_RTT_AllocUpBuffer 1590 | * 1591 | * Function description 1592 | * Run-time configuration of the next up-buffer (T->H). 1593 | * The next buffer, which is not used yet is configured. 1594 | * This includes: Buffer address, size, name, flags, ... 1595 | * 1596 | * Parameters 1597 | * sName Pointer to a constant name string. 1598 | * pBuffer Pointer to a buffer to be used. 1599 | * BufferSize Size of the buffer. 1600 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1601 | * 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. 1602 | * 1603 | * Return value 1604 | * >= 0 - O.K. Buffer Index 1605 | * < 0 - Error 1606 | */ 1607 | int SEGGER_RTT_AllocUpBuffer(const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1608 | int BufferIndex; 1609 | volatile SEGGER_RTT_CB* pRTTCB; 1610 | 1611 | INIT(); 1612 | SEGGER_RTT_LOCK(); 1613 | 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 1614 | BufferIndex = 0; 1615 | do { 1616 | if (pRTTCB->aUp[BufferIndex].pBuffer == NULL) { 1617 | break; 1618 | } 1619 | BufferIndex++; 1620 | } while (BufferIndex < pRTTCB->MaxNumUpBuffers); 1621 | if (BufferIndex < pRTTCB->MaxNumUpBuffers) { 1622 | pRTTCB->aUp[BufferIndex].sName = sName; 1623 | pRTTCB->aUp[BufferIndex].pBuffer = (char*)pBuffer; 1624 | pRTTCB->aUp[BufferIndex].SizeOfBuffer = BufferSize; 1625 | pRTTCB->aUp[BufferIndex].RdOff = 0u; 1626 | pRTTCB->aUp[BufferIndex].WrOff = 0u; 1627 | pRTTCB->aUp[BufferIndex].Flags = Flags; 1628 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1629 | } else { 1630 | BufferIndex = -1; 1631 | } 1632 | SEGGER_RTT_UNLOCK(); 1633 | return BufferIndex; 1634 | } 1635 | 1636 | /********************************************************************* 1637 | * 1638 | * SEGGER_RTT_ConfigUpBuffer 1639 | * 1640 | * Function description 1641 | * Run-time configuration of a specific up-buffer (T->H). 1642 | * Buffer to be configured is specified by index. 1643 | * This includes: Buffer address, size, name, flags, ... 1644 | * 1645 | * Parameters 1646 | * BufferIndex Index of the buffer to configure. 1647 | * sName Pointer to a constant name string. 1648 | * pBuffer Pointer to a buffer to be used. 1649 | * BufferSize Size of the buffer. 1650 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1651 | * 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. 1652 | * 1653 | * Return value 1654 | * >= 0 - O.K. 1655 | * < 0 - Error 1656 | * 1657 | * Additional information 1658 | * Buffer 0 is configured on compile-time. 1659 | * May only be called once per buffer. 1660 | * Buffer name and flags can be reconfigured using the appropriate functions. 1661 | */ 1662 | int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1663 | int r; 1664 | volatile SEGGER_RTT_CB* pRTTCB; 1665 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1666 | 1667 | INIT(); 1668 | 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 1669 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1670 | SEGGER_RTT_LOCK(); 1671 | pUp = &pRTTCB->aUp[BufferIndex]; 1672 | if (BufferIndex) { 1673 | pUp->sName = sName; 1674 | pUp->pBuffer = (char*)pBuffer; 1675 | pUp->SizeOfBuffer = BufferSize; 1676 | pUp->RdOff = 0u; 1677 | pUp->WrOff = 0u; 1678 | } 1679 | pUp->Flags = Flags; 1680 | SEGGER_RTT_UNLOCK(); 1681 | r = 0; 1682 | } else { 1683 | r = -1; 1684 | } 1685 | return r; 1686 | } 1687 | 1688 | /********************************************************************* 1689 | * 1690 | * SEGGER_RTT_ConfigDownBuffer 1691 | * 1692 | * Function description 1693 | * Run-time configuration of a specific down-buffer (H->T). 1694 | * Buffer to be configured is specified by index. 1695 | * This includes: Buffer address, size, name, flags, ... 1696 | * 1697 | * Parameters 1698 | * BufferIndex Index of the buffer to configure. 1699 | * sName Pointer to a constant name string. 1700 | * pBuffer Pointer to a buffer to be used. 1701 | * BufferSize Size of the buffer. 1702 | * Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). 1703 | * 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. 1704 | * 1705 | * Return value 1706 | * >= 0 O.K. 1707 | * < 0 Error 1708 | * 1709 | * Additional information 1710 | * Buffer 0 is configured on compile-time. 1711 | * May only be called once per buffer. 1712 | * Buffer name and flags can be reconfigured using the appropriate functions. 1713 | */ 1714 | int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { 1715 | int r; 1716 | volatile SEGGER_RTT_CB* pRTTCB; 1717 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1718 | 1719 | INIT(); 1720 | 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 1721 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1722 | SEGGER_RTT_LOCK(); 1723 | pDown = &pRTTCB->aDown[BufferIndex]; 1724 | if (BufferIndex) { 1725 | pDown->sName = sName; 1726 | pDown->pBuffer = (char*)pBuffer; 1727 | pDown->SizeOfBuffer = BufferSize; 1728 | pDown->RdOff = 0u; 1729 | pDown->WrOff = 0u; 1730 | } 1731 | pDown->Flags = Flags; 1732 | RTT__DMB(); // Force data write to be complete before writing the , in case CPU is allowed to change the order of memory accesses 1733 | SEGGER_RTT_UNLOCK(); 1734 | r = 0; 1735 | } else { 1736 | r = -1; 1737 | } 1738 | return r; 1739 | } 1740 | 1741 | /********************************************************************* 1742 | * 1743 | * SEGGER_RTT_SetNameUpBuffer 1744 | * 1745 | * Function description 1746 | * Run-time configuration of a specific up-buffer name (T->H). 1747 | * Buffer to be configured is specified by index. 1748 | * 1749 | * Parameters 1750 | * BufferIndex Index of the buffer to renamed. 1751 | * sName Pointer to a constant name string. 1752 | * 1753 | * Return value 1754 | * >= 0 O.K. 1755 | * < 0 Error 1756 | */ 1757 | int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { 1758 | int r; 1759 | volatile SEGGER_RTT_CB* pRTTCB; 1760 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1761 | 1762 | INIT(); 1763 | 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 1764 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1765 | SEGGER_RTT_LOCK(); 1766 | pUp = &pRTTCB->aUp[BufferIndex]; 1767 | pUp->sName = sName; 1768 | SEGGER_RTT_UNLOCK(); 1769 | r = 0; 1770 | } else { 1771 | r = -1; 1772 | } 1773 | return r; 1774 | } 1775 | 1776 | /********************************************************************* 1777 | * 1778 | * SEGGER_RTT_SetNameDownBuffer 1779 | * 1780 | * Function description 1781 | * Run-time configuration of a specific Down-buffer name (T->H). 1782 | * Buffer to be configured is specified by index. 1783 | * 1784 | * Parameters 1785 | * BufferIndex Index of the buffer to renamed. 1786 | * sName Pointer to a constant name string. 1787 | * 1788 | * Return value 1789 | * >= 0 O.K. 1790 | * < 0 Error 1791 | */ 1792 | int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { 1793 | int r; 1794 | volatile SEGGER_RTT_CB* pRTTCB; 1795 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1796 | 1797 | INIT(); 1798 | 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 1799 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1800 | SEGGER_RTT_LOCK(); 1801 | pDown = &pRTTCB->aDown[BufferIndex]; 1802 | pDown->sName = sName; 1803 | SEGGER_RTT_UNLOCK(); 1804 | r = 0; 1805 | } else { 1806 | r = -1; 1807 | } 1808 | return r; 1809 | } 1810 | 1811 | /********************************************************************* 1812 | * 1813 | * SEGGER_RTT_SetFlagsUpBuffer 1814 | * 1815 | * Function description 1816 | * Run-time configuration of specific up-buffer flags (T->H). 1817 | * Buffer to be configured is specified by index. 1818 | * 1819 | * Parameters 1820 | * BufferIndex Index of the buffer. 1821 | * Flags Flags to set for the buffer. 1822 | * 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. 1823 | * 1824 | * Return value 1825 | * >= 0 O.K. 1826 | * < 0 Error 1827 | */ 1828 | int SEGGER_RTT_SetFlagsUpBuffer(unsigned BufferIndex, unsigned Flags) { 1829 | int r; 1830 | volatile SEGGER_RTT_CB* pRTTCB; 1831 | volatile SEGGER_RTT_BUFFER_UP* pUp; 1832 | 1833 | INIT(); 1834 | 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 1835 | if (BufferIndex < SEGGER_RTT_MAX_NUM_UP_BUFFERS) { 1836 | SEGGER_RTT_LOCK(); 1837 | pUp = &pRTTCB->aUp[BufferIndex]; 1838 | pUp->Flags = Flags; 1839 | SEGGER_RTT_UNLOCK(); 1840 | r = 0; 1841 | } else { 1842 | r = -1; 1843 | } 1844 | return r; 1845 | } 1846 | 1847 | /********************************************************************* 1848 | * 1849 | * SEGGER_RTT_SetFlagsDownBuffer 1850 | * 1851 | * Function description 1852 | * Run-time configuration of specific Down-buffer flags (T->H). 1853 | * Buffer to be configured is specified by index. 1854 | * 1855 | * Parameters 1856 | * BufferIndex Index of the buffer to renamed. 1857 | * Flags Flags to set for the buffer. 1858 | * 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. 1859 | * 1860 | * Return value 1861 | * >= 0 O.K. 1862 | * < 0 Error 1863 | */ 1864 | int SEGGER_RTT_SetFlagsDownBuffer(unsigned BufferIndex, unsigned Flags) { 1865 | int r; 1866 | volatile SEGGER_RTT_CB* pRTTCB; 1867 | volatile SEGGER_RTT_BUFFER_DOWN* pDown; 1868 | 1869 | INIT(); 1870 | 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 1871 | if (BufferIndex < SEGGER_RTT_MAX_NUM_DOWN_BUFFERS) { 1872 | SEGGER_RTT_LOCK(); 1873 | pDown = &pRTTCB->aDown[BufferIndex]; 1874 | pDown->Flags = Flags; 1875 | SEGGER_RTT_UNLOCK(); 1876 | r = 0; 1877 | } else { 1878 | r = -1; 1879 | } 1880 | return r; 1881 | } 1882 | 1883 | /********************************************************************* 1884 | * 1885 | * SEGGER_RTT_Init 1886 | * 1887 | * Function description 1888 | * Initializes the RTT Control Block. 1889 | * Should be used in RAM targets, at start of the application. 1890 | * 1891 | */ 1892 | void SEGGER_RTT_Init (void) { 1893 | _DoInit(); 1894 | } 1895 | 1896 | /********************************************************************* 1897 | * 1898 | * SEGGER_RTT_SetTerminal 1899 | * 1900 | * Function description 1901 | * Sets the terminal to be used for output on channel 0. 1902 | * 1903 | * Parameters 1904 | * TerminalId Index of the terminal. 1905 | * 1906 | * Return value 1907 | * >= 0 O.K. 1908 | * < 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) 1909 | * 1910 | * Notes 1911 | * (1) Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed 1912 | */ 1913 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId) { 1914 | unsigned char ac[2]; 1915 | SEGGER_RTT_BUFFER_UP* pRing; 1916 | unsigned Avail; 1917 | int r; 1918 | 1919 | INIT(); 1920 | r = 0; 1921 | ac[0] = 0xFFu; 1922 | if (TerminalId < sizeof(_aTerminalId)) { // We only support a certain number of channels 1923 | ac[1] = _aTerminalId[TerminalId]; 1924 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_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 1925 | 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 1926 | if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { 1927 | _ActiveTerminal = TerminalId; 1928 | _WriteBlocking(pRing, (const char*)ac, 2u); 1929 | } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes 1930 | Avail = _GetAvailWriteSpace(pRing); 1931 | if (Avail >= 2) { 1932 | _ActiveTerminal = TerminalId; // Only change active terminal in case of success 1933 | _WriteNoCheck(pRing, (const char*)ac, 2u); 1934 | } else { 1935 | r = -1; 1936 | } 1937 | } 1938 | SEGGER_RTT_UNLOCK(); 1939 | } else { 1940 | r = -1; 1941 | } 1942 | return r; 1943 | } 1944 | 1945 | /********************************************************************* 1946 | * 1947 | * SEGGER_RTT_TerminalOut 1948 | * 1949 | * Function description 1950 | * Writes a string to the given terminal 1951 | * without changing the terminal for channel 0. 1952 | * 1953 | * Parameters 1954 | * TerminalId Index of the terminal. 1955 | * s String to be printed on the terminal. 1956 | * 1957 | * Return value 1958 | * >= 0 - Number of bytes written. 1959 | * < 0 - Error. 1960 | * 1961 | */ 1962 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s) { 1963 | int Status; 1964 | unsigned FragLen; 1965 | unsigned Avail; 1966 | SEGGER_RTT_BUFFER_UP* pRing; 1967 | // 1968 | INIT(); 1969 | // 1970 | // Validate terminal ID. 1971 | // 1972 | if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels 1973 | // 1974 | // Get "to-host" ring buffer. 1975 | // 1976 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_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 1977 | // 1978 | // Need to be able to change terminal, write data, change back. 1979 | // Compute the fixed and variable sizes. 1980 | // 1981 | FragLen = STRLEN(s); 1982 | // 1983 | // How we output depends upon the mode... 1984 | // 1985 | SEGGER_RTT_LOCK(); 1986 | Avail = _GetAvailWriteSpace(pRing); 1987 | switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { 1988 | case SEGGER_RTT_MODE_NO_BLOCK_SKIP: 1989 | // 1990 | // If we are in skip mode and there is no space for the whole 1991 | // of this output, don't bother switching terminals at all. 1992 | // 1993 | if (Avail < (FragLen + 4u)) { 1994 | Status = 0; 1995 | } else { 1996 | _PostTerminalSwitch(pRing, TerminalId); 1997 | Status = (int)_WriteBlocking(pRing, s, FragLen); 1998 | _PostTerminalSwitch(pRing, _ActiveTerminal); 1999 | } 2000 | break; 2001 | case SEGGER_RTT_MODE_NO_BLOCK_TRIM: 2002 | // 2003 | // If we are in trim mode and there is not enough space for everything, 2004 | // trim the output but always include the terminal switch. If no room 2005 | // for terminal switch, skip that totally. 2006 | // 2007 | if (Avail < 4u) { 2008 | Status = -1; 2009 | } else { 2010 | _PostTerminalSwitch(pRing, TerminalId); 2011 | Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); 2012 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2013 | } 2014 | break; 2015 | case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: 2016 | // 2017 | // If we are in blocking mode, output everything. 2018 | // 2019 | _PostTerminalSwitch(pRing, TerminalId); 2020 | Status = (int)_WriteBlocking(pRing, s, FragLen); 2021 | _PostTerminalSwitch(pRing, _ActiveTerminal); 2022 | break; 2023 | default: 2024 | Status = -1; 2025 | break; 2026 | } 2027 | // 2028 | // Finish up. 2029 | // 2030 | SEGGER_RTT_UNLOCK(); 2031 | } else { 2032 | Status = -1; 2033 | } 2034 | return Status; 2035 | } 2036 | 2037 | /********************************************************************* 2038 | * 2039 | * SEGGER_RTT_GetAvailWriteSpace 2040 | * 2041 | * Function description 2042 | * Returns the number of bytes available in the ring buffer. 2043 | * 2044 | * Parameters 2045 | * BufferIndex Index of the up buffer. 2046 | * 2047 | * Return value 2048 | * Number of bytes that are free in the selected up buffer. 2049 | */ 2050 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex) { 2051 | SEGGER_RTT_BUFFER_UP* pRing; 2052 | 2053 | pRing = (SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[BufferIndex] + SEGGER_RTT_UNCACHED_OFF); // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly 2054 | return _GetAvailWriteSpace(pRing); 2055 | } 2056 | 2057 | 2058 | /********************************************************************* 2059 | * 2060 | * SEGGER_RTT_GetBytesInBuffer() 2061 | * 2062 | * Function description 2063 | * Returns the number of bytes currently used in the up buffer. 2064 | * 2065 | * Parameters 2066 | * BufferIndex Index of the up buffer. 2067 | * 2068 | * Return value 2069 | * Number of bytes that are used in the buffer. 2070 | */ 2071 | unsigned SEGGER_RTT_GetBytesInBuffer(unsigned BufferIndex) { 2072 | unsigned RdOff; 2073 | unsigned WrOff; 2074 | unsigned r; 2075 | volatile SEGGER_RTT_CB* pRTTCB; 2076 | // 2077 | // Avoid warnings regarding volatile access order. It's not a problem 2078 | // in this case, but dampen compiler enthusiasm. 2079 | // 2080 | 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 2081 | RdOff = pRTTCB->aUp[BufferIndex].RdOff; 2082 | WrOff = pRTTCB->aUp[BufferIndex].WrOff; 2083 | if (RdOff <= WrOff) { 2084 | r = WrOff - RdOff; 2085 | } else { 2086 | r = pRTTCB->aUp[BufferIndex].SizeOfBuffer - (WrOff - RdOff); 2087 | } 2088 | return r; 2089 | } 2090 | 2091 | /*************************** End of file ****************************/ 2092 | -------------------------------------------------------------------------------- /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 | #else 95 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 96 | #endif 97 | #elif (defined __ARMCC_VERSION) 98 | // 99 | // ARM compiler 100 | // ARM compiler V6.0 and later is clang based. 101 | // Our ASM part is compatible to clang. 102 | // 103 | #if (__ARMCC_VERSION >= 6000000) 104 | #define _CC_HAS_RTT_ASM_SUPPORT 1 105 | #else 106 | #define _CC_HAS_RTT_ASM_SUPPORT 0 107 | #endif 108 | #if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1 109 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture 110 | #elif (defined __ARM_ARCH_7M__) // Cortex-M3 111 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 112 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 113 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 114 | #define _CORE_NEEDS_DMB 1 115 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 116 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 117 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 118 | #define _CORE_NEEDS_DMB 1 119 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 120 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 121 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 122 | #define _CORE_NEEDS_DMB 1 123 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 124 | #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R 125 | #define _CORE_NEEDS_DMB 1 126 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 127 | #else 128 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 129 | #endif 130 | #elif ((defined __GNUC__) || (defined __clang__)) 131 | // 132 | // GCC / Clang 133 | // 134 | #define _CC_HAS_RTT_ASM_SUPPORT 1 135 | // ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__ 136 | #if (defined __ARM_ARCH_7M__) // Cortex-M3 137 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 138 | #elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7 139 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 140 | #define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here... 141 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 142 | #elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23 143 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 144 | #define _CORE_NEEDS_DMB 1 145 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 146 | #elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33 147 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 148 | #define _CORE_NEEDS_DMB 1 149 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 150 | #elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R 151 | #define _CORE_NEEDS_DMB 1 152 | #define RTT__DMB() __asm volatile ("dmb\n" : : :); 153 | #else 154 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 155 | #endif 156 | #elif ((defined __IASMARM__) || (defined __ICCARM__)) 157 | // 158 | // IAR assembler/compiler 159 | // 160 | #define _CC_HAS_RTT_ASM_SUPPORT 1 161 | #if (__VER__ < 6300000) 162 | #define VOLATILE 163 | #else 164 | #define VOLATILE volatile 165 | #endif 166 | #if (defined __ARM7M__) // Needed for old versions that do not know the define yet 167 | #if (__CORE__ == __ARM7M__) // Cortex-M3 168 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 169 | #endif 170 | #endif 171 | #if (defined __ARM7EM__) 172 | #if (__CORE__ == __ARM7EM__) // Cortex-M4/M7 173 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 174 | #define _CORE_NEEDS_DMB 1 175 | #define RTT__DMB() asm VOLATILE ("DMB"); 176 | #endif 177 | #endif 178 | #if (defined __ARM8M_BASELINE__) 179 | #if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23 180 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 181 | #define _CORE_NEEDS_DMB 1 182 | #define RTT__DMB() asm VOLATILE ("DMB"); 183 | #endif 184 | #endif 185 | #if (defined __ARM8M_MAINLINE__) 186 | #if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33 187 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 188 | #define _CORE_NEEDS_DMB 1 189 | #define RTT__DMB() asm VOLATILE ("DMB"); 190 | #endif 191 | #endif 192 | #if (defined __ARM8EM_MAINLINE__) 193 | #if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-??? 194 | #define _CORE_HAS_RTT_ASM_SUPPORT 1 195 | #define _CORE_NEEDS_DMB 1 196 | #define RTT__DMB() asm VOLATILE ("DMB"); 197 | #endif 198 | #endif 199 | #if (defined __ARM7A__) 200 | #if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A 201 | #define _CORE_NEEDS_DMB 1 202 | #define RTT__DMB() asm VOLATILE ("DMB"); 203 | #endif 204 | #endif 205 | #if (defined __ARM7R__) 206 | #if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R 207 | #define _CORE_NEEDS_DMB 1 208 | #define RTT__DMB() asm VOLATILE ("DMB"); 209 | #endif 210 | #endif 211 | // TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A 212 | // TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R 213 | #else 214 | // 215 | // Other compilers 216 | // 217 | #define _CC_HAS_RTT_ASM_SUPPORT 0 218 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 219 | #endif 220 | // 221 | // If IDE and core support the ASM version, enable ASM version by default 222 | // 223 | #ifndef _CORE_HAS_RTT_ASM_SUPPORT 224 | #define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores 225 | #endif 226 | #if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT) 227 | #define RTT_USE_ASM (1) 228 | #else 229 | #define RTT_USE_ASM (0) 230 | #endif 231 | #endif 232 | 233 | #ifndef _CORE_NEEDS_DMB 234 | #define _CORE_NEEDS_DMB 0 235 | #endif 236 | 237 | #ifndef RTT__DMB 238 | #if _CORE_NEEDS_DMB 239 | #error "Don't know how to place inline assembly for DMB" 240 | #else 241 | #define RTT__DMB() 242 | #endif 243 | #endif 244 | 245 | #ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE 246 | #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 247 | #endif 248 | 249 | #ifndef SEGGER_RTT_UNCACHED_OFF 250 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 251 | #error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 252 | #else 253 | #define SEGGER_RTT_UNCACHED_OFF (0) 254 | #endif 255 | #endif 256 | #if RTT_USE_ASM 257 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE 258 | #error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0" 259 | #endif 260 | #endif 261 | 262 | #ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file 263 | #include 264 | #include 265 | 266 | /********************************************************************* 267 | * 268 | * Defines, fixed 269 | * 270 | ********************************************************************** 271 | */ 272 | 273 | // 274 | // Determine how much we must pad the control block to make it a multiple of a cache line in size 275 | // Assuming: U8 = 1B 276 | // U16 = 2B 277 | // U32 = 4B 278 | // U8/U16/U32* = 4B 279 | // 280 | #if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache 281 | #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) 282 | #else 283 | #define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes) 284 | #endif 285 | #define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24)) 286 | #define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE) 287 | 288 | /********************************************************************* 289 | * 290 | * Types 291 | * 292 | ********************************************************************** 293 | */ 294 | 295 | // 296 | // Description for a circular buffer (also called "ring buffer") 297 | // which is used as up-buffer (T->H) 298 | // 299 | typedef struct { 300 | const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" 301 | char* pBuffer; // Pointer to start of buffer 302 | 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. 303 | unsigned WrOff; // Position of next item to be written by either target. 304 | volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host. 305 | 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. 306 | } SEGGER_RTT_BUFFER_UP; 307 | 308 | // 309 | // Description for a circular buffer (also called "ring buffer") 310 | // which is used as down-buffer (H->T) 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 | volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host. 317 | unsigned RdOff; // Position of next item to be read by target (down-buffer). 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_DOWN; 320 | 321 | // 322 | // RTT control block which describes the number of buffers available 323 | // as well as the configuration for each buffer 324 | // 325 | // 326 | typedef struct { 327 | char acID[16]; // Initialized to "SEGGER RTT" 328 | int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) 329 | int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) 330 | SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host 331 | SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target 332 | #if SEGGER_RTT__CB_PADDING 333 | unsigned char aDummy[SEGGER_RTT__CB_PADDING]; 334 | #endif 335 | } SEGGER_RTT_CB; 336 | 337 | /********************************************************************* 338 | * 339 | * Global data 340 | * 341 | ********************************************************************** 342 | */ 343 | extern SEGGER_RTT_CB _SEGGER_RTT; 344 | 345 | /********************************************************************* 346 | * 347 | * RTT API functions 348 | * 349 | ********************************************************************** 350 | */ 351 | #ifdef __cplusplus 352 | extern "C" { 353 | #endif 354 | int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 355 | int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 356 | int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 357 | int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); 358 | int SEGGER_RTT_GetKey (void); 359 | unsigned SEGGER_RTT_HasData (unsigned BufferIndex); 360 | int SEGGER_RTT_HasKey (void); 361 | unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex); 362 | void SEGGER_RTT_Init (void); 363 | unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 364 | unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 365 | int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName); 366 | int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); 367 | int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags); 368 | int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags); 369 | int SEGGER_RTT_WaitKey (void); 370 | unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 371 | unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 372 | unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 373 | unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 374 | unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); 375 | void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 376 | unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c); 377 | unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c); 378 | unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c); 379 | unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex); 380 | unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex); 381 | // 382 | // Function macro for performance optimization 383 | // 384 | #define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) 385 | 386 | #if RTT_USE_ASM 387 | #define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock 388 | #endif 389 | 390 | /********************************************************************* 391 | * 392 | * RTT transfer functions to send RTT data via other channels. 393 | * 394 | ********************************************************************** 395 | */ 396 | unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); 397 | unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); 398 | unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 399 | unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); 400 | 401 | #define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((char*)&_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 402 | 403 | /********************************************************************* 404 | * 405 | * RTT "Terminal" API functions 406 | * 407 | ********************************************************************** 408 | */ 409 | int SEGGER_RTT_SetTerminal (unsigned char TerminalId); 410 | int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s); 411 | 412 | /********************************************************************* 413 | * 414 | * RTT printf functions (require SEGGER_RTT_printf.c) 415 | * 416 | ********************************************************************** 417 | */ 418 | int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); 419 | int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); 420 | 421 | #ifdef __cplusplus 422 | } 423 | #endif 424 | 425 | #endif // ifndef(SEGGER_RTT_ASM) 426 | 427 | /********************************************************************* 428 | * 429 | * Defines 430 | * 431 | ********************************************************************** 432 | */ 433 | 434 | // 435 | // Operating modes. Define behavior if buffer is full (not enough space for entire message) 436 | // 437 | #define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default) 438 | #define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits. 439 | #define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer. 440 | #define SEGGER_RTT_MODE_MASK (3) 441 | 442 | // 443 | // Control sequences, based on ANSI. 444 | // Can be used to control color, and clear the screen 445 | // 446 | #define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors 447 | #define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left 448 | 449 | #define RTT_CTRL_TEXT_BLACK "\x1B[2;30m" 450 | #define RTT_CTRL_TEXT_RED "\x1B[2;31m" 451 | #define RTT_CTRL_TEXT_GREEN "\x1B[2;32m" 452 | #define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m" 453 | #define RTT_CTRL_TEXT_BLUE "\x1B[2;34m" 454 | #define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m" 455 | #define RTT_CTRL_TEXT_CYAN "\x1B[2;36m" 456 | #define RTT_CTRL_TEXT_WHITE "\x1B[2;37m" 457 | 458 | #define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m" 459 | #define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m" 460 | #define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m" 461 | #define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m" 462 | #define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m" 463 | #define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m" 464 | #define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m" 465 | #define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m" 466 | 467 | #define RTT_CTRL_BG_BLACK "\x1B[24;40m" 468 | #define RTT_CTRL_BG_RED "\x1B[24;41m" 469 | #define RTT_CTRL_BG_GREEN "\x1B[24;42m" 470 | #define RTT_CTRL_BG_YELLOW "\x1B[24;43m" 471 | #define RTT_CTRL_BG_BLUE "\x1B[24;44m" 472 | #define RTT_CTRL_BG_MAGENTA "\x1B[24;45m" 473 | #define RTT_CTRL_BG_CYAN "\x1B[24;46m" 474 | #define RTT_CTRL_BG_WHITE "\x1B[24;47m" 475 | 476 | #define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m" 477 | #define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m" 478 | #define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m" 479 | #define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m" 480 | #define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m" 481 | #define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m" 482 | #define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m" 483 | #define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m" 484 | 485 | 486 | #endif 487 | 488 | /*************************** End of file ****************************/ 489 | -------------------------------------------------------------------------------- /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/main.zig: -------------------------------------------------------------------------------- 1 | const microzig = @import("microzig"); 2 | const regs = microzig.chip.registers; 3 | 4 | const rtt = @import("rtt.zig"); 5 | 6 | pub fn main() anyerror!void { 7 | // Enable HSI 8 | regs.RCC.CR.modify(.{ .HSI16ON = 1 }); 9 | // Wait for HSI ready 10 | while (regs.RCC.CR.read().HSI16RDYF != 1) {} 11 | 12 | // Use HSI16 as system clock and wakeup clock 13 | regs.RCC.CFGR.modify(.{ .SW = 0b01, .STOPWUCK = 1 }); 14 | 15 | // Enable power interface clock 16 | regs.RCC.APB1ENR.modify(.{ .PWREN = 1 }); 17 | 18 | // Disable RTC register protection 19 | // This MUST be done once the PWREN has been set in RCC_APB1ENR 20 | regs.PWR.CR.modify(.{ .DBP = 1 }); 21 | 22 | // Enable LSE (external crystal at 32kHz) 23 | regs.RCC.CSR.modify(.{ .LSEON = 1 }); 24 | // Wait for LSE to be stable 25 | while (regs.RCC.CSR.read().LSERDY != 1) {} 26 | 27 | // Use LSE as RTC source and enable RTC 28 | regs.RCC.CSR.modify(.{ 29 | .RTCSEL = 0b01, // LSE 30 | .RTCEN = 1, 31 | }); 32 | 33 | rtt.init(); 34 | 35 | while (true) { 36 | rtt.write("Hello world!\n"); 37 | delay(1000); 38 | } 39 | } 40 | 41 | pub fn delay(ms: u32) void { 42 | // CPU run at 16mHz on HSI16 43 | // each tick is 5 instructions (1000 * 16 / 5) = 3200 44 | var ticks = ms * (1000 * 16 / 5); 45 | var i: u32 = 0; 46 | // One loop is 5 instructions 47 | while (i < ticks) { 48 | microzig.cpu.nop(); 49 | i += 1; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/rtt.zig: -------------------------------------------------------------------------------- 1 | const rtt = @cImport({ 2 | @cInclude("SEGGER_RTT.h"); 3 | }); 4 | 5 | pub fn init() void { 6 | rtt.SEGGER_RTT_Init(); 7 | } 8 | 9 | pub fn write(str: []const u8) void { 10 | _ = rtt.SEGGER_RTT_Write(0, @ptrCast(*const anyopaque, str.ptr), str.len); 11 | } 12 | --------------------------------------------------------------------------------