Eeprom

Struct Eeprom 

Source
pub struct Eeprom {
    pub header: EepromHeader,
    pub vendor_info: VendorInfoAtom,
    pub gpio_map_bank0: GpioMapAtom,
    pub dt_blob: Option<Vec<u8>>,
    pub gpio_map_bank1: Option<GpioMapAtom>,
    pub custom_atoms: Vec<(u8, Vec<u8>)>,
}

Fields§

§header: EepromHeader§vendor_info: VendorInfoAtom§gpio_map_bank0: GpioMapAtom§dt_blob: Option<Vec<u8>>§gpio_map_bank1: Option<GpioMapAtom>§custom_atoms: Vec<(u8, Vec<u8>)>

Implementations§

Source§

impl Eeprom

Source

pub fn from_bytes(data: &[u8]) -> Result<Self, &'static str>

Parses an EEPROM image from a byte slice, validating the signature and CRC.

This variant allocates owned buffers for atoms, making it suitable for environments where alloc is available.

Source

pub fn is_valid(&self) -> bool

Checks if EEPROM contains valid data (by signature and version)

Source

pub fn add_vendor_info(&mut self, atom: VendorInfoAtom)

Source

pub fn add_gpio_map_bank0(&mut self, atom: GpioMapAtom)

Source

pub fn add_dt_blob(&mut self, blob: Vec<u8>)

Source

pub fn add_gpio_map_bank1(&mut self, atom: GpioMapAtom)

Source

pub fn add_custom_atom(&mut self, atom_type: u8, data: Vec<u8>)

Source

pub fn update_header(&mut self)

Recalculate numatoms and eeplen after adding atoms

Examples found in repository?
examples/create_test.rs (line 54)
12fn main() {
13    // Create a vendor info atom
14    let vendor_atom = VendorInfoAtom::new(
15        0x4D4F, // vendor_id (example: "MO")
16        0x1234, // product_id
17        1,      // product_ver
18        "TestVendor",
19        "TestProduct",
20        [
21            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
22            0xDE, 0xF0,
23        ], // UUID
24    );
25
26    // Create GPIO map for bank 0
27    let gpio_atom = GpioMapAtom {
28        flags: 0x0000,
29        pins: [0u8; 28], // All pins as inputs
30    };
31
32    // Create EEPROM structure
33    #[cfg(feature = "alloc")]
34    let mut eeprom = Eeprom {
35        header: EepromHeader::new(),
36        vendor_info: vendor_atom,
37        gpio_map_bank0: gpio_atom,
38        dt_blob: None,
39        gpio_map_bank1: None,
40        custom_atoms: Vec::new(),
41    };
42
43    #[cfg(not(feature = "alloc"))]
44    let mut eeprom = Eeprom {
45        header: EepromHeader::new(),
46        vendor_info: vendor_atom,
47        gpio_map_bank0: gpio_atom,
48        dt_blob: None,
49        gpio_map_bank1: None,
50        custom_atoms: &[],
51    };
52
53    // Update header with correct counts and length
54    eeprom.update_header();
55
56    // Serialize with CRC
57    #[cfg(feature = "alloc")]
58    let serialized = eeprom.serialize_with_crc();
59
60    #[cfg(not(feature = "alloc"))]
61    let serialized = {
62        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
63        let size = eeprom
64            .serialize_with_crc_to_slice(&mut buffer)
65            .expect("Failed to serialize EEPROM");
66        &buffer[..size]
67    };
68
69    // Create output directory if it doesn't exist
70    if std::fs::metadata("tests/data").is_err() {
71        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
72    }
73
74    std::fs::write("tests/data/test.bin", &serialized).expect("Failed to write test file");
75
76    println!("Created tests/data/test.bin ({} bytes)", serialized.len());
77
78    // Verify the created file
79    if Eeprom::verify_crc(&serialized) {
80        println!("✅ CRC verification passed");
81    } else {
82        println!("❌ CRC verification failed");
83    }
84}
More examples
Hide additional examples
examples/create_simple.rs (line 56)
12fn main() {
13    println!("📝 Creating minimal EEPROM with basic vendor info...");
14
15    // Create a minimal vendor info atom
16    let vendor_atom = VendorInfoAtom::new(
17        0x5349, // vendor_id (example: "SI" for Simple)
18        0x4D50, // product_id (example: "MP" for MiniProduct)
19        1,      // product_ver
20        "Simple",
21        "MinimalHAT",
22        [
23            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
24            0xEE, 0xFF,
25        ], // Simple UUID
26    );
27
28    // Create minimal GPIO map
29    let gpio_atom = GpioMapAtom {
30        flags: 0x0000,
31        pins: [0u8; 28], // All pins unused
32    };
33
34    // Create EEPROM structure
35    #[cfg(feature = "alloc")]
36    let mut eeprom = Eeprom {
37        header: EepromHeader::new(),
38        vendor_info: vendor_atom,
39        gpio_map_bank0: gpio_atom,
40        dt_blob: None,
41        gpio_map_bank1: None,
42        custom_atoms: Vec::new(),
43    };
44
45    #[cfg(not(feature = "alloc"))]
46    let mut eeprom = Eeprom {
47        header: EepromHeader::new(),
48        vendor_info: vendor_atom,
49        gpio_map_bank0: gpio_atom,
50        dt_blob: None,
51        gpio_map_bank1: None,
52        custom_atoms: &[],
53    };
54
55    // Update header with correct counts and length
56    eeprom.update_header();
57
58    // Serialize with CRC
59    #[cfg(feature = "alloc")]
60    let serialized = eeprom.serialize_with_crc();
61
62    #[cfg(not(feature = "alloc"))]
63    let serialized = {
64        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
65        let size = eeprom
66            .serialize_with_crc_to_slice(&mut buffer)
67            .expect("Failed to serialize EEPROM");
68        &buffer[..size]
69    };
70
71    // Create output directory if it doesn't exist
72    if std::fs::metadata("tests/data").is_err() {
73        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
74    }
75
76    std::fs::write("tests/data/simple.bin", &serialized).expect("Failed to write simple file");
77
78    println!("Created tests/data/simple.bin ({} bytes)", serialized.len());
79
80    // Verify the created file
81    if Eeprom::verify_crc(&serialized) {
82        println!("✅ CRC verification passed");
83    } else {
84        println!("❌ CRC verification failed");
85    }
86}
examples/bare_metal_example.rs (line 60)
16fn main() {
17    // This example demonstrates how to use ehatrom in a bare-metal environment
18    // without heap allocation
19
20    // Create EEPROM structure with static data
21    let vendor_info = VendorInfoAtom::new(
22        0x0001, // vendor_id
23        0x0002, // product_id
24        0x0001, // product_ver
25        "Acme Corp",
26        "Test HAT",
27        [
28            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
29            0x77, 0x88,
30        ],
31    );
32
33    let gpio_map = GpioMapAtom {
34        flags: 0x0001,
35        pins: [0; 28], // All pins disabled
36    };
37
38    // Custom atoms with static data
39    static CUSTOM_DATA: &[u8] = b"Hello, Bare Metal!";
40
41    // In no_std environment, custom_atoms would be a static slice
42    #[cfg(not(feature = "alloc"))]
43    static CUSTOM_ATOMS: &[(u8, &[u8])] = &[(0x80, CUSTOM_DATA)];
44
45    #[cfg(feature = "alloc")]
46    let custom_atoms = vec![(0x80u8, CUSTOM_DATA.to_vec())];
47
48    let mut eeprom = Eeprom {
49        header: EepromHeader::new(),
50        vendor_info,
51        gpio_map_bank0: gpio_map,
52        dt_blob: None,
53        gpio_map_bank1: None,
54        #[cfg(feature = "alloc")]
55        custom_atoms,
56        #[cfg(not(feature = "alloc"))]
57        custom_atoms: CUSTOM_ATOMS,
58    };
59
60    eeprom.update_header();
61
62    // Calculate required buffer size
63    let buffer_size = eeprom.calculate_serialized_size();
64    println!("Required buffer size: {buffer_size} bytes");
65
66    // Serialize to fixed buffer (demonstrates no heap allocation approach)
67    let mut buffer = vec![0u8; 512]; // In real no_std, this would be a static array
68
69    #[cfg(feature = "alloc")]
70    {
71        // Standard allocation-based serialization
72        let serialized = eeprom.serialize();
73        println!("Serialized {} bytes using Vec", serialized.len());
74    }
75
76    // Demonstrate no-allocation serialization (available in both std and no_std)
77    let mut offset = 0;
78    match eeprom.serialize_to_buffer(&mut buffer, &mut offset) {
79        Ok(()) => {
80            println!("Successfully serialized {offset} bytes to buffer");
81            println!("First 16 bytes: {:02X?}", &buffer[..16.min(offset)]);
82        }
83        Err(e) => {
84            println!("Serialization failed: {e:?}");
85        }
86    }
87
88    println!("EEPROM structure:\n{eeprom}");
89}
examples/create_advanced.rs (line 107)
13fn main() {
14    println!("🚀 Creating advanced EEPROM with Device Tree support...");
15
16    // Create a vendor info atom with detailed information
17    let vendor_atom = VendorInfoAtom::new(
18        0x414C, // vendor_id (example: "AL" for AleksejZaharčenko)
19        0x2024, // product_id (year)
20        1,      // product_ver
21        "4STM4 Ocultum",
22        "Advanced HAT Demo",
23        [
24            // UUID for this specific HAT
25            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
26            0x32, 0x10,
27        ],
28    );
29
30    // Create GPIO map for bank 0 with specific pin configurations
31    let mut gpio_pins = [0u8; 28];
32
33    // Configure some pins as outputs (value 1)
34    gpio_pins[18] = 1; // GPIO 18 as output
35    gpio_pins[19] = 1; // GPIO 19 as output
36    gpio_pins[20] = 1; // GPIO 20 as output
37    gpio_pins[21] = 1; // GPIO 21 as output
38
39    // Other pins remain as inputs (value 0)
40
41    let gpio_atom = GpioMapAtom {
42        flags: 0x0001, // Set some flags
43        pins: gpio_pins,
44    };
45
46    // Create a simple Device Tree blob (minimal example)
47    // In real use, this would be a proper compiled device tree
48    let dt_blob_data = b"# Simple Device Tree overlay for demo HAT
49/dts-v1/;
50/plugin/;
51
52/ {
53    compatible = \"brcm,bcm2835\";
54    
55    fragment@0 {
56        target = <&gpio>;
57        __overlay__ {
58            demo_pins: demo_pins {
59                brcm,pins = <18 19 20 21>;
60                brcm,function = <1>; /* GPIO_OUT */
61            };
62        };
63    };
64    
65    fragment@1 {
66        target-path = \"/\";
67        __overlay__ {
68            demo_hat {
69                compatible = \"4stm4,demo-hat\";
70                pinctrl-names = \"default\";
71                pinctrl-0 = <&demo_pins>;
72                status = \"okay\";
73            };
74        };
75    };
76};"
77    .to_vec();
78
79    // Create EEPROM structure with all components
80    #[cfg(feature = "alloc")]
81    let mut eeprom = Eeprom {
82        header: EepromHeader::new(),
83        vendor_info: vendor_atom,
84        gpio_map_bank0: gpio_atom,
85        dt_blob: Some(dt_blob_data), // dt_blob is Option<Vec<u8>>
86        gpio_map_bank1: None,        // Not used in this example
87        custom_atoms: Vec::new(),
88    };
89
90    #[cfg(not(feature = "alloc"))]
91    // Для no_std режима создаем статические данные
92    let mut eeprom = {
93        // Для no_std нам нужны статические данные, это просто заглушка
94        static DT_BLOB_DATA: [u8; 1] = [0];
95        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
96        Eeprom {
97            header: EepromHeader::new(),
98            vendor_info: vendor_atom,
99            gpio_map_bank0: gpio_atom,
100            dt_blob: Some(&DT_BLOB_DATA), // dt_blob is Option<&[u8]> в no_std
101            gpio_map_bank1: None,
102            custom_atoms: &CUSTOM_ATOMS,
103        }
104    };
105
106    // Update header with correct counts and length
107    eeprom.update_header();
108
109    // Serialize with CRC
110    #[cfg(feature = "alloc")]
111    let serialized = eeprom.serialize_with_crc();
112
113    #[cfg(not(feature = "alloc"))]
114    // Создаем буфер и вектор для копирования данных
115    let serialized = {
116        let mut buffer = [0u8; 4096]; // Больший буфер для DT blob
117        let size = eeprom
118            .serialize_with_crc_to_slice(&mut buffer)
119            .expect("Failed to serialize EEPROM");
120        // Копируем данные в новый вектор
121        buffer[..size].to_vec()
122    };
123    let filename = "tests/data/advanced.bin";
124
125    // Create output directory if it doesn't exist
126    if std::fs::metadata("tests/data").is_err() {
127        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
128    }
129
130    std::fs::write(filename, &serialized).expect("Failed to write advanced EEPROM file");
131
132    println!("✅ Created {} ({} bytes)", filename, serialized.len());
133    println!("📊 EEPROM structure:");
134    println!("   • Header: 12 bytes");
135    println!(
136        "   • Vendor Info: {} bytes",
137        std::mem::size_of::<VendorInfoAtom>() + "4STM4 Ocultum".len() + "Advanced HAT Demo".len()
138    );
139    println!(
140        "   • GPIO Map Bank 0: {} bytes",
141        std::mem::size_of::<GpioMapAtom>()
142    );
143    println!(
144        "   • Device Tree Blob: {} bytes",
145        serialized.len()
146            - 12
147            - std::mem::size_of::<VendorInfoAtom>()
148            - "4STM4 Ocultum".len()
149            - "Advanced HAT Demo".len()
150            - std::mem::size_of::<GpioMapAtom>()
151            - 4
152    );
153    println!("   • CRC32: 4 bytes");
154
155    // Verify the created file
156    if Eeprom::verify_crc(&serialized) {
157        println!("✅ CRC32 verification passed");
158    } else {
159        println!("❌ CRC32 verification failed");
160    }
161
162    println!("🎯 Use './target/release/ehatrom show {filename}' to analyze the created EEPROM");
163}
examples/create_custom_atoms.rs (line 105)
12fn main() {
13    println!("📝 Creating EEPROM with custom atoms...");
14
15    // Create a list to hold our custom atoms
16    let mut custom_atoms = Vec::new();
17
18    // Create vendor info atom
19    let vendor_atom = VendorInfoAtom::new(
20        0x4143, // vendor_id "AC" (example)
21        0x0001, // product_id
22        2,      // product_ver
23        "ACME Custom HATs",
24        "SensorBoard Plus",
25        [
26            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
27            0xEE, 0xFF,
28        ], // UUID
29    );
30
31    // Create GPIO map for bank 0 - more complex pin assignments
32    let mut pins = [0u8; 28];
33    pins[4] = 0x01; // GPIO4 - Input
34    pins[17] = 0x02; // GPIO17 - Output
35    pins[18] = 0x02; // GPIO18 - Output
36    pins[22] = 0x01; // GPIO22 - Input
37    pins[23] = 0x01; // GPIO23 - Input
38    pins[24] = 0x02; // GPIO24 - Output
39    pins[25] = 0x02; // GPIO25 - Output
40    let gpio_atom = GpioMapAtom {
41        flags: 0x0000,
42        pins,
43    };
44
45    // Custom atom 1: Configuration string
46    let config_str = "MODE=SENSORS,INTERVAL=250,UNITS=METRIC".to_string();
47    custom_atoms.push((0x81, config_str.into_bytes())); // Using tuple format (type, data)
48
49    // Custom atom 2: Sensor calibration data (example of binary data)
50    let mut sensor_cal = Vec::new();
51    // Temperature offset and gain
52    sensor_cal.extend_from_slice(&((-2.5f32).to_be_bytes()));
53    sensor_cal.extend_from_slice(&(1.03f32.to_be_bytes()));
54    // Humidity offset and gain
55    sensor_cal.extend_from_slice(&(1.2f32.to_be_bytes()));
56    sensor_cal.extend_from_slice(&(0.98f32.to_be_bytes()));
57    // Pressure offset and gain
58    sensor_cal.extend_from_slice(&(15.0f32.to_be_bytes()));
59    sensor_cal.extend_from_slice(&(1.0f32.to_be_bytes()));
60    custom_atoms.push((0x82, sensor_cal)); // Using tuple format (type, data)
61
62    // Custom atom 3: Hardware version info as string
63    let hw_info = format!(
64        "HW_VERSION={}.{}.{},PCB_REV=C,ASSEMBLY_DATE=2024-12-20",
65        env!("CARGO_PKG_VERSION_MAJOR"),
66        env!("CARGO_PKG_VERSION_MINOR"),
67        env!("CARGO_PKG_VERSION_PATCH")
68    );
69    custom_atoms.push((0x83, hw_info.into_bytes())); // Using tuple format (type, data)
70
71    // Custom atom 4: Binary data (e.g., lookup table)
72    let mut lookup_table = Vec::new();
73    for i in 0..32 {
74        lookup_table.push((i * i) as u8); // Simple quadratic lookup table
75    }
76    custom_atoms.push((0x84, lookup_table)); // Using tuple format (type, data)
77
78    // Create EEPROM structure
79    #[cfg(feature = "alloc")]
80    let mut eeprom = Eeprom {
81        header: EepromHeader::new(),
82        vendor_info: vendor_atom,
83        gpio_map_bank0: gpio_atom,
84        dt_blob: None,
85        gpio_map_bank1: None,
86        custom_atoms,
87    };
88
89    #[cfg(not(feature = "alloc"))]
90    // Для no_std режима создаем статические данные
91    let mut eeprom = {
92        // Для no_std нам нужны статические данные, это просто заглушка
93        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
94        Eeprom {
95            header: EepromHeader::new(),
96            vendor_info: vendor_atom,
97            gpio_map_bank0: gpio_atom,
98            dt_blob: None,
99            gpio_map_bank1: None,
100            custom_atoms: &CUSTOM_ATOMS,
101        }
102    };
103
104    // Update header with correct counts and length
105    eeprom.update_header();
106
107    // Serialize with CRC
108    #[cfg(feature = "alloc")]
109    let serialized = eeprom.serialize_with_crc();
110
111    #[cfg(not(feature = "alloc"))]
112    // Создаем буфер и вектор для копирования данных
113    let serialized = {
114        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
115        let size = eeprom
116            .serialize_with_crc_to_slice(&mut buffer)
117            .expect("Failed to serialize EEPROM");
118        // Копируем данные в новый вектор
119        buffer[..size].to_vec()
120    };
121
122    let filename = "tests/data/custom_atoms.bin";
123
124    // Create output directory if it doesn't exist
125    if std::fs::metadata("tests/data").is_err() {
126        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
127    }
128
129    std::fs::write(filename, &serialized).expect("Failed to write custom atoms EEPROM file");
130
131    println!("✅ Created {} ({} bytes)", filename, serialized.len());
132    println!("📊 EEPROM contains:");
133    println!("   • Standard HAT header");
134    println!("   • Vendor info atom");
135    println!("   • GPIO map atom");
136    println!("   • 4 custom atoms:");
137    println!("     - 0x81: Configuration string");
138    println!("     - 0x82: Sensor calibration data");
139    println!("     - 0x83: Hardware version info");
140    println!("     - 0x84: Lookup table (32 bytes)");
141
142    // Verify the created file
143    if Eeprom::verify_crc(&serialized) {
144        println!("✅ CRC32 verification passed");
145    } else {
146        println!("❌ CRC32 verification failed");
147    }
148
149    println!("💡 This demonstrates how to embed custom application-specific data in HAT EEPROM");
150}
Source

pub fn serialize_with_crc(&self) -> Vec<u8>

Serialize with CRC32 appended (4 bytes LE)

Examples found in repository?
examples/create_test.rs (line 58)
12fn main() {
13    // Create a vendor info atom
14    let vendor_atom = VendorInfoAtom::new(
15        0x4D4F, // vendor_id (example: "MO")
16        0x1234, // product_id
17        1,      // product_ver
18        "TestVendor",
19        "TestProduct",
20        [
21            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
22            0xDE, 0xF0,
23        ], // UUID
24    );
25
26    // Create GPIO map for bank 0
27    let gpio_atom = GpioMapAtom {
28        flags: 0x0000,
29        pins: [0u8; 28], // All pins as inputs
30    };
31
32    // Create EEPROM structure
33    #[cfg(feature = "alloc")]
34    let mut eeprom = Eeprom {
35        header: EepromHeader::new(),
36        vendor_info: vendor_atom,
37        gpio_map_bank0: gpio_atom,
38        dt_blob: None,
39        gpio_map_bank1: None,
40        custom_atoms: Vec::new(),
41    };
42
43    #[cfg(not(feature = "alloc"))]
44    let mut eeprom = Eeprom {
45        header: EepromHeader::new(),
46        vendor_info: vendor_atom,
47        gpio_map_bank0: gpio_atom,
48        dt_blob: None,
49        gpio_map_bank1: None,
50        custom_atoms: &[],
51    };
52
53    // Update header with correct counts and length
54    eeprom.update_header();
55
56    // Serialize with CRC
57    #[cfg(feature = "alloc")]
58    let serialized = eeprom.serialize_with_crc();
59
60    #[cfg(not(feature = "alloc"))]
61    let serialized = {
62        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
63        let size = eeprom
64            .serialize_with_crc_to_slice(&mut buffer)
65            .expect("Failed to serialize EEPROM");
66        &buffer[..size]
67    };
68
69    // Create output directory if it doesn't exist
70    if std::fs::metadata("tests/data").is_err() {
71        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
72    }
73
74    std::fs::write("tests/data/test.bin", &serialized).expect("Failed to write test file");
75
76    println!("Created tests/data/test.bin ({} bytes)", serialized.len());
77
78    // Verify the created file
79    if Eeprom::verify_crc(&serialized) {
80        println!("✅ CRC verification passed");
81    } else {
82        println!("❌ CRC verification failed");
83    }
84}
More examples
Hide additional examples
examples/create_simple.rs (line 60)
12fn main() {
13    println!("📝 Creating minimal EEPROM with basic vendor info...");
14
15    // Create a minimal vendor info atom
16    let vendor_atom = VendorInfoAtom::new(
17        0x5349, // vendor_id (example: "SI" for Simple)
18        0x4D50, // product_id (example: "MP" for MiniProduct)
19        1,      // product_ver
20        "Simple",
21        "MinimalHAT",
22        [
23            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
24            0xEE, 0xFF,
25        ], // Simple UUID
26    );
27
28    // Create minimal GPIO map
29    let gpio_atom = GpioMapAtom {
30        flags: 0x0000,
31        pins: [0u8; 28], // All pins unused
32    };
33
34    // Create EEPROM structure
35    #[cfg(feature = "alloc")]
36    let mut eeprom = Eeprom {
37        header: EepromHeader::new(),
38        vendor_info: vendor_atom,
39        gpio_map_bank0: gpio_atom,
40        dt_blob: None,
41        gpio_map_bank1: None,
42        custom_atoms: Vec::new(),
43    };
44
45    #[cfg(not(feature = "alloc"))]
46    let mut eeprom = Eeprom {
47        header: EepromHeader::new(),
48        vendor_info: vendor_atom,
49        gpio_map_bank0: gpio_atom,
50        dt_blob: None,
51        gpio_map_bank1: None,
52        custom_atoms: &[],
53    };
54
55    // Update header with correct counts and length
56    eeprom.update_header();
57
58    // Serialize with CRC
59    #[cfg(feature = "alloc")]
60    let serialized = eeprom.serialize_with_crc();
61
62    #[cfg(not(feature = "alloc"))]
63    let serialized = {
64        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
65        let size = eeprom
66            .serialize_with_crc_to_slice(&mut buffer)
67            .expect("Failed to serialize EEPROM");
68        &buffer[..size]
69    };
70
71    // Create output directory if it doesn't exist
72    if std::fs::metadata("tests/data").is_err() {
73        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
74    }
75
76    std::fs::write("tests/data/simple.bin", &serialized).expect("Failed to write simple file");
77
78    println!("Created tests/data/simple.bin ({} bytes)", serialized.len());
79
80    // Verify the created file
81    if Eeprom::verify_crc(&serialized) {
82        println!("✅ CRC verification passed");
83    } else {
84        println!("❌ CRC verification failed");
85    }
86}
examples/create_advanced.rs (line 111)
13fn main() {
14    println!("🚀 Creating advanced EEPROM with Device Tree support...");
15
16    // Create a vendor info atom with detailed information
17    let vendor_atom = VendorInfoAtom::new(
18        0x414C, // vendor_id (example: "AL" for AleksejZaharčenko)
19        0x2024, // product_id (year)
20        1,      // product_ver
21        "4STM4 Ocultum",
22        "Advanced HAT Demo",
23        [
24            // UUID for this specific HAT
25            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
26            0x32, 0x10,
27        ],
28    );
29
30    // Create GPIO map for bank 0 with specific pin configurations
31    let mut gpio_pins = [0u8; 28];
32
33    // Configure some pins as outputs (value 1)
34    gpio_pins[18] = 1; // GPIO 18 as output
35    gpio_pins[19] = 1; // GPIO 19 as output
36    gpio_pins[20] = 1; // GPIO 20 as output
37    gpio_pins[21] = 1; // GPIO 21 as output
38
39    // Other pins remain as inputs (value 0)
40
41    let gpio_atom = GpioMapAtom {
42        flags: 0x0001, // Set some flags
43        pins: gpio_pins,
44    };
45
46    // Create a simple Device Tree blob (minimal example)
47    // In real use, this would be a proper compiled device tree
48    let dt_blob_data = b"# Simple Device Tree overlay for demo HAT
49/dts-v1/;
50/plugin/;
51
52/ {
53    compatible = \"brcm,bcm2835\";
54    
55    fragment@0 {
56        target = <&gpio>;
57        __overlay__ {
58            demo_pins: demo_pins {
59                brcm,pins = <18 19 20 21>;
60                brcm,function = <1>; /* GPIO_OUT */
61            };
62        };
63    };
64    
65    fragment@1 {
66        target-path = \"/\";
67        __overlay__ {
68            demo_hat {
69                compatible = \"4stm4,demo-hat\";
70                pinctrl-names = \"default\";
71                pinctrl-0 = <&demo_pins>;
72                status = \"okay\";
73            };
74        };
75    };
76};"
77    .to_vec();
78
79    // Create EEPROM structure with all components
80    #[cfg(feature = "alloc")]
81    let mut eeprom = Eeprom {
82        header: EepromHeader::new(),
83        vendor_info: vendor_atom,
84        gpio_map_bank0: gpio_atom,
85        dt_blob: Some(dt_blob_data), // dt_blob is Option<Vec<u8>>
86        gpio_map_bank1: None,        // Not used in this example
87        custom_atoms: Vec::new(),
88    };
89
90    #[cfg(not(feature = "alloc"))]
91    // Для no_std режима создаем статические данные
92    let mut eeprom = {
93        // Для no_std нам нужны статические данные, это просто заглушка
94        static DT_BLOB_DATA: [u8; 1] = [0];
95        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
96        Eeprom {
97            header: EepromHeader::new(),
98            vendor_info: vendor_atom,
99            gpio_map_bank0: gpio_atom,
100            dt_blob: Some(&DT_BLOB_DATA), // dt_blob is Option<&[u8]> в no_std
101            gpio_map_bank1: None,
102            custom_atoms: &CUSTOM_ATOMS,
103        }
104    };
105
106    // Update header with correct counts and length
107    eeprom.update_header();
108
109    // Serialize with CRC
110    #[cfg(feature = "alloc")]
111    let serialized = eeprom.serialize_with_crc();
112
113    #[cfg(not(feature = "alloc"))]
114    // Создаем буфер и вектор для копирования данных
115    let serialized = {
116        let mut buffer = [0u8; 4096]; // Больший буфер для DT blob
117        let size = eeprom
118            .serialize_with_crc_to_slice(&mut buffer)
119            .expect("Failed to serialize EEPROM");
120        // Копируем данные в новый вектор
121        buffer[..size].to_vec()
122    };
123    let filename = "tests/data/advanced.bin";
124
125    // Create output directory if it doesn't exist
126    if std::fs::metadata("tests/data").is_err() {
127        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
128    }
129
130    std::fs::write(filename, &serialized).expect("Failed to write advanced EEPROM file");
131
132    println!("✅ Created {} ({} bytes)", filename, serialized.len());
133    println!("📊 EEPROM structure:");
134    println!("   • Header: 12 bytes");
135    println!(
136        "   • Vendor Info: {} bytes",
137        std::mem::size_of::<VendorInfoAtom>() + "4STM4 Ocultum".len() + "Advanced HAT Demo".len()
138    );
139    println!(
140        "   • GPIO Map Bank 0: {} bytes",
141        std::mem::size_of::<GpioMapAtom>()
142    );
143    println!(
144        "   • Device Tree Blob: {} bytes",
145        serialized.len()
146            - 12
147            - std::mem::size_of::<VendorInfoAtom>()
148            - "4STM4 Ocultum".len()
149            - "Advanced HAT Demo".len()
150            - std::mem::size_of::<GpioMapAtom>()
151            - 4
152    );
153    println!("   • CRC32: 4 bytes");
154
155    // Verify the created file
156    if Eeprom::verify_crc(&serialized) {
157        println!("✅ CRC32 verification passed");
158    } else {
159        println!("❌ CRC32 verification failed");
160    }
161
162    println!("🎯 Use './target/release/ehatrom show {filename}' to analyze the created EEPROM");
163}
examples/create_custom_atoms.rs (line 109)
12fn main() {
13    println!("📝 Creating EEPROM with custom atoms...");
14
15    // Create a list to hold our custom atoms
16    let mut custom_atoms = Vec::new();
17
18    // Create vendor info atom
19    let vendor_atom = VendorInfoAtom::new(
20        0x4143, // vendor_id "AC" (example)
21        0x0001, // product_id
22        2,      // product_ver
23        "ACME Custom HATs",
24        "SensorBoard Plus",
25        [
26            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
27            0xEE, 0xFF,
28        ], // UUID
29    );
30
31    // Create GPIO map for bank 0 - more complex pin assignments
32    let mut pins = [0u8; 28];
33    pins[4] = 0x01; // GPIO4 - Input
34    pins[17] = 0x02; // GPIO17 - Output
35    pins[18] = 0x02; // GPIO18 - Output
36    pins[22] = 0x01; // GPIO22 - Input
37    pins[23] = 0x01; // GPIO23 - Input
38    pins[24] = 0x02; // GPIO24 - Output
39    pins[25] = 0x02; // GPIO25 - Output
40    let gpio_atom = GpioMapAtom {
41        flags: 0x0000,
42        pins,
43    };
44
45    // Custom atom 1: Configuration string
46    let config_str = "MODE=SENSORS,INTERVAL=250,UNITS=METRIC".to_string();
47    custom_atoms.push((0x81, config_str.into_bytes())); // Using tuple format (type, data)
48
49    // Custom atom 2: Sensor calibration data (example of binary data)
50    let mut sensor_cal = Vec::new();
51    // Temperature offset and gain
52    sensor_cal.extend_from_slice(&((-2.5f32).to_be_bytes()));
53    sensor_cal.extend_from_slice(&(1.03f32.to_be_bytes()));
54    // Humidity offset and gain
55    sensor_cal.extend_from_slice(&(1.2f32.to_be_bytes()));
56    sensor_cal.extend_from_slice(&(0.98f32.to_be_bytes()));
57    // Pressure offset and gain
58    sensor_cal.extend_from_slice(&(15.0f32.to_be_bytes()));
59    sensor_cal.extend_from_slice(&(1.0f32.to_be_bytes()));
60    custom_atoms.push((0x82, sensor_cal)); // Using tuple format (type, data)
61
62    // Custom atom 3: Hardware version info as string
63    let hw_info = format!(
64        "HW_VERSION={}.{}.{},PCB_REV=C,ASSEMBLY_DATE=2024-12-20",
65        env!("CARGO_PKG_VERSION_MAJOR"),
66        env!("CARGO_PKG_VERSION_MINOR"),
67        env!("CARGO_PKG_VERSION_PATCH")
68    );
69    custom_atoms.push((0x83, hw_info.into_bytes())); // Using tuple format (type, data)
70
71    // Custom atom 4: Binary data (e.g., lookup table)
72    let mut lookup_table = Vec::new();
73    for i in 0..32 {
74        lookup_table.push((i * i) as u8); // Simple quadratic lookup table
75    }
76    custom_atoms.push((0x84, lookup_table)); // Using tuple format (type, data)
77
78    // Create EEPROM structure
79    #[cfg(feature = "alloc")]
80    let mut eeprom = Eeprom {
81        header: EepromHeader::new(),
82        vendor_info: vendor_atom,
83        gpio_map_bank0: gpio_atom,
84        dt_blob: None,
85        gpio_map_bank1: None,
86        custom_atoms,
87    };
88
89    #[cfg(not(feature = "alloc"))]
90    // Для no_std режима создаем статические данные
91    let mut eeprom = {
92        // Для no_std нам нужны статические данные, это просто заглушка
93        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
94        Eeprom {
95            header: EepromHeader::new(),
96            vendor_info: vendor_atom,
97            gpio_map_bank0: gpio_atom,
98            dt_blob: None,
99            gpio_map_bank1: None,
100            custom_atoms: &CUSTOM_ATOMS,
101        }
102    };
103
104    // Update header with correct counts and length
105    eeprom.update_header();
106
107    // Serialize with CRC
108    #[cfg(feature = "alloc")]
109    let serialized = eeprom.serialize_with_crc();
110
111    #[cfg(not(feature = "alloc"))]
112    // Создаем буфер и вектор для копирования данных
113    let serialized = {
114        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
115        let size = eeprom
116            .serialize_with_crc_to_slice(&mut buffer)
117            .expect("Failed to serialize EEPROM");
118        // Копируем данные в новый вектор
119        buffer[..size].to_vec()
120    };
121
122    let filename = "tests/data/custom_atoms.bin";
123
124    // Create output directory if it doesn't exist
125    if std::fs::metadata("tests/data").is_err() {
126        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
127    }
128
129    std::fs::write(filename, &serialized).expect("Failed to write custom atoms EEPROM file");
130
131    println!("✅ Created {} ({} bytes)", filename, serialized.len());
132    println!("📊 EEPROM contains:");
133    println!("   • Standard HAT header");
134    println!("   • Vendor info atom");
135    println!("   • GPIO map atom");
136    println!("   • 4 custom atoms:");
137    println!("     - 0x81: Configuration string");
138    println!("     - 0x82: Sensor calibration data");
139    println!("     - 0x83: Hardware version info");
140    println!("     - 0x84: Lookup table (32 bytes)");
141
142    // Verify the created file
143    if Eeprom::verify_crc(&serialized) {
144        println!("✅ CRC32 verification passed");
145    } else {
146        println!("❌ CRC32 verification failed");
147    }
148
149    println!("💡 This demonstrates how to embed custom application-specific data in HAT EEPROM");
150}
Source

pub fn verify_crc(data: &[u8]) -> bool

CRC32 check (expects last 4 bytes to be CRC32 LE)

Examples found in repository?
examples/create_test.rs (line 79)
12fn main() {
13    // Create a vendor info atom
14    let vendor_atom = VendorInfoAtom::new(
15        0x4D4F, // vendor_id (example: "MO")
16        0x1234, // product_id
17        1,      // product_ver
18        "TestVendor",
19        "TestProduct",
20        [
21            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC,
22            0xDE, 0xF0,
23        ], // UUID
24    );
25
26    // Create GPIO map for bank 0
27    let gpio_atom = GpioMapAtom {
28        flags: 0x0000,
29        pins: [0u8; 28], // All pins as inputs
30    };
31
32    // Create EEPROM structure
33    #[cfg(feature = "alloc")]
34    let mut eeprom = Eeprom {
35        header: EepromHeader::new(),
36        vendor_info: vendor_atom,
37        gpio_map_bank0: gpio_atom,
38        dt_blob: None,
39        gpio_map_bank1: None,
40        custom_atoms: Vec::new(),
41    };
42
43    #[cfg(not(feature = "alloc"))]
44    let mut eeprom = Eeprom {
45        header: EepromHeader::new(),
46        vendor_info: vendor_atom,
47        gpio_map_bank0: gpio_atom,
48        dt_blob: None,
49        gpio_map_bank1: None,
50        custom_atoms: &[],
51    };
52
53    // Update header with correct counts and length
54    eeprom.update_header();
55
56    // Serialize with CRC
57    #[cfg(feature = "alloc")]
58    let serialized = eeprom.serialize_with_crc();
59
60    #[cfg(not(feature = "alloc"))]
61    let serialized = {
62        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
63        let size = eeprom
64            .serialize_with_crc_to_slice(&mut buffer)
65            .expect("Failed to serialize EEPROM");
66        &buffer[..size]
67    };
68
69    // Create output directory if it doesn't exist
70    if std::fs::metadata("tests/data").is_err() {
71        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
72    }
73
74    std::fs::write("tests/data/test.bin", &serialized).expect("Failed to write test file");
75
76    println!("Created tests/data/test.bin ({} bytes)", serialized.len());
77
78    // Verify the created file
79    if Eeprom::verify_crc(&serialized) {
80        println!("✅ CRC verification passed");
81    } else {
82        println!("❌ CRC verification failed");
83    }
84}
More examples
Hide additional examples
examples/create_simple.rs (line 81)
12fn main() {
13    println!("📝 Creating minimal EEPROM with basic vendor info...");
14
15    // Create a minimal vendor info atom
16    let vendor_atom = VendorInfoAtom::new(
17        0x5349, // vendor_id (example: "SI" for Simple)
18        0x4D50, // product_id (example: "MP" for MiniProduct)
19        1,      // product_ver
20        "Simple",
21        "MinimalHAT",
22        [
23            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
24            0xEE, 0xFF,
25        ], // Simple UUID
26    );
27
28    // Create minimal GPIO map
29    let gpio_atom = GpioMapAtom {
30        flags: 0x0000,
31        pins: [0u8; 28], // All pins unused
32    };
33
34    // Create EEPROM structure
35    #[cfg(feature = "alloc")]
36    let mut eeprom = Eeprom {
37        header: EepromHeader::new(),
38        vendor_info: vendor_atom,
39        gpio_map_bank0: gpio_atom,
40        dt_blob: None,
41        gpio_map_bank1: None,
42        custom_atoms: Vec::new(),
43    };
44
45    #[cfg(not(feature = "alloc"))]
46    let mut eeprom = Eeprom {
47        header: EepromHeader::new(),
48        vendor_info: vendor_atom,
49        gpio_map_bank0: gpio_atom,
50        dt_blob: None,
51        gpio_map_bank1: None,
52        custom_atoms: &[],
53    };
54
55    // Update header with correct counts and length
56    eeprom.update_header();
57
58    // Serialize with CRC
59    #[cfg(feature = "alloc")]
60    let serialized = eeprom.serialize_with_crc();
61
62    #[cfg(not(feature = "alloc"))]
63    let serialized = {
64        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
65        let size = eeprom
66            .serialize_with_crc_to_slice(&mut buffer)
67            .expect("Failed to serialize EEPROM");
68        &buffer[..size]
69    };
70
71    // Create output directory if it doesn't exist
72    if std::fs::metadata("tests/data").is_err() {
73        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
74    }
75
76    std::fs::write("tests/data/simple.bin", &serialized).expect("Failed to write simple file");
77
78    println!("Created tests/data/simple.bin ({} bytes)", serialized.len());
79
80    // Verify the created file
81    if Eeprom::verify_crc(&serialized) {
82        println!("✅ CRC verification passed");
83    } else {
84        println!("❌ CRC verification failed");
85    }
86}
examples/create_advanced.rs (line 156)
13fn main() {
14    println!("🚀 Creating advanced EEPROM with Device Tree support...");
15
16    // Create a vendor info atom with detailed information
17    let vendor_atom = VendorInfoAtom::new(
18        0x414C, // vendor_id (example: "AL" for AleksejZaharčenko)
19        0x2024, // product_id (year)
20        1,      // product_ver
21        "4STM4 Ocultum",
22        "Advanced HAT Demo",
23        [
24            // UUID for this specific HAT
25            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
26            0x32, 0x10,
27        ],
28    );
29
30    // Create GPIO map for bank 0 with specific pin configurations
31    let mut gpio_pins = [0u8; 28];
32
33    // Configure some pins as outputs (value 1)
34    gpio_pins[18] = 1; // GPIO 18 as output
35    gpio_pins[19] = 1; // GPIO 19 as output
36    gpio_pins[20] = 1; // GPIO 20 as output
37    gpio_pins[21] = 1; // GPIO 21 as output
38
39    // Other pins remain as inputs (value 0)
40
41    let gpio_atom = GpioMapAtom {
42        flags: 0x0001, // Set some flags
43        pins: gpio_pins,
44    };
45
46    // Create a simple Device Tree blob (minimal example)
47    // In real use, this would be a proper compiled device tree
48    let dt_blob_data = b"# Simple Device Tree overlay for demo HAT
49/dts-v1/;
50/plugin/;
51
52/ {
53    compatible = \"brcm,bcm2835\";
54    
55    fragment@0 {
56        target = <&gpio>;
57        __overlay__ {
58            demo_pins: demo_pins {
59                brcm,pins = <18 19 20 21>;
60                brcm,function = <1>; /* GPIO_OUT */
61            };
62        };
63    };
64    
65    fragment@1 {
66        target-path = \"/\";
67        __overlay__ {
68            demo_hat {
69                compatible = \"4stm4,demo-hat\";
70                pinctrl-names = \"default\";
71                pinctrl-0 = <&demo_pins>;
72                status = \"okay\";
73            };
74        };
75    };
76};"
77    .to_vec();
78
79    // Create EEPROM structure with all components
80    #[cfg(feature = "alloc")]
81    let mut eeprom = Eeprom {
82        header: EepromHeader::new(),
83        vendor_info: vendor_atom,
84        gpio_map_bank0: gpio_atom,
85        dt_blob: Some(dt_blob_data), // dt_blob is Option<Vec<u8>>
86        gpio_map_bank1: None,        // Not used in this example
87        custom_atoms: Vec::new(),
88    };
89
90    #[cfg(not(feature = "alloc"))]
91    // Для no_std режима создаем статические данные
92    let mut eeprom = {
93        // Для no_std нам нужны статические данные, это просто заглушка
94        static DT_BLOB_DATA: [u8; 1] = [0];
95        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
96        Eeprom {
97            header: EepromHeader::new(),
98            vendor_info: vendor_atom,
99            gpio_map_bank0: gpio_atom,
100            dt_blob: Some(&DT_BLOB_DATA), // dt_blob is Option<&[u8]> в no_std
101            gpio_map_bank1: None,
102            custom_atoms: &CUSTOM_ATOMS,
103        }
104    };
105
106    // Update header with correct counts and length
107    eeprom.update_header();
108
109    // Serialize with CRC
110    #[cfg(feature = "alloc")]
111    let serialized = eeprom.serialize_with_crc();
112
113    #[cfg(not(feature = "alloc"))]
114    // Создаем буфер и вектор для копирования данных
115    let serialized = {
116        let mut buffer = [0u8; 4096]; // Больший буфер для DT blob
117        let size = eeprom
118            .serialize_with_crc_to_slice(&mut buffer)
119            .expect("Failed to serialize EEPROM");
120        // Копируем данные в новый вектор
121        buffer[..size].to_vec()
122    };
123    let filename = "tests/data/advanced.bin";
124
125    // Create output directory if it doesn't exist
126    if std::fs::metadata("tests/data").is_err() {
127        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
128    }
129
130    std::fs::write(filename, &serialized).expect("Failed to write advanced EEPROM file");
131
132    println!("✅ Created {} ({} bytes)", filename, serialized.len());
133    println!("📊 EEPROM structure:");
134    println!("   • Header: 12 bytes");
135    println!(
136        "   • Vendor Info: {} bytes",
137        std::mem::size_of::<VendorInfoAtom>() + "4STM4 Ocultum".len() + "Advanced HAT Demo".len()
138    );
139    println!(
140        "   • GPIO Map Bank 0: {} bytes",
141        std::mem::size_of::<GpioMapAtom>()
142    );
143    println!(
144        "   • Device Tree Blob: {} bytes",
145        serialized.len()
146            - 12
147            - std::mem::size_of::<VendorInfoAtom>()
148            - "4STM4 Ocultum".len()
149            - "Advanced HAT Demo".len()
150            - std::mem::size_of::<GpioMapAtom>()
151            - 4
152    );
153    println!("   • CRC32: 4 bytes");
154
155    // Verify the created file
156    if Eeprom::verify_crc(&serialized) {
157        println!("✅ CRC32 verification passed");
158    } else {
159        println!("❌ CRC32 verification failed");
160    }
161
162    println!("🎯 Use './target/release/ehatrom show {filename}' to analyze the created EEPROM");
163}
examples/create_custom_atoms.rs (line 143)
12fn main() {
13    println!("📝 Creating EEPROM with custom atoms...");
14
15    // Create a list to hold our custom atoms
16    let mut custom_atoms = Vec::new();
17
18    // Create vendor info atom
19    let vendor_atom = VendorInfoAtom::new(
20        0x4143, // vendor_id "AC" (example)
21        0x0001, // product_id
22        2,      // product_ver
23        "ACME Custom HATs",
24        "SensorBoard Plus",
25        [
26            0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
27            0xEE, 0xFF,
28        ], // UUID
29    );
30
31    // Create GPIO map for bank 0 - more complex pin assignments
32    let mut pins = [0u8; 28];
33    pins[4] = 0x01; // GPIO4 - Input
34    pins[17] = 0x02; // GPIO17 - Output
35    pins[18] = 0x02; // GPIO18 - Output
36    pins[22] = 0x01; // GPIO22 - Input
37    pins[23] = 0x01; // GPIO23 - Input
38    pins[24] = 0x02; // GPIO24 - Output
39    pins[25] = 0x02; // GPIO25 - Output
40    let gpio_atom = GpioMapAtom {
41        flags: 0x0000,
42        pins,
43    };
44
45    // Custom atom 1: Configuration string
46    let config_str = "MODE=SENSORS,INTERVAL=250,UNITS=METRIC".to_string();
47    custom_atoms.push((0x81, config_str.into_bytes())); // Using tuple format (type, data)
48
49    // Custom atom 2: Sensor calibration data (example of binary data)
50    let mut sensor_cal = Vec::new();
51    // Temperature offset and gain
52    sensor_cal.extend_from_slice(&((-2.5f32).to_be_bytes()));
53    sensor_cal.extend_from_slice(&(1.03f32.to_be_bytes()));
54    // Humidity offset and gain
55    sensor_cal.extend_from_slice(&(1.2f32.to_be_bytes()));
56    sensor_cal.extend_from_slice(&(0.98f32.to_be_bytes()));
57    // Pressure offset and gain
58    sensor_cal.extend_from_slice(&(15.0f32.to_be_bytes()));
59    sensor_cal.extend_from_slice(&(1.0f32.to_be_bytes()));
60    custom_atoms.push((0x82, sensor_cal)); // Using tuple format (type, data)
61
62    // Custom atom 3: Hardware version info as string
63    let hw_info = format!(
64        "HW_VERSION={}.{}.{},PCB_REV=C,ASSEMBLY_DATE=2024-12-20",
65        env!("CARGO_PKG_VERSION_MAJOR"),
66        env!("CARGO_PKG_VERSION_MINOR"),
67        env!("CARGO_PKG_VERSION_PATCH")
68    );
69    custom_atoms.push((0x83, hw_info.into_bytes())); // Using tuple format (type, data)
70
71    // Custom atom 4: Binary data (e.g., lookup table)
72    let mut lookup_table = Vec::new();
73    for i in 0..32 {
74        lookup_table.push((i * i) as u8); // Simple quadratic lookup table
75    }
76    custom_atoms.push((0x84, lookup_table)); // Using tuple format (type, data)
77
78    // Create EEPROM structure
79    #[cfg(feature = "alloc")]
80    let mut eeprom = Eeprom {
81        header: EepromHeader::new(),
82        vendor_info: vendor_atom,
83        gpio_map_bank0: gpio_atom,
84        dt_blob: None,
85        gpio_map_bank1: None,
86        custom_atoms,
87    };
88
89    #[cfg(not(feature = "alloc"))]
90    // Для no_std режима создаем статические данные
91    let mut eeprom = {
92        // Для no_std нам нужны статические данные, это просто заглушка
93        static CUSTOM_ATOMS: [(u8, &[u8]); 0] = [];
94        Eeprom {
95            header: EepromHeader::new(),
96            vendor_info: vendor_atom,
97            gpio_map_bank0: gpio_atom,
98            dt_blob: None,
99            gpio_map_bank1: None,
100            custom_atoms: &CUSTOM_ATOMS,
101        }
102    };
103
104    // Update header with correct counts and length
105    eeprom.update_header();
106
107    // Serialize with CRC
108    #[cfg(feature = "alloc")]
109    let serialized = eeprom.serialize_with_crc();
110
111    #[cfg(not(feature = "alloc"))]
112    // Создаем буфер и вектор для копирования данных
113    let serialized = {
114        let mut buffer = [0u8; 1024]; // Буфер достаточного размера
115        let size = eeprom
116            .serialize_with_crc_to_slice(&mut buffer)
117            .expect("Failed to serialize EEPROM");
118        // Копируем данные в новый вектор
119        buffer[..size].to_vec()
120    };
121
122    let filename = "tests/data/custom_atoms.bin";
123
124    // Create output directory if it doesn't exist
125    if std::fs::metadata("tests/data").is_err() {
126        std::fs::create_dir_all("tests/data").expect("Failed to create tests/data directory");
127    }
128
129    std::fs::write(filename, &serialized).expect("Failed to write custom atoms EEPROM file");
130
131    println!("✅ Created {} ({} bytes)", filename, serialized.len());
132    println!("📊 EEPROM contains:");
133    println!("   • Standard HAT header");
134    println!("   • Vendor info atom");
135    println!("   • GPIO map atom");
136    println!("   • 4 custom atoms:");
137    println!("     - 0x81: Configuration string");
138    println!("     - 0x82: Sensor calibration data");
139    println!("     - 0x83: Hardware version info");
140    println!("     - 0x84: Lookup table (32 bytes)");
141
142    // Verify the created file
143    if Eeprom::verify_crc(&serialized) {
144        println!("✅ CRC32 verification passed");
145    } else {
146        println!("❌ CRC32 verification failed");
147    }
148
149    println!("💡 This demonstrates how to embed custom application-specific data in HAT EEPROM");
150}
Source

pub fn serialize(&self) -> Vec<u8>

Serialize EEPROM structure to Vec<u8> (without CRC)

Examples found in repository?
examples/bare_metal_example.rs (line 72)
16fn main() {
17    // This example demonstrates how to use ehatrom in a bare-metal environment
18    // without heap allocation
19
20    // Create EEPROM structure with static data
21    let vendor_info = VendorInfoAtom::new(
22        0x0001, // vendor_id
23        0x0002, // product_id
24        0x0001, // product_ver
25        "Acme Corp",
26        "Test HAT",
27        [
28            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
29            0x77, 0x88,
30        ],
31    );
32
33    let gpio_map = GpioMapAtom {
34        flags: 0x0001,
35        pins: [0; 28], // All pins disabled
36    };
37
38    // Custom atoms with static data
39    static CUSTOM_DATA: &[u8] = b"Hello, Bare Metal!";
40
41    // In no_std environment, custom_atoms would be a static slice
42    #[cfg(not(feature = "alloc"))]
43    static CUSTOM_ATOMS: &[(u8, &[u8])] = &[(0x80, CUSTOM_DATA)];
44
45    #[cfg(feature = "alloc")]
46    let custom_atoms = vec![(0x80u8, CUSTOM_DATA.to_vec())];
47
48    let mut eeprom = Eeprom {
49        header: EepromHeader::new(),
50        vendor_info,
51        gpio_map_bank0: gpio_map,
52        dt_blob: None,
53        gpio_map_bank1: None,
54        #[cfg(feature = "alloc")]
55        custom_atoms,
56        #[cfg(not(feature = "alloc"))]
57        custom_atoms: CUSTOM_ATOMS,
58    };
59
60    eeprom.update_header();
61
62    // Calculate required buffer size
63    let buffer_size = eeprom.calculate_serialized_size();
64    println!("Required buffer size: {buffer_size} bytes");
65
66    // Serialize to fixed buffer (demonstrates no heap allocation approach)
67    let mut buffer = vec![0u8; 512]; // In real no_std, this would be a static array
68
69    #[cfg(feature = "alloc")]
70    {
71        // Standard allocation-based serialization
72        let serialized = eeprom.serialize();
73        println!("Serialized {} bytes using Vec", serialized.len());
74    }
75
76    // Demonstrate no-allocation serialization (available in both std and no_std)
77    let mut offset = 0;
78    match eeprom.serialize_to_buffer(&mut buffer, &mut offset) {
79        Ok(()) => {
80            println!("Successfully serialized {offset} bytes to buffer");
81            println!("First 16 bytes: {:02X?}", &buffer[..16.min(offset)]);
82        }
83        Err(e) => {
84            println!("Serialization failed: {e:?}");
85        }
86    }
87
88    println!("EEPROM structure:\n{eeprom}");
89}
Source

pub fn serialize_to_slice_universal( &self, buffer: &mut [u8], ) -> Result<usize, EhatromError>

Serialize EEPROM structure to buffer (universal version)

Source

pub fn calculate_serialized_size(&self) -> usize

Helper method to calculate total serialized size

Examples found in repository?
examples/bare_metal_example.rs (line 63)
16fn main() {
17    // This example demonstrates how to use ehatrom in a bare-metal environment
18    // without heap allocation
19
20    // Create EEPROM structure with static data
21    let vendor_info = VendorInfoAtom::new(
22        0x0001, // vendor_id
23        0x0002, // product_id
24        0x0001, // product_ver
25        "Acme Corp",
26        "Test HAT",
27        [
28            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
29            0x77, 0x88,
30        ],
31    );
32
33    let gpio_map = GpioMapAtom {
34        flags: 0x0001,
35        pins: [0; 28], // All pins disabled
36    };
37
38    // Custom atoms with static data
39    static CUSTOM_DATA: &[u8] = b"Hello, Bare Metal!";
40
41    // In no_std environment, custom_atoms would be a static slice
42    #[cfg(not(feature = "alloc"))]
43    static CUSTOM_ATOMS: &[(u8, &[u8])] = &[(0x80, CUSTOM_DATA)];
44
45    #[cfg(feature = "alloc")]
46    let custom_atoms = vec![(0x80u8, CUSTOM_DATA.to_vec())];
47
48    let mut eeprom = Eeprom {
49        header: EepromHeader::new(),
50        vendor_info,
51        gpio_map_bank0: gpio_map,
52        dt_blob: None,
53        gpio_map_bank1: None,
54        #[cfg(feature = "alloc")]
55        custom_atoms,
56        #[cfg(not(feature = "alloc"))]
57        custom_atoms: CUSTOM_ATOMS,
58    };
59
60    eeprom.update_header();
61
62    // Calculate required buffer size
63    let buffer_size = eeprom.calculate_serialized_size();
64    println!("Required buffer size: {buffer_size} bytes");
65
66    // Serialize to fixed buffer (demonstrates no heap allocation approach)
67    let mut buffer = vec![0u8; 512]; // In real no_std, this would be a static array
68
69    #[cfg(feature = "alloc")]
70    {
71        // Standard allocation-based serialization
72        let serialized = eeprom.serialize();
73        println!("Serialized {} bytes using Vec", serialized.len());
74    }
75
76    // Demonstrate no-allocation serialization (available in both std and no_std)
77    let mut offset = 0;
78    match eeprom.serialize_to_buffer(&mut buffer, &mut offset) {
79        Ok(()) => {
80            println!("Successfully serialized {offset} bytes to buffer");
81            println!("First 16 bytes: {:02X?}", &buffer[..16.min(offset)]);
82        }
83        Err(e) => {
84            println!("Serialization failed: {e:?}");
85        }
86    }
87
88    println!("EEPROM structure:\n{eeprom}");
89}
Source

pub fn serialize_to_buffer( &self, buffer: &mut [u8], offset: &mut usize, ) -> Result<(), EhatromError>

Internal method to serialize into buffer (no_std version)

Examples found in repository?
examples/bare_metal_example.rs (line 78)
16fn main() {
17    // This example demonstrates how to use ehatrom in a bare-metal environment
18    // without heap allocation
19
20    // Create EEPROM structure with static data
21    let vendor_info = VendorInfoAtom::new(
22        0x0001, // vendor_id
23        0x0002, // product_id
24        0x0001, // product_ver
25        "Acme Corp",
26        "Test HAT",
27        [
28            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
29            0x77, 0x88,
30        ],
31    );
32
33    let gpio_map = GpioMapAtom {
34        flags: 0x0001,
35        pins: [0; 28], // All pins disabled
36    };
37
38    // Custom atoms with static data
39    static CUSTOM_DATA: &[u8] = b"Hello, Bare Metal!";
40
41    // In no_std environment, custom_atoms would be a static slice
42    #[cfg(not(feature = "alloc"))]
43    static CUSTOM_ATOMS: &[(u8, &[u8])] = &[(0x80, CUSTOM_DATA)];
44
45    #[cfg(feature = "alloc")]
46    let custom_atoms = vec![(0x80u8, CUSTOM_DATA.to_vec())];
47
48    let mut eeprom = Eeprom {
49        header: EepromHeader::new(),
50        vendor_info,
51        gpio_map_bank0: gpio_map,
52        dt_blob: None,
53        gpio_map_bank1: None,
54        #[cfg(feature = "alloc")]
55        custom_atoms,
56        #[cfg(not(feature = "alloc"))]
57        custom_atoms: CUSTOM_ATOMS,
58    };
59
60    eeprom.update_header();
61
62    // Calculate required buffer size
63    let buffer_size = eeprom.calculate_serialized_size();
64    println!("Required buffer size: {buffer_size} bytes");
65
66    // Serialize to fixed buffer (demonstrates no heap allocation approach)
67    let mut buffer = vec![0u8; 512]; // In real no_std, this would be a static array
68
69    #[cfg(feature = "alloc")]
70    {
71        // Standard allocation-based serialization
72        let serialized = eeprom.serialize();
73        println!("Serialized {} bytes using Vec", serialized.len());
74    }
75
76    // Demonstrate no-allocation serialization (available in both std and no_std)
77    let mut offset = 0;
78    match eeprom.serialize_to_buffer(&mut buffer, &mut offset) {
79        Ok(()) => {
80            println!("Successfully serialized {offset} bytes to buffer");
81            println!("First 16 bytes: {:02X?}", &buffer[..16.min(offset)]);
82        }
83        Err(e) => {
84            println!("Serialization failed: {e:?}");
85        }
86    }
87
88    println!("EEPROM structure:\n{eeprom}");
89}
Source

pub fn set_version(&mut self, version: u8)

Trait Implementations§

Source§

impl Clone for Eeprom

Source§

fn clone(&self) -> Eeprom

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Eeprom

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Eeprom

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Eeprom

§

impl RefUnwindSafe for Eeprom

§

impl Send for Eeprom

§

impl Sync for Eeprom

§

impl Unpin for Eeprom

§

impl UnwindSafe for Eeprom

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.