Synchronization
So far the example implements a blinking LED in one thread. Let us now extend the application such that the delay time can be adjusted using a button on the board. The value will be adjusted in an interrupt service routing (ISR) and shared with the blinky thread. The thread and the ISR run in different contexts pseudoparallel. Thus, access to the shared delay must be synchronized to prevent inconsistent data.
[project]/main.rs
let mut led = board.led;
let mut button = board.button;
PROC.init(move |c| {
let delay = Arc::new(Mutex::new(100_u32));1
let delay_reader = delay.clone();
Thread::new(c)
.stack(Stack::try_new_in(c, 1024).unwrap())
.spawn(move || {
let mut local_delay = 100;
loop {
led.set_high();
sleep(200);
led.set_low();
delay_reader.try_lock()2
.map(|s| local_delay = *s).ok();
sleep(local_delay);
}
});
InterruptHandler::new(c)3
.stack(InterruptStack::Kernel)
.connect_interrupt(stm32f4xx_hal::interrupt::EXTI15_10 as u16)4
.handler(move |_c| {
button.clear_interrupt_pending_bit();
delay.try_lock()5
.map(|mut s| {
*s = if *s < 1000 { *s + 100 } else { 100 };
}).ok();
});
}).unwrap();
Listing: Process initialization with interrupt handler and synchronization.
We use a mutex to synchronize access to the shared delay value. The mutex is allocated on the process heap at
Setting up an interrupt handler is similar to a thread
This example illustrates the basic usage of the Bern RTOS kernel. The next chapter explains the design and usage of all kernel components.