I2C works
This commit is contained in:
parent
9f55b6dc08
commit
03195921b8
388
.gdbdash
388
.gdbdash
|
@ -5,11 +5,9 @@ python
|
|||
# https://github.com/cyrus-and/gdb-dashboard
|
||||
|
||||
import ast
|
||||
import fcntl
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
import termios
|
||||
import traceback
|
||||
import math
|
||||
|
||||
|
@ -34,8 +32,23 @@ The list of all the available styles can be obtained with (from GDB itself):
|
|||
python from pygments.styles import get_all_styles as styles
|
||||
python for s in styles(): print(s)
|
||||
""",
|
||||
'default': 'vim',
|
||||
'type': str
|
||||
'default': 'vim'
|
||||
},
|
||||
# values formatting
|
||||
'compact_values': {
|
||||
'doc': 'Display complex objects in a single line.',
|
||||
'default': False,
|
||||
'type': bool
|
||||
},
|
||||
'max_value_length': {
|
||||
'doc': 'Maximum length for displayed values.',
|
||||
'default': 0,
|
||||
'type': int
|
||||
},
|
||||
'dereference': {
|
||||
'doc': 'Annotate pointers with the pointed value.',
|
||||
'default': True,
|
||||
'type': bool
|
||||
},
|
||||
# prompt
|
||||
'prompt': {
|
||||
|
@ -183,39 +196,59 @@ def to_string(value):
|
|||
value_string = str(value)
|
||||
except UnicodeEncodeError:
|
||||
value_string = unicode(value).encode('utf8')
|
||||
except gdb.error as e:
|
||||
value_string = ansi(e, R.style_error)
|
||||
return value_string
|
||||
|
||||
def format_address(address):
|
||||
pointer_size = gdb.parse_and_eval('$pc').type.sizeof
|
||||
return ('0x{{:0{}x}}').format(pointer_size * 2).format(address)
|
||||
|
||||
def format_value(value):
|
||||
def format_value(value, compact=None):
|
||||
# format references as referenced values
|
||||
# (TYPE_CODE_RVALUE_REF is not supported by old GDB)
|
||||
if value.type.code in (getattr(gdb, 'TYPE_CODE_REF', None),
|
||||
getattr(gdb, 'TYPE_CODE_RVALUE_REF', None)):
|
||||
try:
|
||||
return to_string(value.referenced_value())
|
||||
except gdb.MemoryError:
|
||||
return to_string(value)
|
||||
else:
|
||||
try:
|
||||
return to_string(value)
|
||||
except gdb.MemoryError as e:
|
||||
return ansi(e, R.style_error)
|
||||
value = value.referenced_value()
|
||||
# format the value
|
||||
out = to_string(value)
|
||||
# dereference up to the actual value if requested
|
||||
if R.dereference and value.type.code == gdb.TYPE_CODE_PTR:
|
||||
while value.type.code == gdb.TYPE_CODE_PTR:
|
||||
try:
|
||||
value = value.dereference()
|
||||
except gdb.error as e:
|
||||
break
|
||||
else:
|
||||
formatted = to_string(value)
|
||||
out += '{} {}'.format(ansi(':', R.style_low), formatted)
|
||||
# compact the value
|
||||
if compact is not None and compact or R.compact_values:
|
||||
out = re.sub(r'$\s*', '', out, flags=re.MULTILINE)
|
||||
# truncate the value
|
||||
if R.max_value_length > 0 and len(out) > R.max_value_length:
|
||||
out = out[0:R.max_value_length] + ansi('[...]', R.style_error)
|
||||
return out
|
||||
|
||||
class Beautifier():
|
||||
def __init__(self, filename, tab_size=4):
|
||||
def __init__(self, hint, tab_size=4):
|
||||
self.tab_spaces = ' ' * tab_size
|
||||
self.active = False
|
||||
if not R.ansi:
|
||||
return
|
||||
# attempt to set up Pygments
|
||||
try:
|
||||
from pygments.lexers import get_lexer_for_filename
|
||||
import pygments
|
||||
from pygments.lexers import GasLexer, NasmLexer
|
||||
from pygments.formatters import Terminal256Formatter
|
||||
if hint == 'att':
|
||||
self.lexer = GasLexer()
|
||||
elif hint == 'intel':
|
||||
self.lexer = NasmLexer()
|
||||
else:
|
||||
from pygments.lexers import get_lexer_for_filename
|
||||
self.lexer = get_lexer_for_filename(hint, stripnl=False)
|
||||
self.formatter = Terminal256Formatter(style=R.syntax_highlighting)
|
||||
self.lexer = get_lexer_for_filename(filename, stripnl=False)
|
||||
self.active = True
|
||||
except ImportError:
|
||||
# Pygments not available
|
||||
|
@ -383,8 +416,13 @@ class Dashboard(gdb.Command):
|
|||
# skip disabled modules
|
||||
if not instance:
|
||||
continue
|
||||
# ask the module to generate the content
|
||||
lines = instance.lines(width, style_changed)
|
||||
try:
|
||||
# ask the module to generate the content
|
||||
lines = instance.lines(width, style_changed)
|
||||
except Exception as e:
|
||||
# allow to continue on exceptions in modules
|
||||
stacktrace = traceback.format_exc().strip()
|
||||
lines = [ansi(stacktrace, R.style_error)]
|
||||
# create the divider accordingly
|
||||
div = divider(width, instance.label(), True, lines)
|
||||
# write the data
|
||||
|
@ -427,10 +465,22 @@ class Dashboard(gdb.Command):
|
|||
|
||||
@staticmethod
|
||||
def get_term_width(fd=1): # defaults to the main terminal
|
||||
# first 2 shorts (4 byte) of struct winsize
|
||||
raw = fcntl.ioctl(fd, termios.TIOCGWINSZ, ' ' * 4)
|
||||
height, width = struct.unpack('hh', raw)
|
||||
return int(width)
|
||||
if sys.platform == 'win32':
|
||||
try:
|
||||
import curses
|
||||
# XXX always neglects the fd parameter
|
||||
_, width = curses.initscr().getmaxyx()
|
||||
curses.endwin()
|
||||
return int(width)
|
||||
except ImportError:
|
||||
return 80 # hardcoded fallback value
|
||||
else:
|
||||
import termios
|
||||
import fcntl
|
||||
# first 2 shorts (4 byte) of struct winsize
|
||||
raw = fcntl.ioctl(fd, termios.TIOCGWINSZ, ' ' * 4)
|
||||
_, width = struct.unpack('hh', raw)
|
||||
return int(width)
|
||||
|
||||
@staticmethod
|
||||
def set_custom_prompt(dashboard):
|
||||
|
@ -959,11 +1009,9 @@ instructions constituting the current statement are marked, if available."""
|
|||
frame = gdb.selected_frame() # PC is here
|
||||
disassemble = frame.architecture().disassemble
|
||||
try:
|
||||
# try to fetch the function boundaries using the disassemble command
|
||||
output = run('disassemble').split('\n')
|
||||
start = int(re.split('[ :]', output[1][3:], 1)[0], 16)
|
||||
end = int(re.split('[ :]', output[-3][3:], 1)[0], 16)
|
||||
asm = disassemble(start, end_pc=end)
|
||||
# disassemble the current block
|
||||
block = gdb.block_for_pc(frame.pc())
|
||||
asm = disassemble(block.start, end_pc=block.end - 1)
|
||||
# find the location of the PC
|
||||
pc_index = next(index for index, instr in enumerate(asm)
|
||||
if instr['addr'] == frame.pc())
|
||||
|
@ -974,7 +1022,7 @@ instructions constituting the current statement are marked, if available."""
|
|||
# line_info is not None but line_info.last is None
|
||||
line_info = gdb.find_pc_line(frame.pc())
|
||||
line_info = line_info if line_info.last else None
|
||||
except (gdb.error, StopIteration):
|
||||
except (gdb.error, RuntimeError, StopIteration):
|
||||
# if it is not possible (stripped binary or the PC is not present in
|
||||
# the output of `disassemble` as per issue #31) start from PC and
|
||||
# end after twice the context
|
||||
|
@ -995,17 +1043,13 @@ instructions constituting the current statement are marked, if available."""
|
|||
func_start = to_unsigned(value)
|
||||
except gdb.error:
|
||||
pass # e.g., @plt
|
||||
# fetch the assembly flavor and the extension used by Pygments
|
||||
# fetch the assembly flavor anduse it as hint for Pygments
|
||||
try:
|
||||
flavor = gdb.parameter('disassembly-flavor')
|
||||
except:
|
||||
flavor = None # not always defined (see #36)
|
||||
filename = {
|
||||
'att': '.s',
|
||||
'intel': '.asm'
|
||||
}.get(flavor, '.s')
|
||||
flavor = 'att' # not always defined (see #36)
|
||||
# prepare the highlighter
|
||||
highlighter = Beautifier(filename)
|
||||
highlighter = Beautifier(flavor)
|
||||
# compute the maximum offset size
|
||||
if func_start:
|
||||
max_offset = max(len(str(abs(asm[0]['addr'] - func_start))),
|
||||
|
@ -1087,6 +1131,84 @@ instructions constituting the current statement are marked, if available."""
|
|||
}
|
||||
}
|
||||
|
||||
class Variables(Dashboard.Module):
|
||||
"""Show arguments and locals of the selected frame."""
|
||||
|
||||
def label(self):
|
||||
return 'Variables'
|
||||
|
||||
def lines(self, term_width, style_changed):
|
||||
return Variables.format_variables(
|
||||
gdb.selected_frame(),
|
||||
self.show_arguments, self.show_locals, self.compact)
|
||||
|
||||
def attributes(self):
|
||||
return {
|
||||
'arguments': {
|
||||
'doc': 'Frame arguments visibility flag.',
|
||||
'default': True,
|
||||
'name': 'show_arguments',
|
||||
'type': bool
|
||||
},
|
||||
'locals': {
|
||||
'doc': 'Frame locals visibility flag.',
|
||||
'default': True,
|
||||
'name': 'show_locals',
|
||||
'type': bool
|
||||
},
|
||||
'compact': {
|
||||
'doc': 'Single-line display flag.',
|
||||
'default': False,
|
||||
'type': bool
|
||||
}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def format_variables(frame, show_arguments, show_locals, compact):
|
||||
out = []
|
||||
# fetch frame arguments and locals
|
||||
decorator = gdb.FrameDecorator.FrameDecorator(frame)
|
||||
separator = ansi(', ', R.style_low)
|
||||
if show_arguments:
|
||||
def prefix(line):
|
||||
return Stack.format_line('arg', line)
|
||||
frame_args = decorator.frame_args()
|
||||
args_lines = Variables.fetch(frame, frame_args, compact)
|
||||
if args_lines:
|
||||
if compact:
|
||||
args_line = separator.join(args_lines)
|
||||
single_line = prefix(args_line)
|
||||
out.append(single_line)
|
||||
else:
|
||||
out.extend(map(prefix, args_lines))
|
||||
else:
|
||||
out.append(ansi('(no arguments)', R.style_low))
|
||||
if show_locals:
|
||||
def prefix(line):
|
||||
return Stack.format_line('loc', line)
|
||||
frame_locals = decorator.frame_locals()
|
||||
locals_lines = Variables.fetch(frame, frame_locals, compact)
|
||||
if locals_lines:
|
||||
if compact:
|
||||
locals_line = separator.join(locals_lines)
|
||||
single_line = prefix(locals_line)
|
||||
out.append(single_line)
|
||||
else:
|
||||
out.extend(map(prefix, locals_lines))
|
||||
else:
|
||||
out.append(ansi('(no locals)', R.style_low))
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def fetch(frame, data, compact):
|
||||
lines = []
|
||||
for elem in data or []:
|
||||
name = elem.sym
|
||||
equal = ansi('=', R.style_low)
|
||||
value = format_value(elem.sym.value(frame), compact)
|
||||
lines.append('{} {} {}'.format(name, equal, value))
|
||||
return lines
|
||||
|
||||
class Stack(Dashboard.Module):
|
||||
"""Show the current stack trace including the function name and the file
|
||||
location, if available. Optionally list the frame arguments and locals too."""
|
||||
|
@ -1119,40 +1241,9 @@ location, if available. Optionally list the frame arguments and locals too."""
|
|||
info = Stack.get_pc_line(frame, style)
|
||||
frame_lines = []
|
||||
frame_lines.append('[{}] {}'.format(frame_id, info))
|
||||
# fetch frame arguments and locals
|
||||
decorator = gdb.FrameDecorator.FrameDecorator(frame)
|
||||
separator = ansi(', ', R.style_low)
|
||||
strip_newlines = re.compile(r'$\s*', re.MULTILINE)
|
||||
if self.show_arguments:
|
||||
def prefix(line):
|
||||
return Stack.format_line('arg', line)
|
||||
frame_args = decorator.frame_args()
|
||||
args_lines = Stack.fetch_frame_info(frame, frame_args)
|
||||
if args_lines:
|
||||
if self.compact:
|
||||
args_line = separator.join(args_lines)
|
||||
args_line = strip_newlines.sub('', args_line)
|
||||
single_line = prefix(args_line)
|
||||
frame_lines.append(single_line)
|
||||
else:
|
||||
frame_lines.extend(map(prefix, args_lines))
|
||||
else:
|
||||
frame_lines.append(ansi('(no arguments)', R.style_low))
|
||||
if self.show_locals:
|
||||
def prefix(line):
|
||||
return Stack.format_line('loc', line)
|
||||
frame_locals = decorator.frame_locals()
|
||||
locals_lines = Stack.fetch_frame_info(frame, frame_locals)
|
||||
if locals_lines:
|
||||
if self.compact:
|
||||
locals_line = separator.join(locals_lines)
|
||||
locals_line = strip_newlines.sub('', locals_line)
|
||||
single_line = prefix(locals_line)
|
||||
frame_lines.append(single_line)
|
||||
else:
|
||||
frame_lines.extend(map(prefix, locals_lines))
|
||||
else:
|
||||
frame_lines.append(ansi('(no locals)', R.style_low))
|
||||
# add frame arguments and locals
|
||||
frame_lines.extend(Variables.format_variables(
|
||||
frame, self.show_arguments, self.show_locals, self.compact))
|
||||
# add frame
|
||||
frames.append(frame_lines)
|
||||
# next
|
||||
|
@ -1178,16 +1269,6 @@ location, if available. Optionally list the frame arguments and locals too."""
|
|||
prefix = ansi(prefix, R.style_low)
|
||||
return '{} {}'.format(prefix, line)
|
||||
|
||||
@staticmethod
|
||||
def fetch_frame_info(frame, data):
|
||||
lines = []
|
||||
for elem in data or []:
|
||||
name = elem.sym
|
||||
equal = ansi('=', R.style_low)
|
||||
value = format_value(elem.sym.value(frame))
|
||||
lines.append('{} {} {}'.format(name, equal, value))
|
||||
return lines
|
||||
|
||||
@staticmethod
|
||||
def get_pc_line(frame, style):
|
||||
frame_pc = ansi(format_address(frame.pc()), style)
|
||||
|
@ -1220,13 +1301,13 @@ location, if available. Optionally list the frame arguments and locals too."""
|
|||
return {
|
||||
'limit': {
|
||||
'doc': 'Maximum number of displayed frames (0 means no limit).',
|
||||
'default': 2,
|
||||
'default': 10,
|
||||
'type': int,
|
||||
'check': check_ge_zero
|
||||
},
|
||||
'arguments': {
|
||||
'doc': 'Frame arguments visibility flag.',
|
||||
'default': True,
|
||||
'default': False,
|
||||
'name': 'show_arguments',
|
||||
'type': bool
|
||||
},
|
||||
|
@ -1275,6 +1356,61 @@ class History(Dashboard.Module):
|
|||
class Memory(Dashboard.Module):
|
||||
"""Allow to inspect memory regions."""
|
||||
|
||||
class Region():
|
||||
def __init__(self, address, length, module):
|
||||
self.address = address
|
||||
self.length = length
|
||||
self.module = module
|
||||
self.original = None
|
||||
self.latest = None
|
||||
|
||||
def format(self):
|
||||
# fetch the memory content
|
||||
try:
|
||||
inferior = gdb.selected_inferior()
|
||||
memory = inferior.read_memory(self.address, self.length)
|
||||
# set the original memory snapshot if needed
|
||||
if not self.original:
|
||||
self.original = memory
|
||||
except gdb.error:
|
||||
msg = 'Cannot access {} bytes starting at {}'
|
||||
msg = msg.format(self.length, format_address(self.address))
|
||||
return [ansi(msg, R.style_error)]
|
||||
|
||||
# format the memory content
|
||||
out = []
|
||||
for i in range(0, len(memory), self.module.row_length):
|
||||
region = memory[i:i + self.module.row_length]
|
||||
pad = self.module.row_length - len(region)
|
||||
address = format_address(self.address + i)
|
||||
# compute changes
|
||||
hexa = []
|
||||
text = []
|
||||
for j in range(len(region)):
|
||||
rel = i + j
|
||||
byte = memory[rel]
|
||||
hexa_byte = '{:02x}'.format(ord(byte))
|
||||
text_byte = Memory.format_byte(byte)
|
||||
# differences against the latest have the highest priority
|
||||
if self.latest and memory[rel] != self.latest[rel]:
|
||||
hexa_byte = ansi(hexa_byte, R.style_selected_1)
|
||||
text_byte = ansi(text_byte, R.style_selected_1)
|
||||
# cumulative changes if enabled
|
||||
elif (self.module.cumulative and
|
||||
memory[rel] != self.original[rel]):
|
||||
hexa_byte = ansi(hexa_byte, R.style_selected_2)
|
||||
text_byte = ansi(text_byte, R.style_selected_2)
|
||||
hexa.append(hexa_byte)
|
||||
text.append(text_byte)
|
||||
# output the formatted line
|
||||
out.append('{} {}{} {}{}'.format(
|
||||
ansi(address, R.style_low),
|
||||
' '.join(hexa), ansi(pad * ' --', R.style_low),
|
||||
''.join(text), ansi(pad * '.', R.style_low)))
|
||||
# update the latest memory snapshot
|
||||
self.latest = memory
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def format_byte(byte):
|
||||
# `type(byte) is bytes` in Python 3
|
||||
|
@ -1294,35 +1430,13 @@ class Memory(Dashboard.Module):
|
|||
self.row_length = 16
|
||||
self.table = {}
|
||||
|
||||
def format_memory(self, start, memory):
|
||||
out = []
|
||||
for i in range(0, len(memory), self.row_length):
|
||||
region = memory[i:i + self.row_length]
|
||||
pad = self.row_length - len(region)
|
||||
address = format_address(start + i)
|
||||
hexa = (' '.join('{:02x}'.format(ord(byte)) for byte in region))
|
||||
text = (''.join(Memory.format_byte(byte) for byte in region))
|
||||
out.append('{} {}{} {}{}'.format(ansi(address, R.style_low),
|
||||
hexa,
|
||||
ansi(pad * ' --', R.style_low),
|
||||
ansi(text, R.style_high),
|
||||
ansi(pad * '.', R.style_low)))
|
||||
return out
|
||||
|
||||
def label(self):
|
||||
return 'Memory'
|
||||
|
||||
def lines(self, term_width, style_changed):
|
||||
out = []
|
||||
inferior = gdb.selected_inferior()
|
||||
for address, length in sorted(self.table.items()):
|
||||
try:
|
||||
memory = inferior.read_memory(address, length)
|
||||
out.extend(self.format_memory(address, memory))
|
||||
except gdb.error:
|
||||
msg = 'Cannot access {} bytes starting at {}'
|
||||
msg = msg.format(length, format_address(address))
|
||||
out.append(ansi(msg, R.style_error))
|
||||
for address, region in sorted(self.table.items()):
|
||||
out.extend(region.format())
|
||||
out.append(divider(term_width))
|
||||
# drop last divider
|
||||
if out:
|
||||
|
@ -1337,7 +1451,7 @@ class Memory(Dashboard.Module):
|
|||
length = Memory.parse_as_address(length)
|
||||
else:
|
||||
length = self.row_length
|
||||
self.table[address] = length
|
||||
self.table[address] = Memory.Region(address, length, self)
|
||||
else:
|
||||
raise Exception('Specify an address')
|
||||
|
||||
|
@ -1372,6 +1486,15 @@ class Memory(Dashboard.Module):
|
|||
}
|
||||
}
|
||||
|
||||
def attributes(self):
|
||||
return {
|
||||
'cumulative': {
|
||||
'doc': 'Highlight changes cumulatively, watch again to reset.',
|
||||
'default': False,
|
||||
'type': bool
|
||||
}
|
||||
}
|
||||
|
||||
class Registers(Dashboard.Module):
|
||||
"""Show the CPU registers and their values."""
|
||||
|
||||
|
@ -1385,11 +1508,18 @@ class Registers(Dashboard.Module):
|
|||
# skip if the current thread is not stopped
|
||||
if not gdb.selected_thread().is_stopped():
|
||||
return []
|
||||
# obtain the registers to display
|
||||
if style_changed:
|
||||
self.table = {}
|
||||
if self.register_list:
|
||||
register_list = self.register_list.split()
|
||||
else:
|
||||
register_list = list(map(lambda line: line.split(None, 1)[0],
|
||||
run('info registers').strip().split('\n')))
|
||||
|
||||
# fetch registers status
|
||||
registers = []
|
||||
for reg_info in run('info registers').strip().split('\n'):
|
||||
# fetch register and update the table
|
||||
name = reg_info.split(None, 1)[0]
|
||||
for name in register_list:
|
||||
# Exclude registers with a dot '.' or parse_and_eval() will fail
|
||||
if '.' in name:
|
||||
continue
|
||||
|
@ -1404,15 +1534,10 @@ class Registers(Dashboard.Module):
|
|||
max_name = max(len(name) for name, _, _ in registers)
|
||||
max_value = max(len(value) for _, value, _ in registers)
|
||||
max_width = max_name + max_value + 2
|
||||
per_line = int((term_width + 1) / max_width) or 1
|
||||
per_line = min(int((term_width + 1) / max_width) or 1, len(registers))
|
||||
# redistribute extra space among columns
|
||||
extra = int((term_width + 1 - max_width * per_line) / per_line)
|
||||
if per_line == 1:
|
||||
# center when there is only one column
|
||||
max_name += int(extra / 2)
|
||||
max_value += int(extra / 2)
|
||||
else:
|
||||
max_value += extra
|
||||
max_name += int(extra / 2)
|
||||
# format registers info
|
||||
partial = []
|
||||
for name, value, changed in registers:
|
||||
|
@ -1440,6 +1565,12 @@ class Registers(Dashboard.Module):
|
|||
'default': False,
|
||||
'name': 'column_major',
|
||||
'type': bool
|
||||
},
|
||||
'list': {
|
||||
'doc': """String of space-separated register names to display.
|
||||
The empty list (default) causes to show all the available registers.""",
|
||||
'default': '',
|
||||
'name': 'register_list',
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1468,13 +1599,22 @@ class Threads(Dashboard.Module):
|
|||
restore_frame = gdb.selected_thread().is_stopped()
|
||||
if restore_frame:
|
||||
selected_frame = gdb.selected_frame()
|
||||
for thread in gdb.Inferior.threads(gdb.selected_inferior()):
|
||||
# fetch the thread list
|
||||
threads = []
|
||||
for inferior in gdb.inferiors():
|
||||
if self.all_inferiors or inferior == gdb.selected_inferior():
|
||||
threads += gdb.Inferior.threads(inferior)
|
||||
for thread in threads:
|
||||
# skip running threads if requested
|
||||
if self.skip_running and thread.is_running():
|
||||
continue
|
||||
is_selected = (thread.ptid == selected_thread.ptid)
|
||||
style = R.style_selected_1 if is_selected else R.style_selected_2
|
||||
number = ansi(str(thread.num), style)
|
||||
if self.all_inferiors:
|
||||
number = '{}.{}'.format(thread.inferior.num, thread.num)
|
||||
else:
|
||||
number = str(thread.num)
|
||||
number = ansi(number, style)
|
||||
tid = ansi(str(thread.ptid[1] or thread.ptid[2]), style)
|
||||
info = '[{}] id {}'.format(number, tid)
|
||||
if thread.name:
|
||||
|
@ -1500,7 +1640,13 @@ class Threads(Dashboard.Module):
|
|||
'default': False,
|
||||
'name': 'skip_running',
|
||||
'type': bool
|
||||
}
|
||||
},
|
||||
'all-inferiors': {
|
||||
'doc': 'Show threads from all inferiors.',
|
||||
'default': False,
|
||||
'name': 'all_inferiors',
|
||||
'type': bool
|
||||
},
|
||||
}
|
||||
|
||||
class Expressions(Dashboard.Module):
|
||||
|
@ -1579,7 +1725,7 @@ set python print-stack full
|
|||
python Dashboard.start()
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2017 Andrea Cardaci <cyrus.and@gmail.com>
|
||||
# Copyright (c) 2015-2019 Andrea Cardaci <cyrus.and@gmail.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
authors = ["sebastian"]
|
||||
edition = "2018"
|
||||
readme = "README.md"
|
||||
name = "STM32F1Test"
|
||||
name = "cheapsdo"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
|
@ -27,7 +27,7 @@ features = ["unproven"]
|
|||
|
||||
# this lets you use `cargo fix`!
|
||||
[[bin]]
|
||||
name = "STM32F1Test"
|
||||
name = "cheapsdo"
|
||||
test = false
|
||||
bench = false
|
||||
|
||||
|
|
2
run.sh
2
run.sh
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
cargo build || exit -1
|
||||
arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/STM32F1Test
|
||||
arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/cheapsdo
|
||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -1,21 +1,16 @@
|
|||
//! Blinks an LED
|
||||
//!
|
||||
//! This assumes that a LED is connected to pc13 as is the case on the blue pill board.
|
||||
//!
|
||||
//! Note: Without additional hardware, PC13 should not be used to drive an LED, see page 5.1.2 of
|
||||
//! the reference manaual for an explanation. This is not an issue on the blue pill.
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use panic_halt as _;
|
||||
use cortex_m_semihosting::hprintln; // logs messages to the host; requires a debugger
|
||||
|
||||
use nb::block;
|
||||
|
||||
use stm32f1xx_hal::{
|
||||
prelude::*,
|
||||
pac,
|
||||
i2c,
|
||||
timer::Timer,
|
||||
};
|
||||
use cortex_m_rt::entry;
|
||||
|
@ -23,6 +18,7 @@ use embedded_hal::digital::v2::OutputPin;
|
|||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
|
||||
// Get access to the core peripherals from the cortex-m crate
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
// Get access to the device specific peripherals from the peripheral access crate
|
||||
|
@ -32,6 +28,7 @@ fn main() -> ! {
|
|||
// HAL structs
|
||||
let mut flash = dp.FLASH.constrain();
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
|
||||
|
||||
// Freeze the configuration of all the clocks in the system and store the frozen frequencies in
|
||||
// `clocks`
|
||||
|
@ -40,6 +37,23 @@ fn main() -> ! {
|
|||
// Acquire the GPIOC peripheral
|
||||
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
|
||||
|
||||
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
|
||||
let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl);
|
||||
let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl);
|
||||
|
||||
let mut i2c = i2c::BlockingI2c::i2c1(dp.I2C1, (scl, sda),
|
||||
&mut afio.mapr,
|
||||
i2c::Mode::Standard{frequency: 400_000},
|
||||
clocks,
|
||||
&mut rcc.apb1,
|
||||
5,
|
||||
1,
|
||||
5,
|
||||
5);
|
||||
|
||||
hprintln!("I2C setup").unwrap();
|
||||
|
||||
|
||||
// Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function
|
||||
// in order to configure the port. For pins 0-7, crl should be passed instead.
|
||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||
|
@ -50,6 +64,14 @@ fn main() -> ! {
|
|||
loop {
|
||||
block!(timer.wait()).unwrap();
|
||||
led.set_high().unwrap();
|
||||
|
||||
let res = i2c.write(96, &[0x23, 0x82]);
|
||||
if res.is_ok() {
|
||||
hprintln!("write worked!").unwrap();
|
||||
} else {
|
||||
hprintln!("write failed!").unwrap();
|
||||
}
|
||||
|
||||
block!(timer.wait()).unwrap();
|
||||
led.set_low().unwrap();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue