/ firmware / tests / system.rs
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  }