Nav apraksta
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

main.rs 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #![no_main]
  2. #![no_std]
  3. mod display;
  4. mod information;
  5. mod pins;
  6. mod radio;
  7. mod sensors;
  8. // TODO: Enable warnings again.
  9. #[allow(unused)]
  10. mod assets {
  11. include!(concat!(env!("OUT_DIR"), "/assets.rs"));
  12. }
  13. use mkl25z4_hal::clocks::ClockConfiguration;
  14. use mkl25z4_hal::time::{CopyableMonoTimer, NonCopyableMonoTimer, U32Ext};
  15. use panic_semihosting as _;
  16. use display::{Display, DisplayState};
  17. use information::{Information, TemperatureHumidity};
  18. use pins::{BME280Pins, DisplayBmeSpi};
  19. use radio::Radio;
  20. #[rtfm::app(device = mkl25z4_hal::mkl25z4, peripherals = true)]
  21. const APP: () = {
  22. struct Resources {
  23. info: Information,
  24. display_state: DisplayState,
  25. display: Display,
  26. display_bme_spi: Option<DisplayBmeSpi>,
  27. bme_pins: Option<BME280Pins>,
  28. radio: Option<Radio>,
  29. time: CopyableMonoTimer,
  30. }
  31. #[init(spawn = [fetch_update])]
  32. fn init(ctx: init::Context) -> init::LateResources {
  33. let mut sim = ctx.device.SIM;
  34. mkl25z4_hal::watchdog::disable(&mut sim);
  35. let clocks = ClockConfiguration::new()
  36. .use_irc()
  37. .core_clock(24.mhz())
  38. .bus_clock(24.mhz())
  39. .apply(&mut sim, ctx.device.OSC0, ctx.device.MCG);
  40. let mut pins = pins::Pins::configure(
  41. &mut sim,
  42. clocks,
  43. ctx.device.GPIOA,
  44. ctx.device.GPIOB,
  45. ctx.device.GPIOC,
  46. ctx.device.GPIOD,
  47. ctx.device.GPIOE,
  48. ctx.device.SPI0,
  49. ctx.device.SPI1,
  50. );
  51. let time =
  52. CopyableMonoTimer::new(NonCopyableMonoTimer::new(ctx.device.PIT, clocks, &mut sim));
  53. let display = Display::init(pins.display, &mut pins.display_bme_spi, time);
  54. let radio = Radio::init(pins.nrf, time);
  55. // Fetch the first update.
  56. ctx.spawn.fetch_update().ok();
  57. init::LateResources {
  58. info: Information {
  59. time: 0,
  60. valid: false,
  61. inside: None,
  62. outside: None,
  63. bathroom: None,
  64. pressure: None,
  65. },
  66. display_state: DisplayState{
  67. // TODO
  68. },
  69. display,
  70. display_bme_spi: Some(pins.display_bme_spi),
  71. bme_pins: Some(pins.bme),
  72. radio: Some(radio),
  73. time,
  74. }
  75. }
  76. #[task(binds = LPTMR0, priority = 3, spawn = [fetch_update])]
  77. fn lptmr0_interrupt(ctx: lptmr0_interrupt::Context) {
  78. // Restart the timer.
  79. // TODO
  80. // Trigger an update of the displayed values.
  81. ctx.spawn.fetch_update().ok();
  82. }
  83. #[task(binds = LLWU, priority = 3)]
  84. fn llwu_interrupt(_: llwu_interrupt::Context) {
  85. // TODO
  86. }
  87. #[task(priority = 1, spawn = [update_display], resources = [info, bme_pins, display_bme_spi, &time, radio])]
  88. fn fetch_update(mut ctx: fetch_update::Context) {
  89. // Fetch local updates.
  90. let time = ctx.resources.time.clone();
  91. let pins = ctx.resources.bme_pins.take().unwrap();
  92. let (pins, values) = ctx.resources.display_bme_spi.lock(|display_bme_spi| {
  93. let spi = display_bme_spi.take().unwrap();
  94. let (pins, spi, values) = sensors::bme280(pins, spi, time);
  95. *display_bme_spi = Some(spi);
  96. (pins, values)
  97. });
  98. *ctx.resources.bme_pins = Some(pins);
  99. // Send local measurements to the base station. This needs to be done before fetching data
  100. // from the base station as the base station might return the data to us.
  101. let mut radio = ctx.resources.radio.as_mut().unwrap().enable();
  102. radio.send_sensor_values(values);
  103. // TODO
  104. // Fetch updates via radio.
  105. // TODO
  106. ctx.resources.info.lock(|info| {
  107. info.inside = Some(TemperatureHumidity {
  108. temperature: values.temperature,
  109. humidity: values.humidity,
  110. });
  111. info.pressure = Some(values.pressure);
  112. });
  113. // If the update failed, simply increment the time and place a hint that
  114. // the information might be invalid.
  115. // TODO
  116. // Update the display to show the new values.
  117. ctx.spawn.update_display().ok();
  118. }
  119. #[task(priority = 2, resources = [info, display_state, display, display_bme_spi, &time])]
  120. fn update_display(ctx: update_display::Context) {
  121. ctx.resources.display.update(
  122. &ctx.resources.display_state,
  123. &ctx.resources.info,
  124. ctx.resources.display_bme_spi.as_mut().unwrap(),
  125. ctx.resources.time.clone(),
  126. );
  127. }
  128. #[idle]
  129. fn idle(_cx: idle::Context) -> ! {
  130. // Sleep
  131. loop {
  132. // wfi needs to be disabled for GDB
  133. /*// add some side effect to prevent this from turning into a UDF instruction
  134. // see rust-lang/rust#28728 for details
  135. atomic::compiler_fence(Ordering::SeqCst);*/
  136. cortex_m::asm::wfi();
  137. }
  138. }
  139. extern "C" {
  140. fn I2C0();
  141. fn I2C1();
  142. }
  143. };