diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-04 00:18:23 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-04 00:18:23 -0700 |
commit | 47cee5df1e5e63a8d0a5f1b634ac6d4e1ff00af7 (patch) | |
tree | d72daabeedecbc397cdce739639f8cf2cb947685 /gdb-helpers | |
parent | 355d7a495b0ca1a622d600427a8c737f3207a803 (diff) | |
parent | 3f49a57b99e7fe5aafa73e70ed146d98b1ae174c (diff) |
Merge branch 'lukeshu/dma'
Diffstat (limited to 'gdb-helpers')
-rw-r--r-- | gdb-helpers/rp2040.py | 176 |
1 files changed, 155 insertions, 21 deletions
diff --git a/gdb-helpers/rp2040.py b/gdb-helpers/rp2040.py index 30a936a..983e13b 100644 --- a/gdb-helpers/rp2040.py +++ b/gdb-helpers/rp2040.py @@ -1,8 +1,10 @@ # gdb-helpers/rp2040.py - GDB helpers for the RP2040 CPU. # -# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> +# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later +import typing + import gdb @@ -18,6 +20,23 @@ def fmt32(x: int) -> str: return "0b" + bin(x)[2:].rjust(32, "0") +def box(title: str, content: str) -> str: + width = 80 + + lines = content.split("\n") + while len(lines) and lines[0] == "": + lines = lines[1:] + while len(lines) and lines[-1] == "": + lines = lines[:-1] + lines = ["", *lines, ""] + + ret = "┏━[" + title + "]" + ("━" * (width - len(title) - 5)) + "┓\n" + for line in content.split("\n"): + ret += f"┃ {line.ljust(width-4)} ┃\n" + ret += "┗" + ("━" * (width - 2)) + "┛" + return ret + + def read_prio(addr: int) -> str: prios: list[int] = 32 * [0] for regnum in range(0, 8): @@ -96,22 +115,20 @@ class RP2040ShowInterrupts(gdb.Command): ) def invoke(self, arg: str, from_tty: bool) -> None: + self.arm_cortex_m0plus_registers() + self.arm_cortex_m0plus_mmregisters() + self.rp2040_dma_mmregisters() + + def arm_cortex_m0plus_mmregisters(self) -> None: base: int = 0xE0000000 icsr = read_mmreg(base + 0xED04) - psr = read_reg("xPSR") - # ║├┤║├┤├┤║├┤║║├┤├──┤║║║├──┤ - # 10987654321098765432109876543210 (dec bitnum) - # 3 2 1 0 - # ║├┤║├┤├┤║├┤║║├┤├──┤║║║├──┤ - # fedcba9876543210fedcba9876543210 (hex bitnum) - # 1 0 print( - f""" -ARM Cortex-M0+ memory-mapped registers: - + box( + "ARM Cortex-M0+ memory-mapped registers", + f""" clocks╖ ┌SIO SPI┐ ║ │╓QSPI - UART┐│ ║ │║╓bank0 ╓XIP + UART┐│ ║ │║╓GPIO ╓XIP ADC╖ ││ ║ │║║┌DMA ║╓USB I2C┐ ║ ││ ║ │║║│ ┌PIO║║╓PWM RTC╖├┐║┌┤├┐║┌┤║║├┐├──┐║║║┌──┬timers @@ -142,22 +159,139 @@ AIRCR : {fmt32(read_mmreg(base+0xed0c)) } Application Interrupt and Reset Co ╓sleep_deep s_ev_on_pend╖ ║╓sleep_on_exit SCR : {fmt32(read_mmreg(base+0xed10)) } System Control +""", + ) + ) -ARM Cortex-M0+ processor core registers: - + def arm_cortex_m0plus_registers(self) -> None: + psr = read_reg("xPSR") + print( + box( + "ARM Cortex-M0+ processor-core registers", + f""" ╓pm (0=normal, 1=top priority) PRIMASK : {fmt32(read_reg('primask')) } Priority Mask - [C]arry╖╓o[V]erflow - [Z]ero╖║║ ╓[T]humb ╓require [a]lignment - [N]egative╖║║║ ║ exec ║ ┌interrupt - app╫╫╫╢ ╟───────┴──────╢┌────┴──┐ + app exec intr + ┌┴─┐ ┌───────┴──────┐┌───┴───┐ xPSR : {fmt32(psr) } {{Application,Execution,Interrupt}} Program Status - └────┬──┘ - └{psr&0x1FF} ({exception_names[psr&0x1FF]}) + ║║║║ ║ ║└───┬───┘ + [N]egative╜║║║ ║ ║ └{psr&0x1FF} ({exception_names[psr&0x1FF]}) + [Z]ero╜║║ ╙[T]humb ╙require [a]lignment + [C]arry╜║ + o[V]erflow╜ +""", + ) + ) -""" + def rp2040_dma_mmregisters(self) -> None: + base: int = 0x50000000 + + def fmt12(x: int) -> str: + s = fmt32(x) + return s[:-12] + "_" + s[-12:] + + print( + box( + "RP2040 DMA memory-mapped registers", + f""" + + 8 4 0 + ┌──┴───┴───┤ +INTR : {fmt12(read_mmreg(base + 0x400))} Raw + │ │ │ │ +INTE0: {fmt12(read_mmreg(base + 0x404))} IRQ_DMA_0 Enable +INTF0: {fmt12(read_mmreg(base + 0x408))} IRQ_DMA_0 Force +INTS0: {fmt12(read_mmreg(base + 0x40c))} IRQ_DMA_0 Status + │ │ │ │ +INTE1: {fmt12(read_mmreg(base + 0x414))} IRQ_DMA_1 Enable +INTF1: {fmt12(read_mmreg(base + 0x418))} IRQ_DMA_1 Force +INTS1: {fmt12(read_mmreg(base + 0x41c))} IRQ_DMA_1 Status +""", + ) ) RP2040ShowInterrupts() + + +class RP2040ShowDMA(gdb.Command): + """Show the RP2040's DMA control registers.""" + + def __init__(self) -> None: + super(RP2040ShowDMA, self).__init__("rp2040-show-dma", gdb.COMMAND_USER) + + def invoke(self, arg: str, from_tty: bool) -> None: + base: int = 0x50000000 + u32_size: int = 4 + + nchan = read_mmreg(base + 0x448) + + def chreg( + ch: int, + name: typing.Literal[ + "read_addr", + "write_addr", + "trans_count", + "ctrl", + "dbg_ctdreq", + "dbg_tcr", + ], + ) -> int: + fieldcnt: int = 4 * 4 + fieldnum: int + debug = False + match name: + case "read_addr": + fieldnum = 0 + case "write_addr": + fieldnum = 1 + case "trans_count": + fieldnum = 2 + case "ctrl": + fieldnum = 4 + case "dbg_ctdreq": + fieldnum = 0 + debug = True + case "dbg_tcr": + fieldnum = 1 + debug = True + return read_mmreg( + base + + (0x800 if debug else 0) + + (ch * u32_size * fieldcnt) + + (u32_size * fieldnum) + ) + + def ctrl(ch: int) -> str: + s = fmt32(chreg(ch, "ctrl")) + return s[:10] + "_" + s[10:] + + def chaddr(ch: int, name: typing.Literal["read", "write"]) -> str: + val = chreg(ch, name + "_addr") # type: ignore + if val == 0: + return "NULL " + return f"0x{val:08x}" + + ret = f""" + ╓sniff_enable + ║╓bswap + ║║╓irq_quiet + ║║║ ┌treq_sel + ║║║ │ ┌chain_to + ║║║ │ │ ╓ring_sel + ║║║ │ │ ║ ┌ring_size + ║║║ │ │ ║ │ ╓incr_write + busy╖ ║║║ │ │ ║ │ ║╓incr_read +write_err╖ ║ ║║║ │ │ ║ │ ║║┌data_size +read_err╖║ ║ ║║║ │ │ ║ │ ║║│ ╓high_priority +ahb_err╖║║ ║ ║║║ │ │ ║ │ ║║│ ║╓enable + ║║║ ║ ║║║ │ │ ║ │ ║║│ ║║ trans_cnt + ║║║ ║ ║║║┌─┴──┐┌┴─┐║┌┴─┐║║├┐║║ read_addr write_addr cur/reload +""" + for ch in range(0, nchan): + ret += f"{ch: 3}: {ctrl(ch)} {chaddr(ch, 'read')} {chaddr(ch, 'write')} {chreg(ch, 'trans_count')}/{chreg(ch, 'dbg_tcr')}\n" + print(box("RP2040 DMA channels", ret)) + + +RP2040ShowDMA() |