summaryrefslogtreecommitdiff
path: root/gdb-helpers
diff options
context:
space:
mode:
Diffstat (limited to 'gdb-helpers')
-rw-r--r--gdb-helpers/rp2040.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/gdb-helpers/rp2040.py b/gdb-helpers/rp2040.py
new file mode 100644
index 0000000..30a936a
--- /dev/null
+++ b/gdb-helpers/rp2040.py
@@ -0,0 +1,163 @@
+# gdb-helpers/rp2040.py - GDB helpers for the RP2040 CPU.
+#
+# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+import gdb
+
+
+def read_mmreg(addr: int) -> int:
+ return int(gdb.parse_and_eval(f"*(uint32_t*)({addr})"))
+
+
+def read_reg(name: str) -> int:
+ return int(gdb.selected_frame().read_register(name))
+
+
+def fmt32(x: int) -> str:
+ return "0b" + bin(x)[2:].rjust(32, "0")
+
+
+def read_prio(addr: int) -> str:
+ prios: list[int] = 32 * [0]
+ for regnum in range(0, 8):
+ regval = read_mmreg(addr + (regnum * 4))
+ prios[(regnum * 4) + 0] = (regval >> (0 + 6)) & 0b11
+ prios[(regnum * 4) + 1] = (regval >> (8 + 6)) & 0b11
+ prios[(regnum * 4) + 2] = (regval >> (16 + 6)) & 0b11
+ prios[(regnum * 4) + 3] = (regval >> (24 + 6)) & 0b11
+ return " " + "".join(str(p) for p in reversed(prios))
+
+
+nvic_names = [
+ "TIMER_0", # 0
+ "TIMER_1", # 1
+ "TIMER_2", # 2
+ "TIMER_3", # 3
+ "PWM", # 4
+ "USB", # 5
+ "XIP", # 6
+ "PIO0_0", # 7
+ "PIO0_1", # 8
+ "PIO1_0", # 9
+ "PIO1_1", # 10
+ "DMA_0", # 11
+ "DMA_1", # 12
+ "IO_BANK0", # 13
+ "IO_QSPI", # 14
+ "SIO_PROC0", # 15
+ "SIO_PROC1", # 16
+ "CLOCKS", # 17
+ "SPI0", # 18
+ "SPI1", # 19
+ "UART0", # 20
+ "UART1", # 21
+ "ADC_FIFO", # 22
+ "I2C0", # 23
+ "I2C1", # 24
+ "RTC", # 25
+ "unused(26)", # 26
+ "unused(27)", # 27
+ "unused(28)", # 28
+ "unused(29)", # 29
+ "unused(30)", # 30
+ "unused(31)", # 31
+]
+
+exception_names = [
+ "none", # 0
+ "reset", # 1
+ "NMI", # 2
+ "hard fault", # 3
+ "reserved(4)", # 4
+ "reserved(5)", # 5
+ "reserved(6)", # 6
+ "reserved(7)", # 7
+ "reserved(8)", # 8
+ "reserved(9)", # 9
+ "reserved(10)", # 10
+ "SVCall", # 11
+ "reserved(12)", # 12
+ "reserved(13)", # 13
+ "PendSV", # 14
+ "SysTick", # 15
+ *[f"nvic_{nvic}" for nvic in nvic_names],
+]
+while len(exception_names) < 1 << 9:
+ exception_names += [f"unused({len(exception_names)})"]
+
+
+class RP2040ShowInterrupts(gdb.Command):
+ """Show the RP2040's interrupt state."""
+
+ def __init__(self) -> None:
+ super(RP2040ShowInterrupts, self).__init__(
+ "rp2040-show-interrupts", gdb.COMMAND_USER
+ )
+
+ def invoke(self, arg: str, from_tty: bool) -> 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:
+
+ clocks╖ ┌SIO
+ SPI┐ ║ │╓QSPI
+ UART┐│ ║ │║╓bank0 ╓XIP
+ ADC╖ ││ ║ │║║┌DMA ║╓USB
+ I2C┐ ║ ││ ║ │║║│ ┌PIO║║╓PWM
+ RTC╖├┐║┌┤├┐║┌┤║║├┐├──┐║║║┌──┬timers
+NVIC_ISER: {fmt32(read_mmreg(base+0xe100)) } Set-Enable
+NVIC_ICER: {fmt32(read_mmreg(base+0xe180)) } Clear-Enable
+NVIC_ISPR: {fmt32(read_mmreg(base+0xe200)) } Set-Pending
+NVIC_ICPR: {fmt32(read_mmreg(base+0xe280)) } Clear-Pending
+ ║├┤║├┤├┤║├┤║║├┤├──┤║║║├──┤
+NVIC_IPR-: {read_prio(base+0xe400) } Priority (0=highest, 3=lowest)
+
+ isr_pending╖
+ isr_preempt╖║
+ pend_st_clr╖ ║║
+ pend_st_set╖║ ║║
+ pend_sv_clr╖║║ ║║ ┌vect_pending
+ pend_sv_set╖║║║ ║║ | ┌vect_active
+ nmi_pend_set╖ ║║║║ ║║ ┌────┴──┐ ┌────┴──┐
+ICSR : {fmt32(icsr) } Control and State
+ └────┬──┘ └────┬──┘
+ | └{icsr&0x1FF} ({exception_names[icsr&0x1FF]})
+ └{(icsr>>11)&0x1FF} ({exception_names[(icsr>>11)&0x1FF]})
+
+ ╓endiannes (0=little, 1=big)
+ vect_key┐ ║ ╓sys_reset_req
+ ┌───────┴──────┐║ ║╓vect_clr_active
+AIRCR : {fmt32(read_mmreg(base+0xed0c)) } Application Interrupt and Reset Control
+
+ ╓sleep_deep
+ s_ev_on_pend╖ ║╓sleep_on_exit
+SCR : {fmt32(read_mmreg(base+0xed10)) } System Control
+
+ARM Cortex-M0+ processor core registers:
+
+ ╓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╫╫╫╢ ╟───────┴──────╢┌────┴──┐
+xPSR : {fmt32(psr) } {{Application,Execution,Interrupt}} Program Status
+ └────┬──┘
+ └{psr&0x1FF} ({exception_names[psr&0x1FF]})
+
+"""
+ )
+
+
+RP2040ShowInterrupts()