Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0734b05

Browse files
committed
segger_rtt: implement uart Receiver
Implements the receive path for Segger RTT. Unfortunately, RTT has no mechanism of notifying (e.g. via an interrupt) for the availability of RX data so, instead, when the waiting for outstanding data, the implementation just polls the RTT buffer every 100 milliseconds---fast enough to be unnoticable to a human but infrequent enough to interrupt most computations.
1 parent 418a526 commit 0734b05

File tree

1 file changed

+59
-12
lines changed

1 file changed

+59
-12
lines changed

chips/segger/src/lib.rs

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ pub const DEFAULT_UP_BUFFER_LENGTH: usize = 1024;
107107
/// Suggested length for the down buffer to pass to the Segger RTT capsule.
108108
pub const DEFAULT_DOWN_BUFFER_LENGTH: usize = 32;
109109

110+
/// Milliseconds to wait to flush tx buffer after writing
111+
const TX_MS_DELAY: u32 = 1;
112+
113+
/// Milliseconds to wait between checking if rx data is available
114+
const RX_MS_DELAY: u32 = 100;
115+
110116
/// This structure is defined by the segger RTT protocol. It must exist in
111117
/// memory in exactly this form so that the segger JTAG tool can find it in the
112118
/// chip's memory and read and write messages to the appropriate buffers.
@@ -194,26 +200,34 @@ impl<'a> SeggerRttMemory<'a> {
194200
pub struct SeggerRtt<'a, A: hil::time::Alarm<'a>> {
195201
alarm: &'a A, // Dummy alarm so we can get a callback.
196202
config: TakeCell<'a, SeggerRttMemory<'a>>,
197-
client: OptionalCell<&'a dyn uart::TransmitClient>,
198-
client_buffer: TakeCell<'static, [u8]>,
203+
tx_client: OptionalCell<&'a dyn uart::TransmitClient>,
204+
tx_client_buffer: TakeCell<'static, [u8]>,
199205
tx_len: Cell<usize>,
206+
rx_client: OptionalCell<&'a dyn uart::ReceiveClient>,
207+
rx_client_buffer: TakeCell<'static, [u8]>,
208+
rx_cursor: Cell<usize>,
209+
rx_len: Cell<usize>,
200210
}
201211

202212
impl<'a, A: hil::time::Alarm<'a>> SeggerRtt<'a, A> {
203213
pub fn new(alarm: &'a A, config: &'a mut SeggerRttMemory<'a>) -> SeggerRtt<'a, A> {
204214
SeggerRtt {
205215
alarm,
206216
config: TakeCell::new(config),
207-
client: OptionalCell::empty(),
208-
client_buffer: TakeCell::empty(),
217+
tx_client: OptionalCell::empty(),
218+
tx_client_buffer: TakeCell::empty(),
209219
tx_len: Cell::new(0),
220+
rx_client: OptionalCell::empty(),
221+
rx_client_buffer: TakeCell::empty(),
222+
rx_cursor: Cell::new(0),
223+
rx_len: Cell::new(0),
210224
}
211225
}
212226
}
213227

214228
impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> {
215229
fn set_transmit_client(&self, client: &'a dyn uart::TransmitClient) {
216-
self.client.set(client);
230+
self.tx_client.set(client);
217231
}
218232

219233
fn transmit_buffer(
@@ -237,7 +251,7 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> {
237251
config.up_buffer.write_position.set(index as u32);
238252
self.tx_len.set(tx_len);
239253
// Save the client buffer so we can pass it back with the callback.
240-
self.client_buffer.replace(tx_data);
254+
self.tx_client_buffer.replace(tx_data);
241255

242256
// Start a short timer so that we get a callback and can issue the callback to
243257
// the client.
@@ -246,7 +260,7 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> {
246260
// board, passing buffers up to 1500 bytes from userspace. 100 micro-seconds
247261
// was too short, even for buffers as small as 128 bytes. 1 milli-second seems to
248262
// be reliable.
249-
let delay = self.alarm.ticks_from_us(1000);
263+
let delay = self.alarm.ticks_from_ms(TX_MS_DELAY);
250264
self.alarm.set_alarm(self.alarm.now(), delay);
251265
});
252266
Ok(())
@@ -266,11 +280,35 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> {
266280

267281
impl<'a, A: hil::time::Alarm<'a>> hil::time::AlarmClient for SeggerRtt<'a, A> {
268282
fn alarm(&self) {
269-
self.client.map(|client| {
270-
self.client_buffer.take().map(|buffer| {
283+
self.tx_client.map(|client| {
284+
self.tx_client_buffer.take().map(|buffer| {
271285
client.transmitted_buffer(buffer, self.tx_len.get(), Ok(()));
272286
});
273287
});
288+
self.rx_client.map(|client| {
289+
self.rx_client_buffer.take().map(|buffer| {
290+
self.config.map(|config| {
291+
let write_position = &config.down_buffer.write_position;
292+
let read_position = &config.down_buffer.read_position;
293+
while self.rx_cursor.get() < self.rx_len.get()
294+
&& write_position.get() != read_position.get()
295+
{
296+
buffer[self.rx_cursor.get()] =
297+
config.down_buffer[read_position.get() as usize].get();
298+
self.rx_cursor.set(self.rx_cursor.get() + 1);
299+
read_position
300+
.set((read_position.get() + 1) % config.down_buffer.length.get());
301+
}
302+
});
303+
if self.rx_cursor.get() == self.rx_len.get() {
304+
client.received_buffer(buffer, self.rx_len.get(), Ok(()), uart::Error::None);
305+
} else {
306+
let delay = self.alarm.ticks_from_ms(RX_MS_DELAY);
307+
self.alarm.set_alarm(self.alarm.now(), delay);
308+
self.rx_client_buffer.put(Some(buffer))
309+
}
310+
});
311+
});
274312
}
275313
}
276314

@@ -285,14 +323,23 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Configure for SeggerRtt<'a, A> {
285323
// Dummy implementation so this can act as the underlying UART for a
286324
// virtualized UART MUX. -pal 1/10/19
287325
impl<'a, A: hil::time::Alarm<'a>> uart::Receive<'a> for SeggerRtt<'a, A> {
288-
fn set_receive_client(&self, _client: &'a dyn uart::ReceiveClient) {}
326+
fn set_receive_client(&self, client: &'a dyn uart::ReceiveClient) {
327+
self.rx_client.set(client)
328+
}
289329

290330
fn receive_buffer(
291331
&self,
292332
buffer: &'static mut [u8],
293-
_len: usize,
333+
len: usize,
294334
) -> Result<(), (ErrorCode, &'static mut [u8])> {
295-
Err((ErrorCode::FAIL, buffer))
335+
self.rx_client_buffer.put(Some(buffer));
336+
self.rx_len.set(len);
337+
self.rx_cursor.set(0);
338+
if !self.alarm.is_armed() {
339+
let delay = self.alarm.ticks_from_ms(RX_MS_DELAY);
340+
self.alarm.set_alarm(self.alarm.now(), delay);
341+
}
342+
Ok(())
296343
}
297344

298345
fn receive_word(&self) -> Result<(), ErrorCode> {

0 commit comments

Comments
 (0)