Skip to content

Commit

Permalink
I2CMasterSlaveDriver: add write_read command. (#681)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vagabond authored and alevy committed Nov 9, 2017
1 parent ae8b39c commit 63f06d3
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
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

0 comments on commit 63f06d3

Please sign in to comment.