-
Notifications
You must be signed in to change notification settings - Fork 117
Description
Whenever i try to serialize a chrono::NaiveDateTime
or any struct that contains it internally, the program resets, if it's being run on an AVR microcontroller (ATmega328p specifically). It can be as simple as:
let entry = NaiveDateTime::MIN;
// This is where it crashes and the board resets and restarts running from the beginning
let output: postcard::Result<Vec<u8, 64>> = to_vec(&entry);
Serializing other stuff seems to work fine, e.g., this example code from the docs works as expected:
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
struct RefStruct<'a> {
bytes: &'a [u8],
str_s: &'a str,
}
let message = "hElLo";
let bytes = [0x01, 0x10, 0x02, 0x20];
let output: postcard::Result<Vec<u8, 11>> = to_vec(&RefStruct {
bytes: &bytes,
str_s: message,
});
Also, the same code runs without issue on x64, which makes me suspect a miscompilation on AVR but verifying that seems to be beyond my ability currently (tried looking at the AVR disassembly but there's simply too much going on there).
I'm building the code using the nightly-2023-03-24
toolchain.
Minimal reproducible example
main.rs
#![no_std]
#![no_main]
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use heapless::Vec;
use panic_halt as _;
use postcard::to_vec;
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
struct RefStruct<'a> {
bytes: &'a [u8],
str_s: &'a str,
}
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let mut serial = arduino_hal::default_serial!(dp, pins, 9600);
ufmt::uwriteln!(&mut serial, "Serial set up, entering loop").unwrap();
arduino_hal::delay_ms(1000);
loop {
let entry = NaiveDateTime::MIN;
ufmt::uwriteln!(&mut serial, "Converting").unwrap();
arduino_hal::delay_ms(1000);
// For some reason this serialization code works ...
//
// let message = "hElLo";
// let bytes = [0x01, 0x10, 0x02, 0x20];
// let output: postcard::Result<Vec<u8, 11>> = to_vec(&RefStruct {
// bytes: &bytes,
// str_s: message,
// });
// ... but this doesn't
//
// NOTE: Not sure how much memory this takes but 64 bytes should be
// plenty for serialization, i guess
let output: postcard::Result<Vec<u8, 64>> = to_vec(&entry);
ufmt::uwriteln!(&mut serial, "Writing").unwrap();
arduino_hal::delay_ms(1000);
match output {
Ok(output) => {
for byte in output {
serial.write_byte(byte);
}
serial.flush();
}
Err(_e) => ufmt::uwriteln!(&mut serial, "Serialization error").unwrap(),
}
arduino_hal::delay_ms(5000);
}
}
Cargo.toml
[package]
name = "templog-arduino"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[[bin]]
name = "templog-arduino"
test = false
bench = false
[dependencies]
panic-halt = "0.2.0"
ufmt = "0.1.0"
embedded-hal = "0.2.3"
serde = { version = "1.0.147", features = ["derive"], default-features = false }
chrono = { version = "0.4.23", features = ["serde"], default-features = false }
heapless = { git = "https://github.com/japaric/heapless" }
[dependencies.postcard]
# this refers to postcard rev 62c05473f76ead781aaa9d4a3e4057b86e543747
# with an updated version of `heapless` dependency
path = "../../postcard"
[dependencies.arduino-hal]
git = "https://github.com/rahix/avr-hal"
rev = "3b8f39fa2ec5e3359c7bedc33d982e75e8cc3700"
features = ["arduino-uno"]
# This doesn't seem to have any effect, don't know why
# [patch.crates-io]
# heapless = { git = 'https://github.com/japaric/heapless' }
# Configure the build for minimal size - AVRs have very little program memory
[profile.dev]
panic = "abort"
lto = true
opt-level = "s"
[profile.release]
panic = "abort"
codegen-units = 1
debug = true
lto = true
opt-level = "s"
Other things to note
I'm using postcard
rev 62c05473f76ead781aaa9d4a3e4057b86e543747
with the following diff applied to it to work around #82
diff --git a/Cargo.toml b/Cargo.toml
index 6498e55..d16e0dd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,7 +29,8 @@ version = "0.2.24"
optional = true
[dependencies.heapless]
-version = "0.7.0"
+# version = "0.7.0"
+git = 'https://github.com/japaric/heapless'
default-features = false
features = ["serde"]
optional = true
heapless
is at rev 644653bf3b831c6bb4963be2de24804acf5e5001
.