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 gdb.selected_frame().read_register(name) def fmt32(x: int) -> str: return "0b" + bin(x)[2:].rjust(32, "0") def read_prio(addr: 0) -> 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()