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