Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I2CMasterSlaveDriver: add write_read command. #681

Merged
merged 1 commit into from Nov 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions capsules/src/i2c_master_slave_driver.rs
Expand Up @@ -48,6 +48,7 @@ impl Default for App {
enum MasterAction {
Read(u8),
Write,
WriteRead(u8),
}


Expand Down Expand Up @@ -117,6 +118,17 @@ impl<'a> hil::i2c::I2CHwMasterClient for I2CMasterSlaveDriver<'a> {
app.callback.map(|mut cb| { cb.schedule(1, err as usize, 0); });
});
}

MasterAction::WriteRead(read_len) => {
self.app.map(|app| {
app.master_tx_buffer.as_mut().map(move |app_buffer| {
let len = cmp::min(app_buffer.len(), read_len as usize);
app_buffer.as_mut()[..len].copy_from_slice(&buffer[..len]);
self.master_buffer.replace(buffer);
});
app.callback.map(|mut cb| { cb.schedule(7, err as usize, 0); });
});
}
}

// Check to see if we were listening as an I2C slave and should re-enable
Expand Down Expand Up @@ -363,6 +375,33 @@ impl<'a> Driver for I2CMasterSlaveDriver<'a> {
ReturnCode::SUCCESS
}

// Perform write-to then read-from a slave device.
// Uses tx buffer for both read and write.
7 => {
let address = (data & 0xFF) as u8;
let read_len = (data >> 8) & 0xFF;
let write_len = (data >> 16) & 0xFF;
self.app.map(|app| {
app.master_tx_buffer.as_mut().map(|app_tx| {
self.master_buffer.take().map(|kernel_tx| {
// Check bounds for write length
let buf_len = cmp::min(app_tx.len(), kernel_tx.len());
let write_len = cmp::min(buf_len, write_len);
let read_len = cmp::min(buf_len, read_len);
kernel_tx[..write_len].copy_from_slice(&app_tx.as_ref()[..write_len]);
self.master_action.set(MasterAction::WriteRead(read_len as u8));
hil::i2c::I2CMaster::enable(self.i2c);
hil::i2c::I2CMaster::write_read(self.i2c,
address,
kernel_tx,
write_len as u8,
read_len as u8);
});
});
});
ReturnCode::SUCCESS
}

// default
_ => ReturnCode::ENOSUPPORT,
}
Expand Down
21 changes: 21 additions & 0 deletions userland/libtock/i2c_master_slave.c
Expand Up @@ -46,6 +46,11 @@ int i2c_master_slave_write(uint8_t address, uint8_t length) {
return command(DRIVER_NUM_I2CMASTERSLAVE, 1, a, 0);
}

int i2c_master_slave_write_read(uint8_t address, uint8_t write_length, uint8_t read_length) {
uint32_t a = (((uint32_t) write_length) << 16) | ((uint32_t) read_length << 8) | address;
return command(DRIVER_NUM_I2CMASTERSLAVE, 7, a, 0);
}

int i2c_master_slave_read(uint16_t address, uint16_t len) {
uint32_t a = (((uint32_t) len) << 16) | address;
return command(DRIVER_NUM_I2CMASTERSLAVE, 2, a, 0);
Expand Down Expand Up @@ -79,6 +84,22 @@ int i2c_master_slave_write_sync(uint8_t address, uint8_t len) {
return result.length;
}

int i2c_master_slave_write_read_sync(uint8_t address, uint8_t wlen, uint8_t rlen) {
int err;
result.fired = false;

err = i2c_master_slave_set_callback(i2c_master_slave_cb, (void*) &result);
if (err < 0) return err;

err = i2c_master_slave_write_read(address, wlen, rlen);
if (err < 0) return err;

// Wait for the callback.
yield_for(&result.fired);

return result.length;
}

int i2c_master_slave_read_sync(uint16_t address, uint16_t len) {
int err;
result.fired = false;
Expand Down
2 changes: 2 additions & 0 deletions userland/libtock/i2c_master_slave.h
Expand Up @@ -20,12 +20,14 @@ int i2c_master_slave_set_master_read_buffer(uint8_t* buffer, uint32_t len);
int i2c_master_slave_set_slave_read_buffer(uint8_t* buffer, uint32_t len);
int i2c_master_slave_set_slave_write_buffer(uint8_t* buffer, uint32_t len);
int i2c_master_slave_write(uint8_t address, uint8_t length);
int i2c_master_slave_write_read(uint8_t address, uint8_t write_length, uint8_t read_length);
int i2c_master_slave_read(uint16_t address, uint16_t len);
int i2c_master_slave_listen(void);
int i2c_master_slave_set_slave_address(uint8_t address);
int i2c_master_slave_enable_slave_read(uint32_t len);

int i2c_master_slave_write_sync(uint8_t address, uint8_t length);
int i2c_master_slave_write_read_sync(uint8_t address, uint8_t wlen, uint8_t rlen);
int i2c_master_slave_read_sync(uint16_t address, uint16_t len);

#ifdef __cplusplus
Expand Down