forked from ROMEO/fsw-ws
starting interface access from rust
This commit is contained in:
@@ -1 +1 @@
|
||||
target_sources(bsp PRIVATE hardware.c)
|
||||
target_sources(bsp PRIVATE hardware.c serial.c)
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <hardware/interfaces.h>
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
extern const char *sim_ip;
|
||||
extern int ai_family;
|
||||
|
||||
@@ -38,7 +40,16 @@ const char *get_port_number(const char *path, size_t path_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int hw_device_open(const char *path, size_t path_len) {
|
||||
|
||||
int serial_fd = serial_open(path, path_len);
|
||||
|
||||
if (serial_fd != -1) {
|
||||
return serial_fd;
|
||||
}
|
||||
|
||||
const char *port_number = get_port_number(path, path_len);
|
||||
if (port_number == NULL) {
|
||||
return -1;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// TODO FIXME
|
||||
int compare_string_chars(const char *c_string, const char *chars,
|
||||
size_t chars_len);
|
||||
|
||||
int convert_errno(int errno_value) {
|
||||
// errno on linux will always be >0
|
||||
if (errno <= 0) {
|
||||
// something is very wrong
|
||||
return -1;
|
||||
} else {
|
||||
return -errno - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// returns fd if ok, converted errno if error
|
||||
int serial_open_actual(const char *path, speed_t speed) {
|
||||
// open serial
|
||||
int fd = open(path, O_RDWR | O_NOCTTY | O_SYNC);
|
||||
if (fd < 0) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
struct termios termios;
|
||||
|
||||
// initialize termios struct
|
||||
int ret = tcgetattr(fd, &termios);
|
||||
if (ret < 0) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
// configure for raw input
|
||||
cfmakeraw(&termios);
|
||||
|
||||
// make it non-blocking
|
||||
termios.c_cc[VMIN] = 0;
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// set speed
|
||||
ret = cfsetspeed(&termios, speed);
|
||||
if (ret < 0) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
ret = tcsetattr(fd, TCSANOW, &termios);
|
||||
if (ret < 0) {
|
||||
return convert_errno(errno);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
// returns fd if success, -1 if no path match <-1 if error
|
||||
int serial_open(const char *path, size_t path_len) {
|
||||
if (compare_string_chars("ps/uart_mtg", path, path_len) == 1) {
|
||||
return serial_open_actual("/dev/ttyUSB0", B921600);
|
||||
}
|
||||
if (compare_string_chars("debug/uart🚀", path, path_len) == 1) {
|
||||
return serial_open_actual("/dev/ttyUSB0", B115200);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// returns fd if success, -1 if no path match <-1 if error
|
||||
int serial_open(const char *path, size_t path_len);
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -288,4 +290,4 @@ void *freertos_mutex_create_static(char *mutex_data, uint32_t mutex_data_len) {
|
||||
return NULL;
|
||||
}
|
||||
return xSemaphoreCreateRecursiveMutexStatic((StaticSemaphore_t *)mutex_data);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
mod ffi;
|
||||
pub(crate) mod ffi;
|
||||
pub mod sync;
|
||||
pub mod once;
|
||||
pub mod thread;
|
||||
pub mod queue;
|
||||
|
||||
pub mod error;
|
||||
pub mod io;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#[derive(Debug)]
|
||||
pub enum UnixError{
|
||||
NoSuchFileOrDirectory,
|
||||
Unknown(i32)
|
||||
}
|
||||
|
||||
impl From<i32> for UnixError{
|
||||
fn from(value: i32) -> Self {
|
||||
match value {
|
||||
2 => UnixError::NoSuchFileOrDirectory,
|
||||
any => Self::Unknown(any)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
//TODO verify uXX == uintXX_t
|
||||
// TODO verify uXX == uintXX_t
|
||||
// TODO track current state of usize == size_t (needed for some)
|
||||
|
||||
type TaskFunction = unsafe extern "C" fn(*mut core::ffi::c_void) -> !;
|
||||
|
||||
@@ -26,6 +27,10 @@ impl Sizes {
|
||||
|
||||
|
||||
extern "C" {
|
||||
////////////////////////
|
||||
/// FreeRTOS API
|
||||
/// shimmed in mission/freeRTOS_rust_helper.c
|
||||
|
||||
//void *create_task_static(TaskFunction_t taskFunction, void *parameter,
|
||||
// char *task_data, uint32_t task_data_len, char *stack, uint32_t stack_size)
|
||||
pub fn freertos_create_task_static(
|
||||
@@ -82,5 +87,28 @@ extern "C" {
|
||||
//uint8_t freertos_simple_once(uint8_t *once_data)
|
||||
pub fn freertos_simple_once(once_data: *const u8) -> u8;
|
||||
|
||||
|
||||
////////////////////////
|
||||
/// Harware Abstraction API in common/include/interfaces.h
|
||||
/// Used for access to peripherals to make switching between linux and embedded easier
|
||||
|
||||
//int hw_device_open(const char * path, size_t path_len);
|
||||
pub fn hw_device_open(path: *const core::ffi::c_char, path_len: usize) -> core::ffi::c_int;
|
||||
|
||||
////////////////////////
|
||||
/// POSIX/UNIX/LINUX API
|
||||
|
||||
//TODO, linux seems to use ssize_t (confirm!), newlib int as return value and count
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn write(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: usize) -> isize;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn read(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: usize) -> isize;
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
pub fn write(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: core::ffi::c_int) -> core::ffi::c_int;
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
pub fn read(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: core::ffi::c_int) -> core::ffi::c_int;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
pub use super::error::UnixError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error{
|
||||
Unix(UnixError),
|
||||
AlreadyOpen,
|
||||
InvalidPath,
|
||||
Unknown(i32)
|
||||
}
|
||||
|
||||
// TODO error values should be in ffi
|
||||
impl From<i32> for Error {
|
||||
fn from(value: i32) -> Self {
|
||||
match value {
|
||||
-2 => Error::AlreadyOpen,
|
||||
-3 => Error::InvalidPath,
|
||||
any => Error::Unknown(any)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Result<T> = core::result::Result<T,Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Interface{
|
||||
fd: core::ffi::c_int,
|
||||
}
|
||||
|
||||
impl Interface {
|
||||
pub fn new(path: &str) -> Result<Self> {
|
||||
// Safe: we trust our own implementation to only read
|
||||
// as we cut our string into bytes, conversion to c_char is correct, as C will compare bit value
|
||||
let fd = unsafe{ crate::osal::ffi::hw_device_open(path.as_bytes().as_ptr() as *const core::ffi::c_char, path.as_bytes().len())};
|
||||
if fd >= 0 {
|
||||
Ok(Self { fd })
|
||||
} else {
|
||||
// revert errno conversion done by hw_device_open
|
||||
let errno = -fd -1;
|
||||
Err(Error::Unix(errno.into()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: &[u8]) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,23 +6,29 @@ pub struct Stderr {}
|
||||
// TODO why or how does pub work (users from same crate need to use core::fmt::... )
|
||||
pub use core::fmt::{Error, Write};
|
||||
|
||||
extern "C" {
|
||||
pub fn write(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: usize) -> core::ffi::c_int;
|
||||
}
|
||||
// TODO this is already in osal
|
||||
// extern "C" {
|
||||
// pub fn write(fd: core::ffi::c_int, buffer: *const core::ffi::c_void, count: usize) -> core::ffi::c_int;
|
||||
// }
|
||||
|
||||
impl Write for Stdout {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
|
||||
// Safe because write will only read the pointer an then return
|
||||
// try_into is used as write call is different depending on platform
|
||||
let len_converted = match s.as_bytes().len().try_into(){
|
||||
Ok(value) => value,
|
||||
Err(_) => return Err(Error)
|
||||
};
|
||||
let result = unsafe {
|
||||
write(
|
||||
crate::fsrc::osal::ffi::write(
|
||||
1,
|
||||
s.as_bytes().as_ptr() as *const core::ffi::c_void,
|
||||
s.as_bytes().len(),
|
||||
len_converted,
|
||||
)
|
||||
};
|
||||
// We do not retry incomplete writes, this is stdout after all...
|
||||
let safe_count: i32 = match s.as_bytes().len().try_into() {
|
||||
let safe_count = match s.as_bytes().len().try_into() {
|
||||
Ok(count)=> count,
|
||||
Err(_) => return Err(Error)
|
||||
};
|
||||
@@ -38,15 +44,20 @@ impl Write for Stderr {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
|
||||
// Safe because write will only read the pointer an then return
|
||||
// try_into is used as write call is different depending on platform
|
||||
let len_converted = match s.as_bytes().len().try_into(){
|
||||
Ok(value) => value,
|
||||
Err(_) => return Err(Error)
|
||||
};
|
||||
let result = unsafe {
|
||||
write(
|
||||
2,
|
||||
crate::fsrc::osal::ffi::write(
|
||||
1,
|
||||
s.as_bytes().as_ptr() as *const core::ffi::c_void,
|
||||
s.as_bytes().len(),
|
||||
len_converted,
|
||||
)
|
||||
};
|
||||
// We do not retry incomplete writes, this is stdout after all...
|
||||
let safe_count: i32 = match s.as_bytes().len().try_into() {
|
||||
let safe_count = match s.as_bytes().len().try_into() {
|
||||
Ok(count)=> count,
|
||||
Err(_) => return Err(Error)
|
||||
};
|
||||
|
||||
@@ -16,6 +16,8 @@ use osal::{
|
||||
thread,
|
||||
};
|
||||
|
||||
use crate::fsrc::osal::io::Interface;
|
||||
|
||||
|
||||
|
||||
static THREAD_INIT: StaticReadOnceLock<
|
||||
@@ -182,6 +184,8 @@ static THREAD_3: StaticReadOnceLock<
|
||||
fn init_task() -> ! {
|
||||
sifln!("Mission enter");
|
||||
|
||||
sifln!("{:?}", Interface::new("debug/uart🚀"));
|
||||
|
||||
|
||||
let test1 = TEST1.take().unwrap();
|
||||
let test2 = TEST2.take().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user