From 9915d1ba46e30990ea149c7a09d1d2ed0d13a331 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Wed, 1 Jun 2016 21:03:05 +0200 Subject: 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(-) create mode 100644 libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c 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 +* +*

© COPYRIGHT(c) 2014 STMicroelectronics

+* +* 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 +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, -- cgit v1.2.3