imix/
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 Imix development platform.
6//!
7//! - <https://github.com/tock/tock/tree/master/boards/imix>
8//! - <https://github.com/tock/imix>
9
10#![no_std]
11#![no_main]
12#![deny(missing_docs)]
13
14mod imix_components;
15
16use capsules_core::alarm::AlarmDriver;
17use capsules_core::console_ordered::ConsoleOrdered;
18use capsules_core::virtualizers::virtual_aes_ccm::MuxAES128CCM;
19use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
20use capsules_core::virtualizers::virtual_i2c::MuxI2C;
21use capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice;
22use capsules_extra::net::ieee802154::MacAddress;
23use capsules_extra::net::ipv6::ip_utils::IPAddr;
24use kernel::capabilities;
25use kernel::component::Component;
26use kernel::debug::PanicResources;
27use kernel::deferred_call::DeferredCallClient;
28use kernel::hil::i2c::I2CMaster;
29use kernel::hil::radio;
30#[allow(unused_imports)]
31use kernel::hil::radio::{RadioConfig, RadioData};
32use kernel::hil::symmetric_encryption::AES128;
33use kernel::platform::{KernelResources, SyscallDriverLookup};
34use kernel::scheduler::round_robin::RoundRobinSched;
35use kernel::utilities::single_thread_value::SingleThreadValue;
36
37//use kernel::hil::time::Alarm;
38use kernel::hil::led::LedHigh;
39use kernel::hil::Controller;
40#[allow(unused_imports)]
41use kernel::{create_capability, debug, debug_gpio, static_buf, static_init};
42use sam4l::chip::Sam4lDefaultPeripherals;
43
44use components::alarm::{AlarmDriverComponent, AlarmMuxComponent};
45use components::console::{ConsoleOrderedComponent, UartMuxComponent};
46use components::crc::CrcComponent;
47use components::debug_writer::DebugWriterComponent;
48use components::gpio::GpioComponent;
49use components::isl29035::AmbientLightComponent;
50use components::isl29035::Isl29035Component;
51use components::led::LedsComponent;
52use components::nrf51822::Nrf51822Component;
53use components::process_console::ProcessConsoleComponent;
54use components::rng::RngComponent;
55use components::si7021::SI7021Component;
56use components::spi::{SpiComponent, SpiSyscallComponent};
57
58/// Support routines for debugging I/O.
59///
60/// Note: Use of this module will trample any other USART3 configuration.
61pub mod io;
62
63// Unit Tests for drivers.
64#[allow(dead_code)]
65mod test;
66
67// Helper functions for enabling/disabling power on Imix submodules
68mod power;
69
70#[allow(dead_code)]
71mod alarm_test;
72
73#[allow(dead_code)]
74mod multi_timer_test;
75
76// State for loading apps.
77
78const NUM_PROCS: usize = 4;
79
80// Constants related to the configuration of the 15.4 network stack
81// TODO: Notably, the radio MAC addresses can be configured from userland at the moment
82// We probably want to change this from a security perspective (multiple apps being
83// able to change the MAC address seems problematic), but it is very convenient for
84// development to be able to just flash two corresponding apps onto two devices and
85// have those devices talk to each other without having to modify the kernel flashed
86// onto each device. This makes MAC address configuration a good target for capabilities -
87// only allow one app per board to have control of MAC address configuration?
88const RADIO_CHANNEL: radio::RadioChannel = radio::RadioChannel::Channel26;
89const DST_MAC_ADDR: MacAddress = MacAddress::Short(49138);
90const DEFAULT_CTX_PREFIX_LEN: u8 = 8; //Length of context for 6LoWPAN compression
91const DEFAULT_CTX_PREFIX: [u8; 16] = [0x0_u8; 16]; //Context for 6LoWPAN Compression
92const PAN_ID: u16 = 0xABCD;
93
94// how should the kernel respond when a process faults
95const FAULT_RESPONSE: capsules_system::process_policies::StopFaultPolicy =
96    capsules_system::process_policies::StopFaultPolicy {};
97
98type ChipHw = sam4l::chip::Sam4l<Sam4lDefaultPeripherals>;
99type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
100
101// TODO: remove once panic UART doesn't require an existing instance any more
102static mut CHIP: Option<&'static sam4l::chip::Sam4l<Sam4lDefaultPeripherals>> = None;
103
104/// Resources for when a board panics used by io.rs.
105static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
106    SingleThreadValue::new(PanicResources::new());
107
108kernel::stack_size! {0x2000}
109
110type SI7021Sensor = components::si7021::SI7021ComponentType<
111    capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>,
112    capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, sam4l::i2c::I2CHw<'static>>,
113>;
114type TemperatureDriver = components::temperature::TemperatureComponentType<SI7021Sensor>;
115type HumidityDriver = components::humidity::HumidityComponentType<SI7021Sensor>;
116type RngDriver = components::rng::RngComponentType<sam4l::trng::Trng<'static>>;
117
118type Rf233 = capsules_extra::rf233::RF233<
119    'static,
120    VirtualSpiMasterDevice<'static, sam4l::spi::SpiHw<'static>>,
121>;
122type Ieee802154MacDevice =
123    components::ieee802154::Ieee802154ComponentMacDeviceType<Rf233, sam4l::aes::Aes<'static>>;
124
125struct Imix {
126    pconsole: &'static capsules_core::process_console::ProcessConsole<
127        'static,
128        { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
129        capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
130            'static,
131            sam4l::ast::Ast<'static>,
132        >,
133        components::process_console::Capability,
134    >,
135    console: &'static capsules_core::console_ordered::ConsoleOrdered<
136        'static,
137        VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>,
138    >,
139    gpio: &'static capsules_core::gpio::GPIO<'static, sam4l::gpio::GPIOPin<'static>>,
140    alarm: &'static AlarmDriver<'static, VirtualMuxAlarm<'static, sam4l::ast::Ast<'static>>>,
141    temp: &'static TemperatureDriver,
142    humidity: &'static HumidityDriver,
143    ambient_light: &'static capsules_extra::ambient_light::AmbientLight<'static>,
144    adc: &'static capsules_core::adc::AdcDedicated<'static, sam4l::adc::Adc<'static>>,
145    led: &'static capsules_core::led::LedDriver<
146        'static,
147        LedHigh<'static, sam4l::gpio::GPIOPin<'static>>,
148        1,
149    >,
150    button: &'static capsules_core::button::Button<'static, sam4l::gpio::GPIOPin<'static>>,
151    rng: &'static RngDriver,
152    analog_comparator: &'static capsules_extra::analog_comparator::AnalogComparator<
153        'static,
154        sam4l::acifc::Acifc<'static>,
155    >,
156    spi: &'static capsules_core::spi_controller::Spi<
157        'static,
158        VirtualSpiMasterDevice<'static, sam4l::spi::SpiHw<'static>>,
159    >,
160    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
161    ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
162    udp_driver: &'static capsules_extra::net::udp::UDPDriver<'static>,
163    crc: &'static capsules_extra::crc::CrcDriver<'static, sam4l::crccu::Crccu<'static>>,
164    usb_driver: &'static capsules_extra::usb::usb_user::UsbSyscallDriver<
165        'static,
166        capsules_extra::usb::usbc_client::Client<'static, sam4l::usbc::Usbc<'static>>,
167    >,
168    nrf51822: &'static capsules_extra::nrf51822_serialization::Nrf51822Serialization<'static>,
169    nonvolatile_storage:
170        &'static capsules_extra::nonvolatile_storage_driver::NonvolatileStorage<'static>,
171    scheduler: &'static RoundRobinSched<'static>,
172    systick: cortexm4::systick::SysTick,
173}
174
175impl SyscallDriverLookup for Imix {
176    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
177    where
178        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
179    {
180        match driver_num {
181            capsules_core::console_ordered::DRIVER_NUM => f(Some(self.console)),
182            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
183            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
184            capsules_core::spi_controller::DRIVER_NUM => f(Some(self.spi)),
185            capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
186            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
187            capsules_core::button::DRIVER_NUM => f(Some(self.button)),
188            capsules_extra::analog_comparator::DRIVER_NUM => f(Some(self.analog_comparator)),
189            capsules_extra::ambient_light::DRIVER_NUM => f(Some(self.ambient_light)),
190            capsules_extra::temperature::DRIVER_NUM => f(Some(self.temp)),
191            capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
192            capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
193            capsules_extra::crc::DRIVER_NUM => f(Some(self.crc)),
194            capsules_extra::usb::usb_user::DRIVER_NUM => f(Some(self.usb_driver)),
195            capsules_extra::net::udp::DRIVER_NUM => f(Some(self.udp_driver)),
196            capsules_extra::nrf51822_serialization::DRIVER_NUM => f(Some(self.nrf51822)),
197            capsules_extra::nonvolatile_storage_driver::DRIVER_NUM => {
198                f(Some(self.nonvolatile_storage))
199            }
200            capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
201            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
202            _ => f(None),
203        }
204    }
205}
206
207impl KernelResources<sam4l::chip::Sam4l<Sam4lDefaultPeripherals>> for Imix {
208    type SyscallDriverLookup = Self;
209    type SyscallFilter = ();
210    type ProcessFault = ();
211    type Scheduler = RoundRobinSched<'static>;
212    type SchedulerTimer = cortexm4::systick::SysTick;
213    type WatchDog = ();
214    type ContextSwitchCallback = ();
215
216    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
217        self
218    }
219    fn syscall_filter(&self) -> &Self::SyscallFilter {
220        &()
221    }
222    fn process_fault(&self) -> &Self::ProcessFault {
223        &()
224    }
225    fn scheduler(&self) -> &Self::Scheduler {
226        self.scheduler
227    }
228    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
229        &self.systick
230    }
231    fn watchdog(&self) -> &Self::WatchDog {
232        &()
233    }
234    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
235        &()
236    }
237}
238
239unsafe fn set_pin_primary_functions(peripherals: &Sam4lDefaultPeripherals) {
240    use sam4l::gpio::PeripheralFunction::{A, B, C, E};
241
242    // Right column: Imix pin name
243    // Left  column: SAM4L peripheral function
244    peripherals.pa[04].configure(Some(A)); // AD0         --  ADCIFE AD0
245    peripherals.pa[05].configure(Some(A)); // AD1         --  ADCIFE AD1
246    peripherals.pa[06].configure(Some(C)); // EXTINT1     --  EIC EXTINT1
247    peripherals.pa[07].configure(Some(A)); // AD1         --  ADCIFE AD2
248    peripherals.pa[08].configure(None); //... RF233 IRQ   --  GPIO pin
249    peripherals.pa[09].configure(None); //... RF233 RST   --  GPIO pin
250    peripherals.pa[10].configure(None); //... RF233 SLP   --  GPIO pin
251    peripherals.pa[13].configure(None); //... TRNG EN     --  GPIO pin
252    peripherals.pa[14].configure(None); //... TRNG_OUT    --  GPIO pin
253    peripherals.pa[17].configure(None); //... NRF INT     -- GPIO pin
254    peripherals.pa[18].configure(Some(A)); // NRF CLK     -- USART2_CLK
255    peripherals.pa[20].configure(None); //... D8          -- GPIO pin
256    peripherals.pa[21].configure(Some(E)); // TWI2 SDA    -- TWIM2_SDA
257    peripherals.pa[22].configure(Some(E)); // TWI2 SCL    --  TWIM2 TWCK
258    peripherals.pa[25].configure(Some(A)); // USB_N       --  USB DM
259    peripherals.pa[26].configure(Some(A)); // USB_P       --  USB DP
260    peripherals.pb[00].configure(Some(A)); // TWI1_SDA    --  TWIMS1 TWD
261    peripherals.pb[01].configure(Some(A)); // TWI1_SCL    --  TWIMS1 TWCK
262    peripherals.pb[02].configure(Some(A)); // AD3         --  ADCIFE AD3
263    peripherals.pb[03].configure(Some(A)); // AD4         --  ADCIFE AD4
264    peripherals.pb[04].configure(Some(A)); // AD5         --  ADCIFE AD5
265    peripherals.pb[05].configure(Some(A)); // VHIGHSAMPLE --  ADCIFE AD6
266    peripherals.pb[06].configure(Some(A)); // RTS3        --  USART3 RTS
267    peripherals.pb[07].configure(None); //... NRF RESET   --  GPIO
268    peripherals.pb[09].configure(Some(A)); // RX3         --  USART3 RX
269    peripherals.pb[10].configure(Some(A)); // TX3         --  USART3 TX
270    peripherals.pb[11].configure(Some(A)); // CTS0        --  USART0 CTS
271    peripherals.pb[12].configure(Some(A)); // RTS0        --  USART0 RTS
272    peripherals.pb[13].configure(Some(A)); // CLK0        --  USART0 CLK
273    peripherals.pb[14].configure(Some(A)); // RX0         --  USART0 RX
274    peripherals.pb[15].configure(Some(A)); // TX0         --  USART0 TX
275    peripherals.pc[00].configure(Some(A)); // CS2         --  SPI Nperipherals.pcS2
276    peripherals.pc[01].configure(Some(A)); // CS3 (RF233) --  SPI Nperipherals.pcS3
277    peripherals.pc[02].configure(Some(A)); // CS1         --  SPI Nperipherals.pcS1
278    peripherals.pc[03].configure(Some(A)); // CS0         --  SPI Nperipherals.pcS0
279    peripherals.pc[04].configure(Some(A)); // MISO        --  SPI MISO
280    peripherals.pc[05].configure(Some(A)); // MOSI        --  SPI MOSI
281    peripherals.pc[06].configure(Some(A)); // SCK         --  SPI CLK
282    peripherals.pc[07].configure(Some(B)); // RTS2 (BLE)  -- USART2_RTS
283    peripherals.pc[08].configure(Some(E)); // CTS2 (BLE)  -- USART2_CTS
284                                           //peripherals.pc[09].configure(None); //... NRF GPIO    -- GPIO
285                                           //peripherals.pc[10].configure(None); //... USER LED    -- GPIO
286    peripherals.pc[09].configure(Some(E)); // ACAN1       -- ACIFC comparator
287    peripherals.pc[10].configure(Some(E)); // ACAP1       -- ACIFC comparator
288    peripherals.pc[11].configure(Some(B)); // RX2 (BLE)   -- USART2_RX
289    peripherals.pc[12].configure(Some(B)); // TX2 (BLE)   -- USART2_TX
290                                           //peripherals.pc[13].configure(None); //... ACC_INT1    -- GPIO
291                                           //peripherals.pc[14].configure(None); //... ACC_INT2    -- GPIO
292    peripherals.pc[13].configure(Some(E)); //... ACBN1    -- ACIFC comparator
293    peripherals.pc[14].configure(Some(E)); //... ACBP1    -- ACIFC comparator
294    peripherals.pc[16].configure(None); //... SENSE_PWR   --  GPIO pin
295    peripherals.pc[17].configure(None); //... NRF_PWR     --  GPIO pin
296    peripherals.pc[18].configure(None); //... RF233_PWR   --  GPIO pin
297    peripherals.pc[19].configure(None); //... TRNG_PWR    -- GPIO Pin
298    peripherals.pc[22].configure(None); //... KERNEL LED  -- GPIO Pin
299    peripherals.pc[24].configure(None); //... USER_BTN    -- GPIO Pin
300    peripherals.pc[25].configure(Some(B)); // LI_INT      --  EIC EXTINT2
301    peripherals.pc[26].configure(None); //... D7          -- GPIO Pin
302    peripherals.pc[27].configure(None); //... D6          -- GPIO Pin
303    peripherals.pc[28].configure(None); //... D5          -- GPIO Pin
304    peripherals.pc[29].configure(None); //... D4          -- GPIO Pin
305    peripherals.pc[30].configure(None); //... D3          -- GPIO Pin
306    peripherals.pc[31].configure(None); //... D2          -- GPIO Pin
307}
308
309/// This is in a separate, inline(never) function so that its stack frame is
310/// removed when this function returns. Otherwise, the stack space used for
311/// these static_inits is wasted.
312#[inline(never)]
313unsafe fn start() -> (
314    &'static kernel::Kernel,
315    Imix,
316    &'static sam4l::chip::Sam4l<Sam4lDefaultPeripherals>,
317) {
318    sam4l::init();
319
320    // Initialize deferred calls very early.
321    kernel::deferred_call::initialize_deferred_call_state::<
322        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
323    >();
324
325    // Bind global variables to this thread.
326    PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
327
328    let pm = static_init!(sam4l::pm::PowerManager, sam4l::pm::PowerManager::new());
329    let peripherals = static_init!(Sam4lDefaultPeripherals, Sam4lDefaultPeripherals::new(pm));
330
331    pm.setup_system_clock(
332        sam4l::pm::SystemClockSource::PllExternalOscillatorAt48MHz {
333            frequency: sam4l::pm::OscillatorFrequency::Frequency16MHz,
334            startup_mode: sam4l::pm::OscillatorStartup::FastStart,
335        },
336        &peripherals.flash_controller,
337    );
338
339    // Source 32Khz and 1Khz clocks from RC23K (SAM4L Datasheet 11.6.8)
340    sam4l::bpm::set_ck32source(sam4l::bpm::CK32Source::RC32K);
341
342    set_pin_primary_functions(peripherals);
343
344    peripherals.setup_circular_deps();
345    let chip = static_init!(
346        sam4l::chip::Sam4l<Sam4lDefaultPeripherals>,
347        sam4l::chip::Sam4l::new(pm, peripherals)
348    );
349    CHIP = Some(chip);
350    PANIC_RESOURCES.get().map(|resources| {
351        resources.chip.put(chip);
352    });
353
354    // Create capabilities that the board needs to call certain protected kernel
355    // functions.
356    let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
357
358    power::configure_submodules(
359        &peripherals.pa,
360        &peripherals.pb,
361        &peripherals.pc,
362        power::SubmoduleConfig {
363            rf233: true,
364            nrf51422: true,
365            sensors: true,
366            trng: true,
367        },
368    );
369
370    // Create an array to hold process references.
371    let processes = components::process_array::ProcessArrayComponent::new()
372        .finalize(components::process_array_component_static!(NUM_PROCS));
373    PANIC_RESOURCES.get().map(|resources| {
374        resources.processes.put(processes.as_slice());
375    });
376
377    // Setup space to store the core kernel data structure.
378    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
379
380    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
381        .finalize(components::process_printer_text_component_static!());
382    PANIC_RESOURCES.get().map(|resources| {
383        resources.printer.put(process_printer);
384    });
385
386    // # CONSOLE
387    // Create a shared UART channel for the consoles and for kernel debug.
388    peripherals.usart3.set_mode(sam4l::usart::UsartMode::Uart);
389    let uart_mux = UartMuxComponent::new(&peripherals.usart3, 115200)
390        .finalize(components::uart_mux_component_static!());
391
392    // # TIMER
393    let mux_alarm = AlarmMuxComponent::new(&peripherals.ast)
394        .finalize(components::alarm_mux_component_static!(sam4l::ast::Ast));
395    peripherals.ast.configure(mux_alarm);
396
397    let alarm =
398        AlarmDriverComponent::new(board_kernel, capsules_core::alarm::DRIVER_NUM, mux_alarm)
399            .finalize(components::alarm_component_static!(sam4l::ast::Ast));
400
401    let pconsole = ProcessConsoleComponent::new(
402        board_kernel,
403        uart_mux,
404        mux_alarm,
405        process_printer,
406        Some(cortexm4::support::reset),
407    )
408    .finalize(components::process_console_component_static!(
409        sam4l::ast::Ast
410    ));
411
412    let console = ConsoleOrderedComponent::new(
413        board_kernel,
414        capsules_core::console_ordered::DRIVER_NUM,
415        uart_mux,
416        mux_alarm,
417        200,
418        5,
419        5,
420    )
421    .finalize(components::console_ordered_component_static!(
422        sam4l::ast::Ast
423    ));
424    DebugWriterComponent::new::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>(
425        uart_mux,
426        create_capability!(capabilities::SetDebugWriterCapability),
427    )
428    .finalize(components::debug_writer_component_static!());
429
430    // Allow processes to communicate over BLE through the nRF51822
431    peripherals.usart2.set_mode(sam4l::usart::UsartMode::Uart);
432    let nrf_serialization = Nrf51822Component::new(
433        board_kernel,
434        capsules_extra::nrf51822_serialization::DRIVER_NUM,
435        &peripherals.usart2,
436        &peripherals.pb[07],
437    )
438    .finalize(components::nrf51822_component_static!());
439
440    // # I2C and I2C Sensors
441    let mux_i2c = static_init!(
442        MuxI2C<'static, sam4l::i2c::I2CHw<'static>>,
443        MuxI2C::new(&peripherals.i2c2, None)
444    );
445    kernel::deferred_call::DeferredCallClient::register(mux_i2c);
446    peripherals.i2c2.set_master_client(mux_i2c);
447
448    let isl29035 = Isl29035Component::new(mux_i2c, mux_alarm).finalize(
449        components::isl29035_component_static!(sam4l::ast::Ast, sam4l::i2c::I2CHw<'static>),
450    );
451    let ambient_light = AmbientLightComponent::new(
452        board_kernel,
453        capsules_extra::ambient_light::DRIVER_NUM,
454        isl29035,
455    )
456    .finalize(components::ambient_light_component_static!());
457
458    let si7021 = SI7021Component::new(mux_i2c, mux_alarm, 0x40).finalize(
459        components::si7021_component_static!(sam4l::ast::Ast, sam4l::i2c::I2CHw<'static>),
460    );
461    let temp = components::temperature::TemperatureComponent::new(
462        board_kernel,
463        capsules_extra::temperature::DRIVER_NUM,
464        si7021,
465    )
466    .finalize(components::temperature_component_static!(SI7021Sensor));
467    let humidity = components::humidity::HumidityComponent::new(
468        board_kernel,
469        capsules_extra::humidity::DRIVER_NUM,
470        si7021,
471    )
472    .finalize(components::humidity_component_static!(SI7021Sensor));
473
474    let fxos8700 = components::fxos8700::Fxos8700Component::new(mux_i2c, 0x1e, &peripherals.pc[13])
475        .finalize(components::fxos8700_component_static!(
476            sam4l::i2c::I2CHw<'static>
477        ));
478
479    let ninedof = components::ninedof::NineDofComponent::new(
480        board_kernel,
481        capsules_extra::ninedof::DRIVER_NUM,
482    )
483    .finalize(components::ninedof_component_static!(fxos8700));
484
485    // SPI MUX, SPI syscall driver and RF233 radio
486    let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.spi).finalize(
487        components::spi_mux_component_static!(sam4l::spi::SpiHw<'static>),
488    );
489
490    let spi_syscalls = SpiSyscallComponent::new(
491        board_kernel,
492        mux_spi,
493        sam4l::spi::Peripheral::Peripheral2,
494        capsules_core::spi_controller::DRIVER_NUM,
495    )
496    .finalize(components::spi_syscall_component_static!(
497        sam4l::spi::SpiHw<'static>
498    ));
499    let rf233_spi = SpiComponent::new(mux_spi, sam4l::spi::Peripheral::Peripheral3).finalize(
500        components::spi_component_static!(sam4l::spi::SpiHw<'static>),
501    );
502    let rf233 = components::rf233::RF233Component::new(
503        rf233_spi,
504        &peripherals.pa[09], // reset
505        &peripherals.pa[10], // sleep
506        &peripherals.pa[08], // irq
507        &peripherals.pa[08],
508        RADIO_CHANNEL,
509    )
510    .finalize(components::rf233_component_static!(
511        sam4l::spi::SpiHw<'static>
512    ));
513
514    // Setup ADC
515    let adc_channels = static_init!(
516        [sam4l::adc::AdcChannel; 6],
517        [
518            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD1), // AD0
519            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD2), // AD1
520            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD3), // AD2
521            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD4), // AD3
522            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD5), // AD4
523            sam4l::adc::AdcChannel::new(sam4l::adc::Channel::AD6), // AD5
524        ]
525    );
526    let adc = components::adc::AdcDedicatedComponent::new(
527        &peripherals.adc,
528        adc_channels,
529        board_kernel,
530        capsules_core::adc::DRIVER_NUM,
531    )
532    .finalize(components::adc_dedicated_component_static!(sam4l::adc::Adc));
533
534    let gpio = GpioComponent::new(
535        board_kernel,
536        capsules_core::gpio::DRIVER_NUM,
537        components::gpio_component_helper!(
538            sam4l::gpio::GPIOPin,
539            0 => &peripherals.pc[31],
540            1 => &peripherals.pc[30],
541            2 => &peripherals.pc[29],
542            3 => &peripherals.pc[28],
543            4 => &peripherals.pc[27],
544            5 => &peripherals.pc[26],
545            6 => &peripherals.pa[20]
546        ),
547    )
548    .finalize(components::gpio_component_static!(sam4l::gpio::GPIOPin));
549
550    let led = LedsComponent::new().finalize(components::led_component_static!(
551        LedHigh<'static, sam4l::gpio::GPIOPin>,
552        LedHigh::new(&peripherals.pc[10]),
553    ));
554
555    let button = components::button::ButtonComponent::new(
556        board_kernel,
557        capsules_core::button::DRIVER_NUM,
558        components::button_component_helper!(
559            sam4l::gpio::GPIOPin,
560            (
561                &peripherals.pc[24],
562                kernel::hil::gpio::ActivationMode::ActiveLow,
563                kernel::hil::gpio::FloatingState::PullNone
564            )
565        ),
566    )
567    .finalize(components::button_component_static!(sam4l::gpio::GPIOPin));
568
569    let crc = CrcComponent::new(
570        board_kernel,
571        capsules_extra::crc::DRIVER_NUM,
572        &peripherals.crccu,
573    )
574    .finalize(components::crc_component_static!(sam4l::crccu::Crccu));
575
576    let ac_0 = static_init!(
577        sam4l::acifc::AcChannel,
578        sam4l::acifc::AcChannel::new(sam4l::acifc::Channel::AC0)
579    );
580    let ac_1 = static_init!(
581        sam4l::acifc::AcChannel,
582        sam4l::acifc::AcChannel::new(sam4l::acifc::Channel::AC0)
583    );
584    let ac_2 = static_init!(
585        sam4l::acifc::AcChannel,
586        sam4l::acifc::AcChannel::new(sam4l::acifc::Channel::AC0)
587    );
588    let ac_3 = static_init!(
589        sam4l::acifc::AcChannel,
590        sam4l::acifc::AcChannel::new(sam4l::acifc::Channel::AC0)
591    );
592    let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
593        &peripherals.acifc,
594        components::analog_comparator_component_helper!(
595            <sam4l::acifc::Acifc as kernel::hil::analog_comparator::AnalogComparator>::Channel,
596            ac_0,
597            ac_1,
598            ac_2,
599            ac_3
600        ),
601        board_kernel,
602        capsules_extra::analog_comparator::DRIVER_NUM,
603    )
604    .finalize(components::analog_comparator_component_static!(
605        sam4l::acifc::Acifc
606    ));
607    let rng = RngComponent::new(
608        board_kernel,
609        capsules_core::rng::DRIVER_NUM,
610        &peripherals.trng,
611    )
612    .finalize(components::rng_component_static!(sam4l::trng::Trng));
613
614    // For now, assign the 802.15.4 MAC address on the device as
615    // simply a 16-bit short address which represents the last 16 bits
616    // of the serial number of the sam4l for this device.  In the
617    // future, we could generate the DEFAULT_EXT_SRC_MAC address by hashing the full
618    // 120-bit serial number
619    let serial_num: sam4l::serial_num::SerialNum = sam4l::serial_num::SerialNum::new();
620    let serial_num_bottom_16 = (serial_num.get_lower_64() & 0x0000_0000_0000_ffff) as u16;
621    let src_mac_from_serial_num: MacAddress = MacAddress::Short(serial_num_bottom_16);
622    const DEFAULT_EXT_SRC_MAC: [u8; 8] = [0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77];
623
624    let aes_mux = static_init!(
625        MuxAES128CCM<'static, sam4l::aes::Aes>,
626        MuxAES128CCM::new(&peripherals.aes)
627    );
628    aes_mux.register();
629    peripherals.aes.set_client(aes_mux);
630
631    let (_, mux_mac) = components::ieee802154::Ieee802154Component::new(
632        board_kernel,
633        capsules_extra::ieee802154::DRIVER_NUM,
634        rf233,
635        aes_mux,
636        PAN_ID,
637        serial_num_bottom_16,
638        DEFAULT_EXT_SRC_MAC,
639    )
640    .finalize(components::ieee802154_component_static!(
641        capsules_extra::rf233::RF233<
642            'static,
643            VirtualSpiMasterDevice<'static, sam4l::spi::SpiHw<'static>>,
644        >,
645        sam4l::aes::Aes<'static>
646    ));
647
648    let usb_driver = components::usb::UsbComponent::new(
649        board_kernel,
650        capsules_extra::usb::usb_user::DRIVER_NUM,
651        &peripherals.usbc,
652    )
653    .finalize(components::usb_component_static!(sam4l::usbc::Usbc));
654
655    // Kernel storage region, allocated with the storage_volume!
656    // macro in common/utils.rs
657    extern "C" {
658        /// Beginning on the ROM region containing app images.
659        static _sstorage: u8;
660        static _estorage: u8;
661    }
662
663    let nonvolatile_storage = components::nonvolatile_storage::NonvolatileStorageComponent::new(
664        board_kernel,
665        capsules_extra::nonvolatile_storage_driver::DRIVER_NUM,
666        &peripherals.flash_controller,
667        0x60000, // Start address for userspace accessible region
668        0x20000, // Length of userspace accessible region
669        core::ptr::addr_of!(_sstorage) as usize, //start address of kernel region
670        core::ptr::addr_of!(_estorage) as usize - core::ptr::addr_of!(_sstorage) as usize, // length of kernel region
671    )
672    .finalize(components::nonvolatile_storage_component_static!(
673        sam4l::flashcalw::FLASHCALW
674    ));
675
676    let local_ip_ifaces = static_init!(
677        [IPAddr; 3],
678        [
679            IPAddr([
680                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
681                0x0e, 0x0f,
682            ]),
683            IPAddr([
684                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
685                0x1e, 0x1f,
686            ]),
687            IPAddr::generate_from_mac(src_mac_from_serial_num),
688        ]
689    );
690
691    let (udp_send_mux, udp_recv_mux, udp_port_table) = components::udp_mux::UDPMuxComponent::new(
692        mux_mac,
693        DEFAULT_CTX_PREFIX_LEN,
694        DEFAULT_CTX_PREFIX,
695        DST_MAC_ADDR,
696        src_mac_from_serial_num, //comment out for dual rx test only
697        //MacAddress::Short(49138), //comment in for dual rx test only
698        local_ip_ifaces,
699        mux_alarm,
700    )
701    .finalize(components::udp_mux_component_static!(
702        sam4l::ast::Ast,
703        Ieee802154MacDevice
704    ));
705
706    // UDP driver initialization happens here
707    let udp_driver = components::udp_driver::UDPDriverComponent::new(
708        board_kernel,
709        capsules_extra::net::udp::driver::DRIVER_NUM,
710        udp_send_mux,
711        udp_recv_mux,
712        udp_port_table,
713        local_ip_ifaces,
714    )
715    .finalize(components::udp_driver_component_static!(sam4l::ast::Ast));
716
717    let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
718        .finalize(components::round_robin_component_static!(NUM_PROCS));
719
720    // Create the software-based SHA engine.
721    let sha = components::sha::ShaSoftware256Component::new()
722        .finalize(components::sha_software_256_component_static!());
723
724    // Create the credential checker.
725    let checking_policy = components::appid::checker_sha::AppCheckerSha256Component::new(sha)
726        .finalize(components::app_checker_sha256_component_static!());
727
728    // Create the AppID assigner.
729    let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
730        .finalize(components::appid_assigner_names_component_static!());
731
732    // Create the process checking machine.
733    let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
734        .finalize(components::process_checker_machine_component_static!());
735
736    //--------------------------------------------------------------------------
737    // STORAGE PERMISSIONS
738    //--------------------------------------------------------------------------
739
740    let storage_permissions_policy =
741        components::storage_permissions::individual::StoragePermissionsIndividualComponent::new()
742            .finalize(
743                components::storage_permissions_individual_component_static!(
744                    sam4l::chip::Sam4l<Sam4lDefaultPeripherals>,
745                    kernel::process::ProcessStandardDebugFull,
746                ),
747            );
748
749    //--------------------------------------------------------------------------
750    // PROCESS LOADING
751    //--------------------------------------------------------------------------
752
753    // These symbols are defined in the standard Tock linker script.
754    extern "C" {
755        /// Beginning of the ROM region containing app images.
756        static _sapps: u8;
757        /// End of the ROM region containing app images.
758        static _eapps: u8;
759        /// Beginning of the RAM region for app memory.
760        static mut _sappmem: u8;
761        /// End of the RAM region for app memory.
762        static _eappmem: u8;
763    }
764
765    let app_flash = core::slice::from_raw_parts(
766        core::ptr::addr_of!(_sapps),
767        core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
768    );
769    let app_memory = core::slice::from_raw_parts_mut(
770        core::ptr::addr_of_mut!(_sappmem),
771        core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
772    );
773
774    // Create and start the asynchronous process loader.
775    let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
776        checker,
777        board_kernel,
778        chip,
779        &FAULT_RESPONSE,
780        assigner,
781        storage_permissions_policy,
782        app_flash,
783        app_memory,
784    )
785    .finalize(components::process_loader_sequential_component_static!(
786        sam4l::chip::Sam4l<Sam4lDefaultPeripherals>,
787        kernel::process::ProcessStandardDebugFull,
788        NUM_PROCS
789    ));
790
791    let imix = Imix {
792        pconsole,
793        console,
794        alarm,
795        gpio,
796        temp,
797        humidity,
798        ambient_light,
799        adc,
800        led,
801        button,
802        rng,
803        analog_comparator,
804        crc,
805        spi: spi_syscalls,
806        ipc: kernel::ipc::IPC::new(board_kernel, kernel::ipc::DRIVER_NUM, &grant_cap),
807        ninedof,
808        udp_driver,
809        usb_driver,
810        nrf51822: nrf_serialization,
811        nonvolatile_storage,
812        scheduler,
813        systick: cortexm4::systick::SysTick::new(),
814    };
815
816    // Need to initialize the UART for the nRF51 serialization.
817    imix.nrf51822.initialize();
818
819    // These two lines need to be below the creation of the chip for
820    // initialization to work.
821    let _ = rf233.reset();
822    let _ = rf233.start();
823
824    let _ = imix.pconsole.start();
825
826    // Optional kernel tests. Note that these might conflict
827    // with normal operation (e.g., steal callbacks from drivers, etc.),
828    // so do not run these and expect all services/applications to work.
829    // Once everything is virtualized in the kernel this won't be a problem.
830    // -pal, 11/20/18
831    //
832    //test::virtual_uart_rx_test::run_virtual_uart_receive(uart_mux);
833    //test::rng_test::run_entropy32(&peripherals.trng);
834    //test::virtual_aes_ccm_test::run(&peripherals.aes);
835    //test::aes_test::run_aes128_ctr(&peripherals.aes);
836    //test::aes_test::run_aes128_cbc(&peripherals.aes);
837    //test::log_test::run(
838    //    mux_alarm,
839    //    &peripherals.flash_controller,
840    //);
841    //test::linear_log_test::run(
842    //    mux_alarm,
843    //    &peripherals.flash_controller,
844    //);
845    //test::icmp_lowpan_test::run(mux_mac, mux_alarm);
846    //let lowpan_frag_test = test::ipv6_lowpan_test::initialize_all(mux_mac, mux_alarm);
847    //lowpan_frag_test.start(); // If flashing the transmitting Imix
848    /*let udp_lowpan_test = test::udp_lowpan_test::initialize_all(
849       udp_send_mux,
850        udp_recv_mux,
851        udp_port_table,
852        mux_alarm,
853    );*/
854    //udp_lowpan_test.start();
855
856    // alarm_test::run_alarm(&peripherals.ast);
857    /*let virtual_alarm_timer = static_init!(
858        VirtualMuxAlarm<'static, sam4l::ast::Ast>,
859        VirtualMuxAlarm::new(mux_alarm)
860    );
861    virtual_alarm_timer.setup();
862
863    let mux_timer = static_init!(
864        MuxTimer<'static, sam4l::ast::Ast>,
865        MuxTimer::new(virtual_alarm_timer)
866    );*/
867    //virtual_alarm_timer.set_alarm_client(mux_timer);
868
869    //test::sha256_test::run_sha256();
870
871    /*components::test::multi_alarm_test::MultiAlarmTestComponent::new(mux_alarm)
872    .finalize(components::multi_alarm_test_component_buf!(sam4l::ast::Ast))
873    .run();*/
874
875    debug!("Initialization complete. Entering main loop");
876
877    (board_kernel, imix, chip)
878}
879
880/// Main function called after RAM initialized.
881#[no_mangle]
882pub unsafe fn main() {
883    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
884
885    let (board_kernel, platform, chip) = start();
886    board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
887}