fixeria has uploaded this change for review.
[WIP] soft_uart: implement OSMO_SUART_RX_MODE_N_FRAMES
This is a hack allowing us to examine the receiver's internal buffer
without having to wait for a timeout to expire. I am not sure if
such mode would be useful for anything else. Maybe adding API to
access the Rx msgb would be a more flexible solution?
Change-Id: Ib3249a06c84f3ddb2723d0787db51873c4707d81
Related: OS#4396
---
M include/osmocom/core/soft_uart.h
M src/core/soft_uart.c
2 files changed, 67 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/45/35045/1
diff --git a/include/osmocom/core/soft_uart.h b/include/osmocom/core/soft_uart.h
index 6088922..19af0cf 100644
--- a/include/osmocom/core/soft_uart.h
+++ b/include/osmocom/core/soft_uart.h
@@ -45,6 +45,14 @@
};
#endif
+/*! Rx data pulling mode */
+enum osmo_soft_uart_rx_mode {
+ /*! the .rx_cb() is called on timeout */
+ OSMO_SUART_RX_MODE_TIMEOUT,
+ /*! the .rx_cb() is called on a specified number of UART frames */
+ OSMO_SUART_RX_MODE_N_FRAMES,
+};
+
/* configuration for a soft-uart */
struct osmo_soft_uart_cfg {
/*! number of data bits (typically 5, 6, 7 or 8) */
@@ -53,14 +61,25 @@
uint8_t num_stop_bits;
/*! parity mode (none, even, odd) */
enum osmo_soft_uart_parity_mode parity_mode;
+
/*! size of transmit buffer */
unsigned int tx_buf_size;
- /*! size of receive buffer; UART will buffer up to that number of characters
- * before calling the receive call-back */
+ /*! size of receive buffer */
unsigned int rx_buf_size;
- /*! receive timeout; UART will flush receive buffer via the receive call-back
- * after indicated number of milli-seconds even if it is not full yet */
- unsigned int rx_timeout_ms;
+
+ /*! Rx data pulling mode */
+ enum osmo_soft_uart_rx_mode rx_pull_mode;
+ /*! Rx data pulling parameters */
+ union {
+ /*! receive timeout for OSMO_SUART_RX_MODE_TIMEOUT; UART will flush receive
+ * buffer via the receive call-back after indicated number of milli-seconds
+ * even if it is not full yet. */
+ unsigned int rx_timeout_ms;
+ /*! number of received UART frames for OSMO_SUART_RX_MODE_N_FRAMES; UART
+ * will flush receive buffer via the receive call-back after indicated number
+ * of UART frames had been received. */
+ unsigned int rx_n_uart_frames;
+ } rx_pull_param;
/*! opaque application-private data; passed to call-backs */
void *priv;
diff --git a/src/core/soft_uart.c b/src/core/soft_uart.c
index 9b6ca05..c7179a6 100644
--- a/src/core/soft_uart.c
+++ b/src/core/soft_uart.c
@@ -47,6 +47,7 @@
unsigned int flags;
unsigned int status;
struct osmo_timer_list timer;
+ unsigned int n_uart_frames;
enum suart_flow_state flow_state;
} rx;
struct {
@@ -71,7 +72,8 @@
.parity_mode = OSMO_SUART_PARITY_NONE,
.tx_buf_size = 1024,
.rx_buf_size = 1024,
- .rx_timeout_ms = 100,
+ .rx_pull_mode = OSMO_SUART_RX_MODE_TIMEOUT,
+ .rx_pull_param = { .rx_timeout_ms = 100 },
.priv = NULL,
.rx_cb = NULL,
.status_change_cb = NULL,
@@ -105,12 +107,29 @@
msgb_put_u8(suart->rx.msg, ch);
msg_len = msgb_length(suart->rx.msg);
- /* first character in new message: start timer */
- if (msg_len == 1) {
- osmo_timer_schedule(&suart->rx.timer, suart->cfg.rx_timeout_ms / 1000,
- (suart->cfg.rx_timeout_ms % 1000) * 1000);
- } else if (msg_len >= suart->cfg.rx_buf_size || suart->rx.flags) {
+ /* flush immediately:
+ * a) when the Rx buffer gets full;
+ * b) when a parity/framing error is occured. */
+ if (msg_len >= suart->cfg.rx_buf_size || suart->rx.flags) {
suart_flush_rx(suart);
+ return;
+ }
+
+ switch (suart->cfg.rx_pull_mode) {
+ case OSMO_SUART_RX_MODE_TIMEOUT:
+ /* first character in new message: start timer */
+ if (msg_len == 1) {
+ unsigned int rx_timeout_ms = suart->cfg.rx_pull_param.rx_timeout_ms;
+ osmo_timer_schedule(&suart->rx.timer, rx_timeout_ms / 1000,
+ (rx_timeout_ms % 1000) * 1000);
+ }
+ break;
+ case OSMO_SUART_RX_MODE_N_FRAMES:
+ if (suart->rx.n_uart_frames >= suart->cfg.rx_pull_param.rx_n_uart_frames) {
+ suart->rx.n_uart_frames = 0;
+ suart_flush_rx(suart);
+ }
+ break;
}
}
@@ -171,6 +190,7 @@
if (suart->rx.bit_count >= (suart->cfg.num_data_bits + suart->cfg.num_stop_bits)) {
/* we have accumulated enough stop bits */
+ suart->rx.n_uart_frames++;
suart_rx_ch(suart, suart->rx.shift_reg);
suart->rx.flow_state = SUART_FLOW_ST_IDLE;
}
@@ -358,10 +378,12 @@
if (cfg->rx_buf_size == 0)
return -EINVAL;
+#if 0
if (suart->cfg.rx_buf_size > cfg->rx_buf_size ||
suart->cfg.rx_timeout_ms > cfg->rx_timeout_ms) {
suart_flush_rx(suart);
}
+#endif
suart->cfg = *cfg;
To view, visit change 35045. To unsubscribe, or for help writing mail filters, visit settings.