Send NAK when reading last byte
This commit is contained in:
1
usb4/Cargo.lock
generated
1
usb4/Cargo.lock
generated
@@ -125,6 +125,7 @@ name = "usb4"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"coreboot-collector",
|
"coreboot-collector",
|
||||||
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@@ -8,3 +8,4 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
coreboot-collector = { path = "../tools/coreboot-collector" }
|
coreboot-collector = { path = "../tools/coreboot-collector" }
|
||||||
|
libc = "0.2"
|
||||||
|
@@ -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) => {
|
||||||
|
Reference in New Issue
Block a user