[Cryptech-Commits] [sw/stm32] 03/06: Implement circular buffer UART RX using interrupts.

git at cryptech.is git at cryptech.is
Thu Jun 2 12:58:02 UTC 2016


This is an automated email from the git hooks/post-receive script.

fredrik at thulin.net pushed a commit to branch master
in repository sw/stm32.

commit 9915d1ba46e30990ea149c7a09d1d2ed0d13a331
Author: Fredrik Thulin <fredrik at thulin.net>
AuthorDate: Wed Jun 1 21:03:05 2016 +0200

    Implement circular buffer UART RX using interrupts.
---
 Makefile                                           |   3 +-
 .../TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c           | 169 +++++++++++++++++++++
 projects/cli-test/cli-test.c                       |  21 ++-
 projects/cli-test/mgmt-cli.c                       |  60 +++++++-
 projects/cli-test/mgmt-cli.h                       |   4 +
 projects/hsm/main.c                                |   7 -
 stm-uart.c                                         |  24 ++-
 7 files changed, 260 insertions(+), 28 deletions(-)

diff --git a/Makefile b/Makefile
index e2159ed..1f4ca74 100644
--- a/Makefile
+++ b/Makefile
@@ -63,7 +63,8 @@ export BOARD_OBJS = \
 	$(TOPLEVEL)/syscalls.o \
 	$(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \
 	$(BOARD_DIR)/system_stm32f4xx.o \
-	$(BOARD_DIR)/stm32f4xx_hal_msp.o
+	$(BOARD_DIR)/stm32f4xx_hal_msp.o \
+	$(BOARD_DIR)/stm32f4xx_it.o
 
 # cross-building tools
 PREFIX=arm-none-eabi-
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c
new file mode 100644
index 0000000..a174d73
--- /dev/null
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c
@@ -0,0 +1,169 @@
+/**
+******************************************************************************
+* @file    GPIO/GPIO_IOToggle/Src/stm32f4xx_it.c
+* @author  MCD Application Team
+* @version V1.0.1
+* @date    26-February-2014
+* @brief   Main Interrupt Service Routines.
+*          This file provides template for all exceptions handler and
+*          peripherals interrupt service routine.
+******************************************************************************
+* @attention
+*
+* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+
+#include "stm-init.h"
+#include "stm-uart.h"
+
+/******************************************************************************/
+/*            Cortex-M4 Processor Exceptions Handlers                         */
+/******************************************************************************/
+
+/**
+ * @brief   This function handles NMI exception.
+ * @param  None
+ * @retval None
+ */
+void NMI_Handler(void)
+{
+}
+
+/**
+ * @brief  This function handles Hard Fault exception.
+ * @param  None
+ * @retval None
+ */
+void HardFault_Handler(void)
+{
+    /* Go to infinite loop when Hard Fault exception occurs */
+    while (1) { ; }
+}
+
+/**
+ * @brief  This function handles Memory Manage exception.
+ * @param  None
+ * @retval None
+ */
+void MemManage_Handler(void)
+{
+    /* Go to infinite loop when Memory Manage exception occurs */
+    while (1) { ; }
+}
+
+/**
+ * @brief  This function handles Bus Fault exception.
+ * @param  None
+ * @retval None
+ */
+void BusFault_Handler(void)
+{
+    /* Go to infinite loop when Bus Fault exception occurs */
+    while (1) { ; }
+}
+
+/**
+ * @brief  This function handles Usage Fault exception.
+ * @param  None
+ * @retval None
+ */
+void UsageFault_Handler(void)
+{
+    /* Go to infinite loop when Usage Fault exception occurs */
+    while (1) { ; }
+}
+
+
+#if 0  /* already defined in libraries/mbed/rtos/ */
+/**
+ * @brief  This function handles SVCall exception.
+ * @param  None
+ * @retval None
+ */
+void SVC_Handler(void)
+{
+}
+
+/**
+ * @brief  This function handles Debug Monitor exception.
+ * @param  None
+ * @retval None
+ */
+void DebugMon_Handler(void)
+{
+}
+
+/**
+ * @brief  This function handles PendSVC exception.
+ * @param  None
+ * @retval None
+ */
+void PendSV_Handler(void)
+{
+}
+
+/**
+ * @brief  This function handles SysTick Handler.
+ * @param  None
+ * @retval None
+ */
+void SysTick_Handler(void)
+{
+    HAL_IncTick();
+}
+#endif
+
+/******************************************************************************/
+/*                 STM32F4xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32f4xx.s).                                               */
+/******************************************************************************/
+
+/**
+ * @brief  This function handles UART interrupt request.
+ * @param  None
+ * @retval None
+ * @Note   HAL_UART_IRQHandler will call HAL_UART_TxCpltCallback in main.c.
+ */
+void USART1_IRQHandler(void)
+{
+    HAL_UART_IRQHandler(&huart_mgmt);
+}
+
+/**
+ * @brief  This function handles UART interrupt request.
+ * @param  None
+ * @retval None
+ * @Note   HAL_UART_IRQHandler will call HAL_UART_TxCpltCallback in main.c.
+ */
+void USART2_IRQHandler(void)
+{
+    HAL_UART_IRQHandler(&huart_user);
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index 26ebbc2..b90d0dd 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -49,6 +49,9 @@
 
 extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len);
 
+/* MGMT UART interrupt receive buffer (data will be put in a larger ring buffer) */
+volatile uint8_t uart_rx;
+
 
 int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc)
 {
@@ -286,6 +289,22 @@ void do_early_dfu_jump(void)
     while (1);
 }
 
+/* Callback for HAL_UART_Receive_IT(). */
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+    if (huart->Instance == huart_mgmt.Instance) {
+	mgmt_cli_uart_isr((const uint8_t *) &uart_rx, 1);
+
+	/* Set things up to receive another byte. */
+	HAL_UART_Receive_IT(huart, (uint8_t *) &uart_rx, 1);
+    }
+}
+
+void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
+{
+    led_on(LED_RED);
+    led_on(LED_YELLOW);
+}
 
 int
 main()
@@ -318,7 +337,7 @@ main()
 
     /* embedded_cli_loop returns when the user enters 'quit' or 'exit' */
 
-    cli_print(&cli, "Rebooting in 4 seconds");
+    cli_print(&cli, "Rebooting in 3 seconds");
     HAL_Delay(3000);
     HAL_NVIC_SystemReset();
 
diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c
index 46faae8..abbd999 100644
--- a/projects/cli-test/mgmt-cli.c
+++ b/projects/cli-test/mgmt-cli.c
@@ -33,10 +33,27 @@
  */
 #include "stm-init.h"
 #include "stm-uart.h"
+#include "stm-led.h"
 #include "mgmt-cli.h"
 
 #include <string.h>
 
+extern uint8_t uart_rx;
+
+struct uart_ringbuf_t {
+    uint32_t enabled, ridx, widx, overflow;
+    uint8_t buf[CLI_UART_RECVBUF_SIZE];
+};
+
+volatile struct uart_ringbuf_t uart_ringbuf = {1, 0, 0, 0, {0}};
+
+#define RINGBUF_RIDX(rb)       (rb.ridx & CLI_UART_RECVBUF_MASK)
+#define RINGBUF_WIDX(rb)       (rb.widx & CLI_UART_RECVBUF_MASK)
+#define RINGBUF_COUNT(rb)      ((unsigned)(rb.widx - rb.ridx))
+#define RINGBUF_FULL(rb)       (RINGBUF_RIDX(rb) == ((rb.widx + 1) & CLI_UART_RECVBUF_MASK))
+#define RINGBUF_READ(rb, dst)  {dst = rb.buf[RINGBUF_RIDX(rb)]; rb.buf[RINGBUF_RIDX(rb)] = '.'; rb.ridx++;}
+#define RINGBUF_WRITE(rb, src) {rb.buf[RINGBUF_WIDX(rb)] = src; rb.widx++;}
+
 void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf)
 {
     char crlf[] = "\r\n";
@@ -46,8 +63,23 @@ void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *bu
 
 int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count)
 {
-    if (uart_recv_char2(STM_UART_MGMT, buf, count) != HAL_OK) {
-	return -1;
+    uint32_t timeout = 0xffffff;
+
+    /* Always explicitly enable the RX interrupt when we get here.
+     * Prevents us getting stuck waiting for an interrupt that will never come.
+     */
+    __HAL_UART_FLUSH_DRREGISTER(&huart_mgmt);
+    HAL_UART_Receive_IT(&huart_mgmt, (uint8_t *) &uart_rx, 1);
+
+    while (count && timeout--) {
+	if (RINGBUF_COUNT(uart_ringbuf)) {
+	    RINGBUF_READ(uart_ringbuf, *(uint8_t *) buf);
+	    buf++;
+	    count--;
+	} else {
+	    led_toggle(LED_GREEN);
+	    HAL_Delay(10);
+	}
     }
     return 1;
 }
@@ -83,7 +115,11 @@ int embedded_cli_loop(struct cli_def *cli)
 
 	    n = cli_loop_read_next_char(cli, &ctx, &c);
 
-	    //cli_print(cli, "Next char: '%c' (n == %i)", c, n);
+	    /*
+	    cli_print(cli, "Next char: '%c'/%i, ringbuf ridx %i, widx %i (%i/%i) - count %i",
+		      c, (int) c, uart_ringbuf.ridx, uart_ringbuf.widx, RINGBUF_RIDX(uart_ringbuf),
+		      RINGBUF_WIDX(uart_ringbuf), RINGBUF_COUNT(uart_ringbuf));
+	    */
 	    if (n == CLI_LOOP_CTRL_BREAK)
 		break;
 	    if (n == CLI_LOOP_CTRL_CONTINUE)
@@ -98,7 +134,7 @@ int embedded_cli_loop(struct cli_def *cli)
 
 	if (ctx.l < 0) break;
 
-	//cli_print(cli, "Process command: '%s'", ctx.cmd);
+	/* cli_print(cli, "Process command: '%s'", ctx.cmd); */
 	n = cli_loop_process_cmd(cli, &ctx);
 	if (n == CLI_LOOP_CTRL_BREAK)
 	    break;
@@ -107,6 +143,22 @@ int embedded_cli_loop(struct cli_def *cli)
     return CLI_OK;
 }
 
+/* Interrupt service routine to be called when data has been received on the MGMT UART. */
+void mgmt_cli_uart_isr(const uint8_t *buf, size_t count)
+{
+    if (! uart_ringbuf.enabled) return;
+
+    while (count) {
+	if (RINGBUF_FULL(uart_ringbuf)) {
+	    uart_ringbuf.overflow++;
+	    return;
+	}
+	RINGBUF_WRITE(uart_ringbuf, *buf);
+	buf++;
+	count--;
+    }
+}
+
 void mgmt_cli_init(struct cli_def *cli)
 {
     cli_init(cli);
diff --git a/projects/cli-test/mgmt-cli.h b/projects/cli-test/mgmt-cli.h
index dd6a58b..3b7f503 100644
--- a/projects/cli-test/mgmt-cli.h
+++ b/projects/cli-test/mgmt-cli.h
@@ -68,10 +68,14 @@
     cli_register_command2(cli, &cmd_##name##_s, NULL)
 
 
+#define CLI_UART_RECVBUF_SIZE  256  /* This must be a power of 2 */
+#define CLI_UART_RECVBUF_MASK  (CLI_UART_RECVBUF_SIZE - 1)
+
 extern void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf);
 extern int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count);
 extern int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count);
 extern int embedded_cli_loop(struct cli_def *cli);
 extern void mgmt_cli_init(struct cli_def *cli);
+extern void mgmt_cli_uart_isr(const uint8_t *buf, size_t count);
 
 #endif /* __STM32_MGMT_CLI_H */
diff --git a/projects/hsm/main.c b/projects/hsm/main.c
index ed93aed..2508f07 100644
--- a/projects/hsm/main.c
+++ b/projects/hsm/main.c
@@ -198,13 +198,6 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
     HAL_UART_Receive_IT(huart, &c, 1);
 }
 
-/* UART interrupt handler. This eventually calls HAL_UART_RxCpltCallback.
- */
-void USART2_IRQHandler(void)
-{
-    HAL_UART_IRQHandler(&huart_user);
-}
-
 /* The main thread. After the system setup, it waits for the RPC-request
  * semaphore from HAL_UART_RxCpltCallback, and spawns a dispatch thread.
  */
diff --git a/stm-uart.c b/stm-uart.c
index 297718d..2f3aabe 100644
--- a/stm-uart.c
+++ b/stm-uart.c
@@ -62,12 +62,7 @@ HAL_StatusTypeDef uart_send_char(uint8_t ch)
 
 HAL_StatusTypeDef uart_send_char2(enum stm_uart_port port, uint8_t ch)
 {
-    UART_HandleTypeDef *uart = _which_uart(port);
-
-    if (uart)
-        return HAL_UART_Transmit(uart, &ch, 1, 0x1);
-
-    return HAL_ERROR;
+    return uart_send_bytes(port, &ch, 1);
 }
 
 /* receive a single character */
@@ -96,21 +91,21 @@ HAL_StatusTypeDef uart_send_string(char *s)
 /* send a string */
 HAL_StatusTypeDef uart_send_string2(enum stm_uart_port port, const char *s)
 {
-    UART_HandleTypeDef *uart = _which_uart(port);
-
-    if (uart)
-	return HAL_UART_Transmit(uart, (uint8_t *) s, strlen(s), 0x1);
-
-    return HAL_ERROR;
+    return uart_send_bytes(port, (uint8_t *) s, strlen(s));
 }
 
 /* send raw bytes */
 HAL_StatusTypeDef uart_send_bytes(enum stm_uart_port port, uint8_t *buf, size_t len)
 {
+    uint32_t timeout = 100;
     UART_HandleTypeDef *uart = _which_uart(port);
 
-    if (uart)
+    if (uart) {
+	while (HAL_UART_GetState(uart) != HAL_UART_STATE_READY && timeout--) { ; }
+	if (! timeout) return HAL_ERROR;
+
         return HAL_UART_Transmit(uart, (uint8_t *) buf, (uint32_t) len, 0x1);
+    }
 
     return HAL_ERROR;
 }
@@ -139,7 +134,6 @@ HAL_StatusTypeDef uart_send_number2(enum stm_uart_port port, uint32_t num, uint8
     #define BUFSIZE 32
     char buf[BUFSIZE];
     char *where = buf + BUFSIZE;
-    UART_HandleTypeDef *uart = _which_uart(port);
 
     /* initialize buf so we can add leading 0 by adjusting the pointer */
     memset(buf, '0', BUFSIZE);
@@ -163,7 +157,7 @@ HAL_StatusTypeDef uart_send_number2(enum stm_uart_port port, uint32_t num, uint8
 	/* number is larger than the specified number of digits */
 	digits = buf + BUFSIZE - where;
 
-    return HAL_UART_Transmit(uart, (uint8_t *) where, digits, 0x1);
+    return uart_send_bytes(port, (uint8_t *) where, digits);
 }
 
 HAL_StatusTypeDef uart_send_hexdump(enum stm_uart_port port, const uint8_t *buf,



More information about the Commits mailing list