forked from ROMEO/fsw-ws
First Version of IO
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -62,7 +62,7 @@ void mission(void) {
|
||||
write(1, "\n", 1);
|
||||
|
||||
|
||||
test_hardware();
|
||||
//test_hardware();
|
||||
|
||||
|
||||
freertos_init_and_start_scheduling(init_task);
|
||||
|
||||
@@ -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
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user