| use core::cell::Cell; |
| use core::ptr; |
| use libtock::futures; |
| use libtock::syscalls; |
| use matcha_config::*; |
| |
| //------------------------------------------------------------------------------ |
| |
| pub struct MailboxClient {} |
| |
| impl MailboxClient { |
| pub fn init() { |
| let _ = syscalls::command(CAPSULE_MAILBOX, CMD_MAILBOX_INIT, 0, 0); |
| } |
| |
| pub async fn wait_message_async(buffer: &mut [u8]) -> usize { |
| // To coordinate with async/await we need a "global-ish" flag that can |
| // have multiple mutable references. The Tock workaround is to put those |
| // kind of things in 'Cells'. |
| let message_size: Cell<usize> = Cell::new(0); |
| |
| // The mailbox capsule will notify us using this callback, |
| unsafe extern "C" fn subscribe_callback(_ok: usize, _len: usize, _: usize, data: usize) { |
| // which just sets the message flag to true. |
| let message_size = &*(data as *const Cell<usize>); |
| message_size.set(_len) |
| } |
| |
| // We give Tock a reference to our message and our callback+flag |
| unsafe { |
| syscalls::raw::allow( |
| CAPSULE_MAILBOX, |
| CMD_MAILBOX_RECV, |
| buffer.as_ptr() as *mut u8, |
| buffer.len(), |
| ); |
| syscalls::raw::subscribe( |
| CAPSULE_MAILBOX, |
| CMD_MAILBOX_RECV, |
| subscribe_callback as *const _, |
| &message_size as *const _ as usize, |
| ); |
| } |
| |
| // and asynchronously wait until the callback sets the flag. |
| futures::wait_until(|| (message_size.get() > 0)).await; |
| |
| // Then we clear Tock's references to our message and callback. |
| unsafe { |
| syscalls::raw::subscribe(CAPSULE_MAILBOX, 0, ptr::null(), 0); |
| syscalls::raw::allow(CAPSULE_MAILBOX, 0, ptr::null_mut(), 0); |
| } |
| |
| return message_size.get(); |
| } |
| |
| pub fn send_message_sync(size: usize, buffer: &[u8]) { |
| unsafe { |
| syscalls::raw::allow( |
| CAPSULE_MAILBOX, |
| CMD_MAILBOX_SEND, |
| buffer.as_ptr() as *mut u8, |
| buffer.len(), |
| ); |
| let _ = syscalls::command(CAPSULE_MAILBOX, CMD_MAILBOX_SEND, size, 0); |
| syscalls::raw::allow(CAPSULE_MAILBOX, CMD_MAILBOX_SEND, ptr::null_mut(), 0); |
| } |
| } |
| } |