diff --git a/.cargo/config b/.cargo/config index 87cc5b0..2ee00ba 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,19 +1,22 @@ [target.thumbv7em-none-eabihf] rustflags = [ - "-C", "link-arg=-mthumb", - "-C", "link-arg=-Tnrf52dk-sys.ld", - "-C", "link-arg=-mcpu=cortex-m4", - "-C", "link-arg=--specs=nano.specs", - - "-C", "link-arg=-Wl,--gc-sections", - "-C", "link-arg=-Wl,--start-group", - "-C", "link-arg=-Wl,--end-group", - "-C", "link-arg=-Wl,--build-id=none", + # "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tcustom.x", + # "-C", "link-arg=-Tmemory.x", + "-C", "link-arg=-mcpu=cortex-m4", + "-C", "link-arg=-mthumb", "-C", "link-arg=-mabi=aapcs", "-C", "link-arg=-mfloat-abi=hard", "-C", "link-arg=-mfpu=fpv4-sp-d16", + + "-C", "link-arg=--specs=nano.specs", + + # "-C", "link-arg=-Wl,--gc-sections", + # "-C", "link-arg=-Wl,--start-group", + # "-C", "link-arg=-Wl,--end-group", + # "-C", "link-arg=-Wl,--build-id=none", ] [build] diff --git a/Cargo.toml b/Cargo.toml index c7989bb..30a4673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,10 @@ repository = "https://github.com/jamesmunns/nrf52dk-sys" description = "nrf52 support using the nRF5-SDK and SoftDevice S132" [dependencies] -cortex-m = "0.1.6" -r0 = "0.2.0" +cortex-m = "0.5.2" +cortex-m-rt = "0.5.0" +cortex-m-semihosting = "0.3.0" +panic-semihosting = "0.3.0" [build-dependencies] gcc = "0.3.46" diff --git a/README.md b/README.md index 144a2e1..23f91cd 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,12 @@ This project aims to be a reference on how to combine C and Rust components, in This project requires the following tools before building: -Tool | Recommended Version | Link/Install -:--- | :------------------ | :--- -Clang | 3.9 | [debian/ubuntu](http://apt.llvm.org/) or [source](http://releases.llvm.org/download.html) -arm-none-eabi-gcc | 6.1 | [Current Version](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) -Rust (nightly) | nightly-2017-11-15 | [rustup.rs](https://www.rustup.rs/) -Rust source | nightly-2017-11-15 | `rustup component add rust-src` -Xargo | 0.3.8 | `cargo install xargo --vers 0.3.8` -Bindgen | 0.31.3 | `cargo install bindgen --vers 0.31.3` +| Tool | Recommended Version | Link/Install | +| :---------------- | :------------------ | :---------------------------------------------------------------------------------------- | +| Clang | 3.9 | [debian/ubuntu](http://apt.llvm.org/) or [source](http://releases.llvm.org/download.html) | +| arm-none-eabi-gcc | 6.1 | [Current Version](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) | +| Rust (nightly) | nightly-2017-11-15 | [rustup.rs](https://www.rustup.rs/) | +| Bindgen | 0.31.3 | `cargo install bindgen --vers 0.31.3` | If you would like more detailed installation instructions, please look at [The Detailed Setup Instructions](./SETUP.md). @@ -25,17 +23,17 @@ If you use `docker`, please see the debian based [Dockerfile](./Dockerfile). Additionally, the following tools are required to run or debug the firmware: -Tool | Recommended Version | Link/Install ---- | --- | --- -SoftDevice | S132-v4.0.2 | [Nordic Download](http://www.nordicsemi.com/eng/nordic/Products/nRF52832/S132-SD-v4/58803) -JLink | v6.16 | [JLink Download](https://www.segger.com/downloads/jlink) +| Tool | Recommended Version | Link/Install | +| ---------- | ------------------- | ------------------------------------------------------------------------------------------ | +| SoftDevice | S132-v4.0.2 | [Nordic Download](http://www.nordicsemi.com/eng/nordic/Products/nRF52832/S132-SD-v4/58803) | +| JLink | v6.16 | [JLink Download](https://www.segger.com/downloads/jlink) | ## Building ```text git clone --recursive https://github.com/jamesmunns/nrf52dk-sys cd nrf52dk-sys -xargo build --example blinky +cargo build --example blinky Compiling core v0.0.0 (file:///root/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore) Finished release [optimized] target(s) in 14.8 secs Updating registry `https://github.com/rust-lang/crates.io-index` @@ -114,7 +112,6 @@ JLinkGDBServer -device NRF52832_XXAA -if SWD -speed 4000 # Waiting for GDB connection... ``` - Then, in another terminal: ```text diff --git a/build.rs b/build.rs index 5ff6a94..2c72b4f 100644 --- a/build.rs +++ b/build.rs @@ -1,16 +1,29 @@ extern crate gcc; -use std::collections::{HashMap, HashSet}; use gcc::Build; +use std::collections::{HashMap, HashSet}; use std::env; -use std::path::PathBuf; -use std::process::Command; use std::fs::File; use std::io::Write; +use std::path::PathBuf; +use std::process::Command; fn main() { - let outdir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + + // Put the linker script somewhere the linker can find it + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // If any of these files/folders change, we should regenerate + // the whole C + bindings component + println!("cargo:rerun-if-changed=memory.x"); + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=bindings.h"); // We're going to generate app_config.h from their feature // selection, so let's extract that from the env. @@ -23,13 +36,7 @@ fn main() { } }) .collect(); - - write_app_config(&outdir, &features); - - // If any of these files/folders change, we should regenerate - // the whole C + bindings component - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-changed=bindings.h"); + write_app_config(&out, &features); let mut info = SdkInfo::default(); info.add_from_path(&PathBuf::from("nRF5-sdk")); @@ -42,15 +49,15 @@ fn main() { println!("cargo:rerun-if-changed={}", hdr.display()); } - process_linker_file(&outdir); - generate_ble(&outdir, &info); - make_c_deps(&outdir, &info, &features); + // process_linker_file(&out); + generate_ble(&out, &info); + make_c_deps(&out, &info, &features); } /// Emit app_config.h based on the enabled features. This is used /// to override things in sdk_config.h -fn write_app_config(outdir: &PathBuf, features: &HashSet) { - let mut app_config = File::create(outdir.join("app_config.h")).unwrap(); +fn write_app_config(out: &PathBuf, features: &HashSet) { + let mut app_config = File::create(out.join("app_config.h")).unwrap(); for feature in features.iter() { writeln!(app_config, "#define {}_ENABLED 1", feature).ok(); } @@ -97,27 +104,26 @@ impl SdkInfo { } } -fn process_linker_file(out: &PathBuf) { - // Copy over the target specific linker script - File::create(out.join("nrf52dk-sys.ld")) - .unwrap() - .write_all(include_bytes!("nrf52dk-sys.ld")) - .unwrap(); - - // Also copy the nrf general linker script - File::create(out.join("nrf5x_common.ld")) - .unwrap() - .write_all(include_bytes!("nrf5x_common.ld")) - .unwrap(); +// fn process_linker_file(out: &PathBuf) { +// // Copy over the target specific linker script +// File::create(out.join("nrf52dk-sys.ld")) +// .unwrap() +// .write_all(include_bytes!("nrf52dk-sys.ld")) +// .unwrap(); - println!("cargo:rustc-link-search={}", out.display()); -} +// // Also copy the nrf general linker script +// File::create(out.join("nrf5x_common.ld")) +// .unwrap() +// .write_all(include_bytes!("nrf5x_common.ld")) +// .unwrap(); +// println!("cargo:rustc-link-search={}", out.display()); +// } -fn make_c_deps(out_path: &PathBuf, info: &SdkInfo, features: &HashSet) { +fn make_c_deps(out: &PathBuf, info: &SdkInfo, features: &HashSet) { let mut config = Build::new(); - config.out_dir(out_path); + config.out_dir(out); for f in FLAGS { config.flag(f); @@ -134,16 +140,16 @@ fn make_c_deps(out_path: &PathBuf, info: &SdkInfo, features: &HashSet) { } } - // out_path is where we find the app_config.h that we generate + // out is where we find the app_config.h that we generate // from the enabled features - config.include(out_path); + config.include(out); for i in info.dirs.iter() { config.include(i); } config.compile("libnrf.a"); - println!("cargo:rustc-link-search={}", out_path.display()); + println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rustc-link-lib=static=nrf"); } @@ -180,9 +186,9 @@ fn generate_ble(out: &PathBuf, info: &SdkInfo) { cmd.arg("--ctypes-prefix=ctypes"); cmd.arg("--with-derive-default"); cmd.arg("--verbose"); - cmd.arg("--blacklist-type"); + cmd.arg("--blacklist-type"); cmd.arg("IRQn_Type"); - cmd.arg("--blacklist-type"); + cmd.arg("--blacklist-type"); cmd.arg("__va_list"); // This type wraps a mutable void pointer, and we cannot safely impl Copy. cmd.arg("--output"); @@ -225,9 +231,7 @@ fn generate_ble(out: &PathBuf, info: &SdkInfo) { cmd.arg("-target"); cmd.arg(env::var("TARGET").unwrap()); - assert!(cmd.status() - .expect("failed to build BLE libs") - .success()); + assert!(cmd.status().expect("failed to build BLE libs").success()); } /// Build SRC_TO_FEAT into something using PathBufs @@ -267,6 +271,7 @@ static FLAGS: &[&str] = &[ "-mfpu=fpv4-sp-d16", "-ffunction-sections", "-fdata-sections", + "-fno-pic", "-fno-strict-aliasing", "-fno-builtin", // the headers are riddled with unused parameters and emit @@ -274,6 +279,8 @@ static FLAGS: &[&str] = &[ "-Wno-unused-parameter", "-Wno-sign-compare", "-Wno-missing-field-initializers", + "-Wno-expansion-to-defined", + "-Wimplicit-fallthrough=0", "--short-enums", ]; diff --git a/custom.x b/custom.x new file mode 100644 index 0000000..be8c939 --- /dev/null +++ b/custom.x @@ -0,0 +1,14 @@ +SEARCH_DIR(.) + +GROUP(-lgcc -lc -lnosys) + +SECTIONS +{ + .heap (COPY): + { + PROVIDE(end = .); + KEEP(*(.heap*)) + } > RAM +} INSERT AFTER .bss; + +INCLUDE "link.x" diff --git a/examples/ble_app_template.rs b/examples/ble_app_template.rs index b9a7047..b7c0ced 100644 --- a/examples/ble_app_template.rs +++ b/examples/ble_app_template.rs @@ -1,10 +1,17 @@ #![no_std] #![no_main] -#![feature(asm)] +#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] + +#[macro_use(entry, exception)] +extern crate cortex_m_rt as rt; + +// makes `panic!` print messages to the host stderr using semihosting +extern crate panic_semihosting; +use rt::ExceptionFrame; extern crate nrf52dk_sys; -use nrf52dk_sys as nrf; use nrf::check; +use nrf52dk_sys as nrf; static NAME: &str = "RUST-BLE"; @@ -38,48 +45,59 @@ static mut M_GATT: nrf::nrf_ble_gatt_t = nrf::nrf_ble_gatt_t { evt_handler: None, }; -static mut M_ADV_UUIDS: [nrf::ble_uuid_t; 1] = [ - nrf::ble_uuid_t { - uuid: nrf::BLE_UUID_DEVICE_INFORMATION_SERVICE as u16, - type_: nrf::BLE_UUID_TYPE_BLE as u8, - }, -]; +static mut M_ADV_UUIDS: [nrf::ble_uuid_t; 1] = [nrf::ble_uuid_t { + uuid: nrf::BLE_UUID_DEVICE_INFORMATION_SERVICE as u16, + type_: nrf::BLE_UUID_TYPE_BLE as u8, +}]; unsafe fn nrf_log_info(output: &'static str) { nrf::nrf_log_frontend_std_0(nrf::NRF_LOG_LEVEL_INFO as u8, output.as_ptr()); } -#[no_mangle] -pub unsafe extern "C" fn main() { - let mut erase_bonds = false; - - // BSP Init - log_init(); - nrf_log_info("Hello, nRF52!\r\n\0"); - timers_init(); - buttons_leds_init(&mut erase_bonds); - - // BLE Init - ble_stack_init(); - gap_params_init(); - gatt_init(); - advertising_init(); - services_init(); - conn_params_init(); - peer_manager_init(); - - application_timers_start(); - - advertising_start(erase_bonds); - - // Mimic example - loop { - if !nrf::nrf_log_frontend_dequeue() { - nrf::sd_app_evt_wait(); +entry!(main); + +fn main() -> ! { + unsafe { + let mut erase_bonds = false; + + // BSP Init + log_init(); + nrf_log_info("Hello, nRF52!\r\n\0"); + timers_init(); + buttons_leds_init(&mut erase_bonds); + + // BLE Init + ble_stack_init(); + gap_params_init(); + gatt_init(); + advertising_init(); + services_init(); + conn_params_init(); + peer_manager_init(); + + application_timers_start(); + + advertising_start(erase_bonds); + + // Mimic example + loop { + if !nrf::nrf_log_frontend_dequeue() { + nrf::sd_app_evt_wait(); + } } } } +exception!(HardFault, hard_fault); +fn hard_fault(ef: &ExceptionFrame) -> ! { + panic!("HardFault at {:#?}", ef); +} + +exception!(*, default_handler); +fn default_handler(irqn: i16) { + panic!("Unhandled exception (IRQn = {})", irqn); +} + /// Function for initializing the nrf log module. unsafe fn log_init() { check(nrf::nrf_log_init(None)).unwrap(); @@ -95,7 +113,6 @@ unsafe fn timers_init() { /// Function for initializing buttons and leds. unsafe fn buttons_leds_init(erase_bonds: &mut bool) { - let mut startup_event: nrf::bsp_event_t = nrf::bsp_event_t_BSP_EVENT_NOTHING; check(nrf::bsp_init( @@ -129,10 +146,11 @@ unsafe fn ble_stack_init() { // Overwrite some of the default configurations for the BLE stack. let mut ble_cfg = nrf::ble_cfg_t::default(); - check(nrf::sd_ble_cfg_set(nrf::BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID as u32, - &mut ble_cfg, - ram_start)) - .unwrap(); + check(nrf::sd_ble_cfg_set( + nrf::BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID as u32, + &mut ble_cfg, + ram_start, + )).unwrap(); // Configure the maximum number of connections. let mut ble_cfg = nrf::ble_cfg_t::default(); @@ -142,10 +160,11 @@ unsafe fn ble_stack_init() { central_sec_count: 0, }; - check(nrf::sd_ble_cfg_set(nrf::BLE_GAP_CFGS_BLE_GAP_CFG_ROLE_COUNT as u32, - &mut ble_cfg, - ram_start)) - .unwrap(); + check(nrf::sd_ble_cfg_set( + nrf::BLE_GAP_CFGS_BLE_GAP_CFG_ROLE_COUNT as u32, + &mut ble_cfg, + ram_start, + )).unwrap(); // Enable BLE stack. check(nrf::softdevice_enable(&mut ram_start)).unwrap(); @@ -253,7 +272,7 @@ unsafe fn peer_manager_init() { // Security parameters to be used for all security procedures. let mut sec_param = nrf::ble_gap_sec_params_t { - _bitfield_1: 0, + _bitfield_1: nrf::__BindgenBitfieldUnit::<[u8; 1], u8>::new([0]), min_key_size: 7, max_key_size: 16, kdist_own: kdist_own, @@ -328,10 +347,11 @@ unsafe extern "C" fn sys_evt_dispatch(evt_id: u32) { } unsafe extern "C" fn on_adv_evt(ble_adv_evt: nrf::ble_adv_evt_t) { - match ble_adv_evt { BLE_ADV_EVT_FAST => { - check(nrf::bsp_indication_set(nrf::bsp_indication_t_BSP_INDICATE_ADVERTISING)).unwrap(); + check(nrf::bsp_indication_set( + nrf::bsp_indication_t_BSP_INDICATE_ADVERTISING, + )).unwrap(); } BLE_ADV_EVT_IDLE => { sleep_mode_enter(); @@ -341,7 +361,6 @@ unsafe extern "C" fn on_adv_evt(ble_adv_evt: nrf::ble_adv_evt_t) { } unsafe extern "C" fn on_conn_params_evt(p_evt: *mut nrf::ble_conn_params_evt_t) { - match (*p_evt).evt_type { BLE_CONN_PARAMS_EVT_FAILED => { check(nrf::sd_ble_gap_disconnect( @@ -373,7 +392,9 @@ unsafe fn advertising_start(erase_bonds: bool) { delete_bonds(); // Advertising is started by PM_EVT_PEERS_DELETED_SUCEEDED evetnt } else { - check(nrf::ble_advertising_start(nrf::ble_adv_mode_t_BLE_ADV_MODE_FAST)).unwrap(); + check(nrf::ble_advertising_start( + nrf::ble_adv_mode_t_BLE_ADV_MODE_FAST, + )).unwrap(); } } @@ -384,7 +405,6 @@ unsafe fn delete_bonds() { } unsafe extern "C" fn pm_evt_handler(p_evt: *const nrf::pm_evt_t) { - match (*p_evt).evt_id { PM_EVT_BONDED_PEER_CONNECTED => { nrf_log_info("Connected to a previously bonded device.\r\n\0"); @@ -460,43 +480,46 @@ unsafe extern "C" fn pm_evt_handler(p_evt: *const nrf::pm_evt_t) { /// Function for handling the Application's BLE Stack events. unsafe fn on_ble_evt(p_ble_evt: *mut nrf::ble_evt_t) { - let x = (*p_ble_evt).header.evt_id; // We can't use a match here because the nordic mixes enum types :( if x == nrf::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED as u16 { nrf_log_info("Disconnected.\r\n\0"); - check(nrf::bsp_indication_set(nrf::bsp_indication_t_BSP_INDICATE_IDLE)).unwrap(); + check(nrf::bsp_indication_set( + nrf::bsp_indication_t_BSP_INDICATE_IDLE, + )).unwrap(); } else if x == nrf::BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED as u16 { nrf_log_info("Connected.\r\n\0"); - check(nrf::bsp_indication_set(nrf::bsp_indication_t_BSP_INDICATE_CONNECTED)).unwrap(); + check(nrf::bsp_indication_set( + nrf::bsp_indication_t_BSP_INDICATE_CONNECTED, + )).unwrap(); M_CONN_HANDLE = (*p_ble_evt).evt.gap_evt.conn_handle; } else if x == nrf::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT as u16 { nrf_log_info("GATT Client Timeout.\r\n\0"); - check(nrf::sd_ble_gap_disconnect((*p_ble_evt).evt.gattc_evt.conn_handle, - nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8)) - .unwrap(); + check(nrf::sd_ble_gap_disconnect( + (*p_ble_evt).evt.gattc_evt.conn_handle, + nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8, + )).unwrap(); } else if x == nrf::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT as u16 { nrf_log_info("GATT Client Timeout.\r\n\0"); - check(nrf::sd_ble_gap_disconnect((*p_ble_evt).evt.gattc_evt.conn_handle, - nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8)) - .unwrap(); + check(nrf::sd_ble_gap_disconnect( + (*p_ble_evt).evt.gattc_evt.conn_handle, + nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8, + )).unwrap(); } else if x == nrf::BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT as u16 { nrf_log_info("GATT Server Timeout.\r\n\0"); - check(nrf::sd_ble_gap_disconnect((*p_ble_evt).evt.gatts_evt.conn_handle, - nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8)) - .unwrap(); + check(nrf::sd_ble_gap_disconnect( + (*p_ble_evt).evt.gatts_evt.conn_handle, + nrf::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8, + )).unwrap(); } else if x == nrf::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST as u16 { - check(nrf::sd_ble_user_mem_reply((*p_ble_evt).evt.gattc_evt.conn_handle, - core::ptr::null())) - .unwrap(); + check(nrf::sd_ble_user_mem_reply( + (*p_ble_evt).evt.gattc_evt.conn_handle, + core::ptr::null(), + )).unwrap(); } else if x == nrf::BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST as u16 { - let req = (*p_ble_evt) - .evt - .gatts_evt - .params - .authorize_request; + let req = (*p_ble_evt).evt.gatts_evt.params.authorize_request; if req.type_ != nrf::BLE_GATTS_AUTHORIZE_TYPE_INVALID as u8 { let op = req.request.write.op; diff --git a/examples/blinky.rs b/examples/blinky.rs index dd29fd9..81e1694 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -1,19 +1,38 @@ // Based on nRF5-sdk/examples/peripheral/blinky/main.c -#![no_std] #![no_main] -#![feature(asm)] +#![no_std] + +#[macro_use(entry, exception)] +extern crate cortex_m_rt as rt; + +// makes `panic!` print messages to the host stderr using semihosting +extern crate panic_semihosting; +use rt::ExceptionFrame; extern crate nrf52dk_sys; use nrf52dk_sys as nrf; -#[no_mangle] -pub unsafe extern "C" fn main() { - nrf::bsp_board_leds_init(); +entry!(main); + +fn main() -> ! { + unsafe { + nrf::bsp_board_leds_init(); - loop { - for led in 0..nrf::LEDS_NUMBER { - nrf::bsp_board_led_invert(led); - nrf::_nrf_delay_ms(500); + loop { + for led in 0..nrf::LEDS_NUMBER { + nrf::bsp_board_led_invert(led); + nrf::_nrf_delay_ms(500); + } } } } + +exception!(HardFault, hard_fault); +fn hard_fault(ef: &ExceptionFrame) -> ! { + panic!("HardFault at {:#?}", ef); +} + +exception!(*, default_handler); +fn default_handler(irqn: i16) { + panic!("Unhandled exception (IRQn = {})", irqn); +} diff --git a/examples/logging.rs b/examples/logging.rs index f72e600..7f22e0c 100644 --- a/examples/logging.rs +++ b/examples/logging.rs @@ -1,29 +1,46 @@ -// Based on nRF5-sdk/examples/peripheral/blinky/main.c -#![no_std] #![no_main] -#![feature(asm)] +#![no_std] + +#[macro_use(entry, exception)] +extern crate cortex_m_rt as rt; + +// makes `panic!` print messages to the host stderr using semihosting +extern crate panic_semihosting; +use rt::ExceptionFrame; -#[macro_use] extern crate nrf52dk_sys; use nrf52dk_sys as nrf; -#[no_mangle] -pub unsafe extern "C" fn main() { - nrf::bsp_board_leds_init(); - nrf::check(nrf::nrf_log_init(None)).unwrap(); - nrf::check(nrf::app_timer_init()).unwrap(); - - loop { - for led in 0..nrf::LEDS_NUMBER { - nrf::bsp_board_led_invert(led); - nrf::_nrf_delay_ms(500); - log_str("INFO: this is a test\r\n\x00"); - nrf::sd_app_evt_wait(); - process_log(); +entry!(main); + +fn main() -> ! { + unsafe { + nrf::bsp_board_leds_init(); + nrf::check(nrf::nrf_log_init(None)).unwrap(); + nrf::check(nrf::app_timer_init()).unwrap(); + + loop { + for led in 0..nrf::LEDS_NUMBER { + nrf::bsp_board_led_invert(led); + nrf::_nrf_delay_ms(500); + log_str("INFO: this is a test\r\n\x00"); + nrf::sd_app_evt_wait(); + process_log(); + } } } } +exception!(HardFault, hard_fault); +fn hard_fault(ef: &ExceptionFrame) -> ! { + panic!("HardFault at {:#?}", ef); +} + +exception!(*, default_handler); +fn default_handler(irqn: i16) { + panic!("Unhandled exception (IRQn = {})", irqn); +} + unsafe fn process_log() { loop { nrf::sd_app_evt_wait(); @@ -37,17 +54,3 @@ unsafe fn process_log() { unsafe fn log_str(foo: &'static str) { nrf::nrf_log_frontend_std_0(nrf::NRF_LOG_LEVEL_INFO as u8, foo.as_ptr()); } - -// NRF_LOG_PROCESS() -// NRF_LOG_INTERNAL_PROCESS() -// nrf_log_frontend_dequeue() - -// NRF_LOG_INTERNAL_FLUSH - -// NRF_LOG_INFO -// NRF_LOG_INTERNAL_INFO( __VA_ARGS__) -// LOG_INTERNAL(NRF_LOG_LEVEL_INFO, LOG_INFO_PREFIX, __VA_ARGS__); -// LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \ -// __VA_ARGS__), type, prefix, __VA_ARGS__) -// CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__) -// nrf_log_frontend_std_0(type, prefix str) diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..e53c99e --- /dev/null +++ b/memory.x @@ -0,0 +1,7 @@ +/* Linker script for the nRF52832. */ +MEMORY +{ + /* Flash and RAM is offset to leave room for the S132 soft device. */ + FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 + RAM (rwx) : ORIGIN = 0x20001fc0, LENGTH = 0xe040 +} diff --git a/src/lang_items.rs b/src/lang_items.rs deleted file mode 100644 index a173ef9..0000000 --- a/src/lang_items.rs +++ /dev/null @@ -1,48 +0,0 @@ -/// Default panic handler -#[linkage = "weak"] -#[lang = "panic_fmt"] -unsafe extern "C" fn panic_fmt( - _args: ::core::fmt::Arguments, - _file: &'static str, - _line: u32, -) -> ! { - hprint!("panicked at '"); - match () { - #[cfg(feature = "semihosting")] - () => { - ::cortex_m_semihosting::io::write_fmt(_args); - } - #[cfg(not(feature = "semihosting"))] - () => {} - } - hprintln!("', {}:{}", _file, _line); - - bkpt!(); - - loop {} -} - -/// Lang item required to make the normal `main` work in applications -// This is how the `start` lang item works: -// When `rustc` compiles a binary crate, it creates a `main` function that looks -// like this: -// -// ``` -// #[export_name = "main"] -// pub extern "C" fn rustc_main(argc: isize, argv: *const *const u8) -> isize { -// start(main) -// } -// ``` -// -// Where `start` is this function and `main` is the binary crate's `main` -// function. -// -// The final piece is that the entry point of our program, the reset handler, -// has to call `rustc_main`. That's covered by the `reset_handler` function in -// `src/exceptions.rs` -#[lang = "start"] -extern "C" fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize { - main(); - - 0 -} diff --git a/src/lib.rs b/src/lib.rs index 68da051..e41e200 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,24 +8,9 @@ #![feature(asm)] #![feature(lang_items)] #![feature(linkage)] -#![feature(macro_reexport)] #![feature(naked_functions)] #![no_std] -#[macro_reexport(bkpt)] -#[macro_use] -extern crate cortex_m; -#[cfg(feature = "semihosting")] -#[macro_reexport(hprint, hprintln)] -#[macro_use] -extern crate cortex_m_semihosting; -extern crate r0; - -#[macro_use] -mod macros; - -mod lang_items; - /// Copied from https://github.com/rust-lang/rust/blob/master/src/libstd/os/raw.rs pub mod ctypes { // Unconditional @@ -39,8 +24,10 @@ pub mod ctypes { pub type c_ulonglong = u64; #[repr(u8)] pub enum c_void { - #[doc(hidden)] __variant1, - #[doc(hidden)] __variant2, + #[doc(hidden)] + __variant1, + #[doc(hidden)] + __variant2, } // Non-Windows diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index e8d515d..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(not(feature = "semihosting"))] -#[macro_export] -macro_rules! hprint { - ($($arg:tt)*) => (); -} - -#[cfg(not(feature = "semihosting"))] -#[macro_export] -macro_rules! hprintln { - ($($arg:tt)*) => (); -}