So Ihr Lieben, da bin ich wieder!
Inzwischen hab ich mich mit allen möglichen Arten von atomischen Operationen, Mutexen, und anderen Ideen, wie man möglichst statisch (= zur Compilezeit) absichern kann dass nichts schief geht, herumgeschlagen. Ich denke ich bin soweit ganz happy, aber was meint Ihr denn so?
Hier mal ein kleines Beispiel, das nun einen Ringbuffer für USART_RXC implementiert:
Code:
use rp6::{interrupt::mutex::Mutex, *};
// Shared data: While constants can be accessed safely (since they are never modified, it is
// recommended to wrap your mutable data in an `rp6::interrupt::Mutex`. Note that a `Mutex` can
// only be used inside a `CriticalSection`, e.g., by calling `interrupt::without_interrupts`.
const USART_BUFFER_SIZE: usize = 32;
static USART_BUFFER: Mutex<[u8; USART_BUFFER_SIZE]> = Mutex::new([' ' as u8; USART_BUFFER_SIZE]);
static USART_WRITE_PTR: Mutex<usize> = Mutex::new(0);
#[interrupt]
fn USART_RXC() {
interrupt::without_interrupts(|cs| {
let buffer = USART_BUFFER.lock(cs);
let write_ptr = USART_WRITE_PTR.lock(cs);
// save newly received byte to the ringbuffer
buffer.update(|mut b| {
b[write_ptr.get()] = Serial::read_raw();
b
});
// increment USART write pointer and wrap around if necessary
write_ptr.update(|x| if x + 1 < USART_BUFFER_SIZE { x + 1 } else { 0 });
});
}
Eventuell besser zu lesen mit Code-Highlighting auf Github!
In Anlehnung an das RP6Example gibt das Programm (weiter unten in der main) dann einfach regelmässig einen hochzählenden Counter aus, sowie den aktuellen Inhalt des Ringbuffers.
Na, wie sieht das für Euch (noch-)nicht-Rustaceans aus?
LG und gute Nacht,
Roland
Lesezeichen