I2C works

This commit is contained in:
Sebastian 2019-08-23 18:50:19 +02:00
parent 9f55b6dc08
commit 03195921b8
4 changed files with 299 additions and 131 deletions

388
.gdbdash
View File

@ -5,11 +5,9 @@ python
# https://github.com/cyrus-and/gdb-dashboard # https://github.com/cyrus-and/gdb-dashboard
import ast import ast
import fcntl
import os import os
import re import re
import struct import struct
import termios
import traceback import traceback
import math 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 from pygments.styles import get_all_styles as styles
python for s in styles(): print(s) python for s in styles(): print(s)
""", """,
'default': 'vim', 'default': 'vim'
'type': str },
# 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
'prompt': { 'prompt': {
@ -183,39 +196,59 @@ def to_string(value):
value_string = str(value) value_string = str(value)
except UnicodeEncodeError: except UnicodeEncodeError:
value_string = unicode(value).encode('utf8') value_string = unicode(value).encode('utf8')
except gdb.error as e:
value_string = ansi(e, R.style_error)
return value_string return value_string
def format_address(address): def format_address(address):
pointer_size = gdb.parse_and_eval('$pc').type.sizeof pointer_size = gdb.parse_and_eval('$pc').type.sizeof
return ('0x{{:0{}x}}').format(pointer_size * 2).format(address) 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 # format references as referenced values
# (TYPE_CODE_RVALUE_REF is not supported by old GDB) # (TYPE_CODE_RVALUE_REF is not supported by old GDB)
if value.type.code in (getattr(gdb, 'TYPE_CODE_REF', None), if value.type.code in (getattr(gdb, 'TYPE_CODE_REF', None),
getattr(gdb, 'TYPE_CODE_RVALUE_REF', None)): getattr(gdb, 'TYPE_CODE_RVALUE_REF', None)):
try: value = value.referenced_value()
return to_string(value.referenced_value()) # format the value
except gdb.MemoryError: out = to_string(value)
return to_string(value) # dereference up to the actual value if requested
else: if R.dereference and value.type.code == gdb.TYPE_CODE_PTR:
try: while value.type.code == gdb.TYPE_CODE_PTR:
return to_string(value) try:
except gdb.MemoryError as e: value = value.dereference()
return ansi(e, R.style_error) 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(): class Beautifier():
def __init__(self, filename, tab_size=4): def __init__(self, hint, tab_size=4):
self.tab_spaces = ' ' * tab_size self.tab_spaces = ' ' * tab_size
self.active = False self.active = False
if not R.ansi: if not R.ansi:
return return
# attempt to set up Pygments # attempt to set up Pygments
try: try:
from pygments.lexers import get_lexer_for_filename import pygments
from pygments.lexers import GasLexer, NasmLexer
from pygments.formatters import Terminal256Formatter 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.formatter = Terminal256Formatter(style=R.syntax_highlighting)
self.lexer = get_lexer_for_filename(filename, stripnl=False)
self.active = True self.active = True
except ImportError: except ImportError:
# Pygments not available # Pygments not available
@ -383,8 +416,13 @@ class Dashboard(gdb.Command):
# skip disabled modules # skip disabled modules
if not instance: if not instance:
continue continue
# ask the module to generate the content try:
lines = instance.lines(width, style_changed) # 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 # create the divider accordingly
div = divider(width, instance.label(), True, lines) div = divider(width, instance.label(), True, lines)
# write the data # write the data
@ -427,10 +465,22 @@ class Dashboard(gdb.Command):
@staticmethod @staticmethod
def get_term_width(fd=1): # defaults to the main terminal def get_term_width(fd=1): # defaults to the main terminal
# first 2 shorts (4 byte) of struct winsize if sys.platform == 'win32':
raw = fcntl.ioctl(fd, termios.TIOCGWINSZ, ' ' * 4) try:
height, width = struct.unpack('hh', raw) import curses
return int(width) # 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 @staticmethod
def set_custom_prompt(dashboard): 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 frame = gdb.selected_frame() # PC is here
disassemble = frame.architecture().disassemble disassemble = frame.architecture().disassemble
try: try:
# try to fetch the function boundaries using the disassemble command # disassemble the current block
output = run('disassemble').split('\n') block = gdb.block_for_pc(frame.pc())
start = int(re.split('[ :]', output[1][3:], 1)[0], 16) asm = disassemble(block.start, end_pc=block.end - 1)
end = int(re.split('[ :]', output[-3][3:], 1)[0], 16)
asm = disassemble(start, end_pc=end)
# find the location of the PC # find the location of the PC
pc_index = next(index for index, instr in enumerate(asm) pc_index = next(index for index, instr in enumerate(asm)
if instr['addr'] == frame.pc()) 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 is not None but line_info.last is None
line_info = gdb.find_pc_line(frame.pc()) line_info = gdb.find_pc_line(frame.pc())
line_info = line_info if line_info.last else None 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 # 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 # the output of `disassemble` as per issue #31) start from PC and
# end after twice the context # end after twice the context
@ -995,17 +1043,13 @@ instructions constituting the current statement are marked, if available."""
func_start = to_unsigned(value) func_start = to_unsigned(value)
except gdb.error: except gdb.error:
pass # e.g., @plt 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: try:
flavor = gdb.parameter('disassembly-flavor') flavor = gdb.parameter('disassembly-flavor')
except: except:
flavor = None # not always defined (see #36) flavor = 'att' # not always defined (see #36)
filename = {
'att': '.s',
'intel': '.asm'
}.get(flavor, '.s')
# prepare the highlighter # prepare the highlighter
highlighter = Beautifier(filename) highlighter = Beautifier(flavor)
# compute the maximum offset size # compute the maximum offset size
if func_start: if func_start:
max_offset = max(len(str(abs(asm[0]['addr'] - 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): class Stack(Dashboard.Module):
"""Show the current stack trace including the function name and the file """Show the current stack trace including the function name and the file
location, if available. Optionally list the frame arguments and locals too.""" 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) info = Stack.get_pc_line(frame, style)
frame_lines = [] frame_lines = []
frame_lines.append('[{}] {}'.format(frame_id, info)) frame_lines.append('[{}] {}'.format(frame_id, info))
# fetch frame arguments and locals # add frame arguments and locals
decorator = gdb.FrameDecorator.FrameDecorator(frame) frame_lines.extend(Variables.format_variables(
separator = ansi(', ', R.style_low) frame, self.show_arguments, self.show_locals, self.compact))
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 # add frame
frames.append(frame_lines) frames.append(frame_lines)
# next # next
@ -1178,16 +1269,6 @@ location, if available. Optionally list the frame arguments and locals too."""
prefix = ansi(prefix, R.style_low) prefix = ansi(prefix, R.style_low)
return '{} {}'.format(prefix, line) 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 @staticmethod
def get_pc_line(frame, style): def get_pc_line(frame, style):
frame_pc = ansi(format_address(frame.pc()), 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 { return {
'limit': { 'limit': {
'doc': 'Maximum number of displayed frames (0 means no limit).', 'doc': 'Maximum number of displayed frames (0 means no limit).',
'default': 2, 'default': 10,
'type': int, 'type': int,
'check': check_ge_zero 'check': check_ge_zero
}, },
'arguments': { 'arguments': {
'doc': 'Frame arguments visibility flag.', 'doc': 'Frame arguments visibility flag.',
'default': True, 'default': False,
'name': 'show_arguments', 'name': 'show_arguments',
'type': bool 'type': bool
}, },
@ -1275,6 +1356,61 @@ class History(Dashboard.Module):
class Memory(Dashboard.Module): class Memory(Dashboard.Module):
"""Allow to inspect memory regions.""" """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 @staticmethod
def format_byte(byte): def format_byte(byte):
# `type(byte) is bytes` in Python 3 # `type(byte) is bytes` in Python 3
@ -1294,35 +1430,13 @@ class Memory(Dashboard.Module):
self.row_length = 16 self.row_length = 16
self.table = {} 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): def label(self):
return 'Memory' return 'Memory'
def lines(self, term_width, style_changed): def lines(self, term_width, style_changed):
out = [] out = []
inferior = gdb.selected_inferior() for address, region in sorted(self.table.items()):
for address, length in sorted(self.table.items()): out.extend(region.format())
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))
out.append(divider(term_width)) out.append(divider(term_width))
# drop last divider # drop last divider
if out: if out:
@ -1337,7 +1451,7 @@ class Memory(Dashboard.Module):
length = Memory.parse_as_address(length) length = Memory.parse_as_address(length)
else: else:
length = self.row_length length = self.row_length
self.table[address] = length self.table[address] = Memory.Region(address, length, self)
else: else:
raise Exception('Specify an address') 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): class Registers(Dashboard.Module):
"""Show the CPU registers and their values.""" """Show the CPU registers and their values."""
@ -1385,11 +1508,18 @@ class Registers(Dashboard.Module):
# skip if the current thread is not stopped # skip if the current thread is not stopped
if not gdb.selected_thread().is_stopped(): if not gdb.selected_thread().is_stopped():
return [] 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 # fetch registers status
registers = [] registers = []
for reg_info in run('info registers').strip().split('\n'): for name in register_list:
# fetch register and update the table
name = reg_info.split(None, 1)[0]
# Exclude registers with a dot '.' or parse_and_eval() will fail # Exclude registers with a dot '.' or parse_and_eval() will fail
if '.' in name: if '.' in name:
continue continue
@ -1404,15 +1534,10 @@ class Registers(Dashboard.Module):
max_name = max(len(name) for name, _, _ in registers) max_name = max(len(name) for name, _, _ in registers)
max_value = max(len(value) for _, value, _ in registers) max_value = max(len(value) for _, value, _ in registers)
max_width = max_name + max_value + 2 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 # redistribute extra space among columns
extra = int((term_width + 1 - max_width * per_line) / per_line) extra = int((term_width + 1 - max_width * per_line) / per_line)
if per_line == 1: max_name += int(extra / 2)
# center when there is only one column
max_name += int(extra / 2)
max_value += int(extra / 2)
else:
max_value += extra
# format registers info # format registers info
partial = [] partial = []
for name, value, changed in registers: for name, value, changed in registers:
@ -1440,6 +1565,12 @@ class Registers(Dashboard.Module):
'default': False, 'default': False,
'name': 'column_major', 'name': 'column_major',
'type': bool '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() restore_frame = gdb.selected_thread().is_stopped()
if restore_frame: if restore_frame:
selected_frame = gdb.selected_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 # skip running threads if requested
if self.skip_running and thread.is_running(): if self.skip_running and thread.is_running():
continue continue
is_selected = (thread.ptid == selected_thread.ptid) is_selected = (thread.ptid == selected_thread.ptid)
style = R.style_selected_1 if is_selected else R.style_selected_2 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) tid = ansi(str(thread.ptid[1] or thread.ptid[2]), style)
info = '[{}] id {}'.format(number, tid) info = '[{}] id {}'.format(number, tid)
if thread.name: if thread.name:
@ -1500,7 +1640,13 @@ class Threads(Dashboard.Module):
'default': False, 'default': False,
'name': 'skip_running', 'name': 'skip_running',
'type': bool 'type': bool
} },
'all-inferiors': {
'doc': 'Show threads from all inferiors.',
'default': False,
'name': 'all_inferiors',
'type': bool
},
} }
class Expressions(Dashboard.Module): class Expressions(Dashboard.Module):
@ -1579,7 +1725,7 @@ set python print-stack full
python Dashboard.start() 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 # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal

View File

@ -2,7 +2,7 @@
authors = ["sebastian"] authors = ["sebastian"]
edition = "2018" edition = "2018"
readme = "README.md" readme = "README.md"
name = "STM32F1Test" name = "cheapsdo"
version = "0.1.0" version = "0.1.0"
[dependencies] [dependencies]
@ -27,7 +27,7 @@ features = ["unproven"]
# this lets you use `cargo fix`! # this lets you use `cargo fix`!
[[bin]] [[bin]]
name = "STM32F1Test" name = "cheapsdo"
test = false test = false
bench = false bench = false

2
run.sh
View File

@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
cargo build || exit -1 cargo build || exit -1
arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/STM32F1Test arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/cheapsdo

View File

@ -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)] #![deny(unsafe_code)]
#![no_std] #![no_std]
#![no_main] #![no_main]
use panic_halt as _; use panic_halt as _;
use cortex_m_semihosting::hprintln; // logs messages to the host; requires a debugger
use nb::block; use nb::block;
use stm32f1xx_hal::{ use stm32f1xx_hal::{
prelude::*, prelude::*,
pac, pac,
i2c,
timer::Timer, timer::Timer,
}; };
use cortex_m_rt::entry; use cortex_m_rt::entry;
@ -23,6 +18,7 @@ use embedded_hal::digital::v2::OutputPin;
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
// Get access to the core peripherals from the cortex-m crate // Get access to the core peripherals from the cortex-m crate
let cp = cortex_m::Peripherals::take().unwrap(); let cp = cortex_m::Peripherals::take().unwrap();
// Get access to the device specific peripherals from the peripheral access crate // Get access to the device specific peripherals from the peripheral access crate
@ -32,6 +28,7 @@ fn main() -> ! {
// HAL structs // HAL structs
let mut flash = dp.FLASH.constrain(); let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.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 // Freeze the configuration of all the clocks in the system and store the frozen frequencies in
// `clocks` // `clocks`
@ -40,6 +37,23 @@ fn main() -> ! {
// Acquire the GPIOC peripheral // Acquire the GPIOC peripheral
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); 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 // 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. // 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); let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
@ -50,6 +64,14 @@ fn main() -> ! {
loop { loop {
block!(timer.wait()).unwrap(); block!(timer.wait()).unwrap();
led.set_high().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(); block!(timer.wait()).unwrap();
led.set_low().unwrap(); led.set_low().unwrap();
} }