stm32f412gdiscovery/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Board file for STM32F412GDiscovery Discovery kit development board
6//!
7//! - <https://www.st.com/en/evaluation-tools/32f412gdiscovery.html>
8
9#![no_std]
10// Disable this attribute when documenting, as a workaround for
11// https://github.com/rust-lang/rust/issues/62184.
12#![cfg_attr(not(doc), no_main)]
13#![deny(missing_docs)]
14use core::ptr::{addr_of, addr_of_mut};
15
16use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
17use components::gpio::GpioComponent;
18use components::rng::RngComponent;
19use kernel::capabilities;
20use kernel::component::Component;
21use kernel::hil::gpio;
22use kernel::hil::led::LedLow;
23use kernel::hil::screen::ScreenRotation;
24use kernel::platform::{KernelResources, SyscallDriverLookup};
25use kernel::scheduler::round_robin::RoundRobinSched;
26use kernel::{create_capability, debug, static_init};
27use stm32f412g::chip_specs::Stm32f412Specs;
28use stm32f412g::clocks::hsi::HSI_FREQUENCY_MHZ;
29use stm32f412g::interrupt_service::Stm32f412gDefaultPeripherals;
30use stm32f412g::rcc::PllSource;
31
32/// Support routines for debugging I/O.
33pub mod io;
34
35// Number of concurrent processes this platform supports.
36const NUM_PROCS: usize = 4;
37
38// Actual memory for holding the active process structures.
39static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
40    [None, None, None, None];
41
42static mut CHIP: Option<&'static stm32f412g::chip::Stm32f4xx<Stm32f412gDefaultPeripherals>> = None;
43static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
44    None;
45
46// How should the kernel respond when a process faults.
47const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
48    capsules_system::process_policies::PanicFaultPolicy {};
49
50/// Dummy buffer that causes the linker to reserve enough space for the stack.
51#[no_mangle]
52#[link_section = ".stack_buffer"]
53pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
54
55type TemperatureSTMSensor = components::temperature_stm::TemperatureSTMComponentType<
56    capsules_core::virtualizers::virtual_adc::AdcDevice<'static, stm32f412g::adc::Adc<'static>>,
57>;
58type TemperatureDriver = components::temperature::TemperatureComponentType<TemperatureSTMSensor>;
59type RngDriver = components::rng::RngComponentType<stm32f412g::trng::Trng<'static>>;
60
61/// A structure representing this platform that holds references to all
62/// capsules for this platform.
63struct STM32F412GDiscovery {
64    console: &'static capsules_core::console::Console<'static>,
65    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
66    led: &'static capsules_core::led::LedDriver<
67        'static,
68        LedLow<'static, stm32f412g::gpio::Pin<'static>>,
69        4,
70    >,
71    button: &'static capsules_core::button::Button<'static, stm32f412g::gpio::Pin<'static>>,
72    alarm: &'static capsules_core::alarm::AlarmDriver<
73        'static,
74        VirtualMuxAlarm<'static, stm32f412g::tim2::Tim2<'static>>,
75    >,
76    gpio: &'static capsules_core::gpio::GPIO<'static, stm32f412g::gpio::Pin<'static>>,
77    adc: &'static capsules_core::adc::AdcVirtualized<'static>,
78    touch: &'static capsules_extra::touch::Touch<'static>,
79    screen: &'static capsules_extra::screen::Screen<'static>,
80    temperature: &'static TemperatureDriver,
81    rng: &'static RngDriver,
82
83    scheduler: &'static RoundRobinSched<'static>,
84    systick: cortexm4::systick::SysTick,
85}
86
87/// Mapping of integer syscalls to objects that implement syscalls.
88impl SyscallDriverLookup for STM32F412GDiscovery {
89    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
90    where
91        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
92    {
93        match driver_num {
94            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
95            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
96            capsules_core::button::DRIVER_NUM => f(Some(self.button)),
97            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
98            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
99            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
100            capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
101            capsules_extra::touch::DRIVER_NUM => f(Some(self.touch)),
102            capsules_extra::screen::DRIVER_NUM => f(Some(self.screen)),
103            capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
104            capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
105            _ => f(None),
106        }
107    }
108}
109
110impl
111    KernelResources<
112        stm32f412g::chip::Stm32f4xx<
113            'static,
114            stm32f412g::interrupt_service::Stm32f412gDefaultPeripherals<'static>,
115        >,
116    > for STM32F412GDiscovery
117{
118    type SyscallDriverLookup = Self;
119    type SyscallFilter = ();
120    type ProcessFault = ();
121    type Scheduler = RoundRobinSched<'static>;
122    type SchedulerTimer = cortexm4::systick::SysTick;
123    type WatchDog = ();
124    type ContextSwitchCallback = ();
125
126    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
127        self
128    }
129    fn syscall_filter(&self) -> &Self::SyscallFilter {
130        &()
131    }
132    fn process_fault(&self) -> &Self::ProcessFault {
133        &()
134    }
135    fn scheduler(&self) -> &Self::Scheduler {
136        self.scheduler
137    }
138    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
139        &self.systick
140    }
141    fn watchdog(&self) -> &Self::WatchDog {
142        &()
143    }
144    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
145        &()
146    }
147}
148
149/// Helper function called during bring-up that configures DMA.
150unsafe fn setup_dma(
151    dma: &stm32f412g::dma::Dma1,
152    dma_streams: &'static [stm32f412g::dma::Stream<stm32f412g::dma::Dma1>; 8],
153    usart2: &'static stm32f412g::usart::Usart<stm32f412g::dma::Dma1>,
154) {
155    use stm32f412g::dma::Dma1Peripheral;
156    use stm32f412g::usart;
157
158    dma.enable_clock();
159
160    let usart2_tx_stream = &dma_streams[Dma1Peripheral::USART2_TX.get_stream_idx()];
161    let usart2_rx_stream = &dma_streams[Dma1Peripheral::USART2_RX.get_stream_idx()];
162
163    usart2.set_dma(
164        usart::TxDMA(usart2_tx_stream),
165        usart::RxDMA(usart2_rx_stream),
166    );
167
168    usart2_tx_stream.set_client(usart2);
169    usart2_rx_stream.set_client(usart2);
170
171    usart2_tx_stream.setup(Dma1Peripheral::USART2_TX);
172    usart2_rx_stream.setup(Dma1Peripheral::USART2_RX);
173
174    cortexm4::nvic::Nvic::new(Dma1Peripheral::USART2_TX.get_stream_irqn()).enable();
175    cortexm4::nvic::Nvic::new(Dma1Peripheral::USART2_RX.get_stream_irqn()).enable();
176}
177
178/// Helper function called during bring-up that configures multiplexed I/O.
179unsafe fn set_pin_primary_functions(
180    syscfg: &stm32f412g::syscfg::Syscfg,
181    i2c1: &stm32f412g::i2c::I2C,
182    gpio_ports: &'static stm32f412g::gpio::GpioPorts<'static>,
183    peripheral_clock_frequency: usize,
184) {
185    use kernel::hil::gpio::Configure;
186    use stm32f412g::gpio::{AlternateFunction, Mode, PinId, PortId};
187
188    syscfg.enable_clock();
189
190    gpio_ports.get_port_from_port_id(PortId::E).enable_clock();
191
192    // User LD3 is connected to PE02. Configure PE02 as `debug_gpio!(0, ...)`
193    gpio_ports.get_pin(PinId::PE02).map(|pin| {
194        pin.make_output();
195
196        // Configure kernel debug gpios as early as possible
197        kernel::debug::assign_gpios(Some(pin), None, None);
198    });
199
200    gpio_ports.get_port_from_port_id(PortId::A).enable_clock();
201
202    // pa2 and pa3 (USART2) is connected to ST-LINK virtual COM port
203    gpio_ports.get_pin(PinId::PA02).map(|pin| {
204        pin.set_mode(Mode::AlternateFunctionMode);
205        // AF7 is USART2_TX
206        pin.set_alternate_function(AlternateFunction::AF7);
207    });
208    gpio_ports.get_pin(PinId::PA03).map(|pin| {
209        pin.set_mode(Mode::AlternateFunctionMode);
210        // AF7 is USART2_RX
211        pin.set_alternate_function(AlternateFunction::AF7);
212    });
213
214    // uncomment this if you do not plan to use the joystick up, as they both use Exti0
215    // joystick selection is connected on pa00
216    // gpio_ports.get_pin(PinId::PA00).map(|pin| {
217    //     pin.enable_interrupt();
218    // });
219
220    // joystick down is connected on pg01
221    gpio_ports.get_pin(PinId::PG01).map(|pin| {
222        pin.enable_interrupt();
223    });
224
225    // joystick left is connected on pf15
226    gpio_ports.get_pin(PinId::PF15).map(|pin| {
227        pin.enable_interrupt();
228    });
229
230    // joystick right is connected on pf14
231    gpio_ports.get_pin(PinId::PF14).map(|pin| {
232        pin.enable_interrupt();
233    });
234
235    // joystick up is connected on pg00
236    gpio_ports.get_pin(PinId::PG00).map(|pin| {
237        pin.enable_interrupt();
238    });
239
240    // enable interrupt for D0
241    gpio_ports.get_pin(PinId::PG09).map(|pin| {
242        pin.enable_interrupt();
243    });
244
245    // Enable clocks for GPIO Ports
246    // Disable some of them if you don't need some of the GPIOs
247    gpio_ports.get_port_from_port_id(PortId::B).enable_clock();
248    // Ports A and E are already enabled
249    gpio_ports.get_port_from_port_id(PortId::C).enable_clock();
250    gpio_ports.get_port_from_port_id(PortId::D).enable_clock();
251    gpio_ports.get_port_from_port_id(PortId::F).enable_clock();
252    gpio_ports.get_port_from_port_id(PortId::G).enable_clock();
253    gpio_ports.get_port_from_port_id(PortId::H).enable_clock();
254
255    // I2C1 has the TouchPanel connected
256    gpio_ports.get_pin(PinId::PB06).map(|pin| {
257        // pin.make_output();
258        pin.set_mode_output_opendrain();
259        pin.set_mode(Mode::AlternateFunctionMode);
260        pin.set_floating_state(kernel::hil::gpio::FloatingState::PullNone);
261        // AF4 is I2C
262        pin.set_alternate_function(AlternateFunction::AF4);
263    });
264    gpio_ports.get_pin(PinId::PB07).map(|pin| {
265        // pin.make_output();
266        pin.set_mode_output_opendrain();
267        pin.set_floating_state(kernel::hil::gpio::FloatingState::PullNone);
268        pin.set_mode(Mode::AlternateFunctionMode);
269        // AF4 is I2C
270        pin.set_alternate_function(AlternateFunction::AF4);
271    });
272
273    i2c1.enable_clock();
274    i2c1.set_speed(
275        stm32f412g::i2c::I2CSpeed::Speed400k,
276        peripheral_clock_frequency,
277    );
278
279    // FT6206 interrupt
280    gpio_ports.get_pin(PinId::PG05).map(|pin| {
281        pin.enable_interrupt();
282    });
283
284    // ADC
285
286    // Arduino A0
287    gpio_ports.get_pin(PinId::PA01).map(|pin| {
288        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
289    });
290
291    // Arduino A1
292    gpio_ports.get_pin(PinId::PC01).map(|pin| {
293        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
294    });
295
296    // Arduino A2
297    gpio_ports.get_pin(PinId::PC03).map(|pin| {
298        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
299    });
300
301    // Arduino A3
302    gpio_ports.get_pin(PinId::PC04).map(|pin| {
303        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
304    });
305
306    // Arduino A4
307    gpio_ports.get_pin(PinId::PC05).map(|pin| {
308        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
309    });
310
311    // Arduino A5
312    gpio_ports.get_pin(PinId::PB00).map(|pin| {
313        pin.set_mode(stm32f412g::gpio::Mode::AnalogMode);
314    });
315
316    // EXTI9_5 interrupts is delivered at IRQn 23 (EXTI9_5)
317    cortexm4::nvic::Nvic::new(stm32f412g::nvic::EXTI9_5).enable();
318
319    // LCD
320
321    let pins = [
322        PinId::PD00,
323        PinId::PD01,
324        PinId::PD04,
325        PinId::PD05,
326        PinId::PD08,
327        PinId::PD09,
328        PinId::PD10,
329        PinId::PD14,
330        PinId::PD15,
331        PinId::PD07,
332        PinId::PE07,
333        PinId::PE08,
334        PinId::PE09,
335        PinId::PE10,
336        PinId::PE11,
337        PinId::PE12,
338        PinId::PE13,
339        PinId::PE14,
340        PinId::PE15,
341        PinId::PF00,
342    ];
343
344    for pin in pins.iter() {
345        gpio_ports.get_pin(*pin).map(|pin| {
346            pin.set_mode(stm32f412g::gpio::Mode::AlternateFunctionMode);
347            pin.set_floating_state(gpio::FloatingState::PullUp);
348            pin.set_speed();
349            pin.set_alternate_function(stm32f412g::gpio::AlternateFunction::AF12);
350        });
351    }
352
353    use kernel::hil::gpio::Output;
354
355    gpio_ports.get_pin(PinId::PF05).map(|pin| {
356        pin.make_output();
357        pin.set_floating_state(gpio::FloatingState::PullNone);
358        pin.set();
359    });
360
361    gpio_ports.get_pin(PinId::PG04).map(|pin| {
362        pin.make_input();
363    });
364}
365
366/// Helper function for miscellaneous peripheral functions
367unsafe fn setup_peripherals(
368    tim2: &stm32f412g::tim2::Tim2,
369    fsmc: &stm32f412g::fsmc::Fsmc,
370    trng: &stm32f412g::trng::Trng,
371) {
372    // USART2 IRQn is 38
373    cortexm4::nvic::Nvic::new(stm32f412g::nvic::USART2).enable();
374
375    // TIM2 IRQn is 28
376    tim2.enable_clock();
377    tim2.start();
378    cortexm4::nvic::Nvic::new(stm32f412g::nvic::TIM2).enable();
379
380    // FSMC
381    fsmc.enable();
382
383    // RNG
384    trng.enable_clock();
385}
386
387/// Main function.
388///
389/// This is in a separate, inline(never) function so that its stack frame is
390/// removed when this function returns. Otherwise, the stack space used for
391/// these static_inits is wasted.
392#[inline(never)]
393unsafe fn start() -> (
394    &'static kernel::Kernel,
395    STM32F412GDiscovery,
396    &'static stm32f412g::chip::Stm32f4xx<'static, Stm32f412gDefaultPeripherals<'static>>,
397) {
398    stm32f412g::init();
399
400    let rcc = static_init!(stm32f412g::rcc::Rcc, stm32f412g::rcc::Rcc::new());
401    let clocks = static_init!(
402        stm32f412g::clocks::Clocks<Stm32f412Specs>,
403        stm32f412g::clocks::Clocks::new(rcc)
404    );
405
406    let syscfg = static_init!(
407        stm32f412g::syscfg::Syscfg,
408        stm32f412g::syscfg::Syscfg::new(clocks)
409    );
410
411    let exti = static_init!(stm32f412g::exti::Exti, stm32f412g::exti::Exti::new(syscfg));
412
413    let dma1 = static_init!(stm32f412g::dma::Dma1, stm32f412g::dma::Dma1::new(clocks));
414    let dma2 = static_init!(stm32f412g::dma::Dma2, stm32f412g::dma::Dma2::new(clocks));
415
416    let peripherals = static_init!(
417        Stm32f412gDefaultPeripherals,
418        Stm32f412gDefaultPeripherals::new(clocks, exti, dma1, dma2)
419    );
420
421    peripherals.init();
422
423    let _ = clocks.set_ahb_prescaler(stm32f412g::rcc::AHBPrescaler::DivideBy1);
424    let _ = clocks.set_apb1_prescaler(stm32f412g::rcc::APBPrescaler::DivideBy4);
425    let _ = clocks.set_apb2_prescaler(stm32f412g::rcc::APBPrescaler::DivideBy2);
426    let _ = clocks.set_pll_frequency_mhz(PllSource::HSI, 100);
427    let _ = clocks.pll.enable();
428    let _ = clocks.set_sys_clock_source(stm32f412g::rcc::SysClockSource::PLL);
429
430    let base_peripherals = &peripherals.stm32f4;
431    setup_peripherals(
432        &base_peripherals.tim2,
433        &base_peripherals.fsmc,
434        &peripherals.trng,
435    );
436
437    set_pin_primary_functions(
438        syscfg,
439        &base_peripherals.i2c1,
440        &base_peripherals.gpio_ports,
441        clocks.get_apb1_frequency_mhz(),
442    );
443
444    setup_dma(
445        dma1,
446        &base_peripherals.dma1_streams,
447        &base_peripherals.usart2,
448    );
449
450    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
451
452    let chip = static_init!(
453        stm32f412g::chip::Stm32f4xx<Stm32f412gDefaultPeripherals>,
454        stm32f412g::chip::Stm32f4xx::new(peripherals)
455    );
456    CHIP = Some(chip);
457
458    // UART
459
460    // Create a shared UART channel for kernel debug.
461    base_peripherals.usart2.enable_clock();
462    let uart_mux = components::console::UartMuxComponent::new(&base_peripherals.usart2, 115200)
463        .finalize(components::uart_mux_component_static!());
464
465    (*addr_of_mut!(io::WRITER)).set_initialized();
466
467    // Create capabilities that the board needs to call certain protected kernel
468    // functions.
469    let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
470    let process_management_capability =
471        create_capability!(capabilities::ProcessManagementCapability);
472
473    // Setup the console.
474    let console = components::console::ConsoleComponent::new(
475        board_kernel,
476        capsules_core::console::DRIVER_NUM,
477        uart_mux,
478    )
479    .finalize(components::console_component_static!());
480    // Create the debugger object that handles calls to `debug!()`.
481    components::debug_writer::DebugWriterComponent::new(uart_mux)
482        .finalize(components::debug_writer_component_static!());
483
484    // LEDs
485
486    // Clock to Port A is enabled in `set_pin_primary_functions()`
487
488    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
489        LedLow<'static, stm32f412g::gpio::Pin>,
490        LedLow::new(
491            base_peripherals
492                .gpio_ports
493                .get_pin(stm32f412g::gpio::PinId::PE00)
494                .unwrap()
495        ),
496        LedLow::new(
497            base_peripherals
498                .gpio_ports
499                .get_pin(stm32f412g::gpio::PinId::PE01)
500                .unwrap()
501        ),
502        LedLow::new(
503            base_peripherals
504                .gpio_ports
505                .get_pin(stm32f412g::gpio::PinId::PE02)
506                .unwrap()
507        ),
508        LedLow::new(
509            base_peripherals
510                .gpio_ports
511                .get_pin(stm32f412g::gpio::PinId::PE03)
512                .unwrap()
513        ),
514    ));
515
516    // BUTTONs
517    let button = components::button::ButtonComponent::new(
518        board_kernel,
519        capsules_core::button::DRIVER_NUM,
520        components::button_component_helper!(
521            stm32f412g::gpio::Pin,
522            // Select
523            (
524                base_peripherals
525                    .gpio_ports
526                    .get_pin(stm32f412g::gpio::PinId::PA00)
527                    .unwrap(),
528                kernel::hil::gpio::ActivationMode::ActiveHigh,
529                kernel::hil::gpio::FloatingState::PullNone
530            ),
531            // Down
532            (
533                base_peripherals
534                    .gpio_ports
535                    .get_pin(stm32f412g::gpio::PinId::PG01)
536                    .unwrap(),
537                kernel::hil::gpio::ActivationMode::ActiveHigh,
538                kernel::hil::gpio::FloatingState::PullNone
539            ),
540            // Left
541            (
542                base_peripherals
543                    .gpio_ports
544                    .get_pin(stm32f412g::gpio::PinId::PF15)
545                    .unwrap(),
546                kernel::hil::gpio::ActivationMode::ActiveHigh,
547                kernel::hil::gpio::FloatingState::PullNone
548            ),
549            // Right
550            (
551                base_peripherals
552                    .gpio_ports
553                    .get_pin(stm32f412g::gpio::PinId::PF14)
554                    .unwrap(),
555                kernel::hil::gpio::ActivationMode::ActiveHigh,
556                kernel::hil::gpio::FloatingState::PullNone
557            ),
558            // Up
559            (
560                base_peripherals
561                    .gpio_ports
562                    .get_pin(stm32f412g::gpio::PinId::PG00)
563                    .unwrap(),
564                kernel::hil::gpio::ActivationMode::ActiveHigh,
565                kernel::hil::gpio::FloatingState::PullNone
566            )
567        ),
568    )
569    .finalize(components::button_component_static!(stm32f412g::gpio::Pin));
570
571    // ALARM
572
573    let tim2 = &base_peripherals.tim2;
574    let mux_alarm = components::alarm::AlarmMuxComponent::new(tim2).finalize(
575        components::alarm_mux_component_static!(stm32f412g::tim2::Tim2),
576    );
577
578    let alarm = components::alarm::AlarmDriverComponent::new(
579        board_kernel,
580        capsules_core::alarm::DRIVER_NUM,
581        mux_alarm,
582    )
583    .finalize(components::alarm_component_static!(stm32f412g::tim2::Tim2));
584
585    // GPIO
586    let gpio = GpioComponent::new(
587        board_kernel,
588        capsules_core::gpio::DRIVER_NUM,
589        components::gpio_component_helper!(
590            stm32f412g::gpio::Pin,
591            // Arduino like RX/TX
592            0 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG09).unwrap(), //D0
593            1 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG14).unwrap(), //D1
594            2 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG13).unwrap(), //D2
595            3 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PF04).unwrap(), //D3
596            4 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG12).unwrap(), //D4
597            5 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PF10).unwrap(), //D5
598            6 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PF03).unwrap(), //D6
599            7 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG11).unwrap(), //D7
600            8 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PG10).unwrap(), //D8
601            9 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PB08).unwrap(), //D9
602            // SPI Pins
603            10 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PA15).unwrap(), //D10
604            11 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PA07).unwrap(),  //D11
605            12 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PA06).unwrap(),  //D12
606            13 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PA15).unwrap()  //D13
607
608            // ADC Pins
609            // Enable the to use the ADC pins as GPIO
610            // 14 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PA01).unwrap(), //A0
611            // 15 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PC01).unwrap(), //A1
612            // 16 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PC03).unwrap(), //A2
613            // 17 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PC04).unwrap(), //A3
614            // 19 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PC05).unwrap(), //A4
615            // 20 => base_peripherals.gpio_ports.get_pin(stm32f412g::gpio::PinId::PB00).unwrap() //A5
616        ),
617    )
618    .finalize(components::gpio_component_static!(stm32f412g::gpio::Pin));
619
620    // RNG
621    let rng = RngComponent::new(
622        board_kernel,
623        capsules_core::rng::DRIVER_NUM,
624        &peripherals.trng,
625    )
626    .finalize(components::rng_component_static!(stm32f412g::trng::Trng));
627
628    // FT6206
629
630    let mux_i2c = components::i2c::I2CMuxComponent::new(&base_peripherals.i2c1, None)
631        .finalize(components::i2c_mux_component_static!(stm32f412g::i2c::I2C));
632
633    let ft6x06 = components::ft6x06::Ft6x06Component::new(
634        mux_i2c,
635        0x38,
636        base_peripherals
637            .gpio_ports
638            .get_pin(stm32f412g::gpio::PinId::PG05)
639            .unwrap(),
640    )
641    .finalize(components::ft6x06_component_static!(stm32f412g::i2c::I2C));
642
643    let bus = components::bus::Bus8080BusComponent::new(&base_peripherals.fsmc).finalize(
644        components::bus8080_bus_component_static!(stm32f412g::fsmc::Fsmc,),
645    );
646
647    let tft = components::st77xx::ST77XXComponent::new(
648        mux_alarm,
649        bus,
650        None,
651        base_peripherals
652            .gpio_ports
653            .get_pin(stm32f412g::gpio::PinId::PD11),
654        &capsules_extra::st77xx::ST7789H2,
655    )
656    .finalize(components::st77xx_component_static!(
657        // bus type
658        capsules_extra::bus::Bus8080Bus<'static, stm32f412g::fsmc::Fsmc>,
659        // timer type
660        stm32f412g::tim2::Tim2,
661        // pin type
662        stm32f412g::gpio::Pin,
663    ));
664
665    let _ = tft.init();
666
667    let screen = components::screen::ScreenComponent::new(
668        board_kernel,
669        capsules_extra::screen::DRIVER_NUM,
670        tft,
671        Some(tft),
672    )
673    .finalize(components::screen_component_static!(1024));
674
675    let touch = components::touch::MultiTouchComponent::new(
676        board_kernel,
677        capsules_extra::touch::DRIVER_NUM,
678        ft6x06,
679        Some(ft6x06),
680        Some(tft),
681    )
682    .finalize(components::touch_component_static!());
683
684    touch.set_screen_rotation_offset(ScreenRotation::Rotated90);
685
686    // Uncomment this for multi touch support
687    // let touch =
688    //     components::touch::MultiTouchComponent::new(board_kernel, ft6x06, Some(ft6x06), None)
689    //         .finalize(());
690
691    // ADC
692    let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc1)
693        .finalize(components::adc_mux_component_static!(stm32f412g::adc::Adc));
694
695    let temp_sensor = components::temperature_stm::TemperatureSTMComponent::new(
696        adc_mux,
697        stm32f412g::adc::Channel::Channel18,
698        2.5,
699        0.76,
700    )
701    .finalize(components::temperature_stm_adc_component_static!(
702        stm32f412g::adc::Adc
703    ));
704
705    let temp = components::temperature::TemperatureComponent::new(
706        board_kernel,
707        capsules_extra::temperature::DRIVER_NUM,
708        temp_sensor,
709    )
710    .finalize(components::temperature_component_static!(
711        TemperatureSTMSensor
712    ));
713
714    let adc_channel_0 =
715        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel1)
716            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
717
718    let adc_channel_1 =
719        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel11)
720            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
721
722    let adc_channel_2 =
723        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel13)
724            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
725
726    let adc_channel_3 =
727        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel14)
728            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
729
730    let adc_channel_4 =
731        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel15)
732            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
733
734    let adc_channel_5 =
735        components::adc::AdcComponent::new(adc_mux, stm32f412g::adc::Channel::Channel8)
736            .finalize(components::adc_component_static!(stm32f412g::adc::Adc));
737
738    let adc_syscall =
739        components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
740            .finalize(components::adc_syscall_component_helper!(
741                adc_channel_0,
742                adc_channel_1,
743                adc_channel_2,
744                adc_channel_3,
745                adc_channel_4,
746                adc_channel_5
747            ));
748
749    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
750        .finalize(components::process_printer_text_component_static!());
751    PROCESS_PRINTER = Some(process_printer);
752
753    // PROCESS CONSOLE
754    let process_console = components::process_console::ProcessConsoleComponent::new(
755        board_kernel,
756        uart_mux,
757        mux_alarm,
758        process_printer,
759        Some(cortexm4::support::reset),
760    )
761    .finalize(components::process_console_component_static!(
762        stm32f412g::tim2::Tim2
763    ));
764    let _ = process_console.start();
765
766    let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
767        .finalize(components::round_robin_component_static!(NUM_PROCS));
768
769    let stm32f412g = STM32F412GDiscovery {
770        console,
771        ipc: kernel::ipc::IPC::new(
772            board_kernel,
773            kernel::ipc::DRIVER_NUM,
774            &memory_allocation_capability,
775        ),
776        led,
777        button,
778        alarm,
779        gpio,
780        adc: adc_syscall,
781        touch,
782        screen,
783        temperature: temp,
784        rng,
785
786        scheduler,
787        systick: cortexm4::systick::SysTick::new_with_calibration(
788            (HSI_FREQUENCY_MHZ * 1_000_000) as u32,
789        ),
790    };
791
792    // // Optional kernel tests
793    // //
794    // // See comment in `boards/imix/src/main.rs`
795    // virtual_uart_rx_test::run_virtual_uart_receive(mux_uart);
796    // base_peripherals.fsmc.write(0x04, 120);
797    // debug!("id {}", base_peripherals.fsmc.read(0x05));
798
799    debug!("Initialization complete. Entering main loop");
800
801    extern "C" {
802        /// Beginning of the ROM region containing app images.
803        ///
804        /// This symbol is defined in the linker script.
805        static _sapps: u8;
806
807        /// End of the ROM region containing app images.
808        ///
809        /// This symbol is defined in the linker script.
810        static _eapps: u8;
811
812        /// Beginning of the RAM region for app memory.
813        ///
814        /// This symbol is defined in the linker script.
815        static mut _sappmem: u8;
816
817        /// End of the RAM region for app memory.
818        ///
819        /// This symbol is defined in the linker script.
820        static _eappmem: u8;
821    }
822
823    kernel::process::load_processes(
824        board_kernel,
825        chip,
826        core::slice::from_raw_parts(
827            core::ptr::addr_of!(_sapps),
828            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
829        ),
830        core::slice::from_raw_parts_mut(
831            core::ptr::addr_of_mut!(_sappmem),
832            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
833        ),
834        &mut *addr_of_mut!(PROCESSES),
835        &FAULT_RESPONSE,
836        &process_management_capability,
837    )
838    .unwrap_or_else(|err| {
839        debug!("Error loading processes!");
840        debug!("{:?}", err);
841    });
842
843    //Uncomment to run multi alarm test
844    /*components::test::multi_alarm_test::MultiAlarmTestComponent::new(mux_alarm)
845    .finalize(components::multi_alarm_test_component_buf!(stm32f412g::tim2::Tim2))
846    .run();*/
847
848    (board_kernel, stm32f412g, chip)
849}
850
851/// Main function called after RAM initialized.
852#[no_mangle]
853pub unsafe fn main() {
854    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
855
856    let (board_kernel, platform, chip) = start();
857    board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
858}