| //! Trivial capsule to provide minimal debug printing support for userspace. |
| //! |
| //! The default TockOS Console class does heavier-weight stuff with UART |
| //! multiplexing and asynchronous sending and such, which is usually _not_ what |
| //! is wanted in a debug serial port. This capsule implements only one command, |
| //! which dumps data from an allow'ed buffer directly to a memory-mapped UART |
| //! peripheral. |
| //! |
| //! Usage - send buffer directly to UART: |
| //! let driver_num = capsules::debug_uart::DRIVER_NUM; |
| //! let allow = syscalls::allow(driver_num, 0, &mut buffer); |
| //! let result = syscalls::command(driver_num, 0, buffer.len(), 0); |
| //! drop(allow); |
| |
| use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared}; |
| |
| #[derive(Default)] |
| pub struct AppData { |
| pub buffer: Option<AppSlice<Shared, u8>>, |
| } |
| |
| pub struct DebugUartCapsule { |
| pub app_data_grant: Grant<AppData>, |
| } |
| |
| impl Driver for DebugUartCapsule { |
| fn subscribe(&self, _: usize, _: Option<Callback>, _: AppId) -> ReturnCode { |
| ReturnCode::EINVAL |
| } |
| |
| fn command(&self, minor_num: usize, r2: usize, _: usize, app_id: AppId) -> ReturnCode { |
| if minor_num != 0 { |
| return ReturnCode::EINVAL; |
| } |
| |
| let _ = self.app_data_grant.enter(app_id, |app_data, _| { |
| if let Some(buf) = &app_data.buffer { |
| matcha_hal::debug_uart::send_sync(buf.as_ref(), r2); |
| } |
| }); |
| return ReturnCode::SUCCESS; |
| } |
| |
| fn allow(&self, app_id: AppId, _: usize, slice: Option<AppSlice<Shared, u8>>) -> ReturnCode { |
| let _ = self.app_data_grant.enter(app_id, |app_data, _| { |
| app_data.buffer = slice; |
| }); |
| return ReturnCode::SUCCESS; |
| } |
| } |