system.rs
1 //! `describe("System")` 2 //! 3 //! Hardware observability tests — mirrors C++ `hardware/system_test.cpp`. 4 //! Tests what the hardware reports: heap, CPU frequency, chip version, 5 //! reset reason. 6 7 #![no_std] 8 #![no_main] 9 10 #[path = "common/mod.rs"] 11 mod common; 12 13 use defmt::info; 14 15 use common::Device; 16 17 esp_bootloader_esp_idf::esp_app_desc!(); 18 19 #[cfg(test)] 20 #[embedded_test::setup] 21 fn setup() { 22 rtt_target::rtt_init_defmt!(); 23 } 24 25 #[cfg(test)] 26 #[embedded_test::tests(default_timeout = 15, executor = esp_rtos::embassy::Executor::new())] 27 mod tests { 28 use super::*; 29 30 #[init] 31 fn init() -> Device { 32 info!("=== System — describe block ==="); 33 common::setup::boot_device() 34 } 35 36 /// `it("user observes heap reports free memory")` 37 #[test] 38 async fn user_observes_heap_reports_free_memory( 39 _device: Device, 40 ) -> Result<(), &'static str> { 41 let free = esp_alloc::HEAP.free(); 42 let used = esp_alloc::HEAP.used(); 43 let total = free + used; 44 45 info!( 46 "heap: free={=usize} used={=usize} total={=usize} KiB", 47 free / 1024, 48 used / 1024, 49 total / 1024 50 ); 51 52 defmt::assert!(free > 0, "heap reports zero free bytes"); 53 defmt::assert!(total >= 64 * 1024, "heap total below 64 KiB minimum"); 54 Ok(()) 55 } 56 57 /// `it("user observes CPU frequency is 240 MHz")` 58 #[test] 59 async fn user_observes_cpu_frequency_is_240_mhz( 60 _device: Device, 61 ) -> Result<(), &'static str> { 62 let cpu_hz = esp_hal::clock::cpu_clock().as_hz(); 63 let cpu_mhz = cpu_hz / 1_000_000; 64 65 info!("CPU: {=u32} MHz", cpu_mhz); 66 67 defmt::assert_eq!(cpu_mhz, 240, "ESP32-S3 should run at 240 MHz"); 68 Ok(()) 69 } 70 71 /// `it("user observes chip version is readable")` 72 #[test] 73 async fn user_observes_chip_version_is_readable( 74 _device: Device, 75 ) -> Result<(), &'static str> { 76 let major = esp_hal::efuse::major_chip_version(); 77 let minor = esp_hal::efuse::minor_chip_version(); 78 79 info!("chip version: major={=u8} minor={=u8}", major, minor); 80 81 defmt::assert!(major > 0 || minor > 0, "chip version is 0.0"); 82 Ok(()) 83 } 84 85 /// `it("user observes reset reason is available")` 86 #[test] 87 async fn user_observes_reset_reason_is_available( 88 _device: Device, 89 ) -> Result<(), &'static str> { 90 let reason = esp_hal::system::reset_reason(); 91 92 defmt::assert!(reason.is_some(), "reset reason is None"); 93 info!("reset reason is present"); 94 Ok(()) 95 } 96 97 /// `it("user observes chip identity matches ESP32-S3")` 98 #[test] 99 async fn user_observes_chip_identity( 100 _device: Device, 101 ) -> Result<(), &'static str> { 102 let chip = esp_hal::chip!(); 103 104 info!("chip={=str}", chip); 105 106 defmt::assert_eq!(chip, "esp32s3"); 107 Ok(()) 108 } 109 110 /// `it("user observes firmware app descriptor is valid")` 111 #[test] 112 async fn user_observes_app_descriptor_is_valid( 113 _device: Device, 114 ) -> Result<(), &'static str> { 115 defmt::assert_eq!(ESP_APP_DESC.magic_word(), 0xABCD5432, "bad magic word"); 116 117 let version = ESP_APP_DESC.version(); 118 let project = ESP_APP_DESC.project_name(); 119 let idf_ver = ESP_APP_DESC.idf_ver(); 120 let build_time = ESP_APP_DESC.time(); 121 let build_date = ESP_APP_DESC.date(); 122 123 info!("version={=str} project={=str} idf={=str}", version, project, idf_ver); 124 info!("build_time={=str} build_date={=str}", build_time, build_date); 125 126 defmt::assert!(!version.is_empty(), "version is empty"); 127 defmt::assert!(!project.is_empty(), "project name is empty"); 128 defmt::assert!(!idf_ver.is_empty(), "idf version is empty"); 129 Ok(()) 130 } 131 132 // Chip temperature: esp-hal tsens module not available for ESP32-S3. 133 // C++ uses Arduino's temperatureRead() which comes from ESP-IDF. 134 }