remove first person comments and assert disable state when it's necessary
This commit is contained in:
parent
9527d1d934
commit
802bdd1af8
1 changed files with 106 additions and 95 deletions
|
@ -64,8 +64,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
// that if the packet payload length defined by PCNF1.STATLEN and the LENGTH field in the packet specifies a
|
// that if the packet payload length defined by PCNF1.STATLEN and the LENGTH field in the packet specifies a
|
||||||
// packet larger than MAXLEN, the payload will be truncated at MAXLEN
|
// packet larger than MAXLEN, the payload will be truncated at MAXLEN
|
||||||
//
|
//
|
||||||
// To simplify the implementation, I'm setting the max length to the maximum value
|
// To simplify the implementation, It is setted as the maximum value
|
||||||
// and I'm using only the length field to truncate the payload
|
// and the length of the packet is controlled only by the LENGTH field in the packet
|
||||||
.maxlen()
|
.maxlen()
|
||||||
.bits(255)
|
.bits(255)
|
||||||
// Configure the length of the address field in the packet
|
// Configure the length of the address field in the packet
|
||||||
|
@ -92,14 +92,14 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
// Before whitening or de-whitening, the shift register should be
|
// Before whitening or de-whitening, the shift register should be
|
||||||
// initialized based on the channel index.
|
// initialized based on the channel index.
|
||||||
.whiteen()
|
.whiteen()
|
||||||
.set_bit() // Enable whitening
|
.set_bit()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure CRC
|
// Configure CRC
|
||||||
r.crccnf.write(|w| {
|
r.crccnf.write(|w| {
|
||||||
// In BLE the CRC shall be calculated on the PDU of all Link Layer
|
// In BLE the CRC shall be calculated on the PDU of all Link Layer
|
||||||
// packets (even if the packet is encrypted).
|
// packets (even if the packet is encrypted).
|
||||||
// So here we skip the address field
|
// It skips the address field
|
||||||
w.skipaddr()
|
w.skipaddr()
|
||||||
.skip()
|
.skip()
|
||||||
// In BLE 24-bit CRC = 3 bytes
|
// In BLE 24-bit CRC = 3 bytes
|
||||||
|
@ -125,11 +125,18 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
Self { _p: radio }
|
Self { _p: radio }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> RadioState {
|
||||||
|
match T::regs().state.read().state().variant() {
|
||||||
|
Ok(s) => s,
|
||||||
|
None => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn trace_state(&self) {
|
fn trace_state(&self) {
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
match r.state.read().state().variant().unwrap() {
|
match self.state() {
|
||||||
RadioState::DISABLED => trace!("radio:state:DISABLED"),
|
RadioState::DISABLED => trace!("radio:state:DISABLED"),
|
||||||
RadioState::RX_RU => trace!("radio:state:RX_RU"),
|
RadioState::RX_RU => trace!("radio:state:RX_RU"),
|
||||||
RadioState::RX_IDLE => trace!("radio:state:RX_IDLE"),
|
RadioState::RX_IDLE => trace!("radio:state:RX_IDLE"),
|
||||||
|
@ -142,86 +149,12 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn trigger_and_wait_end(&mut self, trigger: impl FnOnce() -> ()) {
|
|
||||||
//self.trace_state();
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
let s = T::state();
|
|
||||||
|
|
||||||
// If the Future is dropped before the end of the transmission
|
|
||||||
// we need to disable the interrupt and stop the transmission
|
|
||||||
// to keep the state consistent
|
|
||||||
let drop = OnDrop::new(|| {
|
|
||||||
trace!("radio drop: stopping");
|
|
||||||
|
|
||||||
r.intenclr.write(|w| w.end().clear());
|
|
||||||
r.events_end.reset();
|
|
||||||
|
|
||||||
r.tasks_stop.write(|w| w.tasks_stop().set_bit());
|
|
||||||
|
|
||||||
// The docs don't explicitly mention any event to acknowledge the stop task
|
|
||||||
// So I guess it's the same as end
|
|
||||||
while r.events_end.read().events_end().bit_is_clear() {}
|
|
||||||
|
|
||||||
trace!("radio drop: stopped");
|
|
||||||
});
|
|
||||||
|
|
||||||
// trace!("radio:enable interrupt");
|
|
||||||
// Clear some remnant side-effects (I'm unsure if this is needed)
|
|
||||||
r.events_end.reset();
|
|
||||||
|
|
||||||
// Enable interrupt
|
|
||||||
r.intenset.write(|w| w.end().set());
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
// Trigger the transmission
|
|
||||||
trigger();
|
|
||||||
// self.trace_state();
|
|
||||||
|
|
||||||
// On poll check if interrupt happen
|
|
||||||
poll_fn(|cx| {
|
|
||||||
s.end_waker.register(cx.waker());
|
|
||||||
if r.events_end.read().events_end().bit_is_set() {
|
|
||||||
// trace!("radio:end");
|
|
||||||
return core::task::Poll::Ready(());
|
|
||||||
}
|
|
||||||
Poll::Pending
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
r.events_disabled.reset(); // ACK
|
|
||||||
|
|
||||||
// Everthing ends fine, so we can disable the drop
|
|
||||||
drop.defuse();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Disable the radio.
|
|
||||||
fn disable(&mut self) {
|
|
||||||
let r = T::regs();
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
// If is already disabled, do nothing
|
|
||||||
if !r.state.read().state().is_disabled() {
|
|
||||||
trace!("radio:disable");
|
|
||||||
// Trigger the disable task
|
|
||||||
r.tasks_disable.write(|w| w.tasks_disable().set_bit());
|
|
||||||
|
|
||||||
// Wait until the radio is disabled
|
|
||||||
while r.events_disabled.read().events_disabled().bit_is_clear() {}
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
// Acknowledge it
|
|
||||||
r.events_disabled.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the radio mode
|
/// Set the radio mode
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_mode(&mut self, mode: Mode) {
|
pub fn set_mode(&mut self, mode: Mode) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
r.mode.write(|w| w.mode().variant(mode));
|
r.mode.write(|w| w.mode().variant(mode));
|
||||||
|
|
||||||
|
@ -235,10 +168,12 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the header size changing the S1 field
|
/// Set the header size changing the S1's len field
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_header_expansion(&mut self, use_s1_field: bool) {
|
pub fn set_header_expansion(&mut self, use_s1_field: bool) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// s1 len in bits
|
// s1 len in bits
|
||||||
|
@ -268,6 +203,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_whitening_init(&mut self, whitening_init: u8) {
|
pub fn set_whitening_init(&mut self, whitening_init: u8) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.datawhiteiv.write(|w| unsafe { w.datawhiteiv().bits(whitening_init) });
|
r.datawhiteiv.write(|w| unsafe { w.datawhiteiv().bits(whitening_init) });
|
||||||
|
@ -276,9 +213,11 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
/// Set the central frequency to be used
|
/// Set the central frequency to be used
|
||||||
/// It should be in the range 2400..2500
|
/// It should be in the range 2400..2500
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// [The radio must be disabled before calling this function](https://devzone.nordicsemi.com/f/nordic-q-a/15829/radio-frequency-change)
|
||||||
pub fn set_frequency(&mut self, frequency: u32) {
|
pub fn set_frequency(&mut self, frequency: u32) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
assert!(2400 <= frequency && frequency <= 2500);
|
assert!(2400 <= frequency && frequency <= 2500);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.frequency
|
r.frequency
|
||||||
|
@ -292,6 +231,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_access_address(&mut self, access_address: u32) {
|
pub fn set_access_address(&mut self, access_address: u32) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
// Configure logical address
|
// Configure logical address
|
||||||
|
@ -309,9 +250,9 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
r.txaddress.write(|w| unsafe { w.txaddress().bits(0) });
|
r.txaddress.write(|w| unsafe { w.txaddress().bits(0) });
|
||||||
|
|
||||||
// Match on logical address
|
// Match on logical address
|
||||||
// For what I understand, this config only filter the packets
|
// This config only filter the packets by the address,
|
||||||
// by the address, so only packages send to the previous address
|
// so only packages send to the previous address
|
||||||
// will finish the reception
|
// will finish the reception (TODO: check the explanation)
|
||||||
r.rxaddresses.write(|w| {
|
r.rxaddresses.write(|w| {
|
||||||
w.addr0()
|
w.addr0()
|
||||||
.enabled()
|
.enabled()
|
||||||
|
@ -331,6 +272,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_crc_poly(&mut self, crc_poly: u32) {
|
pub fn set_crc_poly(&mut self, crc_poly: u32) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.crcpoly.write(|w| unsafe {
|
r.crcpoly.write(|w| unsafe {
|
||||||
|
@ -351,6 +294,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_crc_init(&mut self, crc_init: u32) {
|
pub fn set_crc_init(&mut self, crc_init: u32) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.crcinit.write(|w| unsafe { w.crcinit().bits(crc_init & 0xFFFFFF) });
|
r.crcinit.write(|w| unsafe { w.crcinit().bits(crc_init & 0xFFFFFF) });
|
||||||
|
@ -360,6 +305,8 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
///
|
///
|
||||||
/// The radio must be disabled before calling this function
|
/// The radio must be disabled before calling this function
|
||||||
pub fn set_tx_power(&mut self, tx_power: TxPower) {
|
pub fn set_tx_power(&mut self, tx_power: TxPower) {
|
||||||
|
assert!(self.state() == RadioState::DISABLED);
|
||||||
|
|
||||||
let r = T::regs();
|
let r = T::regs();
|
||||||
|
|
||||||
r.txpower.write(|w| w.txpower().variant(tx_power));
|
r.txpower.write(|w| w.txpower().variant(tx_power));
|
||||||
|
@ -408,19 +355,83 @@ impl<'d, T: Instance> Radio<'d, T> {
|
||||||
// Initialize the transmission
|
// Initialize the transmission
|
||||||
// trace!("rxen");
|
// trace!("rxen");
|
||||||
r.tasks_rxen.write(|w| w.tasks_rxen().set_bit());
|
r.tasks_rxen.write(|w| w.tasks_rxen().set_bit());
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
// Await until ready
|
async fn trigger_and_wait_end(&mut self, trigger: impl FnOnce()) {
|
||||||
while r.events_ready.read().events_ready().bit_is_clear() {}
|
//self.trace_state();
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
// If the Future is dropped before the end of the transmission
|
||||||
|
// we need to disable the interrupt and stop the transmission
|
||||||
|
// to keep the state consistent
|
||||||
|
let drop = OnDrop::new(|| {
|
||||||
|
trace!("radio drop: stopping");
|
||||||
|
|
||||||
|
r.intenclr.write(|w| w.end().clear());
|
||||||
|
r.events_end.reset();
|
||||||
|
|
||||||
|
r.tasks_stop.write(|w| w.tasks_stop().set_bit());
|
||||||
|
|
||||||
|
// The docs don't explicitly mention any event to acknowledge the stop task
|
||||||
|
while r.events_end.read().events_end().bit_is_clear() {}
|
||||||
|
|
||||||
|
trace!("radio drop: stopped");
|
||||||
|
});
|
||||||
|
|
||||||
|
// trace!("radio:enable interrupt");
|
||||||
|
// Clear some remnant side-effects (TODO: check if this is necessary)
|
||||||
|
r.events_end.reset();
|
||||||
|
|
||||||
|
// Enable interrupt
|
||||||
|
r.intenset.write(|w| w.end().set());
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
|
// Trigger the transmission
|
||||||
|
trigger();
|
||||||
|
// self.trace_state();
|
||||||
|
|
||||||
|
// On poll check if interrupt happen
|
||||||
|
poll_fn(|cx| {
|
||||||
|
s.end_waker.register(cx.waker());
|
||||||
|
if r.events_end.read().events_end().bit_is_set() {
|
||||||
|
// trace!("radio:end");
|
||||||
|
return core::task::Poll::Ready(());
|
||||||
|
}
|
||||||
|
Poll::Pending
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
r.events_disabled.reset(); // ACK
|
||||||
|
|
||||||
|
// Everthing ends fine, so we can disable the drop
|
||||||
|
drop.defuse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable the radio
|
||||||
|
fn disable(&mut self) {
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
// If it is already disabled, do nothing
|
||||||
|
if self.state() != RadioState::DISABLED {
|
||||||
|
trace!("radio:disable");
|
||||||
|
// Trigger the disable task
|
||||||
|
r.tasks_disable.write(|w| w.tasks_disable().set_bit());
|
||||||
|
|
||||||
|
// Wait until the radio is disabled
|
||||||
|
while r.events_disabled.read().events_disabled().bit_is_clear() {}
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
// Acknowledge it
|
// Acknowledge it
|
||||||
r.events_ready.reset();
|
r.events_disabled.reset();
|
||||||
|
}
|
||||||
// trace!("radio:start");
|
|
||||||
r.tasks_start.write(|w| w.tasks_start().set_bit());
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue