1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of;
14
15use kernel::capabilities;
16use kernel::component::Component;
17use kernel::hil::led::LedLow;
18use kernel::hil::time::Counter;
19use kernel::hil::usb::Client;
20use kernel::platform::{KernelResources, SyscallDriverLookup};
21use kernel::process::ProcessArray;
22use kernel::scheduler::round_robin::RoundRobinSched;
23#[allow(unused_imports)]
24use kernel::{create_capability, debug, debug_gpio, debug_verbose, static_init};
25
26use nrf52840::gpio::Pin;
27use nrf52840::interrupt_service::Nrf52840DefaultPeripherals;
28
29const LED_PIN: Pin = Pin::P1_11;
35
36const BUTTON_RST_PIN: Pin = Pin::P0_18;
37const BUTTON_PIN: Pin = Pin::P1_15;
38
39const GPIO_D0: Pin = Pin::P0_23;
40const GPIO_D1: Pin = Pin::P0_12;
41const GPIO_D2: Pin = Pin::P0_09;
42const GPIO_D3: Pin = Pin::P0_07;
43
44const _UART_TX_PIN: Pin = Pin::P0_06;
45const _UART_RX_PIN: Pin = Pin::P0_08;
46
47const I2C_SDA_PIN: Pin = Pin::P0_26;
49const I2C_SCL_PIN: Pin = Pin::P0_27;
50
51const PAN_ID: u16 = 0xABCD;
54const DST_MAC_ADDR: capsules_extra::net::ieee802154::MacAddress =
56 capsules_extra::net::ieee802154::MacAddress::Short(49138);
57const DEFAULT_CTX_PREFIX_LEN: u8 = 8; const DEFAULT_CTX_PREFIX: [u8; 16] = [0x0_u8; 16]; pub mod io;
62
63const FAULT_RESPONSE: capsules_system::process_policies::StopWithDebugFaultPolicy =
68 capsules_system::process_policies::StopWithDebugFaultPolicy {};
69
70const NUM_PROCS: usize = 8;
72
73static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
75static mut CHIP: Option<&'static nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>> = None;
76static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
77 None;
78static mut CDC_REF_FOR_PANIC: Option<
79 &'static capsules_extra::usb::cdc::CdcAcm<
80 'static,
81 nrf52::usbd::Usbd,
82 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc>,
83 >,
84> = None;
85static mut NRF52_POWER: Option<&'static nrf52840::power::Power> = None;
86
87kernel::stack_size! {0x1000}
88
89fn baud_rate_reset_bootloader_enter() {
91 unsafe {
92 NRF52_POWER.unwrap().set_gpregret(0x90);
94 cortexm4::scb::reset();
95 }
96}
97
98fn crc(s: &'static str) -> u32 {
99 kernel::utilities::helpers::crc32_posix(s.as_bytes())
100}
101
102type AlarmDriver = components::alarm::AlarmDriverComponentType<nrf52840::rtc::Rtc<'static>>;
107
108type Screen = components::ssd1306::Ssd1306ComponentType<nrf52840::i2c::TWI<'static>>;
109type ScreenDriver = components::screen::ScreenSharedComponentType<Screen>;
110
111type Ieee802154MacDevice = components::ieee802154::Ieee802154ComponentMacDeviceType<
112 nrf52840::ieee802154_radio::Radio<'static>,
113 nrf52840::aes::AesECB<'static>,
114>;
115type Ieee802154Driver = components::ieee802154::Ieee802154ComponentType<
116 nrf52840::ieee802154_radio::Radio<'static>,
117 nrf52840::aes::AesECB<'static>,
118>;
119type RngDriver = components::rng::RngComponentType<nrf52840::trng::Trng<'static>>;
120
121pub struct Platform {
123 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
124 'static,
125 nrf52::ble_radio::Radio<'static>,
126 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
127 'static,
128 nrf52::rtc::Rtc<'static>,
129 >,
130 >,
131 ieee802154_radio: &'static Ieee802154Driver,
132 console: &'static capsules_core::console::Console<'static>,
133 pconsole: &'static capsules_core::process_console::ProcessConsole<
134 'static,
135 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
136 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
137 'static,
138 nrf52::rtc::Rtc<'static>,
139 >,
140 components::process_console::Capability,
141 >,
142 gpio: &'static capsules_core::gpio::GPIO<'static, nrf52::gpio::GPIOPin<'static>>,
143 led: &'static capsules_core::led::LedDriver<
144 'static,
145 LedLow<'static, nrf52::gpio::GPIOPin<'static>>,
146 1,
147 >,
148 adc: &'static capsules_core::adc::AdcVirtualized<'static>,
149 rng: &'static RngDriver,
150 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
151 alarm: &'static AlarmDriver,
152 button: &'static capsules_core::button::Button<'static, nrf52840::gpio::GPIOPin<'static>>,
153 screen: &'static ScreenDriver,
154 udp_driver: &'static capsules_extra::net::udp::UDPDriver<'static>,
155 scheduler: &'static RoundRobinSched<'static>,
156 systick: cortexm4::systick::SysTick,
157}
158
159impl SyscallDriverLookup for Platform {
160 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
161 where
162 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
163 {
164 match driver_num {
165 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
166 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
167 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
168 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
169 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
170 capsules_core::adc::DRIVER_NUM => f(Some(self.adc)),
171 capsules_core::rng::DRIVER_NUM => f(Some(self.rng)),
172 capsules_extra::screen::screen::DRIVER_NUM => f(Some(self.screen)),
173 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
174 capsules_extra::ieee802154::DRIVER_NUM => f(Some(self.ieee802154_radio)),
175 capsules_extra::net::udp::DRIVER_NUM => f(Some(self.udp_driver)),
176 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
177 _ => f(None),
178 }
179 }
180}
181
182impl KernelResources<nrf52::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>>
183 for Platform
184{
185 type SyscallDriverLookup = Self;
186 type SyscallFilter = ();
187 type ProcessFault = ();
188 type Scheduler = RoundRobinSched<'static>;
189 type SchedulerTimer = cortexm4::systick::SysTick;
190 type WatchDog = ();
191 type ContextSwitchCallback = ();
192
193 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
194 self
195 }
196 fn syscall_filter(&self) -> &Self::SyscallFilter {
197 &()
198 }
199 fn process_fault(&self) -> &Self::ProcessFault {
200 &()
201 }
202 fn scheduler(&self) -> &Self::Scheduler {
203 self.scheduler
204 }
205 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
206 &self.systick
207 }
208 fn watchdog(&self) -> &Self::WatchDog {
209 &()
210 }
211 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
212 &()
213 }
214}
215
216#[inline(never)]
220pub unsafe fn start() -> (
221 &'static kernel::Kernel,
222 Platform,
223 &'static nrf52840::chip::NRF52<'static, Nrf52840DefaultPeripherals<'static>>,
224) {
225 nrf52840::init();
226
227 let ieee802154_ack_buf = static_init!(
228 [u8; nrf52840::ieee802154_radio::ACK_BUF_SIZE],
229 [0; nrf52840::ieee802154_radio::ACK_BUF_SIZE]
230 );
231
232 let nrf52840_peripherals = static_init!(
234 Nrf52840DefaultPeripherals,
235 Nrf52840DefaultPeripherals::new(ieee802154_ack_buf)
236 );
237
238 nrf52840_peripherals.init();
240 let base_peripherals = &nrf52840_peripherals.nrf52;
241
242 NRF52_POWER = Some(&base_peripherals.pwr_clk);
245
246 let processes = components::process_array::ProcessArrayComponent::new()
248 .finalize(components::process_array_component_static!(NUM_PROCS));
249 PROCESSES = Some(processes);
250
251 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
253
254 nrf52_components::startup::NrfStartupComponent::new(
257 false,
258 BUTTON_RST_PIN,
259 nrf52840::uicr::Regulator0Output::DEFAULT,
260 &base_peripherals.nvmc,
261 )
262 .finalize(());
263
264 let chip = static_init!(
265 nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
266 nrf52840::chip::NRF52::new(nrf52840_peripherals)
267 );
268 CHIP = Some(chip);
269
270 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
277
278 kernel::debug::assign_gpios(Some(&nrf52840_peripherals.gpio_port[LED_PIN]), None, None);
286
287 let gpio = components::gpio::GpioComponent::new(
292 board_kernel,
293 capsules_core::gpio::DRIVER_NUM,
294 components::gpio_component_helper!(
295 nrf52840::gpio::GPIOPin,
296 0 => &nrf52840_peripherals.gpio_port[GPIO_D0],
297 1 => &nrf52840_peripherals.gpio_port[GPIO_D1],
298 2 => &nrf52840_peripherals.gpio_port[GPIO_D2],
299 3 => &nrf52840_peripherals.gpio_port[GPIO_D3],
300 ),
301 )
302 .finalize(components::gpio_component_static!(nrf52840::gpio::GPIOPin));
303
304 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
309 LedLow<'static, nrf52840::gpio::GPIOPin>,
310 LedLow::new(&nrf52840_peripherals.gpio_port[LED_PIN]),
311 ));
312
313 let button = components::button::ButtonComponent::new(
318 board_kernel,
319 capsules_core::button::DRIVER_NUM,
320 components::button_component_helper!(
321 nrf52840::gpio::GPIOPin,
322 (
323 &nrf52840_peripherals.gpio_port[BUTTON_PIN],
324 kernel::hil::gpio::ActivationMode::ActiveLow,
325 kernel::hil::gpio::FloatingState::PullUp
326 )
327 ),
328 )
329 .finalize(components::button_component_static!(
330 nrf52840::gpio::GPIOPin
331 ));
332
333 let rtc = &base_peripherals.rtc;
338 let _ = rtc.start();
339
340 let mux_alarm = components::alarm::AlarmMuxComponent::new(rtc)
341 .finalize(components::alarm_mux_component_static!(nrf52::rtc::Rtc));
342 let alarm = components::alarm::AlarmDriverComponent::new(
343 board_kernel,
344 capsules_core::alarm::DRIVER_NUM,
345 mux_alarm,
346 )
347 .finalize(components::alarm_component_static!(nrf52::rtc::Rtc));
348
349 let serial_number_buf = static_init!([u8; 17], [0; 17]);
359 let serial_number_string: &'static str =
360 (*addr_of!(nrf52::ficr::FICR_INSTANCE)).address_str(serial_number_buf);
361 let strings = static_init!(
362 [&str; 3],
363 [
364 "MakePython", "NRF52840 - TockOS", serial_number_string, ]
368 );
369
370 let cdc = components::cdc::CdcAcmComponent::new(
371 &nrf52840_peripherals.usbd,
372 capsules_extra::usb::cdc::MAX_CTRL_PACKET_SIZE_NRF52840,
373 0x2341,
374 0x005a,
375 strings,
376 mux_alarm,
377 Some(&baud_rate_reset_bootloader_enter),
378 )
379 .finalize(components::cdc_acm_component_static!(
380 nrf52::usbd::Usbd,
381 nrf52::rtc::Rtc
382 ));
383 CDC_REF_FOR_PANIC = Some(cdc); let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
387 .finalize(components::process_printer_text_component_static!());
388 PROCESS_PRINTER = Some(process_printer);
389
390 let uart_mux = components::console::UartMuxComponent::new(cdc, 115200)
392 .finalize(components::uart_mux_component_static!());
393
394 let pconsole = components::process_console::ProcessConsoleComponent::new(
395 board_kernel,
396 uart_mux,
397 mux_alarm,
398 process_printer,
399 Some(cortexm4::support::reset),
400 )
401 .finalize(components::process_console_component_static!(
402 nrf52::rtc::Rtc<'static>
403 ));
404
405 let console = components::console::ConsoleComponent::new(
407 board_kernel,
408 capsules_core::console::DRIVER_NUM,
409 uart_mux,
410 )
411 .finalize(components::console_component_static!());
412 components::debug_writer::DebugWriterComponent::new(
414 uart_mux,
415 create_capability!(capabilities::SetDebugWriterCapability),
416 )
417 .finalize(components::debug_writer_component_static!());
418
419 let rng = components::rng::RngComponent::new(
424 board_kernel,
425 capsules_core::rng::DRIVER_NUM,
426 &base_peripherals.trng,
427 )
428 .finalize(components::rng_component_static!(nrf52840::trng::Trng));
429
430 base_peripherals.adc.calibrate();
434
435 let adc_mux = components::adc::AdcMuxComponent::new(&base_peripherals.adc)
436 .finalize(components::adc_mux_component_static!(nrf52840::adc::Adc));
437
438 let adc_syscall =
439 components::adc::AdcVirtualComponent::new(board_kernel, capsules_core::adc::DRIVER_NUM)
440 .finalize(components::adc_syscall_component_helper!(
441 components::adc::AdcComponent::new(
443 adc_mux,
444 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput2)
445 )
446 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
447 components::adc::AdcComponent::new(
449 adc_mux,
450 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput3)
451 )
452 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
453 components::adc::AdcComponent::new(
455 adc_mux,
456 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput6)
457 )
458 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
459 components::adc::AdcComponent::new(
461 adc_mux,
462 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput5)
463 )
464 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
465 components::adc::AdcComponent::new(
467 adc_mux,
468 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput7)
469 )
470 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
471 components::adc::AdcComponent::new(
473 adc_mux,
474 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput0)
475 )
476 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
477 components::adc::AdcComponent::new(
479 adc_mux,
480 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput4)
481 )
482 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
483 components::adc::AdcComponent::new(
485 adc_mux,
486 nrf52840::adc::AdcChannelSetup::new(nrf52840::adc::AdcChannel::AnalogInput1)
487 )
488 .finalize(components::adc_component_static!(nrf52840::adc::Adc)),
489 ));
490
491 let i2c_bus = components::i2c::I2CMuxComponent::new(&base_peripherals.twi1, None)
496 .finalize(components::i2c_mux_component_static!(nrf52840::i2c::TWI));
497 base_peripherals.twi1.configure(
498 nrf52840::pinmux::Pinmux::new(I2C_SCL_PIN as u32),
499 nrf52840::pinmux::Pinmux::new(I2C_SDA_PIN as u32),
500 );
501
502 let ssd1306_i2c = components::i2c::I2CComponent::new(i2c_bus, 0x3c)
504 .finalize(components::i2c_component_static!(nrf52840::i2c::TWI));
505
506 let ssd1306 = components::ssd1306::Ssd1306Component::new(ssd1306_i2c, true)
508 .finalize(components::ssd1306_component_static!(nrf52840::i2c::TWI));
509
510 let apps_regions = static_init!(
520 [capsules_extra::screen::screen_shared::AppScreenRegion; 3],
521 [
522 capsules_extra::screen::screen_shared::AppScreenRegion::new(
523 kernel::process::ShortId::Fixed(core::num::NonZeroU32::new(crc("circle")).unwrap()),
524 0, 0, 8 * 8, 8 * 8 ),
529 capsules_extra::screen::screen_shared::AppScreenRegion::new(
530 kernel::process::ShortId::Fixed(core::num::NonZeroU32::new(crc("count")).unwrap()),
531 8 * 8, 0, 8 * 8, 4 * 8 ),
536 capsules_extra::screen::screen_shared::AppScreenRegion::new(
537 kernel::process::ShortId::Fixed(
538 core::num::NonZeroU32::new(crc("tock-scroll")).unwrap()
539 ),
540 8 * 8, 4 * 8, 8 * 8, 4 * 8 )
545 ]
546 );
547
548 let screen = components::screen::ScreenSharedComponent::new(
549 board_kernel,
550 capsules_extra::screen::screen::DRIVER_NUM,
551 ssd1306,
552 apps_regions,
553 )
554 .finalize(components::screen_shared_component_static!(1032, Screen));
555
556 let ble_radio = components::ble::BLEComponent::new(
561 board_kernel,
562 capsules_extra::ble_advertising_driver::DRIVER_NUM,
563 &base_peripherals.ble_radio,
564 mux_alarm,
565 )
566 .finalize(components::ble_component_static!(
567 nrf52840::rtc::Rtc,
568 nrf52840::ble_radio::Radio
569 ));
570
571 use capsules_extra::net::ieee802154::MacAddress;
572
573 let aes_mux = components::ieee802154::MuxAes128ccmComponent::new(&base_peripherals.ecb)
574 .finalize(components::mux_aes128ccm_component_static!(
575 nrf52840::aes::AesECB
576 ));
577
578 let device_id = (*addr_of!(nrf52840::ficr::FICR_INSTANCE)).id();
579 let device_id_bottom_16 = u16::from_le_bytes([device_id[0], device_id[1]]);
580 let (ieee802154_radio, mux_mac) = components::ieee802154::Ieee802154Component::new(
581 board_kernel,
582 capsules_extra::ieee802154::DRIVER_NUM,
583 &nrf52840_peripherals.ieee802154_radio,
584 aes_mux,
585 PAN_ID,
586 device_id_bottom_16,
587 device_id,
588 )
589 .finalize(components::ieee802154_component_static!(
590 nrf52840::ieee802154_radio::Radio,
591 nrf52840::aes::AesECB<'static>
592 ));
593 use capsules_extra::net::ipv6::ip_utils::IPAddr;
594
595 let local_ip_ifaces = static_init!(
596 [IPAddr; 3],
597 [
598 IPAddr([
599 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
600 0x0e, 0x0f,
601 ]),
602 IPAddr([
603 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
604 0x1e, 0x1f,
605 ]),
606 IPAddr::generate_from_mac(capsules_extra::net::ieee802154::MacAddress::Short(
607 device_id_bottom_16
608 )),
609 ]
610 );
611
612 let (udp_send_mux, udp_recv_mux, udp_port_table) = components::udp_mux::UDPMuxComponent::new(
613 mux_mac,
614 DEFAULT_CTX_PREFIX_LEN,
615 DEFAULT_CTX_PREFIX,
616 DST_MAC_ADDR,
617 MacAddress::Short(device_id_bottom_16),
618 local_ip_ifaces,
619 mux_alarm,
620 )
621 .finalize(components::udp_mux_component_static!(
622 nrf52840::rtc::Rtc,
623 Ieee802154MacDevice
624 ));
625
626 let udp_driver = components::udp_driver::UDPDriverComponent::new(
628 board_kernel,
629 capsules_extra::net::udp::DRIVER_NUM,
630 udp_send_mux,
631 udp_recv_mux,
632 udp_port_table,
633 local_ip_ifaces,
634 )
635 .finalize(components::udp_driver_component_static!(nrf52840::rtc::Rtc));
636
637 let sha = components::sha::ShaSoftware256Component::new()
643 .finalize(components::sha_software_256_component_static!());
644
645 let checking_policy = components::appid::checker_sha::AppCheckerSha256Component::new(sha)
647 .finalize(components::app_checker_sha256_component_static!());
648
649 let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
651 .finalize(components::appid_assigner_names_component_static!());
652
653 let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
655 .finalize(components::process_checker_machine_component_static!());
656
657 let storage_permissions_policy =
662 components::storage_permissions::individual::StoragePermissionsIndividualComponent::new()
663 .finalize(
664 components::storage_permissions_individual_component_static!(
665 nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
666 kernel::process::ProcessStandardDebugFull,
667 ),
668 );
669
670 extern "C" {
676 static _sapps: u8;
678 static _eapps: u8;
680 static mut _sappmem: u8;
682 static _eappmem: u8;
684 }
685
686 let app_flash = core::slice::from_raw_parts(
687 core::ptr::addr_of!(_sapps),
688 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
689 );
690 let app_memory = core::slice::from_raw_parts_mut(
691 core::ptr::addr_of_mut!(_sappmem),
692 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
693 );
694
695 let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
697 checker,
698 board_kernel,
699 chip,
700 &FAULT_RESPONSE,
701 assigner,
702 storage_permissions_policy,
703 app_flash,
704 app_memory,
705 )
706 .finalize(components::process_loader_sequential_component_static!(
707 nrf52840::chip::NRF52<Nrf52840DefaultPeripherals>,
708 kernel::process::ProcessStandardDebugFull,
709 NUM_PROCS
710 ));
711
712 nrf52_components::NrfClockComponent::new(&base_peripherals.clock).finalize(());
719
720 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
721 .finalize(components::round_robin_component_static!(NUM_PROCS));
722
723 let platform = Platform {
724 ble_radio,
725 ieee802154_radio,
726 console,
727 pconsole,
728 adc: adc_syscall,
729 led,
730 button,
731 gpio,
732 rng,
733 screen,
734 alarm,
735 udp_driver,
736 ipc: kernel::ipc::IPC::new(
737 board_kernel,
738 kernel::ipc::DRIVER_NUM,
739 &memory_allocation_capability,
740 ),
741 scheduler,
742 systick: cortexm4::systick::SysTick::new_with_calibration(64000000),
743 };
744
745 cdc.enable();
747 cdc.attach();
748
749 debug!("Initialization complete. Entering main loop.");
762 let _ = platform.pconsole.start();
763
764 ssd1306.init_screen();
765
766 (board_kernel, platform, chip)
771}
772
773#[no_mangle]
775pub unsafe fn main() {
776 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
777
778 let (board_kernel, platform, chip) = start();
779 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
780}