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

View File

@ -1,4 +1,5 @@
add_subdirectory(freeRTOS)
add_subdirectory(ps7_cortexa9_0)
add_subdirectory(newlib)
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/xplatform_info.c
src/getpid.c
src/write.c
#src/write.c
src/xil_mem.c
src/kill.c
src/xil_mmu.c

View File

@ -1,37 +1,76 @@
// TODO this is platform specific
pub struct Outbytes {}
pub struct Stdout {}
pub struct Stderr {}
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> {
for c in s.as_bytes() {
unsafe {
crate::fsrc::osal::outbyte(*c);
}
// Safe because write will only read the pointer an then return
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_rules! sifln {
($(,)?) => (
let mut stdout = Outbytes {};
writeln!(stdout);
//let mut stdout = Outbytes {};
writeln!(Stdout {});
);
($($arg:tt)*) => (
let mut stdout = crate::fsrc::sif::Outbytes {};
let _alwaysok = writeln!(stdout, $($arg)*);
let _alwaysok = writeln!(crate::fsrc::sif::Stdout {}, $($arg)*);
);
}
#[macro_export]
macro_rules! sif {
($($arg:tt)*) => (
let mut stdout = crate::fsrc::sif::Outbytes {};
let _alwaysok = write!(stdout, $($arg)*);
let _alwaysok = write!(crate::fsrc::sif::Stdout {}, $($arg)*);
);
}

View File

@ -20,9 +20,9 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
unsafe {
osal::stop_it();
}
// TODO: Make this unicode-safe
sifln!("");
sif!("in task \"");
// TODO: Make this unicode-safe
_ = writeln!(crate::fsrc::sif::Stderr {},"");
_ = write!(crate::fsrc::sif::Stderr {},"in task \"");
unsafe {
//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());
@ -32,12 +32,12 @@ fn panic(panic: &PanicInfo<'_>) -> ! {
sif!("{}", string);
}
Err(_) => {
sif!("Schei<EFBFBD> Encoding");
_ = writeln!(crate::fsrc::sif::Stderr {},"Schei<EFBFBD> Encoding");
}
}
}
sifln!("\":");
sifln!("{}", panic);
_ = writeln!(crate::fsrc::sif::Stderr {},"\":");
_ = writeln!(crate::fsrc::sif::Stderr {},"{}", panic);
//TODO: stop RTOS, exit if hosted
unsafe { done() };
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]