aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Selkirk <paul@psgd.org>2017-07-31 23:23:14 -0400
committerPaul Selkirk <paul@psgd.org>2017-07-31 23:23:14 -0400
commite4302fb3f0f9c9b60d79a83a69d02ca23fb663ff (patch)
treeef6a9e8bd89482271d346b2ce8842951e93900a1
parent9ffead1c015bf05425b78d43b1b4b3e21f109929 (diff)
Adapt uart_rx_thread to the post-thread tasking model, because we're still
subject to the same forces that made it a good idea in the first place. commit 2b6b9f8 Change RPC UART to have a high-priority thread monitoring a large(ish) DMA buffer, because we've observed out-of-order receives under load.
-rw-r--r--projects/hsm/hsm.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/projects/hsm/hsm.c b/projects/hsm/hsm.c
index 8a8f441..28a1e68 100644
--- a/projects/hsm/hsm.c
+++ b/projects/hsm/hsm.c
@@ -244,25 +244,38 @@ static void RxCallback(uint8_t c)
}
}
-static uint8_t uart_rx[2]; /* current character received from UART */
-static uint32_t uart_rx_idx = 0;
-
-/* UART DMA half-complete and complete callbacks. With a 2-character DMA
- * buffer, one or the other of these will fire on each incoming character.
- * Under heavy load, these will sometimes fire in the wrong order, but the
- * data are in the right order in the DMA buffer, so we have a flip-flop
- * buffer index that doesn't depend on the order of the callbacks.
+/* A ring buffer for the UART DMA receiver. In theory, it should get at most
+ * 92 characters per 1ms tick, but we're going to up-size it for safety.
*/
-void HAL_UART2_RxHalfCpltCallback(UART_HandleTypeDef *huart)
-{
- RxCallback(uart_rx[uart_rx_idx]);
- uart_rx_idx ^= 1;
-}
+#ifndef RPC_UART_RECVBUF_SIZE
+#define RPC_UART_RECVBUF_SIZE 1024 /* must be a power of 2 */
+#endif
+#define RPC_UART_RECVBUF_MASK (RPC_UART_RECVBUF_SIZE - 1)
+
+typedef struct {
+ uint32_t ridx;
+ uint8_t buf[RPC_UART_RECVBUF_SIZE];
+} uart_ringbuf_t;
-void HAL_UART2_RxCpltCallback(UART_HandleTypeDef *huart)
+volatile uart_ringbuf_t uart_ringbuf = {0, {0}};
+
+#define RINGBUF_RIDX(rb) (rb.ridx & RPC_UART_RECVBUF_MASK)
+#define RINGBUF_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_user.hdmarx))
+#define RINGBUF_COUNT(rb) ((RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb)) & RPC_UART_RECVBUF_MASK)
+#define RINGBUF_READ(rb, dst) {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.ridx++;}
+
+size_t uart_rx_max = 0;
+
+static void uart_rx_task(void)
{
- RxCallback(uart_rx[uart_rx_idx]);
- uart_rx_idx ^= 1;
+ size_t count = RINGBUF_COUNT(uart_ringbuf);
+ if (uart_rx_max < count) uart_rx_max = count;
+
+ while (RINGBUF_COUNT(uart_ringbuf)) {
+ uint8_t c;
+ RINGBUF_READ(uart_ringbuf, c);
+ RxCallback(c);
+ }
}
/* Send one character over the UART. This is called from
@@ -425,7 +438,9 @@ int main(void)
Error_Handler();
/* Start the UART receiver. */
- if (HAL_UART_Receive_DMA(&huart_user, uart_rx, 2) != CMSIS_HAL_OK)
+ extern void set_SysTick_hook(void (*hook)(void));
+ set_SysTick_hook(uart_rx_task);
+ if (HAL_UART_Receive_DMA(&huart_user, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf)) != CMSIS_HAL_OK)
Error_Handler();
/* Launch other tasks (csprng warm-up task?)