Skip to content

Commit 5bc5f08

Browse files
committed
Add support for RTT through rust
This commit introduces a new `log` macro that calls `rprintln` in case the `rtt` feature is enabled. It also creates a new c function called `util_log` that reuses the rust RTT machinery. The rust `log` macro is used the same way `println` is used. `util_log` is used the same way `printf` is used.
1 parent 69a9bb1 commit 5bc5f08

File tree

9 files changed

+85
-3
lines changed

9 files changed

+85
-3
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ foreach(type ${RUST_LIBS})
370370
FIRMWARE_VERSION_SHORT=${FIRMWARE_VERSION}
371371
$<$<BOOL:${SCCACHE_PROGRAM}>:RUSTC_WRAPPER=${SCCACHE_PROGRAM}>
372372
RUSTC_BOOTSTRAP=1
373-
${CARGO} build $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:-vv> --offline --features target-${type} --target-dir ${RUST_BINARY_DIR}/feature-${type} ${RUST_CARGO_FLAGS} ${RUST_TARGET_ARCH_ARG}
373+
${CARGO} build $<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:-vv> --offline --features target-${type}$<$<STREQUAL:${CMAKE_BUILD_TYPE},DEBUG>:,rtt> --target-dir ${RUST_BINARY_DIR}/feature-${type} ${RUST_CARGO_FLAGS} ${RUST_TARGET_ARCH_ARG}
374374
COMMAND
375375
${CMAKE_COMMAND} -E copy_if_different ${lib} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/lib${type}_rust_c.a
376376
# DEPFILES are only supported with the Ninja build tool

src/platform/platform_init.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,18 @@
1818
#if !defined(BOOTLOADER)
1919
#include "sd_mmc/sd_mmc_start.h"
2020
#endif
21+
#include "rust/rust.h"
2122

2223
void platform_init(void)
2324
{
2425
oled_init();
2526
#if !defined(BOOTLOADER)
27+
// The factory setup image already has a c implementation of RTT.
28+
#if FACTORYSETUP != 1
29+
// these two functions are noops if "rtt" feature isn't enabled in rust
30+
rust_rtt_init();
31+
util_log("platform_init");
32+
#endif
2633
sd_mmc_start();
2734
#endif
2835
}

src/rust/bitbox02-rust-c/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,5 @@ app-cardano = [
9797
# enable this feature in the deps
9898
"bitbox02-rust/app-cardano",
9999
]
100+
101+
rtt = [ "util/rtt" ]

src/rust/bitbox02-rust-c/src/lib.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,37 @@ mod sha2;
3636
mod workflow;
3737

3838
// Whenever execution reaches somewhere it isn't supposed to rust code will "panic". Our panic
39-
// handler will print the available information on the screen. If we compile with `panic=abort`
40-
// this code will never get executed.
39+
// handler will print the available information on the screen and over RTT. If we compile with
40+
// `panic=abort` this code will never get executed.
4141
#[cfg(not(test))]
4242
#[cfg(not(feature = "testing"))]
4343
#[cfg_attr(feature = "bootloader", allow(unused_variables))]
4444
#[panic_handler]
4545
fn panic(info: &core::panic::PanicInfo) -> ! {
46+
::util::log::log!("{}", info);
4647
#[cfg(feature = "firmware")]
4748
bitbox02_rust::print_debug!(0, "Error: {}", info);
4849
loop {}
4950
}
51+
52+
#[no_mangle]
53+
pub extern "C" fn rust_rtt_init() {
54+
::util::log::rtt_init();
55+
}
56+
57+
/// # Safety
58+
///
59+
/// The pointer `ptr` must point to a null terminated string
60+
#[no_mangle]
61+
#[cfg_attr(not(feature = "rtt"), allow(unused))]
62+
pub unsafe extern "C" fn rust_log(ptr: *const ::util::c_types::c_char) {
63+
#[cfg(feature = "rtt")]
64+
{
65+
if ptr.is_null() {
66+
panic!("`ptr` must be a valid pointer");
67+
}
68+
let s = unsafe { core::ffi::CStr::from_ptr(ptr as _) };
69+
let s = unsafe { core::str::from_utf8_unchecked(s.to_bytes()) };
70+
::util::log::rtt_target::rprintln!("{}", s);
71+
}
72+
}

src/rust/util/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ license = "Apache-2.0"
2424
num-bigint = { workspace = true, default-features = false }
2525
rtt-target = { version = "0.5.0", optional = true }
2626
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"], optional = true }
27+
28+
[features]
29+
rtt = ["dep:rtt-target", "dep:cortex-m"]

src/rust/util/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,17 @@ pub mod ascii;
1717
pub mod bip32;
1818
pub mod c_types;
1919
pub mod decimal;
20+
pub mod log;
2021
pub mod name;
2122

2223
// for `format!`
2324
#[macro_use]
2425
extern crate alloc;
2526

27+
// include critical section implementation, needed by rtt-target
28+
#[cfg(feature = "rtt")]
29+
extern crate cortex_m;
30+
2631
/// Guaranteed to wipe the provided buffer
2732
pub fn zero(dst: &mut [u8]) {
2833
for p in dst {

src/rust/util/src/log.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Re-export rtt_target so that it is available to the macro user
2+
#[cfg(feature = "rtt")]
3+
pub use ::rtt_target;
4+
5+
/// Macro to log over RTT if `rtt` feature is set, otherwise noop
6+
#[macro_export]
7+
macro_rules! log {
8+
($($arg:tt)*) => { #[cfg(feature="rtt")] {$crate::log::rtt_target::rprintln!($($arg)*) }};
9+
}
10+
11+
// Make log macro usable in crate
12+
pub use log;
13+
14+
pub fn rtt_init() {
15+
#[cfg(feature = "rtt")]
16+
rtt_target::rtt_init_print!();
17+
log!("RTT Initialized");
18+
}

src/util.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,25 @@ void util_cleanup_64(uint8_t** buf)
6666
{
6767
util_zero(*buf, 64);
6868
}
69+
70+
// Max message size is MAX_LOG_LENGTH-1, becuase vsnprintf will always print a null character
71+
#define MAX_LOG_LENGTH 101
72+
73+
void util_log(const char* fmt, ...)
74+
{
75+
#if !defined(NDEBUG)
76+
char buf[MAX_LOG_LENGTH] = "";
77+
78+
va_list va;
79+
va_start(va, fmt);
80+
int res = vsnprintf(buf, MAX_LOG_LENGTH, fmt, va);
81+
va_end(va);
82+
83+
rust_log(buf);
84+
if (res > MAX_LOG_LENGTH - 1) {
85+
rust_log("The complete log line didn't fit\n");
86+
}
87+
#else
88+
(void)fmt;
89+
#endif
90+
}

src/util.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,6 @@ typedef struct {
109109
*/
110110
typedef enum { ASYNC_OP_TRUE, ASYNC_OP_FALSE, ASYNC_OP_NOT_READY } async_op_result_t;
111111

112+
void util_log(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
113+
112114
#endif

0 commit comments

Comments
 (0)