Using write() for output for better portability

This commit is contained in:
Ulrich Mohr 2024-07-16 14:12:15 +02:00
parent 716fdd7fa0
commit 02a7d525be
7 changed files with 84 additions and 27 deletions

View File

@ -2,10 +2,12 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
void mission(void); void mission(void);
void done() { void done() {
printf("done."); printf("done.\n");
exit(0); exit(0);
} }
@ -15,11 +17,10 @@ void rust_eh_personality() {
puts("eh_personality"); puts("eh_personality");
} }
void outbyte(uint8_t byte){
printf("%c", byte);
}
int main(void) { int main(void) {
printf("std %i sterr %i\n", stdout, stderr);
const char * buffer ="123";
write(STDOUT_FILENO, buffer, 3);
mission(); mission();
return 0; return 0;
} }

View File

@ -1,4 +1,5 @@
add_subdirectory(freeRTOS) add_subdirectory(freeRTOS)
add_subdirectory(ps7_cortexa9_0) add_subdirectory(ps7_cortexa9_0)
add_subdirectory(newlib)
target_sources(${TARGET_NAME} PRIVATE main.c) target_sources(${TARGET_NAME} PRIVATE main.c)

View File

@ -0,0 +1 @@
target_sources(${TARGET_NAME} PRIVATE write.c)

15
bsp_z7/newlib/write.c Normal file
View File

@ -0,0 +1,15 @@
#include "xil_printf.h"
#include "xparameters.h"
int write(int file, char *ptr, int len) {
if (ptr == NULL) {
return 0;
}
// TODO file descriptors
int todo;
for (todo = 0; todo < len; todo++) {
outbyte(*ptr++);
}
return len;
}

View File

@ -22,7 +22,7 @@ target_sources(${TARGET_NAME} PUBLIC
src/xil_testio.c src/xil_testio.c
src/xplatform_info.c src/xplatform_info.c
src/getpid.c src/getpid.c
src/write.c #src/write.c
src/xil_mem.c src/xil_mem.c
src/kill.c src/kill.c
src/xil_mmu.c src/xil_mmu.c

View File

@ -1,37 +1,76 @@
// TODO this is platform specific // TODO this is platform specific
pub struct Outbytes {} pub struct Stdout {}
pub struct Stderr {}
use core::fmt::{Error, Write}; use core::fmt::{Error, Write};
impl Write for Outbytes { 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> { fn write_str(&mut self, s: &str) -> Result<(), Error> {
for c in s.as_bytes() {
unsafe { // Safe because write will only read the pointer an then return
crate::fsrc::osal::outbyte(*c); let result = unsafe {
} write(
1,
s.as_bytes().as_ptr() as *const core::ffi::c_void,
s.as_bytes().len(),
)
};
// We do not retry incomplete writes, this is stdout after all...
let safe_count: i32 = match s.as_bytes().len().try_into() {
Ok(count)=> count,
Err(_) => return Err(Error)
};
if result < safe_count {
Err(Error)
} else {
Ok(())
}
}
}
impl Write for Stderr {
fn write_str(&mut self, s: &str) -> Result<(), Error> {
// Safe because write will only read the pointer an then return
let result = unsafe {
write(
2,
s.as_bytes().as_ptr() as *const core::ffi::c_void,
s.as_bytes().len(),
)
};
// We do not retry incomplete writes, this is stdout after all...
let safe_count: i32 = match s.as_bytes().len().try_into() {
Ok(count)=> count,
Err(_) => return Err(Error)
};
if result < safe_count {
Err(Error)
} else {
Ok(())
} }
Ok(())
} }
} }
#[macro_export] #[macro_export]
macro_rules! sifln { macro_rules! sifln {
($(,)?) => ( ($(,)?) => (
let mut stdout = Outbytes {}; //let mut stdout = Outbytes {};
writeln!(stdout); writeln!(Stdout {});
); );
($($arg:tt)*) => ( ($($arg:tt)*) => (
let mut stdout = crate::fsrc::sif::Outbytes {}; let _alwaysok = writeln!(crate::fsrc::sif::Stdout {}, $($arg)*);
let _alwaysok = writeln!(stdout, $($arg)*);
); );
} }
#[macro_export] #[macro_export]
macro_rules! sif { macro_rules! sif {
($($arg:tt)*) => ( ($($arg:tt)*) => (
let mut stdout = crate::fsrc::sif::Outbytes {}; let _alwaysok = write!(crate::fsrc::sif::Stdout {}, $($arg)*);
let _alwaysok = write!(stdout, $($arg)*);
); );
} }

View File

@ -21,8 +21,8 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
osal::stop_it(); osal::stop_it();
} }
// TODO: Make this unicode-safe // TODO: Make this unicode-safe
sifln!(""); _ = writeln!(crate::fsrc::sif::Stderr {},"");
sif!("in task \""); _ = write!(crate::fsrc::sif::Stderr {},"in task \"");
unsafe { unsafe {
//osal::get_task_name is implemented safely in C, so we trust it //osal::get_task_name is implemented safely in C, so we trust it
let task_name = core::ffi::CStr::from_ptr(osal::get_task_name()); let task_name = core::ffi::CStr::from_ptr(osal::get_task_name());
@ -32,12 +32,12 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
sif!("{}", string); sif!("{}", string);
} }
Err(_) => { Err(_) => {
sif!("Schei<EFBFBD> Encoding"); _ = writeln!(crate::fsrc::sif::Stderr {},"Schei<EFBFBD> Encoding");
} }
} }
} }
sifln!("\":"); _ = writeln!(crate::fsrc::sif::Stderr {},"\":");
sifln!("{}", panic); _ = writeln!(crate::fsrc::sif::Stderr {},"{}", panic);
//TODO: stop RTOS, exit if hosted //TODO: stop RTOS, exit if hosted
unsafe { done() }; unsafe { done() };
loop {} loop {}
@ -59,7 +59,7 @@ extern "C" fn rust_assert_called(ptr: *const core::ffi::c_char, line: core::ffi:
} }
}; };
panic!("assertion failed at {file_name}:{}", line); panic!("assertion failed at {file_name}:{line}");
} }
#[no_mangle] #[no_mangle]