├── .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 |
--------------------------------------------------------------------------------