You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
16 KiB
388 lines
16 KiB
#!/usr/bin/env python3 |
|
import binascii |
|
import struct |
|
import re |
|
import argparse |
|
|
|
class GpioHook: |
|
def __init__(self): |
|
pass |
|
|
|
def call(self, reg, val): |
|
if reg[0].startswith('GPIOPCTL_'): |
|
print " > ", |
|
mask = 0xF |
|
pm = [] |
|
for i in range(8): |
|
v = (val & (mask << (4*i)))>>4*i |
|
pm.append(str(v)) |
|
print ', '.join(['pm[{}]={}'.format(idx, pmval) for idx,pmval in enumerate(pm)]) |
|
|
|
elif reg[0].startswith('GPIOAFSEL_'): |
|
print " > ", |
|
mask = 0xFF |
|
val = val & mask |
|
afsel = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
afsel.append(str(v)) |
|
|
|
print ', '.join(['AF[{}]={}'.format(idx, afval) for idx,afval in enumerate(afsel)]) |
|
|
|
elif reg[0].startswith('GPIOSLR_'): |
|
print " > ", |
|
mask = 0xFF |
|
val = val & mask |
|
srvals = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
srvals.append(str(v)) |
|
|
|
print ', '.join(['SlewRate[{}]={}'.format(idx, srval) for idx,srval in enumerate(srvals)]) |
|
|
|
elif reg[0].startswith('GPIODR2R_'): |
|
print " > ", |
|
mask = 0xFF |
|
val = val & mask |
|
d2vals = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
d2vals.append(str(v)) |
|
|
|
print ', '.join(['2mA[{}]={}'.format(idx, d2val) for idx,d2val in enumerate(d2vals)]) |
|
|
|
elif reg[0].startswith('GPIODR4R_'): |
|
print " > ", |
|
mask = 0xFF |
|
val = val & mask |
|
d4vals = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
d4vals.append(str(v)) |
|
|
|
print ', '.join(['4mA[{}]={}'.format(idx, d4val) for idx,d4val in enumerate(d4vals)]) |
|
|
|
elif reg[0].startswith('GPIODR8R_'): |
|
print " > ", |
|
mask = 0xFF |
|
val = val & mask |
|
d8vals = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
d8vals.append(str(v)) |
|
|
|
print ', '.join(['8mA[{}]={}'.format(idx, d8val) for idx,d8val in enumerate(d8vals)]) |
|
|
|
elif reg[0].startswith('GPIODIR_'): |
|
print ' > ', |
|
mask = 0xFF |
|
val = val & mask |
|
dirvals = [] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
dirvals.append('OUT' if v else 'IN') |
|
|
|
print ', '.join(['Dir[{}]={}'.format(idx, dirval) for idx,dirval in enumerate(dirvals)]) |
|
|
|
class RCC2Hook: |
|
def call(self, reg, val): |
|
usercc2 = (val &(1<<32))!=0 |
|
print ' > [USERCC2] Use RCC2: {}'.format(usercc2) |
|
if not usercc2: |
|
return |
|
|
|
class RCCHook: |
|
def call(self, reg, val): |
|
print ' > Main oscillator {}'.format('DISABLED'if val & 0x1 else 'ENABLED') |
|
oscsrc = (val & (0x3<<4))>>4 |
|
oscvals = {0:'[MOSC] Main Oscillator', |
|
1:'[PIOSC] Precision internal oscillator', |
|
2:'[PIOSC/4] Precision internal oscillator/4', |
|
3:'[LFIOSC] Low-freq internal oscillator/4', |
|
} |
|
print ' > Oscillator source: {}'.format(oscvals[oscsrc]) |
|
xtalvals = { |
|
0x6:('4', 'Reserved'), |
|
0x7:('4.096', 'Reserved'), |
|
0x8:('4.9152', 'Reserved'), |
|
0x9:('5','5'), |
|
0xA:('5.12', '5.12'), |
|
0xB:('6', '6'), |
|
0xC:('6.144', '6.144'), |
|
0xD:('7.3728', '7.3728'), |
|
0xE:('8', '8'), |
|
0xF:('8.192', '8.192'), |
|
0x10:('10.0', '10.0'), |
|
0x11:('12.0', '12.0'), |
|
0x12:('12.288', '12.288'), |
|
0x13:('13.56', '13.56'), |
|
0x14:('14.31818', '14.31818'), |
|
0x15:('16.0', '16.0'), |
|
0x16:('16.364', '16.364'), |
|
0x17:('18.0', '18.0'), |
|
0x18:('20.0', '20.0'), |
|
0x19:('24.0', '24.0'), |
|
0x1A:('25.0', '25.0'), |
|
} |
|
xtalval = (val & (0x1F<<6))>>6 |
|
print ' > [XTAL] Crystal value {} Mhz'.format(xtalvals[xtalval][0]) |
|
|
|
pllbypass = (val & (1<<11)) != 0 |
|
print ' > [BYPASS] The system clock is {} divided by SYSDIV'.format('derived from the OSC' if pllbypass else 'the PLL output') |
|
|
|
pllpwrdown = (val & (1<<13)) != 0 |
|
print ' > PLL is {}'.format('powered down' if pllpwrdown else 'operating normally') |
|
|
|
pwmdiv = (val & (0x7<<17))>>17 |
|
print ' > [PWMDIV] PWM Unit Clock Divisor is {}'.format(2**(pwmdiv+1) if pwmdiv < 5 else '64') |
|
|
|
pwmclockdiv = (val & (1<<20)) != 0 |
|
print ' > [USEPWMDIV] PWM Clock Divisor : {} is the source for PWM'.format('The PWM clock divider' if pwmclockdiv else 'The system clock divider') |
|
|
|
usesysdiv = (val & (1<<22)) != 0 |
|
print ' > [USESYSDIV] Enable System Clock Divider: {}'.format('system clock divider is used (forced when PLL is selected as the source)' if usesysdiv else 'The system clock is used undivided') |
|
|
|
sysdiv = (val & (0xF<<23))>>23 |
|
print ' > [SYSDIV] System Clock Divisor: {}'.format(sysdiv+1) |
|
if not pllbypass: |
|
print ' > {}'.format({ |
|
0x0 : 'reserved', |
|
0x1 : 'reserved', |
|
0x2 : '66.67 Mhz', |
|
0x3 : '50 Mhz', |
|
0x4 : '40 Mhz', |
|
0x5 : '33.33 Mhz', |
|
0x6 : '28.57 Mhz', |
|
0x7 : '25 Mhz', |
|
0x8 : '22.22 Mhz', |
|
0x9 : '20 Mhz', |
|
0xa : '18.18 Mhz', |
|
0xb : '16.67 Mhz', |
|
0xc : '15.38 Mhz', |
|
0xd : '14.29 Mhz', |
|
0xe : '13.33 Mhz', |
|
0xf : '12.5 Mhz', |
|
}[sysdiv]) |
|
|
|
acg = (val & (1<<27)) != 0 |
|
print ' > [ACG] Auto Clock Gating: {}'.format('SCGCn/DCGCn registers are used' if acg else 'RCGCn registers are used') |
|
class UartHook: |
|
def __init__(self, baudrate = 115200): |
|
self.ibrd = None |
|
self.fbrd = None |
|
self.baudrate = baudrate |
|
|
|
def call(self, reg, val): |
|
if reg[0].startswith('UARTIBRD_'): |
|
self.ibrd = val |
|
elif reg[0].startswith('UARTFBRD_'): |
|
self.fbrd = val |
|
print " > ", |
|
print "UART clock is {} for baudrate {}".format( |
|
((2 * (64 * self.ibrd + self.fbrd)-1) * self.baudrate)/8, |
|
self.baudrate) |
|
elif reg[0].startswith('UARTLCHR_'): |
|
print ' > BRK: {}'.format('send' if (val & 0x1) else 'normal' ) |
|
print ' > Parity [PEN]: {}'.format('enabled' if (val & 0x2) else 'disabled') |
|
print ' > Even parity select [EPS]: {}'.format('enabled' if (val & 0x4) else 'disabled') |
|
print ' > 2 stop bits [STP2]: {}'.format('enabled' if (val & (1<<3)) else 'disabled') |
|
print ' > Enable FIFO [FEN]: {}'.format('enabled' if (val & (1<<4)) else 'disabled') |
|
wlen = (val & (0x3<<5))>>5 |
|
print ' > Word len [WLEN]: {} bits'.format(wlen + 5) |
|
print ' > Stick Parity Select [SPS]: {}'.format('checked...' if (val & (1<<7)) else 'disabled') |
|
|
|
elif reg[0].startswith('UARTCTL_'): |
|
print ' > UART Enable [UARTEN]: {}'.format((val & 0x1) != 0) |
|
print ' > UART Sir Enable [SIREN]: {}'.format((val & 0x2) != 0) |
|
print ' > UART Sir LowPower Mode [SIRLP]: {}'.format('enabled' if ((val & (1<<2)) != 0) else 'disabled') |
|
print ' > ISO 7816 support [SMART]: {}'.format('smart mode' if ((val & (0x1<<3)) != 0) else 'normal') |
|
print ' > End of Transmission [EOT]: TXRIS set when {}'.format('all transmitted' if (val & (1<<4)) else 'UARTIFLS conditions...' ) |
|
print ' > High Speed enable [HSE]: sys clock divided by {}'.format(8 if (val&(1<<5)) else 16) |
|
print ' > Loop Back Enable [LBE]: {}'.format('enabled' if (val & (1<<7)) else 'disabled') |
|
print ' > UART Transmit Enable [TXE]: {}'.format('enabled' if (val & (1<<8)) else 'disabled') |
|
print ' > UART Receive Enable [RXE]: {}'.format('enabled' if (val & (1<<9)) else 'disabled') |
|
rtsen = (val & (1<<14)) != 0 |
|
|
|
print ' > Request to send [RTS]: {}'.format('set' if (val & (1<<9)) and not rtsen else 'clear' if (val & (1<<9)) and not rtsen else 'discarded' ) |
|
print ' > Enable Request to Send [RTSEN]: Hardware flow contrlol is {}'.format('enable' if rtsen else 'disabled') |
|
print ' > Enable Clear to Send [CTSEN]: CTS hardware flow is {}'.format('enable' if (val & (1<<15)) else 'disabled') |
|
|
|
class GpioHbctlHook: |
|
def call(self, reg, val): |
|
print " > Use HPB : ", |
|
mask = 0xFF |
|
val = val & mask |
|
hpb_vals = [] |
|
ports = ['PORTA', 'PORTB', 'PORTC', 'PORTD', |
|
'PORTE', 'PORTF'] |
|
for i in range(8): |
|
v = (val & (1<<i)) != 0 |
|
hpb_vals.append(str(v)) |
|
|
|
print ', '.join(['{}: {}'.format(prt, hpb_val) for prt,hpb_val in zip(ports, hpb_vals)]) |
|
|
|
|
|
parser = argparse.ArgumentParser(description='Parse command for reading Tiva status.') |
|
parser.add_argument("-r", '--register', action='append', help='a regexp for matching some registers') |
|
parser.add_argument('--use-apb', action='store_true', help='use legacy APB instead of AHB for GPIO registers') |
|
|
|
class ReadTiva (gdb.Command): |
|
"""Read something.""" |
|
|
|
def __init__ (self): |
|
super (ReadTiva, self).__init__ ("read-tiva", gdb.COMMAND_USER) |
|
|
|
def single_read(self, reg): |
|
name = reg[0] |
|
addr = reg[1] |
|
size = reg[2] |
|
hook = reg[3] |
|
|
|
inf = gdb.selected_inferior () |
|
|
|
m = inf.read_memory (addr, size) |
|
val = struct.unpack('i', m)[0] |
|
|
|
print "{} : 0x{:08X} @ 0x{:08X}".format(name, val, addr) |
|
|
|
if hook: |
|
hook.call(reg,val) |
|
|
|
def invoke (self, arg, from_tty): |
|
args = gdb.string_to_argv(arg) |
|
parsed_args = parser.parse_args(args) |
|
|
|
uart0hook = UartHook() |
|
gpiohook = GpioHook() |
|
rcchook = RCCHook() |
|
rcc2hook = RCC2Hook() |
|
gpiohbctlhook = GpioHbctlHook() |
|
|
|
all_regs = [ |
|
('RCC', 0x400FE060, 4, rcchook), |
|
('RCC2', 0x400FE070, 4, rcc2hook), |
|
('RCGCUART', 0x400FE618, 4, None), |
|
('RCGCGPIO', 0x400FE608, 4, None), |
|
('UARTIBRD_0', 0x4000C024, 4, uart0hook), |
|
('UARTFBRD_0', 0x4000C028, 4, uart0hook), |
|
('UARTLCHR_0', 0x4000C02C, 4, uart0hook), |
|
('UARTCTL_0', 0x4000C030, 4, uart0hook), |
|
('GPIOHBCTL', 0x400FE06C, 4, gpiohbctlhook), |
|
] |
|
if parsed_args.use_apb: |
|
all_regs += [ |
|
('GPIODIR_PORTA', 0x40004400, 4, gpiohook), |
|
('GPIOAFSEL_PORTA', 0x40004420, 4, gpiohook), |
|
('GPIOPCTL_PORTA', 0x4000452C, 4, gpiohook), |
|
('GPIOSLR_PORTA', 0x40004518, 4, gpiohook), |
|
('GPIODR2R_PORTA', 0x40004500, 4, gpiohook), |
|
('GPIODR4R_PORTA', 0x40004504, 4, gpiohook), |
|
('GPIODR8R_PORTA', 0x40004508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTB', 0x40005400, 4, gpiohook), |
|
('GPIOAFSEL_PORTB', 0x40005420, 4, gpiohook), |
|
('GPIOPCTL_PORTB', 0x4000552C, 4, gpiohook), |
|
('GPIOSLR_PORTB', 0x40005518, 4, gpiohook), |
|
('GPIODR2R_PORTB', 0x40005500, 4, gpiohook), |
|
('GPIODR4R_PORTB', 0x40005504, 4, gpiohook), |
|
('GPIODR8R_PORTB', 0x40005508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTC', 0x40006400, 4, gpiohook), |
|
('GPIOAFSEL_PORTC', 0x40006420, 4, gpiohook), |
|
('GPIOPCTL_PORTC', 0x4000652C, 4, gpiohook), |
|
('GPIOSLR_PORTC', 0x40006518, 4, gpiohook), |
|
('GPIODR2R_PORTC', 0x40006500, 4, gpiohook), |
|
('GPIODR4R_PORTC', 0x40006504, 4, gpiohook), |
|
('GPIODR8R_PORTC', 0x40006508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTD', 0x40007400, 4, gpiohook), |
|
('GPIOAFSEL_PORTD', 0x40007420, 4, gpiohook), |
|
('GPIOPCTL_PORTD', 0x4000752C, 4, gpiohook), |
|
('GPIOSLR_PORTD', 0x40007518, 4, gpiohook), |
|
('GPIODR2R_PORTD', 0x40007500, 4, gpiohook), |
|
('GPIODR4R_PORTD', 0x40007504, 4, gpiohook), |
|
('GPIODR8R_PORTD', 0x40007508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTE', 0x40024400, 4, gpiohook), |
|
('GPIOAFSEL_PORTE', 0x40024420, 4, gpiohook), |
|
('GPIOPCTL_PORTE', 0x4002452C, 4, gpiohook), |
|
('GPIOSLR_PORTE', 0x40024518, 4, gpiohook), |
|
('GPIODR2R_PORTE', 0x40024500, 4, gpiohook), |
|
('GPIODR4R_PORTE', 0x40024504, 4, gpiohook), |
|
('GPIODR8R_PORTE', 0x40024508, 4, gpiohook), |
|
|
|
|
|
('GPIODIR_PORTF', 0x40025400, 4, gpiohook), |
|
('GPIOAFSEL_PORTF', 0x40025420, 4, gpiohook), |
|
('GPIOPCTL_PORTF', 0x4002552C, 4, gpiohook), |
|
('GPIOSLR_PORTF', 0x40025518, 4, gpiohook), |
|
('GPIODR2R_PORTF', 0x40025500, 4, gpiohook), |
|
('GPIODR4R_PORTF', 0x40025504, 4, gpiohook), |
|
('GPIODR8R_PORTF', 0x40025508, 4, gpiohook), |
|
|
|
] |
|
else: |
|
all_regs += [ |
|
('GPIODIR_PORTA', 0x40058400, 4, gpiohook), |
|
('GPIOAFSEL_PORTA', 0x40058420, 4, gpiohook), |
|
('GPIOPCTL_PORTA', 0x4005852C, 4, gpiohook), |
|
('GPIOSLR_PORTA', 0x40058518, 4, gpiohook), |
|
('GPIODR2R_PORTA', 0x40058500, 4, gpiohook), |
|
('GPIODR4R_PORTA', 0x40058504, 4, gpiohook), |
|
('GPIODR8R_PORTA', 0x40058508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTB', 0x40059400, 4, gpiohook), |
|
('GPIOAFSEL_PORTB', 0x40059420, 4, gpiohook), |
|
('GPIOPCTL_PORTB', 0x4005952C, 4, gpiohook), |
|
('GPIOSLR_PORTB', 0x40059518, 4, gpiohook), |
|
('GPIODR2R_PORTB', 0x40059500, 4, gpiohook), |
|
('GPIODR4R_PORTB', 0x40059504, 4, gpiohook), |
|
('GPIODR8R_PORTB', 0x40059508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTC', 0x4005A400, 4, gpiohook), |
|
('GPIOAFSEL_PORTC', 0x4005A420, 4, gpiohook), |
|
('GPIOPCTL_PORTC', 0x4005A52C, 4, gpiohook), |
|
('GPIOSLR_PORTC', 0x4005A518, 4, gpiohook), |
|
('GPIODR2R_PORTC', 0x4005A500, 4, gpiohook), |
|
('GPIODR4R_PORTC', 0x4005A504, 4, gpiohook), |
|
('GPIODR8R_PORTC', 0x4005A508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTD', 0x4005B400, 4, gpiohook), |
|
('GPIOAFSEL_PORTD', 0x4005B420, 4, gpiohook), |
|
('GPIOPCTL_PORTD', 0x4005B52C, 4, gpiohook), |
|
('GPIOSLR_PORTD', 0x4005B518, 4, gpiohook), |
|
('GPIODR2R_PORTD', 0x4005B500, 4, gpiohook), |
|
('GPIODR4R_PORTD', 0x4005B504, 4, gpiohook), |
|
('GPIODR8R_PORTD', 0x4005B508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTE', 0x4005C400, 4, gpiohook), |
|
('GPIOAFSEL_PORTE', 0x4005C420, 4, gpiohook), |
|
('GPIOPCTL_PORTE', 0x4005C52C, 4, gpiohook), |
|
('GPIOSLR_PORTE', 0x4005C518, 4, gpiohook), |
|
('GPIODR2R_PORTE', 0x4005C500, 4, gpiohook), |
|
('GPIODR4R_PORTE', 0x4005C504, 4, gpiohook), |
|
('GPIODR8R_PORTE', 0x4005C508, 4, gpiohook), |
|
|
|
('GPIODIR_PORTF', 0x4005D400, 4, gpiohook), |
|
('GPIOAFSEL_PORTF', 0x4005D420, 4, gpiohook), |
|
('GPIOPCTL_PORTF', 0x4005D52C, 4, gpiohook), |
|
('GPIOSLR_PORTF', 0x4005D518, 4, gpiohook), |
|
('GPIODR2R_PORTF', 0x4005D500, 4, gpiohook), |
|
('GPIODR4R_PORTF', 0x4005D504, 4, gpiohook), |
|
('GPIODR8R_PORTF', 0x4005D508, 4, gpiohook), |
|
|
|
] |
|
|
|
reg_to_print = all_regs |
|
|
|
if parsed_args.register: |
|
reg_to_print = [] |
|
|
|
for regex in [re.compile(x) for x in parsed_args.register]: |
|
filtered = [x for x in all_regs] |
|
reg_to_print += filter(lambda x: regex.match(x[0]), all_regs) |
|
|
|
for reg in reg_to_print: |
|
self.single_read(reg) |
|
|
|
ReadTiva ()
|
|
|