Skip to content
This repository has been archived by the owner on Jul 6, 2019. It is now read-only.

build: feature gate arch and cpu specific code #316

Merged
merged 2 commits into from
Jun 18, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ name = "zinc"
crate-type = ["lib"]

[features]
mcu_lpc17xx = []
mcu_stm32f4 = []
mcu_stm32l1 = []
mcu_k20 = []
mcu_tiva_c = []
multitasking = []
cpu_cortex-m3 = []
cpu_cortex-m4 = []

mcu_lpc17xx = ["cpu_cortex-m3"]
mcu_stm32f4 = ["cpu_cortex-m4"]
mcu_stm32l1 = ["cpu_cortex-m3"]
mcu_k20 = ["cpu_cortex-m4"]
mcu_tiva_c = ["cpu_cortex-m4"]
multitasking = ["cpu_cortex-m4"]

[target.thumbv7m-none-eabi.dependencies.core]
git = "https://github.com/hackndev/rust-libcore"
Expand Down
12 changes: 6 additions & 6 deletions src/hal/cortex_common/irq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//! Disabling and enabling interrupts

use core::ops::Drop;
#[cfg(not(test))]
#[cfg(target_os = "none")]
use core::intrinsics::abort;

/// Phantom type to indicate that interrupts are disabled.
Expand All @@ -43,25 +43,25 @@ impl Drop for NoInterrupts {
}
}

#[cfg(not(test))]
#[cfg(target_os = "none")]
static mut irq_level : usize = 0;

/// Disables all interrupts except Reset, HardFault, and NMI.
/// Note that this is reference counted: if `disable_irqs` is called
/// twice then interrupts will only be re-enabled upon the second call
/// to `enable_irqs`.
#[cfg(not(test))]
#[cfg(target_os = "none")]
#[inline(always)]
unsafe fn disable_irqs() {
asm!("cpsid i" :::: "volatile");
irq_level += 1;
}

#[cfg(test)]
#[cfg(not(target_os = "none"))]
unsafe fn disable_irqs() { unimplemented!() }

/// Enables all interrupts except Reset, HardFault, and NMI.
#[cfg(not(test))]
#[cfg(target_os = "none")]
#[inline(always)]
unsafe fn enable_irqs() {
if irq_level == 0 {
Expand All @@ -75,5 +75,5 @@ unsafe fn enable_irqs() {
}
}

#[cfg(test)]
#[cfg(not(target_os = "none"))]
unsafe fn enable_irqs() { unimplemented!() }
1 change: 0 additions & 1 deletion src/hal/cortex_m3/isr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ extern {
fn isr_reserved_1();
}

#[cfg(not(test))]
#[no_mangle]
pub unsafe extern fn isr_handler_wrapper() {
asm!(".weak isr_nmi, isr_hardfault, isr_mmfault, isr_busfault
Expand Down
8 changes: 4 additions & 4 deletions src/hal/cortex_m3/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct Guard<'a>(&'a Lock);

pub static STATIC_LOCK: Lock = Lock { locked: Unsafe { value: 0, marker1: InvariantType } };

#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
unsafe fn exclusive_load(addr: *const u32) -> u32 {
let mut value: u32;
Expand All @@ -42,10 +42,10 @@ unsafe fn exclusive_load(addr: *const u32) -> u32 {
value
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
unsafe fn exclusive_load(addr: *const u32) -> u32 { unimplemented!() }

#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
unsafe fn exclusive_store(addr: *mut u32, value: u32) -> bool {
let mut success: u32;
Expand All @@ -58,7 +58,7 @@ unsafe fn exclusive_store(addr: *mut u32, value: u32) -> bool {
success == 0
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
unsafe fn exclusive_store(addr: *mut u32, value: u32) -> bool {
unimplemented!()
}
Expand Down
18 changes: 9 additions & 9 deletions src/hal/cortex_m3/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,37 @@ pub fn switch_context() {
}

/// Sets task stack pointer (PSP).
#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
pub fn set_task_stack_pointer(val: u32) {
unsafe { asm!("msr psp, $0" :: "r"(val) :: "volatile") };
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
pub fn set_task_stack_pointer(val: u32) { unimplemented!() }

/// Returns task stack pointer (PSP).
#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
pub fn get_task_stack_pointer() -> u32 {
let mut val: u32;
unsafe { asm!("mrs $0, psp" : "=r"(val) ::: "volatile") };
val
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
pub fn get_task_stack_pointer() -> u32 { unimplemented!() }

/// Returns current stack pointer (SP, which may be PSP or MSP).
#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
pub fn get_current_stack_pointer() -> u32 {
let mut val: u32;
unsafe { asm!("mov $0, sp" : "=r"(val) ::: "volatile") };
val
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
pub fn get_current_stack_pointer() -> u32 { unimplemented!() }

/// State, that's saved by hardware upon entering an ISR.
Expand Down Expand Up @@ -92,11 +92,11 @@ impl SavedState {
// TODO(farcaller): this should actually kill the task.
// TODO(bgamari): It should also unlock anything the task holds
/// Default handler for task that tries to return.
#[cfg(not(test))]
#[cfg(target_os = "none")]
unsafe fn task_finished() {
asm!("bkpt" :::: "volatile");
core::intrinsics::breakpoint();
}

#[cfg(test)]
#[cfg(not(target_os = "none"))]
unsafe fn task_finished() { unimplemented!() }

4 changes: 4 additions & 0 deletions src/hal/isr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

#![allow(missing_docs)]

#[cfg(feature = "cpu_cortex-m3")]
#[path="cortex_m3/isr.rs"] pub mod isr_cortex_m3;

#[cfg(feature = "cpu_cortex-m4")]
#[path="cortex_m3/isr.rs"] pub mod isr_cortex_m4;

#[cfg(feature = "mcu_lpc17xx")]
#[path="lpc17xx/isr.rs"] pub mod isr_lpc17xx;

Expand Down
11 changes: 10 additions & 1 deletion src/hal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,23 @@ and each such struct has a `setup()` method that configures the hardware
*/


#[cfg(feature = "mcu_lpc17xx")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually a bad idea I guess, as it feature-gates mcu code from being unit tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But wouldn't you then just test with the features enabled (which we already do)? As a bonus it has exposed some misuse of hal code. I think this is the accepted way of doing it as features are kind of like optional dependencies (which you're allowed to test without). But you can also test with them (which we do with the matrix for travis & build tasks for jenkins).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean — test the specific parts of the mcu hal, like doing a volatilecell replay verification for uart setup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, your comment actually makes sense to me now.

👍

pub mod lpc17xx;
#[cfg(feature = "mcu_stm32f4")]
pub mod stm32f4;
#[cfg(feature = "mcu_stm32l1")]
pub mod stm32l1;
#[cfg(feature = "mcu_k20")]
pub mod k20;
#[cfg(feature = "mcu_tiva_c")]
pub mod tiva_c;

#[cfg(any(feature = "cpu_cortex-m3",
feature = "cpu_cortex-m4"))]
mod cortex_common;
#[cfg(feature = "cpu_cortex-m3")]
pub mod cortex_m3;
#[cfg(feature = "cpu_cortex-m4")]
pub mod cortex_m4;

pub mod mem_init;
Expand All @@ -39,5 +48,5 @@ pub mod stack;
pub mod timer;
pub mod uart;

#[cfg(not(test))]
#[cfg(target_os = "none")]
pub mod isr;
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ STM32F403/407).
#![feature(no_std)]

#[macro_use] extern crate core;
#[cfg(not(test))] extern crate rlibc;
#[cfg(target_os = "none")]
extern crate rlibc;

#[macro_use] #[no_link] extern crate ioreg;
extern crate volatile_cell;
Expand All @@ -66,7 +67,7 @@ pub mod os;
/// for some items in the `std` namespace.
///
/// TODO(farcaller): clean up when fixed.
#[cfg(not(test))]
#[cfg(target_os = "none")]
pub mod std {
pub use core::cmp; // used for #[derive(Eq)] until fixed in rust.
pub use core::option;
Expand Down
18 changes: 18 additions & 0 deletions src/util/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,25 @@ use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use core::marker::{Sync, Send};

#[cfg(feature = "cpu_cortex-m3")]
use hal::cortex_m3::irq::NoInterrupts;
#[cfg(feature = "cpu_cortex-m4")]
use hal::cortex_m4::irq::NoInterrupts;
// If cpu doesn't have nointerrupts provide dummy implementation
#[cfg(not(any(feature = "cpu_cortex-m3",
feature = "cpu_cortex-m4")))]
use self::dummy_irq::NoInterrupts;

#[allow(missing_docs)]
mod dummy_irq {
pub struct NoInterrupts;

impl NoInterrupts {
pub fn new() -> NoInterrupts {
NoInterrupts
}
}
}

/// This allows safe sharing of state, ensuring access occurs only
/// when in a critical section.
Expand Down
26 changes: 8 additions & 18 deletions src/util/support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,15 @@

//! Support functions currently required by the linker for bare-metal targets.

#[doc(hidden)]
#[cfg(test)]
#[no_stack_check]
#[no_mangle]
pub extern fn breakpoint() { unimplemented!() }

/// Call the debugger.
#[cfg(not(test))]
#[no_stack_check]
#[no_mangle]
pub extern fn breakpoint() {
unsafe { asm!("bkpt") }
}
pub use core::intrinsics::breakpoint;

/// Call the debugger and halts execution.
#[no_stack_check]
#[no_mangle]
pub extern fn abort() -> ! {
breakpoint();
unsafe {
breakpoint();
}
loop {}
}

Expand All @@ -49,26 +39,26 @@ pub extern fn __aeabi_memset(dest: *mut u8, size: usize, value: u32) {
}
}

#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
/// NOP instruction
pub fn nop() {
unsafe { asm!("nop" :::: "volatile"); }
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
/// NOP instruction (mock)
pub fn nop() {
}

#[cfg(not(test))]
#[cfg(target_arch = "arm")]
#[inline(always)]
/// WFI instruction
pub fn wfi() {
unsafe { asm!("wfi" :::: "volatile"); }
}

#[cfg(test)]
#[cfg(not(target_arch = "arm"))]
/// WFI instruction (mock)
pub fn wfi() {
}
Expand Down