First Version of IO

This commit is contained in:
2025-10-23 16:26:17 +02:00
parent 556faaba08
commit 3af76b93b2
10 changed files with 809 additions and 61 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ int hw_device_open(const char *path, size_t path_len) {
int serial_fd = serial_open(path, path_len);
if (serial_fd != -1) {
if (serial_fd >= -1) {
return serial_fd;
}
@@ -78,7 +78,7 @@ int hw_device_open(const char *path, size_t path_len) {
for (current_candidate = addr_candidates; current_candidate != NULL;
current_candidate = current_candidate->ai_next) {
sock = socket(current_candidate->ai_family, current_candidate->ai_socktype,
sock = socket(current_candidate->ai_family, current_candidate->ai_socktype | SOCK_NONBLOCK,
current_candidate->ai_protocol);
if (sock == -1) {
continue;
+8 -7
View File
@@ -18,12 +18,13 @@ int convert_errno(int errno_value) {
}
}
// returns fd if ok, converted errno if error
// TODO: can we extend errno safely?
// returns fd if ok, -1 on error 0 if no match
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);
return -1;
}
struct termios termios;
@@ -31,7 +32,7 @@ int serial_open_actual(const char *path, speed_t speed) {
// initialize termios struct
int ret = tcgetattr(fd, &termios);
if (ret < 0) {
return convert_errno(errno);
return -1;
}
// configure for raw input
@@ -44,19 +45,19 @@ int serial_open_actual(const char *path, speed_t speed) {
// set speed
ret = cfsetspeed(&termios, speed);
if (ret < 0) {
return convert_errno(errno);
return -1;
}
ret = tcsetattr(fd, TCSANOW, &termios);
if (ret < 0) {
return convert_errno(errno);
return -1;
}
return fd;
}
// returns fd if success, -1 if no path match <-1 if error
// returns fd if success, -1 on error, -2 if no match
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);
@@ -64,5 +65,5 @@ int serial_open(const char *path, size_t path_len) {
if (compare_string_chars("debug/uart🚀", path, path_len) == 1) {
return serial_open_actual("/dev/ttyUSB0", B115200);
}
return -1;
return -2;
}
+5
View File
@@ -290,4 +290,9 @@ void *freertos_mutex_create_static(char *mutex_data, uint32_t mutex_data_len) {
return NULL;
}
return xSemaphoreCreateRecursiveMutexStatic((StaticSemaphore_t *)mutex_data);
}
// TODO: might be the wrong place
int freertos_get_sys_error(){
return errno;
}
+1 -1
View File
@@ -62,7 +62,7 @@ void mission(void) {
write(1, "\n", 1);
test_hardware();
//test_hardware();
freertos_init_and_start_scheduling(init_task);
+2
View File
@@ -0,0 +1,2 @@
[target.armv7a-none-eabihf]
rustflags = ['-A', 'explicit_builtin_cfgs_in_flags','--cfg', 'target_env="newlib"'] # We use gcc/newlib to link this lib crate
+645 -8
View File
@@ -1,14 +1,651 @@
#[derive(Debug)]
pub enum UnixError{
NoSuchFileOrDirectory,
Unknown(i32)
use core::fmt;
use crate::fsrc::osal::ffi;
// wrap helper shim
pub fn errno() -> i32 {
unsafe { ffi::freertos_get_sys_error() }
}
impl From<i32> for UnixError{
#[cfg(target_os = "linux")]
mod libc {
// We assume a gnu x86_64:
use core::ffi::c_int;
pub const EPERM: c_int = 1;
pub const ENOENT: c_int = 2;
pub const ESRCH: c_int = 3;
pub const EINTR: c_int = 4;
pub const EIO: c_int = 5;
pub const ENXIO: c_int = 6;
pub const E2BIG: c_int = 7;
pub const ENOEXEC: c_int = 8;
pub const EBADF: c_int = 9;
pub const ECHILD: c_int = 10;
pub const EAGAIN: c_int = 11;
//pub const EWOULDBLOCK: c_int = 11;
pub const ENOMEM: c_int = 12;
pub const EACCES: c_int = 13;
pub const EFAULT: c_int = 14;
pub const ENOTBLK: c_int = 15;
pub const EBUSY: c_int = 16;
pub const EEXIST: c_int = 17;
pub const EXDEV: c_int = 18;
pub const ENODEV: c_int = 19;
pub const ENOTDIR: c_int = 20;
pub const EISDIR: c_int = 21;
pub const EINVAL: c_int = 22;
pub const ENFILE: c_int = 23;
pub const EMFILE: c_int = 24;
pub const ENOTTY: c_int = 25;
pub const ETXTBSY: c_int = 26;
pub const EFBIG: c_int = 27;
pub const ENOSPC: c_int = 28;
pub const ESPIPE: c_int = 29;
pub const EROFS: c_int = 30;
pub const EMLINK: c_int = 31;
pub const EPIPE: c_int = 32;
pub const EDOM: c_int = 33;
pub const ERANGE: c_int = 34;
pub const EDEADLOCK: c_int = 35;
pub const ENAMETOOLONG: c_int = 36;
pub const ENOLCK: c_int = 37;
pub const ENOSYS: c_int = 38;
pub const ENOTEMPTY: c_int = 39;
pub const ELOOP: c_int = 40;
pub const ENOMSG: c_int = 42;
pub const EIDRM: c_int = 43;
pub const ECHRNG: c_int = 44;
pub const ELNRNG: c_int = 48;
pub const EUNATCH: c_int = 49;
pub const ENOCSI: c_int = 50;
pub const EBADE: c_int = 52;
pub const EBADR: c_int = 53;
pub const EXFULL: c_int = 54;
pub const ENOANO: c_int = 55;
pub const EBADRQC: c_int = 56;
pub const EBADSLT: c_int = 57;
pub const EBFONT: c_int = 59;
pub const ENOSTR: c_int = 60;
pub const ENODATA: c_int = 61;
pub const ETIME: c_int = 62;
pub const ENOSR: c_int = 63;
pub const ENONET: c_int = 64;
pub const ENOPKG: c_int = 65;
pub const EREMOTE: c_int = 66;
pub const ENOLINK: c_int = 67;
pub const EADV: c_int = 68;
pub const ESRMNT: c_int = 69;
pub const ECOMM: c_int = 70;
pub const EPROTO: c_int = 71;
pub const EMULTIHOP: c_int = 72;
pub const EDOTDOT: c_int = 73;
pub const EBADMSG: c_int = 74;
pub const EOVERFLOW: c_int = 75;
pub const ENOTUNIQ: c_int = 76;
pub const EBADFD: c_int = 77;
pub const EREMCHG: c_int = 78;
pub const ELIBACC: c_int = 79;
pub const ELIBBAD: c_int = 80;
pub const ELIBSCN: c_int = 81;
pub const ELIBMAX: c_int = 82;
pub const ELIBEXEC: c_int = 83;
pub const EILSEQ: c_int = 84;
pub const ERESTART: c_int = 85;
pub const ESTRPIPE: c_int = 86;
pub const EUSERS: c_int = 87;
pub const ENOTSOCK: c_int = 88;
pub const EDESTADDRREQ: c_int = 89;
pub const EMSGSIZE: c_int = 90;
pub const EPROTOTYPE: c_int = 91;
pub const ENOPROTOOPT: c_int = 92;
pub const EPROTONOSUPPORT: c_int = 93;
pub const ESOCKTNOSUPPORT: c_int = 94;
pub const EOPNOTSUPP: c_int = 95;
pub const EPFNOSUPPORT: c_int = 96;
pub const EAFNOSUPPORT: c_int = 97;
pub const EADDRINUSE: c_int = 98;
pub const EADDRNOTAVAIL: c_int = 99;
pub const ENETDOWN: c_int = 100;
pub const ENETUNREACH: c_int = 101;
pub const ENETRESET: c_int = 102;
pub const ECONNABORTED: c_int = 103;
pub const ECONNRESET: c_int = 104;
pub const ENOBUFS: c_int = 105;
pub const EISCONN: c_int = 106;
pub const ENOTCONN: c_int = 107;
pub const ESHUTDOWN: c_int = 108;
pub const ETOOMANYREFS: c_int = 109;
pub const ETIMEDOUT: c_int = 110;
pub const ECONNREFUSED: c_int = 111;
pub const EHOSTDOWN: c_int = 112;
pub const EHOSTUNREACH: c_int = 113;
pub const EALREADY: c_int = 114;
pub const EINPROGRESS: c_int = 115;
pub const ESTALE: c_int = 116;
pub const EUCLEAN: c_int = 117;
pub const ENOTNAM: c_int = 118;
pub const ENAVAIL: c_int = 119;
pub const EISNAM: c_int = 120;
pub const EREMOTEIO: c_int = 121;
pub const EDQUOT: c_int = 122;
pub const ENOMEDIUM: c_int = 123;
pub const EMEDIUMTYPE: c_int = 124;
pub const ECANCELED: c_int = 125;
pub const ENOKEY: c_int = 126;
pub const EKEYEXPIRED: c_int = 127;
pub const EKEYREVOKED: c_int = 128;
pub const EKEYREJECTED: c_int = 129;
pub const EOWNERDEAD: c_int = 130;
pub const ENOTRECOVERABLE: c_int = 131;
pub const ERFKILL: c_int = 132;
pub const EHWPOISON: c_int = 133;
}
#[cfg(target_env = "newlib")]
mod libc {
// taken from rust-lang/libc/src/unix/newlib/mod.rs
use core::ffi::c_int;
pub const EPERM: c_int = 1;
pub const ENOENT: c_int = 2;
pub const ESRCH: c_int = 3;
pub const EINTR: c_int = 4;
pub const EIO: c_int = 5;
pub const ENXIO: c_int = 6;
pub const E2BIG: c_int = 7;
pub const ENOEXEC: c_int = 8;
pub const EBADF: c_int = 9;
pub const ECHILD: c_int = 10;
pub const EAGAIN: c_int = 11;
pub const ENOMEM: c_int = 12;
pub const EACCES: c_int = 13;
pub const EFAULT: c_int = 14;
pub const EBUSY: c_int = 16;
pub const EEXIST: c_int = 17;
pub const EXDEV: c_int = 18;
pub const ENODEV: c_int = 19;
pub const ENOTDIR: c_int = 20;
pub const EISDIR: c_int = 21;
pub const EINVAL: c_int = 22;
pub const ENFILE: c_int = 23;
pub const EMFILE: c_int = 24;
pub const ENOTTY: c_int = 25;
pub const ETXTBSY: c_int = 26;
pub const EFBIG: c_int = 27;
pub const ENOSPC: c_int = 28;
pub const ESPIPE: c_int = 29;
pub const EROFS: c_int = 30;
pub const EMLINK: c_int = 31;
pub const EPIPE: c_int = 32;
pub const EDOM: c_int = 33;
pub const ERANGE: c_int = 34;
pub const ENOMSG: c_int = 35;
pub const EIDRM: c_int = 36;
pub const EDEADLK: c_int = 45;
pub const ENOLCK: c_int = 46;
pub const ENOSTR: c_int = 60;
pub const ENODATA: c_int = 61;
pub const ETIME: c_int = 62;
pub const ENOSR: c_int = 63;
pub const ENOLINK: c_int = 67;
pub const EPROTO: c_int = 71;
pub const EMULTIHOP: c_int = 74;
pub const EBADMSG: c_int = 77;
pub const EFTYPE: c_int = 79;
pub const ENOSYS: c_int = 88;
pub const ENOTEMPTY: c_int = 90;
pub const ENAMETOOLONG: c_int = 91;
pub const ELOOP: c_int = 92;
pub const EOPNOTSUPP: c_int = 95;
pub const EPFNOSUPPORT: c_int = 96;
pub const ECONNRESET: c_int = 104;
pub const ENOBUFS: c_int = 105;
pub const EAFNOSUPPORT: c_int = 106;
pub const EPROTOTYPE: c_int = 107;
pub const ENOTSOCK: c_int = 108;
pub const ENOPROTOOPT: c_int = 109;
pub const ECONNREFUSED: c_int = 111;
pub const EADDRINUSE: c_int = 112;
pub const ECONNABORTED: c_int = 113;
pub const ENETUNREACH: c_int = 114;
pub const ENETDOWN: c_int = 115;
pub const ETIMEDOUT: c_int = 116;
pub const EHOSTDOWN: c_int = 117;
pub const EHOSTUNREACH: c_int = 118;
pub const EINPROGRESS: c_int = 119;
pub const EALREADY: c_int = 120;
pub const EDESTADDRREQ: c_int = 121;
pub const EMSGSIZE: c_int = 122;
pub const EPROTONOSUPPORT: c_int = 123;
pub const EADDRNOTAVAIL: c_int = 125;
pub const ENETRESET: c_int = 126;
pub const EISCONN: c_int = 127;
pub const ENOTCONN: c_int = 128;
pub const ETOOMANYREFS: c_int = 129;
pub const EDQUOT: c_int = 132;
pub const ESTALE: c_int = 133;
pub const ENOTSUP: c_int = 134;
pub const EILSEQ: c_int = 138;
pub const EOVERFLOW: c_int = 139;
pub const ECANCELED: c_int = 140;
pub const ENOTRECOVERABLE: c_int = 141;
pub const EOWNERDEAD: c_int = 142;
pub const EWOULDBLOCK: c_int = 11;
}
#[derive(Debug, PartialEq)]
pub enum OsError {
OperationNotPermitted,
NoSuchFileOrDirectory,
NoSuchProcess,
InterruptedSystemCall,
InputOutputError,
NoSuchDeviceOrAddress,
ArgumentListTooLong,
ExecFormatError,
BadFileDescriptor,
NoChildProcesses,
ResourceTemporarilyUnavailable,
CannotAllocateMemory,
PermissionDenied,
BadAddress,
BlockDeviceRequired,
DeviceOrResourceBusy,
FileExists,
InvalidCrossDeviceLink,
NoSuchDevice,
NotADirectory,
IsADirectory,
InvalidArgument,
TooManyOpenFilesInSystem,
TooManyOpenFiles,
InappropriateIoctlForDevice,
TextFileBusy,
FileTooLarge,
NoSpaceLeftOnDevice,
IllegalSeek,
ReadOnlyFileSystem,
TooManyLinks,
BrokenPipe,
NumericalArgumentOutOfDomain,
NumericalResultOutOfRange,
ResourceDeadlockAvoided,
FileNameTooLong,
NoLocksAvailable,
FunctionNotImplemented,
DirectoryNotEmpty,
TooManyLevelsOfSymbolicLinks,
NoMessageOfDesiredType,
IdentifierRemoved,
ChannelNumberOutOfRange,
LinkNumberOutOfRange,
ProtocolDriverNotAttached,
NoCsiStructureAvailable,
InvalidExchange,
InvalidRequestDescriptor,
ExchangeFull,
NoAnode,
InvalidRequestCode,
InvalidSlot,
BadFontFileFormat,
DeviceNotAStream,
NoDataAvailable,
TimerExpired,
OutOfStreamsResources,
MachineIsNotOnTheNetwork,
PackageNotInstalled,
ObjectIsRemote,
LinkHasBeenSevered,
AdvertiseError,
SrmountError,
CommunicationErrorOnSend,
ProtocolError,
MultihopAttempted,
RfsSpecificError,
BadMessage,
ValueTooLargeForDefinedDataType,
NameNotUniqueOnNetwork,
FileDescriptorInBadState,
RemoteAddressChanged,
CanNotAccessANeededSharedLibrary,
AccessingACorruptedSharedLibrary,
LibSectionCorrupted,
AttemptingToLinkInTooManySharedLibraries,
CannotExecASharedLibraryDirectly,
InvalidOrIncompleteMultibyteOrWideCharacter,
InterruptedSystemCallShouldBeRestarted,
StreamsPipeError,
TooManyUsers,
SocketOperationOnNonSocket,
DestinationAddressRequired,
MessageTooLong,
ProtocolWrongTypeForSocket,
ProtocolNotAvailable,
ProtocolNotSupported,
SocketTypeNotSupported,
OperationNotSupported,
ProtocolFamilyNotSupported,
AddressFamilyNotSupportedByProtocol,
AddressAlreadyInUse,
CannotAssignRequestedAddress,
NetworkIsDown,
NetworkIsUnreachable,
NetworkDroppedConnectionOnReset,
SoftwareCausedConnectionAbort,
ConnectionResetByPeer,
NoBufferSpaceAvailable,
TransportEndpointIsAlreadyConnected,
TransportEndpointIsNotConnected,
CannotSendAfterTransportEndpointShutdown,
TooManyReferencesCannotSplice,
ConnectionTimedOut,
ConnectionRefused,
HostIsDown,
NoRouteToHost,
OperationAlreadyInProgress,
OperationNowInProgress,
StaleFileHandle,
StructureNeedsCleaning,
NotAXenixNamedTypeFile,
NoXenixSemaphoresAvailable,
IsANamedTypeFile,
RemoteIOError,
DiskQuotaExceeded,
NoMediumFound,
WrongMediumType,
OperationCanceled,
RequiredKeyNotAvailable,
KeyHasExpired,
KeyHasBeenRevoked,
KeyWasRejectedByService,
OwnerDied,
StateNotRecoverable,
OperationNotPossibleDueToRfKill,
MemoryPageHasHardwareError,
Other(i32),
}
impl From<i32> for OsError {
fn from(value: i32) -> Self {
use crate::osal::io::OsError::*;
match value {
2 => UnixError::NoSuchFileOrDirectory,
any => Self::Unknown(any)
libc::EPERM => OperationNotPermitted,
libc::ENOENT => NoSuchFileOrDirectory,
libc::ESRCH => NoSuchProcess,
libc::EINTR => InterruptedSystemCall,
libc::EIO => InputOutputError,
libc::ENXIO => NoSuchDeviceOrAddress,
libc::E2BIG => ArgumentListTooLong,
libc::ENOEXEC => ExecFormatError,
libc::EBADF => BadFileDescriptor,
libc::ECHILD => NoChildProcesses,
libc::EAGAIN => ResourceTemporarilyUnavailable,
//libc::EWOULDBLOCK => ResourceTemporarilyUnavailable, == EAGAIN
libc::ENOMEM => CannotAllocateMemory,
libc::EACCES => PermissionDenied,
libc::EFAULT => BadAddress,
libc::ENOTBLK => BlockDeviceRequired,
libc::EBUSY => DeviceOrResourceBusy,
libc::EEXIST => FileExists,
libc::EXDEV => InvalidCrossDeviceLink,
libc::ENODEV => NoSuchDevice,
libc::ENOTDIR => NotADirectory,
libc::EISDIR => IsADirectory,
libc::EINVAL => InvalidArgument,
libc::ENFILE => TooManyOpenFilesInSystem,
libc::EMFILE => TooManyOpenFiles,
libc::ENOTTY => InappropriateIoctlForDevice,
libc::ETXTBSY => TextFileBusy,
libc::EFBIG => FileTooLarge,
libc::ENOSPC => NoSpaceLeftOnDevice,
libc::ESPIPE => IllegalSeek,
libc::EROFS => ReadOnlyFileSystem,
libc::EMLINK => TooManyLinks,
libc::EPIPE => BrokenPipe,
libc::EDOM => NumericalArgumentOutOfDomain,
libc::ERANGE => NumericalResultOutOfRange,
libc::EDEADLOCK => ResourceDeadlockAvoided,
libc::ENAMETOOLONG => FileNameTooLong,
libc::ENOLCK => NoLocksAvailable,
libc::ENOSYS => FunctionNotImplemented,
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::ELOOP => TooManyLevelsOfSymbolicLinks,
libc::ENOMSG => NoMessageOfDesiredType,
libc::EIDRM => IdentifierRemoved,
libc::ECHRNG => ChannelNumberOutOfRange,
libc::ELNRNG => LinkNumberOutOfRange,
libc::EUNATCH => ProtocolDriverNotAttached,
libc::ENOCSI => NoCsiStructureAvailable,
libc::EBADE => InvalidExchange,
libc::EBADR => InvalidRequestDescriptor,
libc::EXFULL => ExchangeFull,
libc::ENOANO => NoAnode,
libc::EBADRQC => InvalidRequestCode,
libc::EBADSLT => InvalidSlot,
libc::EBFONT => BadFontFileFormat,
libc::ENOSTR => DeviceNotAStream,
libc::ENODATA => NoDataAvailable,
libc::ETIME => TimerExpired,
libc::ENOSR => OutOfStreamsResources,
libc::ENONET => MachineIsNotOnTheNetwork,
libc::ENOPKG => PackageNotInstalled,
libc::EREMOTE => ObjectIsRemote,
libc::ENOLINK => LinkHasBeenSevered,
libc::EADV => AdvertiseError,
libc::ESRMNT => SrmountError,
libc::ECOMM => CommunicationErrorOnSend,
libc::EPROTO => ProtocolError,
libc::EMULTIHOP => MultihopAttempted,
libc::EDOTDOT => RfsSpecificError,
libc::EBADMSG => BadMessage,
libc::EOVERFLOW => ValueTooLargeForDefinedDataType,
libc::ENOTUNIQ => NameNotUniqueOnNetwork,
libc::EBADFD => FileDescriptorInBadState,
libc::EREMCHG => RemoteAddressChanged,
libc::ELIBACC => CanNotAccessANeededSharedLibrary,
libc::ELIBBAD => AccessingACorruptedSharedLibrary,
libc::ELIBSCN => LibSectionCorrupted,
libc::ELIBMAX => AttemptingToLinkInTooManySharedLibraries,
libc::ELIBEXEC => CannotExecASharedLibraryDirectly,
libc::EILSEQ => InvalidOrIncompleteMultibyteOrWideCharacter,
libc::ERESTART => InterruptedSystemCallShouldBeRestarted,
libc::ESTRPIPE => StreamsPipeError,
libc::EUSERS => TooManyUsers,
libc::ENOTSOCK => SocketOperationOnNonSocket,
libc::EDESTADDRREQ => DestinationAddressRequired,
libc::EMSGSIZE => MessageTooLong,
libc::EPROTOTYPE => ProtocolWrongTypeForSocket,
libc::ENOPROTOOPT => ProtocolNotAvailable,
libc::EPROTONOSUPPORT => ProtocolNotSupported,
libc::ESOCKTNOSUPPORT => SocketTypeNotSupported,
libc::EOPNOTSUPP => OperationNotSupported,
// libc::ENOTSUP => OperationNotSupported, == EOPNOTSUPP
libc::EPFNOSUPPORT => ProtocolFamilyNotSupported,
libc::EAFNOSUPPORT => AddressFamilyNotSupportedByProtocol,
libc::EADDRINUSE => AddressAlreadyInUse,
libc::EADDRNOTAVAIL => CannotAssignRequestedAddress,
libc::ENETDOWN => NetworkIsDown,
libc::ENETUNREACH => NetworkIsUnreachable,
libc::ENETRESET => NetworkDroppedConnectionOnReset,
libc::ECONNABORTED => SoftwareCausedConnectionAbort,
libc::ECONNRESET => ConnectionResetByPeer,
libc::ENOBUFS => NoBufferSpaceAvailable,
libc::EISCONN => TransportEndpointIsAlreadyConnected,
libc::ENOTCONN => TransportEndpointIsNotConnected,
libc::ESHUTDOWN => CannotSendAfterTransportEndpointShutdown,
libc::ETOOMANYREFS => TooManyReferencesCannotSplice,
libc::ETIMEDOUT => ConnectionTimedOut,
libc::ECONNREFUSED => ConnectionRefused,
libc::EHOSTDOWN => HostIsDown,
libc::EHOSTUNREACH => NoRouteToHost,
libc::EALREADY => OperationAlreadyInProgress,
libc::EINPROGRESS => OperationNowInProgress,
libc::ESTALE => StaleFileHandle,
libc::EUCLEAN => StructureNeedsCleaning,
libc::ENOTNAM => NotAXenixNamedTypeFile,
libc::ENAVAIL => NoXenixSemaphoresAvailable,
libc::EISNAM => IsANamedTypeFile,
libc::EREMOTEIO => RemoteIOError,
libc::EDQUOT => DiskQuotaExceeded,
libc::ENOMEDIUM => NoMediumFound,
libc::EMEDIUMTYPE => WrongMediumType,
libc::ECANCELED => OperationCanceled,
libc::ENOKEY => RequiredKeyNotAvailable,
libc::EKEYEXPIRED => KeyHasExpired,
libc::EKEYREVOKED => KeyHasBeenRevoked,
libc::EKEYREJECTED => KeyWasRejectedByService,
libc::EOWNERDEAD => OwnerDied,
libc::ENOTRECOVERABLE => StateNotRecoverable,
libc::ERFKILL => OperationNotPossibleDueToRfKill,
libc::EHWPOISON => MemoryPageHasHardwareError,
value => Other(value),
}
}
}
}
impl fmt::Display for OsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use OsError::*;
match self {
OperationNotPermitted => write!(f, "Operation not permitted"),
NoSuchFileOrDirectory => write!(f, "No such file or directory"),
NoSuchProcess => write!(f, "No such process"),
InterruptedSystemCall => write!(f, "Interrupted system call"),
InputOutputError => write!(f, "Input/output error"),
NoSuchDeviceOrAddress => write!(f, "No such device or address"),
ArgumentListTooLong => write!(f, "Argument list too long"),
ExecFormatError => write!(f, "Exec format error"),
BadFileDescriptor => write!(f, "Bad file descriptor"),
NoChildProcesses => write!(f, "No child processes"),
ResourceTemporarilyUnavailable => write!(f, "Resource temporarily unavailable"),
CannotAllocateMemory => write!(f, "Cannot allocate memory"),
PermissionDenied => write!(f, "Permission denied"),
BadAddress => write!(f, "Bad address"),
BlockDeviceRequired => write!(f, "Block device required"),
DeviceOrResourceBusy => write!(f, "Device or resource busy"),
FileExists => write!(f, "File exists"),
InvalidCrossDeviceLink => write!(f, "Invalid cross-device link"),
NoSuchDevice => write!(f, "No such device"),
NotADirectory => write!(f, "Not a directory"),
IsADirectory => write!(f, "Is a directory"),
InvalidArgument => write!(f, "Invalid argument"),
TooManyOpenFilesInSystem => write!(f, "Too many open files in system"),
TooManyOpenFiles => write!(f, "Too many open files"),
InappropriateIoctlForDevice => write!(f, "Inappropriate ioctl for device"),
TextFileBusy => write!(f, "Text file busy"),
FileTooLarge => write!(f, "File too large"),
NoSpaceLeftOnDevice => write!(f, "No space left on device"),
IllegalSeek => write!(f, "Illegal seek"),
ReadOnlyFileSystem => write!(f, "Read-only file system"),
TooManyLinks => write!(f, "Too many links"),
BrokenPipe => write!(f, "Broken pipe"),
NumericalArgumentOutOfDomain => write!(f, "Numerical argument out of domain"),
NumericalResultOutOfRange => write!(f, "Numerical result out of range"),
ResourceDeadlockAvoided => write!(f, "Resource deadlock avoided"),
FileNameTooLong => write!(f, "File name too long"),
NoLocksAvailable => write!(f, "No locks available"),
FunctionNotImplemented => write!(f, "Function not implemented"),
DirectoryNotEmpty => write!(f, "Directory not empty"),
TooManyLevelsOfSymbolicLinks => write!(f, "Too many levels of symbolic links"),
NoMessageOfDesiredType => write!(f, "No message of desired type"),
IdentifierRemoved => write!(f, "Identifier removed"),
ChannelNumberOutOfRange => write!(f, "Channel number out of range"),
LinkNumberOutOfRange => write!(f, "Link number out of range"),
ProtocolDriverNotAttached => write!(f, "Protocol driver not attached"),
NoCsiStructureAvailable => write!(f, "No CSI structure available"),
InvalidExchange => write!(f, "Invalid exchange"),
InvalidRequestDescriptor => write!(f, "Invalid request descriptor"),
ExchangeFull => write!(f, "Exchange full"),
NoAnode => write!(f, "No anode"),
InvalidRequestCode => write!(f, "Invalid request code"),
InvalidSlot => write!(f, "Invalid slot"),
BadFontFileFormat => write!(f, "Bad font file format"),
DeviceNotAStream => write!(f, "Device not a stream"),
NoDataAvailable => write!(f, "No data available"),
TimerExpired => write!(f, "Timer expired"),
OutOfStreamsResources => write!(f, "Out of streams resources"),
MachineIsNotOnTheNetwork => write!(f, "Machine is not on the network"),
PackageNotInstalled => write!(f, "Package not installed"),
ObjectIsRemote => write!(f, "Object is remote"),
LinkHasBeenSevered => write!(f, "Link has been severed"),
AdvertiseError => write!(f, "Advertise error"),
SrmountError => write!(f, "Srmount error"),
CommunicationErrorOnSend => write!(f, "Communication error on send"),
ProtocolError => write!(f, "Protocol error"),
MultihopAttempted => write!(f, "Multihop attempted"),
RfsSpecificError => write!(f, "RFS specific error"),
BadMessage => write!(f, "Bad message"),
ValueTooLargeForDefinedDataType => write!(f, "Value too large for defined data type"),
NameNotUniqueOnNetwork => write!(f, "Name not unique on network"),
FileDescriptorInBadState => write!(f, "File descriptor in bad state"),
RemoteAddressChanged => write!(f, "Remote address changed"),
CanNotAccessANeededSharedLibrary => write!(f, "Can not access a needed shared library"),
AccessingACorruptedSharedLibrary => write!(f, "Accessing a corrupted shared library"),
LibSectionCorrupted => write!(f, ".lib section in a.out corrupted"),
AttemptingToLinkInTooManySharedLibraries => {
write!(f, "Attempting to link in too many shared libraries")
}
CannotExecASharedLibraryDirectly => write!(f, "Cannot exec a shared library directly"),
InvalidOrIncompleteMultibyteOrWideCharacter => {
write!(f, "Invalid or incomplete multibyte or wide character")
}
InterruptedSystemCallShouldBeRestarted => {
write!(f, "Interrupted system call should be restarted")
}
StreamsPipeError => write!(f, "Streams pipe error"),
TooManyUsers => write!(f, "Too many users"),
SocketOperationOnNonSocket => write!(f, "Socket operation on non-socket"),
DestinationAddressRequired => write!(f, "Destination address required"),
MessageTooLong => write!(f, "Message too long"),
ProtocolWrongTypeForSocket => write!(f, "Protocol wrong type for socket"),
ProtocolNotAvailable => write!(f, "Protocol not available"),
ProtocolNotSupported => write!(f, "Protocol not supported"),
SocketTypeNotSupported => write!(f, "Socket type not supported"),
OperationNotSupported => write!(f, "Operation not supported"),
ProtocolFamilyNotSupported => write!(f, "Protocol family not supported"),
AddressFamilyNotSupportedByProtocol => {
write!(f, "Address family not supported by protocol")
}
AddressAlreadyInUse => write!(f, "Address already in use"),
CannotAssignRequestedAddress => write!(f, "Cannot assign requested address"),
NetworkIsDown => write!(f, "Network is down"),
NetworkIsUnreachable => write!(f, "Network is unreachable"),
NetworkDroppedConnectionOnReset => write!(f, "Network dropped connection on reset"),
SoftwareCausedConnectionAbort => write!(f, "Software caused connection abort"),
ConnectionResetByPeer => write!(f, "Connection reset by peer"),
NoBufferSpaceAvailable => write!(f, "No buffer space available"),
TransportEndpointIsAlreadyConnected => {
write!(f, "Transport endpoint is already connected")
}
TransportEndpointIsNotConnected => write!(f, "Transport endpoint is not connected"),
CannotSendAfterTransportEndpointShutdown => {
write!(f, "Cannot send after transport endpoint shutdown")
}
TooManyReferencesCannotSplice => write!(f, "Too many references: cannot splice"),
ConnectionTimedOut => write!(f, "Connection timed out"),
ConnectionRefused => write!(f, "Connection refused"),
HostIsDown => write!(f, "Host is down"),
NoRouteToHost => write!(f, "No route to host"),
OperationAlreadyInProgress => write!(f, "Operation already in progress"),
OperationNowInProgress => write!(f, "Operation now in progress"),
StaleFileHandle => write!(f, "Stale file handle"),
StructureNeedsCleaning => write!(f, "Structure needs cleaning"),
NotAXenixNamedTypeFile => write!(f, "Not a XENIX named type file"),
NoXenixSemaphoresAvailable => write!(f, "No XENIX semaphores available"),
IsANamedTypeFile => write!(f, "Is a named type file"),
RemoteIOError => write!(f, "Remote I/O error"),
DiskQuotaExceeded => write!(f, "Disk quota exceeded"),
NoMediumFound => write!(f, "No medium found"),
WrongMediumType => write!(f, "Wrong medium type"),
OperationCanceled => write!(f, "Operation canceled"),
RequiredKeyNotAvailable => write!(f, "Required key not available"),
KeyHasExpired => write!(f, "Key has expired"),
KeyHasBeenRevoked => write!(f, "Key has been revoked"),
KeyWasRejectedByService => write!(f, "Key was rejected by service"),
OwnerDied => write!(f, "Owner died"),
StateNotRecoverable => write!(f, "State not recoverable"),
OperationNotPossibleDueToRfKill => write!(f, "Operation not possible due to RF-kill"),
MemoryPageHasHardwareError => write!(f, "Memory page has hardware error"),
Other(value) => write!(f, "Other error: {}", value),
}
}
}
+31 -18
View File
@@ -3,9 +3,7 @@
type TaskFunction = unsafe extern "C" fn(*mut core::ffi::c_void) -> !;
pub struct Sizes {
}
pub struct Sizes {}
// TODO these should be passed by compile time value
#[cfg(target_os = "linux")]
@@ -17,7 +15,7 @@ impl Sizes {
}
// We use none for bare metal, as we only support one architecture so far
#[cfg(target_os = "none")]
#[cfg(target_env = "newlib")]
impl Sizes {
pub const TASK_DATA_SIZE: usize = 184;
pub const MUTEX_DATA_SIZE: usize = 168;
@@ -25,12 +23,10 @@ impl Sizes {
pub const TASK_MINIMAL_STACK_SIZE: usize = 10240;
}
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(
@@ -49,7 +45,10 @@ extern "C" {
pub fn freertos_task_delete(handle: *const core::ffi::c_void) -> !;
pub fn freertos_task_storage_set(handle: *const core::ffi::c_void, data: *const core::ffi::c_void);
pub fn freertos_task_storage_set(
handle: *const core::ffi::c_void,
data: *const core::ffi::c_void,
);
pub fn freertos_task_storage_get(handle: *const core::ffi::c_void) -> *const core::ffi::c_void;
@@ -60,7 +59,7 @@ extern "C" {
pub fn freertos_task_current() -> *const core::ffi::c_void;
// TODO this should be passed by compile time value
pub fn freertos_task_priority_max()-> u32;
pub fn freertos_task_priority_max() -> u32;
//void *freertos_queue_create_static(uint32_t depth, uint32_t element_size,
// char *queue_data, uint32_t queue_data_len,
@@ -70,11 +69,17 @@ extern "C" {
element_size: u32,
queue_data: *mut core::ffi::c_char,
queue_data_len: u32,
queue: *mut u8
queue: *mut u8,
) -> *const core::ffi::c_void;
pub fn freertos_queue_receive(queue: *const core::ffi::c_void, message: *const core::ffi::c_void) -> u8;
pub fn freertos_queue_send(queue: *const core::ffi::c_void, message: *const core::ffi::c_void) -> u8;
pub fn freertos_queue_receive(
queue: *const core::ffi::c_void,
message: *const core::ffi::c_void,
) -> u8;
pub fn freertos_queue_send(
queue: *const core::ffi::c_void,
message: *const core::ffi::c_void,
) -> u8;
pub fn freertos_mutex_create_static(
mutex_data: *const core::ffi::c_char,
@@ -87,17 +92,18 @@ extern "C" {
//uint8_t freertos_simple_once(uint8_t *once_data)
pub fn freertos_simple_once(once_data: *const u8) -> u8;
//int freertos_get_sys_error()
pub fn freertos_get_sys_error() -> core::ffi::c_int;
////////////////////////
/// 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;
@@ -105,10 +111,17 @@ extern "C" {
#[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_env = "newlib")]
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;
#[cfg(target_env = "newlib")]
pub fn read(
fd: core::ffi::c_int,
buffer: *const core::ffi::c_void,
count: core::ffi::c_int,
) -> core::ffi::c_int;
}
+90 -22
View File
@@ -1,46 +1,114 @@
pub use super::error::UnixError;
use core::fmt::Display;
pub use super::error::OsError;
use super::ffi;
#[derive(Debug)]
pub enum Error{
Unix(UnixError),
AlreadyOpen,
pub enum Error {
Os(OsError),
IncompleteWrite(usize),
InvalidPath,
Unknown(i32)
Unknown(i32),
InternalError,
}
// 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)
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "😢")?;
match self {
Error::Os(os_error) => write!(f, "Os::{}", os_error),
_ => write!(f, "not implemented"),
}
}
}
pub type Result<T> = core::result::Result<T,Error>;
pub type Result<T> = core::result::Result<T, Error>;
pub trait Read {
fn read<'a>(&self, buffer: &'a [u8]) -> Result<&'a [u8]>;
}
pub trait Write {
fn write(&mut self, data: &[u8]) -> Result<()>;
}
#[derive(Debug)]
pub struct Interface{
pub struct HardwareInterface {
fd: core::ffi::c_int,
}
impl Interface {
impl HardwareInterface {
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())};
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()))
// Safe: getter on os
let errno = unsafe { ffi::freertos_get_sys_error() };
Err(Error::Os(errno.into()))
}
}
}
pub fn write(&mut self, data: &[u8]) {
impl Write for HardwareInterface {
fn write(&mut self, data: &[u8]) -> Result<()> {
let written = unsafe {
ffi::write(
self.fd,
data.as_ptr() as *const core::ffi::c_void,
data.len().into(),
)
};
if written < 0 {
// Safe: getter on os
let errno = unsafe { ffi::freertos_get_sys_error() };
return Err(Error::Os(errno.into()));
} else {
let Ok(written_unsigned) = written.try_into() else {
// we are in written >=0, this should never happen
return Err(Error::InternalError);
};
if written_unsigned < data.len() {
return Err(Error::IncompleteWrite(written_unsigned));
} else {
return Ok(());
}
}
}
}
}
impl Read for HardwareInterface {
fn read<'a>(&self, buffer: &'a [u8]) -> Result<&'a [u8]> {
// Safe as we trust the OS
let read = unsafe {
ffi::read(
self.fd,
buffer.as_ptr() as *const core::ffi::c_void,
buffer.len().into(),
)
};
if read < 0 {
// Safe: getter on os
let errno = unsafe { ffi::freertos_get_sys_error() };
let error = errno.into();
if error == OsError::ResourceTemporarilyUnavailable {
// non blocking call returned
return Ok(&[]);
}
return Err(Error::Os(error));
} else {
let Ok(read_unsigned) = read.try_into() else {
// we are in read >=0, this should never happen
return Err(Error::InternalError);
};
Ok(&buffer[..read_unsigned])
}
}
}
+1 -1
View File
@@ -76,7 +76,7 @@ macro_rules! sifln {
writeln!(Stdout {});
);
($($arg:tt)*) => (
let _alwaysok = writeln!(crate::fsrc::sif::Stdout {}, $($arg)*);
{let _alwaysok = writeln!(crate::fsrc::sif::Stdout {}, $($arg)*);}
);
}
+24 -2
View File
@@ -16,7 +16,7 @@ use osal::{
thread,
};
use crate::fsrc::osal::io::Interface;
use crate::fsrc::osal::io::{self, HardwareInterface, Read, Write as IoWrite};
@@ -184,8 +184,30 @@ static THREAD_3: StaticReadOnceLock<
fn init_task() -> ! {
sifln!("Mission enter");
sifln!("{:?}", Interface::new("debug/uart🚀"));
let interface = HardwareInterface::new("ps/uart_mtg");
let Ok(mut interface) = interface else {
let error : io::Error = interface.err().unwrap();
sifln!("open: {error}");
panic!();
};
let buffer = [1,2,3,4];
interface.write(&buffer).unwrap_or_else(|e| sifln!("write: {e}"));
let mut buffer = [0u8;30];
let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]});
sifln!("{res:?}");
osal::thread::current().delay(Duration::from_millis(500));
let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]});
sifln!("{res:?}");
osal::thread::current().delay(Duration::from_millis(500));
let res = interface.read(&mut buffer).unwrap_or_else(|e| {sifln!("read: {e}"); &[]});
sifln!("{res:?}");
let test1 = TEST1.take().unwrap();
let test2 = TEST2.take().unwrap();