1#
2# Copyright (c) 2010-2025 Antmicro
3#
4# This file is licensed under the MIT License.
5# Full license text is available in 'licenses/MIT.txt'.
6#
7
8def mc_setup_segger_rtt(console, with_has_key = True, with_read = True, with_has_data = False):
9    # `mc_` is omitted as it isn't needed in the Monitor.
10    setup_arg_spec = 'setup_segger_rtt(console, with_has_key = True, with_read = True, with_has_data = False)'
11    bus = monitor.Machine.SystemBus
12
13    def has_data(cpu, _):
14        cpu.SetRegisterUlong(0, 1 if console.Contains(ord('\r')) else 0)
15        cpu.PC = cpu.LR
16
17    def read(cpu, _):
18        buffer = cpu.GetRegister(1).RawValue
19        size = cpu.GetRegister(2).RawValue
20        written = console.WriteBufferToMemory(buffer, size, cpu)
21        cpu.SetRegisterUlong(0, written)
22        cpu.PC = cpu.LR
23
24    def write(cpu, _):
25        pointer = cpu.GetRegister(1).RawValue
26        length = cpu.GetRegister(2).RawValue
27        for i in range(length):
28            console.DisplayChar(bus.ReadByte(pointer + i))
29
30        cpu.SetRegisterUlong(0, length)
31        cpu.PC = cpu.LR
32
33    def add_hook(symbol, function, argument_name = None):
34        for cpu in bus.GetCPUs():
35            found, addresses = bus.TryGetAllSymbolAddresses(symbol, context=cpu)
36
37            if not found:
38                cpu.WarningLog("Symbol '{}' not found. Make sure the binary is loaded before calling setup_segger_rtt"
39                              .format(symbol))
40                if argument_name is not None:
41                    cpu.WarningLog("Adding this hook can be omitted by passing False to the optional '{}' argument:\n{}"
42                                  .format(argument_name, setup_arg_spec))
43
44            for address in addresses:
45                cpu.AddHook(address, function)
46
47    if with_has_key:
48        add_hook("SEGGER_RTT_HasKey", has_data, "with_has_key")
49    if with_has_data:
50        add_hook("SEGGER_RTT_HasData", has_data, "with_has_data")
51    if with_read:
52        add_hook("SEGGER_RTT_ReadNoLock", read, "with_read")
53    add_hook("SEGGER_RTT_WriteNoLock", write)
54