summaryrefslogtreecommitdiff
path: root/gdb-helpers
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-04 00:18:23 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-04 00:18:23 -0700
commit47cee5df1e5e63a8d0a5f1b634ac6d4e1ff00af7 (patch)
treed72daabeedecbc397cdce739639f8cf2cb947685 /gdb-helpers
parent355d7a495b0ca1a622d600427a8c737f3207a803 (diff)
parent3f49a57b99e7fe5aafa73e70ed146d98b1ae174c (diff)
Merge branch 'lukeshu/dma'
Diffstat (limited to 'gdb-helpers')
-rw-r--r--gdb-helpers/rp2040.py176
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()