Skip to content

Commit

Permalink
Hack for xtensa va_args wifi-logs
Browse files Browse the repository at this point in the history
  • Loading branch information
karlri committed Jun 29, 2023
1 parent abf6d4b commit 8befe40
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 17 deletions.
19 changes: 18 additions & 1 deletion esp-wifi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,24 @@ fn main() -> Result<(), String> {
}

#[cfg(feature = "esp32")]
println!("cargo:rustc-cfg=esp32");
{
println!("cargo:rustc-cfg=esp32");
// copy and link xtensa va arg hack
use std::env;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn copy_file(out: &PathBuf, from: &str, to: &str) {
let mut file = File::create(out.join(to)).unwrap();
file.write_all(&fs::read(from).unwrap()).unwrap();
}
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
// provides extern "C" { fn va_list_ptr_get_u32(list: *mut [u32; 3]) -> u32; }
copy_file(&out, "./lib_va_list_ptr_get_u32.a", "libvahack.a");
println!("cargo:rustc-link-lib={}", "vahack");
println!("cargo:rustc-link-search={}", out.display());
}

#[cfg(feature = "esp32c2")]
println!("cargo:rustc-cfg=esp32c2");
Expand Down
Binary file added esp-wifi/lib_va_list_ptr_get_u32.a
Binary file not shown.
53 changes: 47 additions & 6 deletions esp-wifi/src/compat/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,55 @@ impl Write for StrBuf {
}

pub unsafe extern "C" fn syslog(_priority: u32, format: *const u8, mut args: VaListImpl) {
#[cfg(all(feature = "wifi-logs", target_arch = "riscv32"))]
#[cfg(feature = "wifi-logs")]
{
let mut buf = [0u8; 512];
vsnprintf(&mut buf as *mut u8, 511, format, args);
let res_str = StrBuf::from(&buf as *const u8);
info!("{}", res_str.as_str_ref());
let s = res_str.as_str_ref().trim();
// Skip empty lines.
if s.len() != 0 {
// TODO: perhaps buffer internally until we get a b'\n', then actually log?
// It seems that line-buffered stream is expected. Some log lines end with b':'
// and they are trying to continue printing with another call to syslog but that
// ends up on another line with this implementation. Also, sometimes they print
// a single newline, perhaps they're expecting to flush the buffered output?
info!("{}", s);
}
}
#[cfg(all(feature = "wifi-logs", not(target_arch = "riscv32")))]
{
let res_str = StrBuf::from(format);
info!("{}", res_str.as_str_ref());
}

#[repr(C)]
struct XtensaVaListImplGcc {
args: [u32; 3],
}

impl XtensaVaListImplGcc {
pub fn arg<T: GetVa>(&mut self) -> T {
T::arg(self)
}
}

trait GetVa {
fn arg(list: &mut XtensaVaListImplGcc) -> Self;
}

extern "C" {
fn va_list_ptr_get_u32(list: *mut XtensaVaListImplGcc) -> u32;
}
impl GetVa for u32 {
fn arg(list: &mut XtensaVaListImplGcc) -> Self {
unsafe { va_list_ptr_get_u32(list) }
}
}
impl GetVa for i32 {
fn arg(list: &mut XtensaVaListImplGcc) -> Self {
unsafe { va_list_ptr_get_u32(list) as i32 }
}
}
impl GetVa for u8 {
fn arg(list: &mut XtensaVaListImplGcc) -> Self {
unsafe { va_list_ptr_get_u32(list) as u8 }
}
}

Expand All @@ -126,6 +164,9 @@ pub(crate) unsafe fn vsnprintf(
format: *const u8,
mut args: VaListImpl,
) -> i32 {
// VaListImpl::get is broken on xtensa. Use alternate implementation that works.
#[cfg(target_arch = "xtensa")]
let mut args: XtensaVaListImplGcc = core::mem::transmute(args);
let fmt_str_ptr = format;

let mut res_str = StrBuf::new();
Expand Down
10 changes: 0 additions & 10 deletions esp-wifi/src/wifi/os_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use crate::{
timer::yield_task,
};

#[cfg(target_arch = "riscv32")]
use crate::compat::common::syslog;

use super::WifiEvent;
Expand Down Expand Up @@ -1515,7 +1514,6 @@ pub unsafe extern "C" fn log_write(
#[cfg(not(feature = "wifi-logs"))]
return;

#[cfg(target_arch = "riscv32")]
syslog(_level, _format as *const u8, _args);
}

Expand Down Expand Up @@ -1545,14 +1543,6 @@ pub unsafe extern "C" fn log_writev(
#[cfg(not(feature = "wifi-logs"))]
return;

#[cfg(target_arch = "xtensa")]
#[allow(unreachable_code)]
{
let s = StrBuf::from(_format as *const u8);
log::info!("{}", s.as_str_ref());
}

#[cfg(target_arch = "riscv32")]
#[allow(unreachable_code)]
{
let _args = core::mem::transmute(_args);
Expand Down
7 changes: 7 additions & 0 deletions esp-wifi/va_list_ptr_get_u32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdarg.h>

// compile with xtensa-esp32-elf-gcc -c va_list_ptr_get_u32.c -o lib_va_list_ptr_get_u32.a
int va_list_ptr_get_u32(va_list *list)
{
return va_arg(*list, int);
}

0 comments on commit 8befe40

Please sign in to comment.