1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
16use components::gpio::GpioComponent;
17use kernel::capabilities;
18use kernel::component::Component;
19use kernel::hil::led::LedHigh;
20use kernel::platform::{KernelResources, SyscallDriverLookup};
21use kernel::process::ProcessArray;
22use kernel::scheduler::round_robin::RoundRobinSched;
23use kernel::{create_capability, debug, static_init};
24
25use stm32f429zi::chip_specs::Stm32f429Specs;
26use stm32f429zi::clocks::hsi::HSI_FREQUENCY_MHZ;
27use stm32f429zi::gpio::{AlternateFunction, Mode, PinId, PortId};
28use stm32f429zi::interrupt_service::Stm32f429ziDefaultPeripherals;
29
30pub mod io;
32
33const NUM_PROCS: usize = 4;
35
36static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
38static mut CHIP: Option<&'static stm32f429zi::chip::Stm32f4xx<Stm32f429ziDefaultPeripherals>> =
39 None;
40static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
41 None;
42
43const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
45 capsules_system::process_policies::PanicFaultPolicy {};
46
47kernel::stack_size! {0x2000}
48
49type TemperatureSTMSensor = components::temperature_stm::TemperatureSTMComponentType<
50 capsules_core::virtualizers::virtual_adc::AdcDevice<'static, stm32f429zi::adc::Adc<'static>>,
51>;
52type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureSTMSensor>;
53
54struct STM32F429IDiscovery {
57 console: &'static capsules_core::console::Console<'static>,
58 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
59 led: &'static capsules_core::led::LedDriver<
60 'static,
61 LedHigh<'static, stm32f429zi::gpio::Pin<'static>>,
62 4,
63 >,
64 button: &'static capsules_core::button::Button<'static, stm32f429zi::gpio::Pin<'static>>,
65 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
66 alarm: &'static capsules_core::alarm::AlarmDriver<
67 'static,
68 VirtualMuxAlarm<'static, stm32f429zi::tim2::Tim2<'static>>,
69 >,
70 temperature: &'static TemperatureDriver,
71 gpio: &'static capsules_core::gpio::GPIO<'static, stm32f429zi::gpio::Pin<'static>>,
72
73 scheduler: &'static RoundRobinSched<'static>,
74 systick: cortexm4::systick::SysTick,
75}
76
77impl SyscallDriverLookup for STM32F429IDiscovery {
79 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
80 where
81 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
82 {
83 match driver_num {
84 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
85 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
86 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
87 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
88 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
89 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
90 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
91 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
92 _ => f(None),
93 }
94 }
95}
96
97impl
98 KernelResources<
99 stm32f429zi::chip::Stm32f4xx<
100 'static,
101 stm32f429zi::interrupt_service::Stm32f429ziDefaultPeripherals<'static>,
102 >,
103 > for STM32F429IDiscovery
104{
105 type SyscallDriverLookup = Self;
106 type SyscallFilter = ();
107 type ProcessFault = ();
108 type Scheduler = RoundRobinSched<'static>;
109 type SchedulerTimer = cortexm4::systick::SysTick;
110 type WatchDog = ();
111 type ContextSwitchCallback = ();
112
113 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
114 self
115 }
116 fn syscall_filter(&self) -> &Self::SyscallFilter {
117 &()
118 }
119 fn process_fault(&self) -> &Self::ProcessFault {
120 &()
121 }
122 fn scheduler(&self) -> &Self::Scheduler {
123 self.scheduler
124 }
125 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
126 &self.systick
127 }
128 fn watchdog(&self) -> &Self::WatchDog {
129 &()
130 }
131 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
132 &()
133 }
134}
135
136unsafe fn setup_dma(
138 dma: &stm32f429zi::dma::Dma2,
139 dma_streams: &'static [stm32f429zi::dma::Stream<'static, stm32f429zi::dma::Dma2>; 8],
140 usart1: &'static stm32f429zi::usart::Usart<stm32f429zi::dma::Dma2>,
141) {
142 use stm32f429zi::dma::Dma2Peripheral;
143 use stm32f429zi::usart;
144
145 dma.enable_clock();
146
147 let usart1_tx_stream = &dma_streams[Dma2Peripheral::USART1_TX.get_stream_idx()];
148 let usart1_rx_stream = &dma_streams[Dma2Peripheral::USART1_RX.get_stream_idx()];
149
150 usart1.set_dma(
151 usart::TxDMA(usart1_tx_stream),
152 usart::RxDMA(usart1_rx_stream),
153 );
154
155 usart1_tx_stream.set_client(usart1);
156 usart1_rx_stream.set_client(usart1);
157
158 usart1_tx_stream.setup(Dma2Peripheral::USART1_TX);
159 usart1_rx_stream.setup(Dma2Peripheral::USART1_RX);
160
161 cortexm4::nvic::Nvic::new(Dma2Peripheral::USART1_TX.get_stream_irqn()).enable();
162 cortexm4::nvic::Nvic::new(Dma2Peripheral::USART1_RX.get_stream_irqn()).enable();
163}
164
165unsafe fn set_pin_primary_functions(
167 syscfg: &stm32f429zi::syscfg::Syscfg,
168 gpio_ports: &'static stm32f429zi::gpio::GpioPorts<'static>,
169) {
170 use kernel::hil::gpio::Configure;
171
172 syscfg.enable_clock();
173
174 gpio_ports.get_port_from_port_id(PortId::G).enable_clock();
175
176 gpio_ports.get_pin(PinId::PG14).map(|pin| {
178 pin.make_output();
179
180 kernel::debug::assign_gpios(Some(pin), None, None);
182 });
183
184 gpio_ports.get_port_from_port_id(PortId::A).enable_clock();
185
186 gpio_ports.get_pin(PinId::PA09).map(|pin| {
189 pin.set_mode(Mode::AlternateFunctionMode);
190 pin.set_alternate_function(AlternateFunction::AF7);
192 });
193 gpio_ports.get_pin(PinId::PA10).map(|pin| {
194 pin.set_mode(Mode::AlternateFunctionMode);
195 pin.set_alternate_function(AlternateFunction::AF7);
197 });
198
199 gpio_ports.get_pin(PinId::PA00).map(|pin| {
201 pin.enable_interrupt();
207 });
208 cortexm4::nvic::Nvic::new(stm32f429zi::nvic::EXTI0).enable(); gpio_ports.get_port_from_port_id(PortId::B).enable_clock();
216 gpio_ports.get_port_from_port_id(PortId::C).enable_clock();
217 gpio_ports.get_port_from_port_id(PortId::D).enable_clock();
218 gpio_ports.get_port_from_port_id(PortId::E).enable_clock();
219 gpio_ports.get_port_from_port_id(PortId::F).enable_clock();
220 gpio_ports.get_port_from_port_id(PortId::H).enable_clock();
222
223 gpio_ports.get_pin(PinId::PA03).map(|pin| {
225 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
226 });
227
228 gpio_ports.get_pin(PinId::PC00).map(|pin| {
230 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
231 });
232
233 gpio_ports.get_pin(PinId::PC03).map(|pin| {
235 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
236 });
237
238 gpio_ports.get_pin(PinId::PF03).map(|pin| {
240 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
241 });
242
243 gpio_ports.get_pin(PinId::PF05).map(|pin| {
245 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
246 });
247
248 gpio_ports.get_pin(PinId::PF10).map(|pin| {
250 pin.set_mode(stm32f429zi::gpio::Mode::AnalogMode);
251 });
252}
253
254unsafe fn setup_peripherals(tim2: &stm32f429zi::tim2::Tim2) {
256 cortexm4::nvic::Nvic::new(stm32f429zi::nvic::USART1).enable();
258
259 tim2.enable_clock();
261 tim2.start();
262 cortexm4::nvic::Nvic::new(stm32f429zi::nvic::TIM2).enable();
263}
264
265#[inline(never)]
271unsafe fn start() -> (
272 &'static kernel::Kernel,
273 STM32F429IDiscovery,
274 &'static stm32f429zi::chip::Stm32f4xx<'static, Stm32f429ziDefaultPeripherals<'static>>,
275) {
276 stm32f429zi::init();
277
278 let rcc = static_init!(stm32f429zi::rcc::Rcc, stm32f429zi::rcc::Rcc::new());
280 let clocks = static_init!(
281 stm32f429zi::clocks::Clocks<Stm32f429Specs>,
282 stm32f429zi::clocks::Clocks::new(rcc)
283 );
284 let syscfg = static_init!(
285 stm32f429zi::syscfg::Syscfg,
286 stm32f429zi::syscfg::Syscfg::new(clocks)
287 );
288 let exti = static_init!(
289 stm32f429zi::exti::Exti,
290 stm32f429zi::exti::Exti::new(syscfg)
291 );
292 let dma1 = static_init!(stm32f429zi::dma::Dma1, stm32f429zi::dma::Dma1::new(clocks));
293 let dma2 = static_init!(stm32f429zi::dma::Dma2, stm32f429zi::dma::Dma2::new(clocks));
294 let peripherals = static_init!(
295 Stm32f429ziDefaultPeripherals,
296 Stm32f429ziDefaultPeripherals::new(clocks, exti, dma1, dma2)
297 );
298
299 peripherals.init();
300 let base_peripherals = &peripherals.stm32f4;
301
302 setup_peripherals(&base_peripherals.tim2);
303
304 set_pin_primary_functions(syscfg, &base_peripherals.gpio_ports);
305
306 setup_dma(
307 dma2,
308 &base_peripherals.dma2_streams,
309 &base_peripherals.usart1,
310 );
311
312 let processes = components::process_array::ProcessArrayComponent::new()
314 .finalize(components::process_array_component_static!(NUM_PROCS));
315 PROCESSES = Some(processes);
316
317 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
319
320 let chip = static_init!(
321 stm32f429zi::chip::Stm32f4xx<Stm32f429ziDefaultPeripherals>,
322 stm32f429zi::chip::Stm32f4xx::new(peripherals)
323 );
324 CHIP = Some(chip);
325
326 base_peripherals.usart1.enable_clock();
333 let uart_mux = components::console::UartMuxComponent::new(&base_peripherals.usart1, 115200)
334 .finalize(components::uart_mux_component_static!());
335
336 (*addr_of_mut!(io::WRITER)).set_initialized();
337
338 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
341 let process_management_capability =
342 create_capability!(capabilities::ProcessManagementCapability);
343
344 let console = components::console::ConsoleComponent::new(
346 board_kernel,
347 capsules_core::console::DRIVER_NUM,
348 uart_mux,
349 )
350 .finalize(components::console_component_static!());
351 components::debug_writer::DebugWriterComponent::new(
353 uart_mux,
354 create_capability!(capabilities::SetDebugWriterCapability),
355 )
356 .finalize(components::debug_writer_component_static!());
357
358 let gpio_ports = &base_peripherals.gpio_ports;
362
363 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
364 LedHigh<'static, stm32f429zi::gpio::Pin>,
365 LedHigh::new(gpio_ports.get_pin(stm32f429zi::gpio::PinId::PG13).unwrap()),
366 LedHigh::new(gpio_ports.get_pin(stm32f429zi::gpio::PinId::PG14).unwrap()),
367 LedHigh::new(gpio_ports.get_pin(stm32f429zi::gpio::PinId::PB13).unwrap()),
368 LedHigh::new(gpio_ports.get_pin(stm32f429zi::gpio::PinId::PC05).unwrap()),
369 ));
370
371 let button = components::button::ButtonComponent::new(
373 board_kernel,
374 capsules_core::button::DRIVER_NUM,
375 components::button_component_helper!(
376 stm32f429zi::gpio::Pin,
377 (
378 gpio_ports.get_pin(stm32f429zi::gpio::PinId::PA00).unwrap(),
379 kernel::hil::gpio::ActivationMode::ActiveHigh,
380 kernel::hil::gpio::FloatingState::PullNone
381 )
382 ),
383 )
384 .finalize(components::button_component_static!(stm32f429zi::gpio::Pin));
385
386 let tim2 = &base_peripherals.tim2;
389 let mux_alarm = components::alarm::AlarmMuxComponent::new(tim2).finalize(
390 components::alarm_mux_component_static!(stm32f429zi::tim2::Tim2),
391 );
392
393 let alarm = components::alarm::AlarmDriverComponent::new(
394 board_kernel,
395 capsules_core::alarm::DRIVER_NUM,
396 mux_alarm,
397 )
398 .finalize(components::alarm_component_static!(stm32f429zi::tim2::Tim2));
399
400 let gpio = GpioComponent::new(
402 board_kernel,
403 capsules_core::gpio::DRIVER_NUM,
404 components::gpio_component_helper!(
405 stm32f429zi::gpio::Pin,
406 0 => gpio_ports.get_pin(PinId::PG09).unwrap(), 1 => gpio_ports.pins[6][14].as_ref().unwrap(), 2 => gpio_ports.pins[5][15].as_ref().unwrap(), 3 => gpio_ports.pins[4][13].as_ref().unwrap(), 4 => gpio_ports.pins[5][14].as_ref().unwrap(), 5 => gpio_ports.pins[4][11].as_ref().unwrap(), 6 => gpio_ports.pins[4][9].as_ref().unwrap(), 7 => gpio_ports.pins[5][13].as_ref().unwrap(), 8 => gpio_ports.pins[5][12].as_ref().unwrap(), 9 => gpio_ports.pins[3][15].as_ref().unwrap(), 10 => gpio_ports.pins[3][14].as_ref().unwrap(), 11 => gpio_ports.pins[0][7].as_ref().unwrap(), 12 => gpio_ports.pins[0][6].as_ref().unwrap(), 13 => gpio_ports.pins[0][5].as_ref().unwrap(), 14 => gpio_ports.pins[1][9].as_ref().unwrap(), 15 => gpio_ports.pins[1][8].as_ref().unwrap(), 16 => gpio_ports.pins[2][6].as_ref().unwrap(), 17 => gpio_ports.pins[1][15].as_ref().unwrap(), 18 => gpio_ports.pins[1][13].as_ref().unwrap(), 19 => gpio_ports.pins[1][12].as_ref().unwrap(), 20 => gpio_ports.pins[0][15].as_ref().unwrap(), 21 => gpio_ports.pins[2][7].as_ref().unwrap(), 26 => gpio_ports.pins[1][6].as_ref().unwrap(), 27 => gpio_ports.pins[1][2].as_ref().unwrap(), 28 => gpio_ports.pins[3][13].as_ref().unwrap(), 29 => gpio_ports.pins[3][12].as_ref().unwrap(), 30 => gpio_ports.pins[3][11].as_ref().unwrap(), 31 => gpio_ports.pins[4][2].as_ref().unwrap(), 33 => gpio_ports.pins[1][0].as_ref().unwrap(), 34 => gpio_ports.pins[4][0].as_ref().unwrap(), 35 => gpio_ports.pins[1][11].as_ref().unwrap(), 36 => gpio_ports.pins[1][10].as_ref().unwrap(), 37 => gpio_ports.pins[4][15].as_ref().unwrap(), 38 => gpio_ports.pins[4][14].as_ref().unwrap(), 39 => gpio_ports.pins[4][12].as_ref().unwrap(), 40 => gpio_ports.pins[4][10].as_ref().unwrap(), 41 => gpio_ports.pins[4][7].as_ref().unwrap(), 42 => gpio_ports.pins[4][8].as_ref().unwrap(), 43 => gpio_ports.pins[2][8].as_ref().unwrap(), 44 => gpio_ports.pins[2][9].as_ref().unwrap(), 45 => gpio_ports.pins[2][10].as_ref().unwrap(), 46 => gpio_ports.pins[2][11].as_ref().unwrap(), 47 => gpio_ports.pins[2][12].as_ref().unwrap(), 48 => gpio_ports.pins[3][2].as_ref().unwrap(), 49 => gpio_ports.pins[6][2].as_ref().unwrap(), 50 => gpio_ports.pins[6][3].as_ref().unwrap(), 51 => gpio_ports.pins[3][7].as_ref().unwrap(), 52 => gpio_ports.pins[3][6].as_ref().unwrap(), 53 => gpio_ports.pins[3][5].as_ref().unwrap(), 54 => gpio_ports.pins[3][4].as_ref().unwrap(), 55 => gpio_ports.pins[3][3].as_ref().unwrap(), 56 => gpio_ports.pins[4][2].as_ref().unwrap(), 57 => gpio_ports.pins[4][4].as_ref().unwrap(), 58 => gpio_ports.pins[4][5].as_ref().unwrap(), 59 => gpio_ports.pins[4][6].as_ref().unwrap(), 60 => gpio_ports.pins[4][3].as_ref().unwrap(), 61 => gpio_ports.pins[5][8].as_ref().unwrap(), 62 => gpio_ports.pins[5][7].as_ref().unwrap(), 63 => gpio_ports.pins[5][9].as_ref().unwrap(), 64 => gpio_ports.pins[6][1].as_ref().unwrap(), 65 => gpio_ports.pins[6][0].as_ref().unwrap(), 66 => gpio_ports.pins[3][1].as_ref().unwrap(), 67 => gpio_ports.pins[3][0].as_ref().unwrap(), 68 => gpio_ports.pins[5][0].as_ref().unwrap(), 69 => gpio_ports.pins[5][1].as_ref().unwrap(), 70 => gpio_ports.pins[5][2].as_ref().unwrap(), 71 => gpio_ports.pins[0][7].as_ref().unwrap() ),
502 )
503 .finalize(components::gpio_component_static!(stm32f429zi::gpio::Pin));
504
505 let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc1)
507 .finalize(components::adc_mux_component_static!(stm32f429zi::adc::Adc));
508
509 let temp_sensor = components::temperature_stm::TemperatureSTMComponent::new(
510 adc_mux,
511 stm32f429zi::adc::Channel::Channel18,
512 2.5,
513 0.76,
514 )
515 .finalize(components::temperature_stm_adc_component_static!(
516 stm32f429zi::adc::Adc
517 ));
518
519 let temp = components::temperature::TemperatureComponent::new(
520 board_kernel,
521 capsules_extra::temperature::DRIVER_NUM,
522 temp_sensor,
523 )
524 .finalize(components::temperature_component_static!(
525 TemperatureSTMSensor
526 ));
527
528 let adc_channel_0 =
529 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel3)
530 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
531
532 let adc_channel_1 =
533 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel10)
534 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
535
536 let adc_channel_2 =
537 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel13)
538 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
539
540 let adc_channel_3 =
541 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel9)
542 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
543
544 let adc_channel_4 =
545 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel15)
546 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
547
548 let adc_channel_5 =
549 components::adc::AdcComponent::new(adc_mux, stm32f429zi::adc::Channel::Channel8)
550 .finalize(components::adc_component_static!(stm32f429zi::adc::Adc));
551
552 let adc_syscall =
553 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
554 .finalize(components::adc_syscall_component_helper!(
555 adc_channel_0,
556 adc_channel_1,
557 adc_channel_2,
558 adc_channel_3,
559 adc_channel_4,
560 adc_channel_5
561 ));
562
563 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
564 .finalize(components::process_printer_text_component_static!());
565 PROCESS_PRINTER = Some(process_printer);
566
567 let process_console = components::process_console::ProcessConsoleComponent::new(
569 board_kernel,
570 uart_mux,
571 mux_alarm,
572 process_printer,
573 Some(cortexm4::support::reset),
574 )
575 .finalize(components::process_console_component_static!(
576 stm32f429zi::tim2::Tim2
577 ));
578 let _ = process_console.start();
579
580 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
581 .finalize(components::round_robin_component_static!(NUM_PROCS));
582
583 let stm32f429i_discovery = STM32F429IDiscovery {
584 console,
585 ipc: kernel::ipc::IPC::new(
586 board_kernel,
587 kernel::ipc::DRIVER_NUM,
588 &memory_allocation_capability,
589 ),
590 adc: adc_syscall,
591 led,
592 temperature: temp,
593 button,
594 alarm,
595 gpio,
596
597 scheduler,
598 systick: cortexm4::systick::SysTick::new_with_calibration(
599 (HSI_FREQUENCY_MHZ * 1_000_000) as u32,
600 ),
601 };
602
603 debug!("Initialization complete. Entering main loop");
609
610 extern "C" {
612 static _sapps: u8;
614 static _eapps: u8;
616 static mut _sappmem: u8;
618 static _eappmem: u8;
620 }
621
622 kernel::process::load_processes(
623 board_kernel,
624 chip,
625 core::slice::from_raw_parts(
626 core::ptr::addr_of!(_sapps),
627 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
628 ),
629 core::slice::from_raw_parts_mut(
630 core::ptr::addr_of_mut!(_sappmem),
631 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
632 ),
633 &FAULT_RESPONSE,
634 &process_management_capability,
635 )
636 .unwrap_or_else(|err| {
637 debug!("Error loading processes!");
638 debug!("{:?}", err);
639 });
640
641 (board_kernel, stm32f429i_discovery, chip)
647}
648
649#[no_mangle]
651pub unsafe fn main() {
652 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
653
654 let (board_kernel, platform, chip) = start();
655 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
656}