Send NAK when reading last byte

This commit is contained in:
Jeremy Soller
2020-12-02 12:32:21 -07:00
parent b6be17019c
commit 0fb6e613d3
3 changed files with 41 additions and 4 deletions

1
usb4/Cargo.lock generated
View File

@@ -125,6 +125,7 @@ name = "usb4"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"coreboot-collector", "coreboot-collector",
"libc",
] ]
[[package]] [[package]]

View File

@@ -8,3 +8,4 @@ edition = "2018"
[dependencies] [dependencies]
coreboot-collector = { path = "../tools/coreboot-collector" } coreboot-collector = { path = "../tools/coreboot-collector" }
libc = "0.2"

View File

@@ -1,6 +1,7 @@
use coreboot_collector::sideband::Sideband; use coreboot_collector::sideband::Sideband;
use std::{ use std::{
fs, fs,
io,
rc::Rc, rc::Rc,
process, process,
thread, thread,
@@ -153,9 +154,10 @@ impl I2CBitbang {
self.sda.enable_tx(false); self.sda.enable_tx(false);
} }
// SDA goes high to low while SCL is high
unsafe fn start(&mut self) { unsafe fn start(&mut self) {
self.set_scl();
self.set_sda(); self.set_sda();
self.set_scl();
self.delay(); self.delay();
self.clr_sda(); self.clr_sda();
self.delay(); self.delay();
@@ -163,6 +165,7 @@ impl I2CBitbang {
self.delay(); self.delay();
} }
// SDA goes low to high while SCL is high
unsafe fn stop(&mut self) { unsafe fn stop(&mut self) {
self.clr_sda(); self.clr_sda();
self.delay(); self.delay();
@@ -172,6 +175,7 @@ impl I2CBitbang {
self.delay(); self.delay();
} }
// SDA is set while SCL is pulsed
unsafe fn write_bit(&mut self, bit: bool) { unsafe fn write_bit(&mut self, bit: bool) {
if bit { if bit {
self.set_sda(); self.set_sda();
@@ -184,6 +188,7 @@ impl I2CBitbang {
self.clr_scl(); self.clr_scl();
} }
// SDA is read while SCL is pulsed
unsafe fn read_bit(&mut self) -> bool { unsafe fn read_bit(&mut self) -> bool {
self.set_sda(); self.set_sda();
self.delay(); self.delay();
@@ -194,6 +199,9 @@ impl I2CBitbang {
bit bit
} }
// Start condition is optionally sent
// 8 bits are written
// 1 bit is read, low if ack, high if nack
unsafe fn write_byte(&mut self, byte: u8, start: bool) -> bool { unsafe fn write_byte(&mut self, byte: u8, start: bool) -> bool {
if start { if start {
self.start(); self.start();
@@ -201,9 +209,11 @@ impl I2CBitbang {
for i in (0..8).rev() { for i in (0..8).rev() {
self.write_bit(byte & (1 << i) != 0); self.write_bit(byte & (1 << i) != 0);
} }
self.read_bit() !self.read_bit()
} }
// 8 bits are read
// 1 bit is written, low if ack, high if nack
unsafe fn read_byte(&mut self, ack: bool) -> u8 { unsafe fn read_byte(&mut self, ack: bool) -> u8 {
let mut byte = 0; let mut byte = 0;
for i in (0..8).rev() { for i in (0..8).rev() {
@@ -215,6 +225,12 @@ impl I2CBitbang {
byte byte
} }
// Start condition
// Address is written with read bit low
// Command is written
// Byte count is written
// Bytes are written
// Stop condition
pub unsafe fn smbus_block_write(&mut self, address: u8, command: u8, bytes: &[u8]) -> usize { pub unsafe fn smbus_block_write(&mut self, address: u8, command: u8, bytes: &[u8]) -> usize {
// Only 32 bytes can be processed at a time // Only 32 bytes can be processed at a time
if bytes.len() > 32 { if bytes.len() > 32 {
@@ -239,6 +255,13 @@ impl I2CBitbang {
count count
} }
// Start condition
// Address is written with read bit low
// Command is written
// Address is written with read bit high
// Byte count is read
// Bytes are read
// Stop condition
pub unsafe fn smbus_block_read(&mut self, address: u8, command: u8) -> Vec<u8> { pub unsafe fn smbus_block_read(&mut self, address: u8, command: u8) -> Vec<u8> {
//TODO: use static buffer? //TODO: use static buffer?
let mut bytes = Vec::new(); let mut bytes = Vec::new();
@@ -246,8 +269,9 @@ impl I2CBitbang {
if self.write_byte(command, false) { if self.write_byte(command, false) {
if self.write_byte(address << 1 | 1, true) { if self.write_byte(address << 1 | 1, true) {
let count = self.read_byte(true); let count = self.read_byte(true);
for _i in 0..count { for i in 0..count {
bytes.push(self.read_byte(true)); let ack = i + 1 != count;
bytes.push(self.read_byte(ack));
} }
} }
} }
@@ -442,6 +466,17 @@ fn main() {
//TODO: check model //TODO: check model
unsafe { unsafe {
if libc::sched_setscheduler(
libc::getpid(),
libc::SCHED_FIFO,
&libc::sched_param {
sched_priority: 99,
}
) != 0 {
eprintln!("Failed to set scheduler priority: {}", io::Error::last_os_error());
process::exit(1);
}
let sideband = match Sideband::new(0xFD00_0000) { let sideband = match Sideband::new(0xFD00_0000) {
Ok(ok) => Rc::new(ok), Ok(ok) => Rc::new(ok),
Err(err) => { Err(err) => {