-
-
Notifications
You must be signed in to change notification settings - Fork 776
Port NRF Serialization to 2.0 #2393
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
Changes from all commits
52b3f12
6f85074
0446d99
e664b12
4ed8309
823e463
f3de6ff
846789b
37a4deb
7df42c7
f9a79bf
1ffd5de
342396c
7639fcd
2625116
562b32e
aaa3b43
d70c0c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,17 +25,20 @@ use core::cmp; | |
use kernel::common::cells::{OptionalCell, TakeCell}; | ||
use kernel::hil; | ||
use kernel::hil::uart; | ||
use kernel::{AppId, AppSlice, Callback, Grant, LegacyDriver, ReturnCode, SharedReadWrite}; | ||
use kernel::{ | ||
AppId, Callback, CommandResult, Driver, ErrorCode, Grant, Read, ReadOnlyAppSlice, ReadWrite, | ||
ReadWriteAppSlice, ReturnCode, | ||
}; | ||
|
||
/// Syscall driver number. | ||
use crate::driver; | ||
pub const DRIVER_NUM: usize = driver::NUM::Nrf51822Serialization as usize; | ||
|
||
#[derive(Default)] | ||
pub struct App { | ||
callback: Option<Callback>, | ||
tx_buffer: Option<AppSlice<SharedReadWrite, u8>>, | ||
rx_buffer: Option<AppSlice<SharedReadWrite, u8>>, | ||
callback: Callback, | ||
tx_buffer: ReadOnlyAppSlice, | ||
rx_buffer: ReadWriteAppSlice, | ||
rx_recv_so_far: usize, // How many RX bytes we have currently received. | ||
rx_recv_total: usize, // The total number of bytes we expect to receive. | ||
} | ||
|
@@ -95,7 +98,7 @@ impl<'a> Nrf51822Serialization<'a> { | |
} | ||
} | ||
|
||
impl LegacyDriver for Nrf51822Serialization<'_> { | ||
impl Driver for Nrf51822Serialization<'_> { | ||
/// Pass application space memory to this driver. | ||
/// | ||
/// This also sets which app is currently using this driver. Only one app | ||
|
@@ -104,38 +107,67 @@ impl LegacyDriver for Nrf51822Serialization<'_> { | |
/// ### `allow_num` | ||
/// | ||
/// - `0`: Provide a RX buffer. | ||
/// - `1`: Provide a TX buffer. | ||
fn allow_readwrite( | ||
&self, | ||
appid: AppId, | ||
allow_type: usize, | ||
slice: Option<AppSlice<SharedReadWrite, u8>>, | ||
) -> ReturnCode { | ||
match allow_type { | ||
mut slice: ReadWriteAppSlice, | ||
) -> Result<ReadWriteAppSlice, (ReadWriteAppSlice, ErrorCode)> { | ||
let res = match allow_type { | ||
// Provide an RX buffer. | ||
0 => { | ||
self.active_app.set(appid); | ||
self.apps | ||
.enter(appid, |app, _| { | ||
app.rx_buffer = slice; | ||
app.rx_recv_so_far = 0; | ||
app.rx_recv_total = 0; | ||
ReturnCode::SUCCESS | ||
core::mem::swap(&mut app.rx_buffer, &mut slice); | ||
}) | ||
.unwrap_or(ReturnCode::FAIL) | ||
.map_err(ErrorCode::from) | ||
} | ||
|
||
_ => Err(ErrorCode::NOSUPPORT), | ||
}; | ||
|
||
if let Err(e) = res { | ||
Err((slice, e)) | ||
} else { | ||
Ok(slice) | ||
} | ||
} | ||
|
||
/// Pass application space memory to this driver. | ||
/// | ||
/// This also sets which app is currently using this driver. Only one app | ||
/// can control the nRF51 serialization driver. | ||
/// | ||
/// ### `allow_num` | ||
/// | ||
/// - `0`: Provide a TX buffer. | ||
fn allow_readonly( | ||
&self, | ||
appid: AppId, | ||
allow_type: usize, | ||
mut slice: ReadOnlyAppSlice, | ||
) -> Result<ReadOnlyAppSlice, (ReadOnlyAppSlice, ErrorCode)> { | ||
let res = match allow_type { | ||
// Provide a TX buffer. | ||
1 => { | ||
0 => { | ||
self.active_app.set(appid); | ||
self.apps | ||
.enter(appid, |app, _| { | ||
app.tx_buffer = slice; | ||
ReturnCode::SUCCESS | ||
core::mem::swap(&mut app.tx_buffer, &mut slice) | ||
}) | ||
.unwrap_or(ReturnCode::FAIL) | ||
.map_err(ErrorCode::from) | ||
} | ||
_ => ReturnCode::ENOSUPPORT, | ||
|
||
_ => Err(ErrorCode::NOSUPPORT), | ||
}; | ||
|
||
if let Err(e) = res { | ||
Err((slice, e)) | ||
} else { | ||
Ok(slice) | ||
} | ||
} | ||
|
||
|
@@ -150,27 +182,25 @@ impl LegacyDriver for Nrf51822Serialization<'_> { | |
fn subscribe( | ||
&self, | ||
subscribe_type: usize, | ||
callback: Option<Callback>, | ||
mut callback: Callback, | ||
appid: AppId, | ||
) -> ReturnCode { | ||
) -> Result<Callback, (Callback, ErrorCode)> { | ||
match subscribe_type { | ||
// Add a callback | ||
0 => { | ||
// Save the callback for the app. | ||
let _ = self.apps.enter(appid, |app, _| { | ||
app.callback = callback; | ||
}); | ||
|
||
// Start the receive now that we have a callback. If there is no | ||
// buffer then the receive has already been started. | ||
self.rx_buffer.take().map(|buffer| { | ||
let len = buffer.len(); | ||
self.uart.receive_automatic(buffer, len, 250); | ||
}); | ||
|
||
ReturnCode::SUCCESS | ||
let result = self | ||
.apps | ||
.enter(appid, |app, _| { | ||
core::mem::swap(&mut app.callback, &mut callback); | ||
}) | ||
.map_err(ErrorCode::from); | ||
match result { | ||
Ok(()) => Ok(callback), | ||
Err(e) => Err((callback, e)), | ||
} | ||
} | ||
_ => ReturnCode::ENOSUPPORT, | ||
_ => Err((callback, ErrorCode::NOSUPPORT)), | ||
} | ||
} | ||
|
||
|
@@ -180,34 +210,47 @@ impl LegacyDriver for Nrf51822Serialization<'_> { | |
/// | ||
/// - `0`: Driver check. | ||
/// - `1`: Send the allowed buffer to the nRF. | ||
/// - `2`: Reset the nRF51822. | ||
fn command(&self, command_type: usize, _: usize, _: usize, appid: AppId) -> ReturnCode { | ||
/// - `2`: Received from the nRF into the allowed buffer. | ||
/// - `3`: Reset the nRF51822. | ||
fn command(&self, command_type: usize, arg1: usize, _: usize, appid: AppId) -> CommandResult { | ||
match command_type { | ||
0 /* check if present */ => ReturnCode::SUCCESS, | ||
0 /* check if present */ => CommandResult::success(), | ||
|
||
// Send a buffer to the nRF51822 over UART. | ||
1 => { | ||
self.apps.enter(appid, |app, _| { | ||
app.tx_buffer.take().map_or(ReturnCode::FAIL, |slice| { | ||
app.tx_buffer.map_or(CommandResult::failure(ErrorCode::FAIL), |slice| { | ||
let write_len = slice.len(); | ||
self.tx_buffer.take().map_or(ReturnCode::FAIL, |buffer| { | ||
self.tx_buffer.take().map_or(CommandResult::failure(ErrorCode::FAIL), |buffer| { | ||
for (i, c) in slice.as_ref().iter().enumerate() { | ||
buffer[i] = *c; | ||
} | ||
let (_err, _opt) = self.uart.transmit_buffer(buffer, write_len); | ||
ReturnCode::SUCCESS | ||
CommandResult::success() | ||
}) | ||
}) | ||
}).unwrap_or(ReturnCode::FAIL) | ||
}).unwrap_or(CommandResult::failure(ErrorCode::FAIL)) | ||
} | ||
// Receive from the nRF51822 | ||
2 => { | ||
self.rx_buffer.take().map_or(CommandResult::failure(ErrorCode::RESERVE), |buffer| { | ||
let len = arg1; | ||
if len > buffer.len() { | ||
CommandResult::failure(ErrorCode::SIZE) | ||
} else { | ||
self.uart.receive_automatic(buffer, len, 250); | ||
CommandResult::success_u32(len as u32) | ||
} | ||
}) | ||
} | ||
|
||
// Initialize the nRF51822 by resetting it. | ||
2 => { | ||
3 => { | ||
self.reset(); | ||
ReturnCode::SUCCESS | ||
CommandResult::success() | ||
} | ||
|
||
_ => ReturnCode::ENOSUPPORT, | ||
_ => CommandResult::failure(ErrorCode::NOSUPPORT), | ||
} | ||
} | ||
} | ||
|
@@ -221,9 +264,7 @@ impl uart::TransmitClient for Nrf51822Serialization<'_> { | |
self.active_app.map(|appid| { | ||
let _ = self.apps.enter(*appid, |app, _| { | ||
// Call the callback after TX has finished | ||
app.callback.as_mut().map(|cb| { | ||
cb.schedule(1, 0, 0); | ||
}); | ||
app.callback.schedule(1, 0, 0); | ||
}); | ||
}); | ||
} | ||
|
@@ -244,24 +285,26 @@ impl uart::ReceiveClient for Nrf51822Serialization<'_> { | |
|
||
self.active_app.map(|appid| { | ||
let _ = self.apps.enter(*appid, |app, _| { | ||
app.rx_buffer = app.rx_buffer.take().map(|mut rb| { | ||
let len = app.rx_buffer.mut_map_or(0, |rb| { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the The comment below says But with the current code, if the I think the fix is simply to remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point -- then we should pass both. I assume these semantics are there for the peculiarities of the nRF serialization library? I'd therefore recommend this become app.callback.schedule(4, rx_len, len); Having implemented a bunch of these capsules, I've come to think that a simple |
||
// Figure out length to copy. | ||
let max_len = cmp::min(rx_len, rb.len()); | ||
|
||
// Copy over data to app buffer. | ||
self.rx_buffer.map(|buffer| { | ||
self.rx_buffer.map_or(0, |buffer| { | ||
for idx in 0..max_len { | ||
rb.as_mut()[idx] = buffer[idx]; | ||
} | ||
}); | ||
app.callback.as_mut().map(|cb| { | ||
// Notify the serialization library in userspace about the | ||
// received buffer. | ||
cb.schedule(4, rx_len, 0); | ||
}); | ||
|
||
rb | ||
max_len | ||
}) | ||
}); | ||
|
||
// Notify the serialization library in userspace about the | ||
// received buffer. | ||
// | ||
// Note: This indicates how many bytes were received by | ||
// hardware, regardless of how much space (if any) was | ||
// available in the buffer provided by the app. | ||
app.callback.schedule(4, rx_len, len); | ||
}); | ||
}); | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.