1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //! Main Rust Application for PineTime with Apache Mynewt OS #![no_std] // Don't link with standard Rust library, which is not compatible with embedded systems #![feature(trace_macros)] // Allow macro tracing: `trace_macros!(true)` #![feature(concat_idents)] // Allow `concat_idents!()` macro used in `coap!()` macro #![feature(const_transmute)] // Allow `transmute` for initialising Mynewt structs #![feature(proc_macro_hygiene)] // Allow Procedural Macros like `run!()` #![feature(specialization)] // Allow Specialised Traits for druid UI library #![feature(exclusive_range_pattern)] // Allow ranges like `0..128` in `match` statements // Declare the libraries that contain macros extern crate cortex_m; // Declare the external library `cortex_m` extern crate mynewt; // Declare the Mynewt library extern crate macros as mynewt_macros; // Declare the Mynewt Procedural Macros library // Declare the modules in our application mod app_network; // Declare `app_network.rs` as Rust module `app_network` for Application Network functions mod app_sensor; // Declare `app_sensor.rs` as Rust module `app_sensor` for Application Sensor functions mod touch_sensor; // Declare `touch_sensor.rs` as Rust module `touch_sensor` for Touch Sensor functions // Declare the optional modules depending on the options in `../Cargo.toml` #[cfg(feature = "display_app")] // If graphics display app is enabled... mod display; // Include the graphics display app #[cfg(feature = "ui_app")] // If druid UI app is enabled... mod ui; // Include the druid UI app #[cfg(feature = "visual_app")] // If Visual Rust app is enabled... #[allow(unused_variables)] // Don't warn about unused variables mod visual; // Include the Visual Rust app #[cfg(feature = "chip8_app")] // If CHIP8 Emulator app is enabled... mod chip8; // Include the CHIP8 Emulator app #[cfg(feature = "use_float")] // If floating-point is enabled... mod gps_sensor; // Include the GPS Sensor functions // Declare the system modules use core::panic::PanicInfo; // Import `PanicInfo` type which is used by `panic()` below use cortex_m::asm::bkpt; // Import cortex_m assembly function to inject breakpoint use mynewt::{ kernel::os, // Import Mynewt OS API sys::console, // Import Mynewt Console API }; // Select the touch handler depending on the options in `../Cargo.toml` #[cfg(feature = "ui_app")] // If druid UI app is enabled... use ui::handle_touch; // Use the touch handler from druid UI app #[cfg(feature = "visual_app")] // If Visual Rust app is enabled... use visual::handle_touch; // Use the touch handler from the Visual Rust app #[cfg(feature = "chip8_app")] // If CHIP8 Emulator app is enabled... use chip8::handle_touch; // Use the touch handler from the CHIP8 Emulator app #[cfg(not(any(feature = "ui_app", feature = "visual_app", feature = "chip8_app")))] // If neither druid UI app nor Visual Rust app are enabled... pub fn handle_touch(_x: u16, _y: u16) { console::print("touch not handled\n"); console::flush(); } // Define a touch handler that does nothing /// Main program that initialises the sensor, network driver and starts reading and sending sensor data in the background. /// main() will be called at Mynewt startup. It replaces the C version of the main() function. #[no_mangle] // Don't mangle the name "main" extern "C" fn main() -> ! { // Declare extern "C" because it will be called by Mynewt // Initialise the Mynewt packages and internal temperature sensor driver. Any startup // functions defined in pkg.yml of our custom drivers and libraries will be called by // sysinit(). Here are the startup functions consolidated by Mynewt: // bin/targets/nrf52_my_sensor/generated/src/nrf52_my_sensor-sysinit-app.c mynewt::sysinit(); // Start Bluetooth Beacon. TODO: Create a safe wrapper for starting Bluetooth LE. // extern { fn start_ble() -> i32; } // let rc = unsafe { start_ble() }; // assert!(rc == 0, "BLE fail"); // Start the display druid::start_display() .expect("DSP fail"); // Test the display #[cfg(feature = "display_app")] // If graphics display app is enabled... display::test_display() .expect("DSP test fail"); // Start the touch sensor touch_sensor::start_touch_sensor() .expect("TCH fail"); // Test the touch sensor // touch_sensor::test() // .expect("TCH test fail"); // Launch the druid UI app #[cfg(feature = "ui_app")] // If druid UI app is enabled... ui::launch(); // Launch the Visual Rust app #[cfg(feature = "visual_app")] // If Visual Rust app is enabled... visual::on_start() .expect("VIS fail"); // Launch the CHIP8 Emulator app #[cfg(feature = "chip8_app")] // If CHIP8 Emulator app is enabled... chip8::on_start() .expect("CHIP8 fail"); // Main event loop loop { // Loop forever... os::eventq_run( // Processing events... os::eventq_dflt_get() // From default event queue. .expect("GET fail") ).expect("RUN fail"); } // Never comes here } /// This function is called on panic, like an assertion failure. We display the filename and line number and pause in the debugger. From https://os.phil-opp.com/freestanding-rust-binary/ #[panic_handler] fn panic(info: &PanicInfo) -> ! { // Display the filename and line number to the Semihosting Console. console::print("panic "); if let Some(location) = info.location() { let file = location.file(); let line = location.line(); console::print("at "); console::buffer(&file); console::print(" line "); console::printint(line as i32); console::print("\n"); console::flush(); } else { console::print("no loc\n"); console::flush(); } // Pause in the debugger. bkpt(); // Display the payload. console::print(info.payload().downcast_ref::<&str>().unwrap()); console::print("\n"); console::flush(); // Loop forever so that device won't restart. loop {} }