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