Skip to content

Commit

Permalink
Support buffering multiple serial sends
Browse files Browse the repository at this point in the history
  • Loading branch information
ah- committed Feb 27, 2018
1 parent dba2073 commit 620c359
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ app! {
resources: {
static KEYBOARD: Keyboard = Keyboard::new();
static KEY_MATRIX: KeyMatrix;
static BLUETOOTH_BUFFERS: [[u8; 0x10]; 2] = [[0; 0x10]; 2];
static BLUETOOTH_BUFFERS: [[u8; 0x20]; 2] = [[0; 0x20]; 2];
static BLUETOOTH: Bluetooth<'static>;
static LED_BUFFERS: [[u8; 0x10]; 2] = [[0; 0x10]; 2];
static LED_BUFFERS: [[u8; 0x20]; 2] = [[0; 0x20]; 2];
static LED: Led<'static>;
static SYST: stm32l151::SYST;
static EXTI: stm32l151::EXTI;
Expand Down
17 changes: 12 additions & 5 deletions src/serial/bluetooth_usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct BluetoothUsart {
_usart: USART2,
dma_rx: C6,
dma_tx: C7,
pending_tx: u16, // number of bits pending while waiting for bt to wake up
}

impl DmaUsart for BluetoothUsart {
Expand All @@ -32,11 +33,13 @@ impl DmaUsart for BluetoothUsart {
}

fn is_send_ready(&mut self) -> bool {
self.dma_tx.cndtr().read().ndt().bits() == 0
self.dma_tx.cndtr().read().ndt().bits() == 0 || self.pending_tx != 0
}

fn send(&mut self, buffer: u32, _len: u16) {
fn send(&mut self, buffer: u32, len: u16) {
// Don't actually send anything yet, just enqueue and wait for wakeup package
// we can still safely modify the buffer while waiting to send it,
// just call this method again to transmit
self.dma_rx.ccr().modify(|_, w| { w.en().clear_bit() });
self.dma_rx.cndtr().modify(|_, w| unsafe { w.ndt().bits(2) });
self.dma_rx.ccr().modify(|_, w| { w.en().set_bit() });
Expand All @@ -45,12 +48,16 @@ impl DmaUsart for BluetoothUsart {

self.pa1.set_low();
self.pa1.set_high();

self.pending_tx = len;
}

fn ack_wakeup(&mut self) {
// TODO: correct length, not just hardcoded 0xb
self.dma_tx.cndtr().modify(|_, w| unsafe { w.ndt().bits(0xb) });
let n_pending = self.pending_tx;
self.dma_tx.cndtr().modify(|_, w| unsafe { w.ndt().bits(n_pending) });
self.dma_tx.ccr().modify(|_, w| w.en().set_bit());

self.pending_tx = 0;
}

fn tx_interrupt(&mut self) {
Expand Down Expand Up @@ -101,6 +108,6 @@ impl BluetoothUsart {
.en().clear_bit()
});

BluetoothUsart { pa1: pa1, _pa2: pa2, _pa3: pa3, _usart: usart, dma_rx: dma_rx, dma_tx: dma_tx }
BluetoothUsart { pa1: pa1, _pa2: pa2, _pa3: pa3, _usart: usart, dma_rx: dma_rx, dma_tx: dma_tx, pending_tx: 0 }
}
}
30 changes: 20 additions & 10 deletions src/serial/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ pub struct Serial<'a, USART>
{
usart: USART,
receive_stage: ReceiveStage,
send_buffer: &'a mut[u8; 0x10],
receive_buffer: &'a mut[u8; 0x10],
send_buffer: &'a mut[u8; 0x20],
receive_buffer: &'a mut[u8; 0x20],
send_buffer_pos: u16,
}

pub trait DmaUsart {
Expand All @@ -35,7 +36,7 @@ const HEADER_SIZE: u16 = 2;
impl<'a, USART> Serial<'a, USART>
where USART: DmaUsart
{
pub fn new(mut usart: USART, buffers: &'a mut[[u8; 0x10]; 2])
pub fn new(mut usart: USART, buffers: &'a mut[[u8; 0x20]; 2])
-> Serial<'a, USART> {
let (send_buffer, receive_buffer) = buffers.split_at_mut(1);
let receive_ptr = receive_buffer[0].as_mut_ptr() as u32;
Expand All @@ -47,6 +48,7 @@ impl<'a, USART> Serial<'a, USART>
receive_stage: ReceiveStage::Header,
send_buffer: &mut send_buffer[0],
receive_buffer: &mut receive_buffer[0],
send_buffer_pos: 0,
}
}

Expand All @@ -73,6 +75,7 @@ impl<'a, USART> Serial<'a, USART>
(MsgType::Ble, 170) => {
// Wakeup acknowledged, send data
self.usart.ack_wakeup();
self.send_buffer_pos = 0;
},
_ => callback(&message)
}
Expand All @@ -89,13 +92,19 @@ impl<'a, USART> Serial<'a, USART>
message_type: MsgType,
operation: u8, // TODO: make this typed?
data: &[u8]) -> nb::Result<(), !> {
if self.usart.is_send_ready() {
self.send_buffer[0] = message_type as u8;
self.send_buffer[1] = 1 + data.len() as u8;
self.send_buffer[2] = operation;
self.send_buffer[3..3 + data.len()].clone_from_slice(data);
let tx_len = 3 + data.len() as u16;
if self.usart.is_send_ready() && self.send_buffer_pos + tx_len < self.send_buffer.len() as u16 {
// TODO: put this into buffer, but then increase buffer offset
// keep counter, use counter when calling send()
let pos = self.send_buffer_pos as usize;
self.send_buffer[pos] = message_type as u8;
self.send_buffer[pos + 1] = 1 + data.len() as u8;
self.send_buffer[pos + 2] = operation;
self.send_buffer[pos + 3..pos + tx_len as usize].clone_from_slice(data);

self.usart.send(self.send_buffer.as_mut_ptr() as u32, 3 + data.len() as u16);
self.send_buffer_pos += tx_len;

self.usart.send(self.send_buffer.as_mut_ptr() as u32, self.send_buffer_pos);
self.receive_stage = ReceiveStage::Header;

return Ok(())
Expand All @@ -105,6 +114,7 @@ impl<'a, USART> Serial<'a, USART>
}

pub fn tx_interrupt(&mut self) {
self.usart.tx_interrupt()
self.usart.tx_interrupt();
self.send_buffer_pos = 0;
}
}

0 comments on commit 620c359

Please sign in to comment.