From 2d08b2038a5cf14a92d8ca3e10fb3421e73e5b74 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Wed, 1 Jun 2016 13:47:46 +0200 Subject: Move FPGA related commands to mgmt-fpga.c --- projects/cli-test/Makefile | 2 +- projects/cli-test/cli-test.c | 135 +------------------------------- projects/cli-test/mgmt-fpga.c | 174 ++++++++++++++++++++++++++++++++++++++++++ projects/cli-test/mgmt-fpga.h | 50 ++++++++++++ 4 files changed, 226 insertions(+), 135 deletions(-) create mode 100644 projects/cli-test/mgmt-fpga.c create mode 100644 projects/cli-test/mgmt-fpga.h diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index 39619fc..2ca61b9 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,6 +1,6 @@ TEST = cli-test -OBJS = crc32.o mgmt-cli.o test_sdram.o mgmt-dfu.o +OBJS = crc32.o mgmt-cli.o test_sdram.o mgmt-dfu.o mgmt-fpga.o CFLAGS += -I$(LIBCLI_DIR) LIBS += $(LIBCLI_DIR)/libcli.a diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 84c268b..26ebbc2 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -40,6 +40,7 @@ #include "stm-sdram.h" #include "mgmt-cli.h" #include "mgmt-dfu.h" +#include "mgmt-fpga.h" #include "test_sdram.h" #include @@ -157,124 +158,6 @@ int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[ return CLI_OK; } -/* The chunk size have to be a multiple of the SPI flash page size (256 bytes), - and it has to match the chunk size in the program sending the bitstream over the UART. -*/ -#define BITSTREAM_UPLOAD_CHUNK_SIZE 4096 - -int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0, i; - uint32_t offset = 0, n = BITSTREAM_UPLOAD_CHUNK_SIZE; - uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE]; - - fpgacfg_access_control(ALLOW_ARM); - - cli_print(cli, "Checking if FPGA config memory is accessible"); - if (fpgacfg_check_id() != 1) { - cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); - return CLI_ERROR; - } - - cli_print(cli, "OK, write FPGA bitstream file size (4 bytes), data in 4096 byte chunks, CRC-32 (4 bytes)"); - - /* Read file size (4 bytes) */ - uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); - cli_print(cli, "File size %li", filesize); - - while (filesize) { - /* By initializing buf to the same value that erased flash has (0xff), we don't - * have to try and be smart when writing the last page of data to the memory. - */ - memset(buf, 0xff, sizeof(buf)); - - if (filesize < n) { - n = filesize; - } - - if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { - cli_print(cli, "Receive timed out"); - return CLI_ERROR; - } - filesize -= n; - - /* After reception of 4 KB but before ACKing we have "all" the time in the world to - * calculate CRC and write it to flash. - */ - my_crc = update_crc(my_crc, buf, n); - - if ((i = fpgacfg_write_data(offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE)) != 1) { - cli_print(cli, "Failed writing data at offset %li (counter = %li): %li", offset, counter, i); - return CLI_ERROR; - } - - offset += BITSTREAM_UPLOAD_CHUNK_SIZE; - - /* ACK this chunk by sending the current chunk counter (4 bytes) */ - counter++; - uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); - } - - /* The sending side will now send it's calculated CRC-32 */ - cli_print(cli, "Send CRC-32"); - uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); - cli_print(cli, "CRC-32 %li", crc); - if (crc == my_crc) { - cli_print(cli, "CRC checksum MATCHED"); - } else { - cli_print(cli, "CRC checksum did NOT match"); - } - - fpgacfg_access_control(ALLOW_FPGA); - - return CLI_OK; -} - -int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - fpgacfg_access_control(ALLOW_ARM); - - cli_print(cli, "Checking if FPGA config memory is accessible"); - if (fpgacfg_check_id() != 1) { - cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); - return CLI_ERROR; - } - - /* Erasing the whole config memory takes a while, we just need to erase the first sector. - * The bitstream has an EOF marker, so even if the next bitstream uploaded is shorter than - * the current one there should be no problem. - * - * This command could be made to accept an argument indicating the whole memory should be erased. - */ - if (! fpgacfg_erase_sectors(1)) { - cli_print(cli, "Erasing first sector in FPGA config memory failed"); - return CLI_ERROR; - } - - cli_print(cli, "Erased FPGA config memory"); - fpgacfg_access_control(ALLOW_FPGA); - - return CLI_OK; -} - -int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - fpgacfg_access_control(ALLOW_FPGA); - fpgacfg_reset_fpga(RESET_FULL); - cli_print(cli, "FPGA has been reset"); - - return CLI_OK; -} - -int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - fpgacfg_access_control(ALLOW_FPGA); - fpgacfg_reset_fpga(RESET_REGISTERS); - cli_print(cli, "FPGA registers have been reset"); - - return CLI_OK; -} - int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) { cli_print(cli, "\n\n\nRebooting\n\n\n"); @@ -372,22 +255,6 @@ void configure_cli_show(struct cli_def *cli) cli_command_node(show_keystore, data, "Show the first page of the keystore memory"); } -void configure_cli_fpga(struct cli_def *cli) -{ - /* fpga */ - cli_command_root(fpga); - /* fpga reset */ - cli_command_node(fpga, reset, "Reset FPGA (config reset)"); - /* fpga reset registers */ - cli_command_node(fpga_reset, registers, "Reset FPGA registers (soft reset)"); - - cli_command_branch(fpga, bitstream); - /* fpga bitstream upload */ - cli_command_node(fpga_bitstream, upload, "Upload new FPGA bitstream"); - /* fpga bitstream erase */ - cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory"); -} - void configure_cli_test(struct cli_def *cli) { /* test */ diff --git a/projects/cli-test/mgmt-fpga.c b/projects/cli-test/mgmt-fpga.c new file mode 100644 index 0000000..c20b7b2 --- /dev/null +++ b/projects/cli-test/mgmt-fpga.c @@ -0,0 +1,174 @@ +/* + * mgmt-fpga.c + * ----------- + * CLI code to manage the FPGA configuration etc. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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" +#include "stm-fpgacfg.h" +#include "mgmt-cli.h" +#include "mgmt-fpga.h" + +#include + + +extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); + + +int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0, i; + uint32_t offset = 0, n = BITSTREAM_UPLOAD_CHUNK_SIZE; + uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE]; + + fpgacfg_access_control(ALLOW_ARM); + + cli_print(cli, "Checking if FPGA config memory is accessible"); + if (fpgacfg_check_id() != 1) { + cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); + return CLI_ERROR; + } + + cli_print(cli, "OK, write FPGA bitstream file size (4 bytes), data in 4096 byte chunks, CRC-32 (4 bytes)"); + + /* Read file size (4 bytes) */ + uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); + cli_print(cli, "File size %li", filesize); + + while (filesize) { + /* By initializing buf to the same value that erased flash has (0xff), we don't + * have to try and be smart when writing the last page of data to the memory. + */ + memset(buf, 0xff, sizeof(buf)); + + if (filesize < n) { + n = filesize; + } + + if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { + cli_print(cli, "Receive timed out"); + return CLI_ERROR; + } + filesize -= n; + + /* After reception of 4 KB but before ACKing we have "all" the time in the world to + * calculate CRC and write it to flash. + */ + my_crc = update_crc(my_crc, buf, n); + + if ((i = fpgacfg_write_data(offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE)) != 1) { + cli_print(cli, "Failed writing data at offset %li (counter = %li): %li", offset, counter, i); + return CLI_ERROR; + } + + offset += BITSTREAM_UPLOAD_CHUNK_SIZE; + + /* ACK this chunk by sending the current chunk counter (4 bytes) */ + counter++; + uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); + } + + /* The sending side will now send it's calculated CRC-32 */ + cli_print(cli, "Send CRC-32"); + uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); + cli_print(cli, "CRC-32 %li", crc); + if (crc == my_crc) { + cli_print(cli, "CRC checksum MATCHED"); + } else { + cli_print(cli, "CRC checksum did NOT match"); + } + + fpgacfg_access_control(ALLOW_FPGA); + + return CLI_OK; +} + +int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_ARM); + + cli_print(cli, "Checking if FPGA config memory is accessible"); + if (fpgacfg_check_id() != 1) { + cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed."); + return CLI_ERROR; + } + + /* Erasing the whole config memory takes a while, we just need to erase the first sector. + * The bitstream has an EOF marker, so even if the next bitstream uploaded is shorter than + * the current one there should be no problem. + * + * This command could be made to accept an argument indicating the whole memory should be erased. + */ + if (! fpgacfg_erase_sectors(1)) { + cli_print(cli, "Erasing first sector in FPGA config memory failed"); + return CLI_ERROR; + } + + cli_print(cli, "Erased FPGA config memory"); + fpgacfg_access_control(ALLOW_FPGA); + + return CLI_OK; +} + +int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_FPGA); + fpgacfg_reset_fpga(RESET_FULL); + cli_print(cli, "FPGA has been reset"); + + return CLI_OK; +} + +int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + fpgacfg_access_control(ALLOW_FPGA); + fpgacfg_reset_fpga(RESET_REGISTERS); + cli_print(cli, "FPGA registers have been reset"); + + return CLI_OK; +} + +void configure_cli_fpga(struct cli_def *cli) +{ + /* fpga */ + cli_command_root(fpga); + /* fpga reset */ + cli_command_node(fpga, reset, "Reset FPGA (config reset)"); + /* fpga reset registers */ + cli_command_node(fpga_reset, registers, "Reset FPGA registers (soft reset)"); + + cli_command_branch(fpga, bitstream); + /* fpga bitstream upload */ + cli_command_node(fpga_bitstream, upload, "Upload new FPGA bitstream"); + /* fpga bitstream erase */ + cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory"); +} diff --git a/projects/cli-test/mgmt-fpga.h b/projects/cli-test/mgmt-fpga.h new file mode 100644 index 0000000..ce185de --- /dev/null +++ b/projects/cli-test/mgmt-fpga.h @@ -0,0 +1,50 @@ +/* + * mgmt-fpga.h + * ----------- + * Management FPGA related code. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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. + */ + +#ifndef __STM32_CLI_MGMT_FPGA_H +#define __STM32_CLI_MGMT_FPGA_H + +#include "stm-init.h" +#include + + +/* The chunk size have to be a multiple of the SPI flash page size (256 bytes), + and it has to match the chunk size in the program sending the bitstream over the UART. +*/ +#define BITSTREAM_UPLOAD_CHUNK_SIZE 4096 + + +extern void configure_cli_fpga(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_FPGA_H */ -- cgit v1.2.3 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 From 1b3870dd4e0429e1809ce40b70a8f558ffb5df3a Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 2 Jun 2016 13:34:04 +0200 Subject: Move the rest of the CLI commands out of cli-test.c. --- projects/cli-test/Makefile | 2 +- projects/cli-test/cli-test.c | 226 +----------------------------------------- projects/cli-test/mgmt-misc.c | 97 ++++++++++++++++++ projects/cli-test/mgmt-misc.h | 43 ++++++++ projects/cli-test/mgmt-show.c | 133 +++++++++++++++++++++++++ projects/cli-test/mgmt-show.h | 43 ++++++++ projects/cli-test/mgmt-test.c | 117 ++++++++++++++++++++++ projects/cli-test/mgmt-test.h | 43 ++++++++ 8 files changed, 481 insertions(+), 223 deletions(-) create mode 100644 projects/cli-test/mgmt-misc.c create mode 100644 projects/cli-test/mgmt-misc.h create mode 100644 projects/cli-test/mgmt-show.c create mode 100644 projects/cli-test/mgmt-show.h create mode 100644 projects/cli-test/mgmt-test.c create mode 100644 projects/cli-test/mgmt-test.h diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index 2ca61b9..acf2720 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,6 +1,6 @@ TEST = cli-test -OBJS = crc32.o mgmt-cli.o test_sdram.o mgmt-dfu.o mgmt-fpga.o +OBJS = crc32.o test_sdram.o mgmt-cli.o mgmt-dfu.c mgmt-fpga.c mgmt-misc.c mgmt-show.c mgmt-test.c CFLAGS += -I$(LIBCLI_DIR) LIBS += $(LIBCLI_DIR)/libcli.a diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index b90d0dd..b6178af 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -31,206 +31,23 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" -#include "stm-uart.h" -#include "stm-fpgacfg.h" -#include "stm-keystore.h" -#include "stm-sdram.h" + #include "mgmt-cli.h" #include "mgmt-dfu.h" #include "mgmt-fpga.h" -#include "test_sdram.h" +#include "mgmt-misc.h" +#include "mgmt-show.h" +#include "mgmt-test.h" #include -#include - -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) -{ - volatile uint32_t hclk; - - hclk = HAL_RCC_GetHCLKFreq(); - cli_print(cli, "HSE_VALUE: %li", HSE_VALUE); - cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000); - cli_print(cli, "SystemCoreClock: %li (%i MHz)", SystemCoreClock, (int) SystemCoreClock / 1000 / 1000); - return CLI_OK; -} - -int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - uint32_t filesize = 0, crc = 0, my_crc = 0, n = 256, counter = 0; - uint8_t buf[256]; - - cli_print(cli, "OK, write file size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", n); - - uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); - cli_print(cli, "File size %li", filesize); - - while (filesize) { - if (filesize < n) { - n = filesize; - } - - if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { - cli_print(cli, "Receive timed out"); - return CLI_ERROR; - } - filesize -= n; - my_crc = update_crc(my_crc, buf, n); - counter++; - uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); - } - - cli_print(cli, "Send CRC-32"); - uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); - cli_print(cli, "CRC-32 %li", crc); - if (crc == my_crc) { - cli_print(cli, "CRC checksum MATCHED"); - } else { - cli_print(cli, "CRC checksum did NOT match"); - } - - return CLI_OK; -} - -int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - cli_print(cli, "FPGA has %sloaded a bitstream", fpgacfg_check_done() ? "":"NOT "); - return CLI_OK; -} - -int cmd_show_keystore_status(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - cli_print(cli, "Keystore memory is %sonline", (keystore_check_id() != 1) ? "NOT ":""); - return CLI_OK; -} - -int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - uint8_t buf[KEYSTORE_PAGE_SIZE]; - uint32_t i; - - if (keystore_check_id() != 1) { - cli_print(cli, "ERROR: The keystore memory is not accessible."); - } - - memset(buf, 0, sizeof(buf)); - if ((i = keystore_read_data(0, buf, sizeof(buf))) != 1) { - cli_print(cli, "Failed reading first page from keystore memory: %li", i); - return CLI_ERROR; - } - - cli_print(cli, "First page from keystore memory:\r\n"); - uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); - uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n"); - - for (i = 0; i < 8; i++) { - if (buf[i] == 0xff) break; /* never written */ - if (buf[i] != 0x55) break; /* something other than a tombstone */ - } - /* As a demo, tombstone byte after byte of the first 8 bytes in the keystore memory - * (as long as they do not appear to contain real data). - * If all of them are tombstones, erase the first sector to start over. - */ - if (i < 8) { - if (buf[i] == 0xff) { - cli_print(cli, "Tombstoning byte %li", i); - buf[i] = 0x55; - if ((i = keystore_write_data(0, buf, sizeof(buf))) != 1) { - cli_print(cli, "Failed writing data at offset 0: %li", i); - return CLI_ERROR; - } - } - } else { - cli_print(cli, "Erasing first sector since all the first 8 bytes are tombstones"); - if ((i = keystore_erase_sectors(1)) != 1) { - cli_print(cli, "Failed erasing the first sector: %li", i); - return CLI_ERROR; - } - cli_print(cli, "Erase result: %li", i); - } - - return CLI_OK; -} - -int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - cli_print(cli, "\n\n\nRebooting\n\n\n"); - HAL_NVIC_SystemReset(); - while (1) {}; -} - -int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc) -{ - // run external memory initialization sequence - HAL_StatusTypeDef status; - int ok, num_cycles = 1, i, test_completed; - - if (argc == 1) { - num_cycles = strtol(argv[0], NULL, 0); - if (num_cycles > 100) num_cycles = 100; - if (num_cycles < 1) num_cycles = 1; - } - - cli_print(cli, "Initializing SDRAM"); - status = sdram_init(); - if (status != HAL_OK) { - cli_print(cli, "Failed initializing SDRAM: %i", (int) status); - return CLI_OK; - } - - for (i = 1; i <= num_cycles; i++) { - cli_print(cli, "Starting SDRAM test (%i/%i)", i, num_cycles); - test_completed = 0; - // set LFSRs to some initial value, LFSRs will produce - // pseudo-random 32-bit patterns to test our memories - lfsr1 = 0xCCAA5533; - lfsr2 = 0xCCAA5533; - - cli_print(cli, "Run sequential write-then-read test for the first chip"); - ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP1); - if (!ok) break; - - cli_print(cli, "Run random write-then-read test for the first chip"); - ok = test_sdram_random(SDRAM_BASEADDR_CHIP1); - if (!ok) break; - - cli_print(cli, "Run sequential write-then-read test for the second chip"); - ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP2); - if (!ok) break; - - cli_print(cli, "Run random write-then-read test for the second chip"); - ok = test_sdram_random(SDRAM_BASEADDR_CHIP2); - if (!ok) break; - - // turn blue led on (testing two chips at the same time) - led_on(LED_BLUE); - - cli_print(cli, "Run interleaved write-then-read test for both chips at once"); - ok = test_sdrams_interleaved(SDRAM_BASEADDR_CHIP1, SDRAM_BASEADDR_CHIP2); - - led_off(LED_BLUE); - test_completed = 1; - cli_print(cli, "SDRAM test (%i/%i) completed\r\n", i, num_cycles); - } - - if (! test_completed) { - cli_print(cli, "SDRAM test failed (%i/%i)", i, num_cycles); - } else { - cli_print(cli, "SDRAM test completed successfully"); - } - - return CLI_OK; -} - int check_auth(const char *username, const char *password) { if (strcasecmp(username, "ct") != 0) @@ -240,41 +57,6 @@ int check_auth(const char *username, const char *password) return CLI_OK; } -void configure_cli_show(struct cli_def *cli) -{ - /* show */ - cli_command_root(show); - - /* show cpuspeed */ - cli_command_node(show, cpuspeed, "Show the speed at which the CPU currently operates"); - - cli_command_branch(show, fpga); - /* show fpga status*/ - cli_command_node(show_fpga, status, "Show status about the FPGA"); - - cli_command_branch(show, keystore); - /* show keystore status*/ - cli_command_node(show_keystore, status, "Show status of the keystore memory"); - cli_command_node(show_keystore, data, "Show the first page of the keystore memory"); -} - -void configure_cli_test(struct cli_def *cli) -{ - /* test */ - cli_command_root(test); - - /* test sdram */ - cli_command_node(test, sdram, "Run SDRAM tests"); -} - -static void configure_cli_misc(struct cli_def *cli) -{ - /* filetransfer */ - cli_command_root_node(filetransfer, "Test file transfering"); - /* reboot */ - cli_command_root_node(reboot, "Reboot the STM32"); -} - typedef void (*pFunction)(void); /* This is it's own function to make it more convenient to set a breakpoint at it in gdb */ diff --git a/projects/cli-test/mgmt-misc.c b/projects/cli-test/mgmt-misc.c new file mode 100644 index 0000000..a98bf8d --- /dev/null +++ b/projects/cli-test/mgmt-misc.c @@ -0,0 +1,97 @@ +/* + * mgmt-misc.c + * ----------- + * Miscellaneous CLI functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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" + +#include "mgmt-cli.h" +#include "mgmt-misc.h" + +#include + + +extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); + +int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint32_t filesize = 0, crc = 0, my_crc = 0, n = 256, counter = 0; + uint8_t buf[256]; + + cli_print(cli, "OK, write file size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", n); + + uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); + cli_print(cli, "File size %li", filesize); + + while (filesize) { + if (filesize < n) { + n = filesize; + } + + if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { + cli_print(cli, "Receive timed out"); + return CLI_ERROR; + } + filesize -= n; + my_crc = update_crc(my_crc, buf, n); + counter++; + uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); + } + + cli_print(cli, "Send CRC-32"); + uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); + cli_print(cli, "CRC-32 %li", crc); + if (crc == my_crc) { + cli_print(cli, "CRC checksum MATCHED"); + } else { + cli_print(cli, "CRC checksum did NOT match"); + } + + return CLI_OK; +} + +int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "\n\n\nRebooting\n\n\n"); + HAL_NVIC_SystemReset(); + while (1) {}; +} + +void configure_cli_misc(struct cli_def *cli) +{ + /* filetransfer */ + cli_command_root_node(filetransfer, "Test file transfering"); + /* reboot */ + cli_command_root_node(reboot, "Reboot the STM32"); +} + diff --git a/projects/cli-test/mgmt-misc.h b/projects/cli-test/mgmt-misc.h new file mode 100644 index 0000000..caf7024 --- /dev/null +++ b/projects/cli-test/mgmt-misc.h @@ -0,0 +1,43 @@ +/* + * mgmt-misc.h + * ----------- + * Management CLI miscellaneous functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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. + */ + +#ifndef __STM32_CLI_MGMT_MISC_H +#define __STM32_CLI_MGMT_MISC_H + +#include "stm-init.h" +#include + +extern void configure_cli_misc(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_MISC_H */ diff --git a/projects/cli-test/mgmt-show.c b/projects/cli-test/mgmt-show.c new file mode 100644 index 0000000..3ae196e --- /dev/null +++ b/projects/cli-test/mgmt-show.c @@ -0,0 +1,133 @@ +/* + * mgmt-show.c + * ----------- + * CLI 'show' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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-keystore.h" +#include "stm-fpgacfg.h" +#include "stm-uart.h" + +#include "mgmt-cli.h" +#include "mgmt-show.h" + +#include + + +int cmd_show_cpuspeed(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + volatile uint32_t hclk; + + hclk = HAL_RCC_GetHCLKFreq(); + cli_print(cli, "HSE_VALUE: %li", HSE_VALUE); + cli_print(cli, "HCLK: %li (%i MHz)", hclk, (int) hclk / 1000 / 1000); + cli_print(cli, "SystemCoreClock: %li (%i MHz)", SystemCoreClock, (int) SystemCoreClock / 1000 / 1000); + return CLI_OK; +} + +int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "FPGA has %sloaded a bitstream", fpgacfg_check_done() ? "":"NOT "); + return CLI_OK; +} + +int cmd_show_keystore_status(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + cli_print(cli, "Keystore memory is %sonline", (keystore_check_id() != 1) ? "NOT ":""); + return CLI_OK; +} + +int cmd_show_keystore_data(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint8_t buf[KEYSTORE_PAGE_SIZE]; + uint32_t i; + + if (keystore_check_id() != 1) { + cli_print(cli, "ERROR: The keystore memory is not accessible."); + } + + memset(buf, 0, sizeof(buf)); + if ((i = keystore_read_data(0, buf, sizeof(buf))) != 1) { + cli_print(cli, "Failed reading first page from keystore memory: %li", i); + return CLI_ERROR; + } + + cli_print(cli, "First page from keystore memory:\r\n"); + uart_send_hexdump(STM_UART_MGMT, buf, 0, sizeof(buf) - 1); + uart_send_string2(STM_UART_MGMT, (char *) "\r\n\r\n"); + + for (i = 0; i < 8; i++) { + if (buf[i] == 0xff) break; /* never written */ + if (buf[i] != 0x55) break; /* something other than a tombstone */ + } + /* As a demo, tombstone byte after byte of the first 8 bytes in the keystore memory + * (as long as they do not appear to contain real data). + * If all of them are tombstones, erase the first sector to start over. + */ + if (i < 8) { + if (buf[i] == 0xff) { + cli_print(cli, "Tombstoning byte %li", i); + buf[i] = 0x55; + if ((i = keystore_write_data(0, buf, sizeof(buf))) != 1) { + cli_print(cli, "Failed writing data at offset 0: %li", i); + return CLI_ERROR; + } + } + } else { + cli_print(cli, "Erasing first sector since all the first 8 bytes are tombstones"); + if ((i = keystore_erase_sectors(1)) != 1) { + cli_print(cli, "Failed erasing the first sector: %li", i); + return CLI_ERROR; + } + cli_print(cli, "Erase result: %li", i); + } + + return CLI_OK; +} + +void configure_cli_show(struct cli_def *cli) +{ + /* show */ + cli_command_root(show); + + /* show cpuspeed */ + cli_command_node(show, cpuspeed, "Show the speed at which the CPU currently operates"); + + cli_command_branch(show, fpga); + /* show fpga status*/ + cli_command_node(show_fpga, status, "Show status about the FPGA"); + + cli_command_branch(show, keystore); + /* show keystore status*/ + cli_command_node(show_keystore, status, "Show status of the keystore memory"); + cli_command_node(show_keystore, data, "Show the first page of the keystore memory"); +} diff --git a/projects/cli-test/mgmt-show.h b/projects/cli-test/mgmt-show.h new file mode 100644 index 0000000..0d7ba3a --- /dev/null +++ b/projects/cli-test/mgmt-show.h @@ -0,0 +1,43 @@ +/* + * mgmt-misc.h + * ----------- + * Management CLI 'show' functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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. + */ + +#ifndef __STM32_CLI_MGMT_SHOW_H +#define __STM32_CLI_MGMT_SHOW_H + +#include "stm-init.h" +#include + +extern void configure_cli_show(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_SHOW_H */ diff --git a/projects/cli-test/mgmt-test.c b/projects/cli-test/mgmt-test.c new file mode 100644 index 0000000..c1f255e --- /dev/null +++ b/projects/cli-test/mgmt-test.c @@ -0,0 +1,117 @@ +/* + * mgmt-test.c + * ----------- + * CLI hardware test functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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-led.h" +#include "stm-sdram.h" + +#include "mgmt-cli.h" +#include "mgmt-test.h" + +#include "test_sdram.h" + +#include + + +int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + // run external memory initialization sequence + HAL_StatusTypeDef status; + int ok, num_cycles = 1, i, test_completed; + + if (argc == 1) { + num_cycles = strtol(argv[0], NULL, 0); + if (num_cycles > 100) num_cycles = 100; + if (num_cycles < 1) num_cycles = 1; + } + + cli_print(cli, "Initializing SDRAM"); + status = sdram_init(); + if (status != HAL_OK) { + cli_print(cli, "Failed initializing SDRAM: %i", (int) status); + return CLI_OK; + } + + for (i = 1; i <= num_cycles; i++) { + cli_print(cli, "Starting SDRAM test (%i/%i)", i, num_cycles); + test_completed = 0; + // set LFSRs to some initial value, LFSRs will produce + // pseudo-random 32-bit patterns to test our memories + lfsr1 = 0xCCAA5533; + lfsr2 = 0xCCAA5533; + + cli_print(cli, "Run sequential write-then-read test for the first chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the first chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run sequential write-then-read test for the second chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the second chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + // turn blue led on (testing two chips at the same time) + led_on(LED_BLUE); + + cli_print(cli, "Run interleaved write-then-read test for both chips at once"); + ok = test_sdrams_interleaved(SDRAM_BASEADDR_CHIP1, SDRAM_BASEADDR_CHIP2); + + led_off(LED_BLUE); + test_completed = 1; + cli_print(cli, "SDRAM test (%i/%i) completed\r\n", i, num_cycles); + } + + if (! test_completed) { + cli_print(cli, "SDRAM test failed (%i/%i)", i, num_cycles); + } else { + cli_print(cli, "SDRAM test completed successfully"); + } + + return CLI_OK; +} + +void configure_cli_test(struct cli_def *cli) +{ + /* test */ + cli_command_root(test); + + /* test sdram */ + cli_command_node(test, sdram, "Run SDRAM tests"); +} diff --git a/projects/cli-test/mgmt-test.h b/projects/cli-test/mgmt-test.h new file mode 100644 index 0000000..3beb2da --- /dev/null +++ b/projects/cli-test/mgmt-test.h @@ -0,0 +1,43 @@ +/* + * mgmt-misc.h + * ----------- + * Management CLI miscellaneous functions. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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. + */ + +#ifndef __STM32_CLI_MGMT_TEST_H +#define __STM32_CLI_MGMT_TEST_H + +#include "stm-init.h" +#include + +extern void configure_cli_test(struct cli_def *cli); + +#endif /* __STM32_CLI_MGMT_TEST_H */ -- cgit v1.2.3 From ae1ecf87f6b8d7c34b32af0547f118ff7697c2ef Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 2 Jun 2016 14:56:56 +0200 Subject: Use DMA for UART RX instead of interrupts. DMA is more efficient and less prone to miss characters than interrupts. An open question is if circular mode is really the best. If someone copy-pastes more than the RX buffer size of configuration into the CLI, we risk the DMA controller catching up with the reader and overwriting data not yet read. Since we don't have flow control back to the users terminal, we will always fail if too much data is entered before we can process it. The question is if failing to stuff new data at the end of a buffer might be better than data being overwritten - thus messing up the commands in unpredictable ways. --- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c | 59 +++++++++++++++++- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_it.c | 17 ++++++ projects/cli-test/cli-test.c | 17 ------ projects/cli-test/filetransfer | 6 +- projects/cli-test/mgmt-cli.c | 71 +++++++++++----------- projects/cli-test/mgmt-cli.h | 7 ++- projects/cli-test/mgmt-fpga.c | 64 ++++--------------- projects/cli-test/mgmt-misc.c | 62 +++++++++++++++---- projects/cli-test/mgmt-misc.h | 6 ++ stm-init.c | 29 +++++++++ stm-uart.c | 7 ++- stm-uart.h | 3 + 12 files changed, 223 insertions(+), 125 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c index 2a207b6..91a6f46 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c @@ -33,10 +33,8 @@ */ /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" +#include "stm-uart.h" -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ /** * Initializes the Global MSP. @@ -121,6 +119,8 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) GPIO_InitTypeDef GPIO_InitStruct; if (huart->Instance == USART1) { + /* This is huart_mgmt (USER_MGMT) */ + /* Peripheral clock enable */ __USART1_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); @@ -138,7 +138,32 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) HAL_NVIC_SetPriority(USART1_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART1_IRQn); + + /* Peripheral DMA init*/ + hdma_usart_mgmt_rx.Instance = DMA2_Stream2; + hdma_usart_mgmt_rx.Init.Channel = DMA_CHANNEL_4; + hdma_usart_mgmt_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart_mgmt_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart_mgmt_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart_mgmt_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart_mgmt_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart_mgmt_rx.Init.Mode = DMA_CIRCULAR; + hdma_usart_mgmt_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_usart_mgmt_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + /* + hdma_usart_mgmt_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; + hdma_usart_mgmt_rx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_usart_mgmt_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; + */ + if (HAL_DMA_Init(&hdma_usart_mgmt_rx) != HAL_OK) { + Error_Handler(); + } + + __HAL_LINKDMA(huart, hdmarx, hdma_usart_mgmt_rx); + } else if (huart->Instance == USART2) { + /* This is huart_user (USER UART) */ + /* Peripheral clock enable */ __USART2_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); @@ -156,6 +181,28 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart) HAL_NVIC_SetPriority(USART2_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART2_IRQn); + + /* Peripheral DMA init*/ + hdma_usart_user_rx.Instance = DMA1_Stream5; + hdma_usart_user_rx.Init.Channel = DMA_CHANNEL_4; + hdma_usart_user_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_usart_user_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_usart_user_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_usart_user_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_usart_user_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_usart_user_rx.Init.Mode = DMA_CIRCULAR; + hdma_usart_user_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_usart_user_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + /* + hdma_usart_user_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; + hdma_usart_user_rx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_usart_user_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; + */ + if (HAL_DMA_Init(&hdma_usart_user_rx) != HAL_OK) { + Error_Handler(); + } + + __HAL_LINKDMA(huart, hdmarx, hdma_usart_user_rx); } } @@ -172,6 +219,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2 | GPIO_PIN_3); HAL_NVIC_DisableIRQ(USART1_IRQn); + + /* Peripheral DMA DeInit*/ + HAL_DMA_DeInit(huart->hdmarx); } else if (huart->Instance == USART2) { /* Peripheral clock disable */ __USART2_CLK_DISABLE(); @@ -183,6 +233,9 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10); HAL_NVIC_DisableIRQ(USART2_IRQn); + + /* Peripheral DMA DeInit*/ + HAL_DMA_DeInit(huart->hdmarx); } } 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 index a174d73..b3de408 100644 --- 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 @@ -166,4 +166,21 @@ void USART2_IRQHandler(void) HAL_UART_IRQHandler(&huart_user); } +/** +* @brief This function handles DMA1 stream5 global interrupt. +*/ +void DMA1_Stream5_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_usart_user_rx); +} + +/** +* @brief This function handles DMA2 stream2 global interrupt. +*/ +void DMA2_Stream2_IRQHandler(void) +{ + HAL_DMA_IRQHandler(&hdma_usart_mgmt_rx); +} + + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index b6178af..ed6aac3 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -71,23 +71,6 @@ 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() { diff --git a/projects/cli-test/filetransfer b/projects/cli-test/filetransfer index 025a6ac..f704e31 100755 --- a/projects/cli-test/filetransfer +++ b/projects/cli-test/filetransfer @@ -77,11 +77,9 @@ def parse_args(): def _write(dst, data): - for i in range(len(data)): - dst.write(data[i]) - time.sleep(0.1) + dst.write(data) if len(data) == 4: - print("Wrote 0x{:02x}{:02x}{:02x}{:02x}".format(ord(data[0]), ord(data[1]), ord(data[2]), ord(data[3]))) + print("Wrote 0x{!s}".format(data.encode('hex'))) else: print("Wrote {!r}".format(data)) diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index abbd999..3b4ffe9 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -41,18 +41,17 @@ extern uint8_t uart_rx; struct uart_ringbuf_t { - uint32_t enabled, ridx, widx, overflow; + uint32_t enabled, ridx; + enum mgmt_cli_dma_state rx_state; uint8_t buf[CLI_UART_RECVBUF_SIZE]; }; -volatile struct uart_ringbuf_t uart_ringbuf = {1, 0, 0, 0, {0}}; +volatile struct uart_ringbuf_t uart_ringbuf = {1, 0, DMA_RX_STOP, {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_WIDX(rb) (sizeof(rb.buf) - __HAL_DMA_GET_COUNTER(huart_mgmt.hdmarx)) +#define RINGBUF_COUNT(rb) ((unsigned)(RINGBUF_WIDX(rb) - RINGBUF_RIDX(rb))) #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) { @@ -64,23 +63,16 @@ 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) { 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--) { + 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); } + timeout--; } + if (! timeout) return 0; + return 1; } @@ -90,6 +82,26 @@ int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf return (int) count; } +int control_mgmt_uart_dma_rx(enum mgmt_cli_dma_state state) +{ + if (state == DMA_RX_START) { + if (uart_ringbuf.rx_state != DMA_RX_START) { + memset((void *) uart_ringbuf.buf, 0, sizeof(uart_ringbuf.buf)); + + /* Start receiving data from the UART using DMA */ + HAL_UART_Receive_DMA(&huart_mgmt, (uint8_t *) uart_ringbuf.buf, sizeof(uart_ringbuf.buf)); + uart_ringbuf.ridx = 0; + uart_ringbuf.rx_state = DMA_RX_START; + } + return 1; + } else if (state == DMA_RX_STOP) { + if (HAL_UART_DMAStop(&huart_mgmt) != HAL_OK) return 0; + uart_ringbuf.rx_state = DMA_RX_STOP; + return 1; + } + return 0; +} + int embedded_cli_loop(struct cli_def *cli) { unsigned char c; @@ -110,15 +122,18 @@ int embedded_cli_loop(struct cli_def *cli) while (1) { cli_loop_start_new_command(cli, &ctx); + control_mgmt_uart_dma_rx(DMA_RX_START); + while (1) { cli_loop_show_prompt(cli, &ctx); n = cli_loop_read_next_char(cli, &ctx, &c); /* - 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)); + cli_print(cli, "Next char: '%c'/%i, ringbuf ridx %i, widx %i", + c, (int) c, + uart_ringbuf.ridx, + RINGBUF_WIDX(uart_ringbuf) */ if (n == CLI_LOOP_CTRL_BREAK) break; @@ -143,22 +158,6 @@ 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 3b7f503..16c9fbd98 100644 --- a/projects/cli-test/mgmt-cli.h +++ b/projects/cli-test/mgmt-cli.h @@ -71,11 +71,16 @@ #define CLI_UART_RECVBUF_SIZE 256 /* This must be a power of 2 */ #define CLI_UART_RECVBUF_MASK (CLI_UART_RECVBUF_SIZE - 1) +enum mgmt_cli_dma_state { + DMA_RX_STOP, + DMA_RX_START, +}; + 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); +extern int control_mgmt_uart_dma_rx(enum mgmt_cli_dma_state state); #endif /* __STM32_MGMT_CLI_H */ diff --git a/projects/cli-test/mgmt-fpga.c b/projects/cli-test/mgmt-fpga.c index c20b7b2..8c1b2a8 100644 --- a/projects/cli-test/mgmt-fpga.c +++ b/projects/cli-test/mgmt-fpga.c @@ -35,21 +35,29 @@ #include "stm-init.h" #include "stm-uart.h" #include "stm-fpgacfg.h" + #include "mgmt-cli.h" #include "mgmt-fpga.h" +#include "mgmt-misc.h" #include -extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); +volatile uint32_t dfu_offset = 0; + +int _flash_write_callback(uint8_t *buf, size_t len) { + int res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE) == 1; + dfu_offset += BITSTREAM_UPLOAD_CHUNK_SIZE; + return res; +} int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc) { - uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0, i; - uint32_t offset = 0, n = BITSTREAM_UPLOAD_CHUNK_SIZE; uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE]; + dfu_offset = 0; + fpgacfg_access_control(ALLOW_ARM); cli_print(cli, "Checking if FPGA config memory is accessible"); @@ -58,57 +66,11 @@ int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *ar return CLI_ERROR; } - cli_print(cli, "OK, write FPGA bitstream file size (4 bytes), data in 4096 byte chunks, CRC-32 (4 bytes)"); - - /* Read file size (4 bytes) */ - uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); - cli_print(cli, "File size %li", filesize); - - while (filesize) { - /* By initializing buf to the same value that erased flash has (0xff), we don't - * have to try and be smart when writing the last page of data to the memory. - */ - memset(buf, 0xff, sizeof(buf)); - - if (filesize < n) { - n = filesize; - } - - if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { - cli_print(cli, "Receive timed out"); - return CLI_ERROR; - } - filesize -= n; - - /* After reception of 4 KB but before ACKing we have "all" the time in the world to - * calculate CRC and write it to flash. - */ - my_crc = update_crc(my_crc, buf, n); - - if ((i = fpgacfg_write_data(offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE)) != 1) { - cli_print(cli, "Failed writing data at offset %li (counter = %li): %li", offset, counter, i); - return CLI_ERROR; - } - - offset += BITSTREAM_UPLOAD_CHUNK_SIZE; - - /* ACK this chunk by sending the current chunk counter (4 bytes) */ - counter++; - uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); - } - - /* The sending side will now send it's calculated CRC-32 */ - cli_print(cli, "Send CRC-32"); - uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); - cli_print(cli, "CRC-32 %li", crc); - if (crc == my_crc) { - cli_print(cli, "CRC checksum MATCHED"); - } else { - cli_print(cli, "CRC checksum did NOT match"); - } + cli_receive_data(cli, &buf[0], sizeof(buf), _flash_write_callback); fpgacfg_access_control(ALLOW_FPGA); + cli_print(cli, "DFU offset now: %li (%li chunks)", dfu_offset, dfu_offset / BITSTREAM_UPLOAD_CHUNK_SIZE); return CLI_OK; } diff --git a/projects/cli-test/mgmt-misc.c b/projects/cli-test/mgmt-misc.c index a98bf8d..aea790a 100644 --- a/projects/cli-test/mgmt-misc.c +++ b/projects/cli-test/mgmt-misc.c @@ -43,34 +43,64 @@ extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); -int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) + +volatile uint32_t demo_crc = 0; + + +int _count_bytes_callback(uint8_t *buf, size_t len) { + demo_crc = update_crc(demo_crc, buf, len); + return 1; +} + +int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback) { - uint32_t filesize = 0, crc = 0, my_crc = 0, n = 256, counter = 0; - uint8_t buf[256]; + uint32_t filesize = 0, crc = 0, my_crc = 0, counter = 0; + size_t n = len; - cli_print(cli, "OK, write file size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", n); + if (! control_mgmt_uart_dma_rx(DMA_RX_STOP)) { + cli_print(cli, "Failed stopping DMA"); + return CLI_OK; + } + + cli_print(cli, "OK, write size (4 bytes), data in %li byte chunks, CRC-32 (4 bytes)", (uint32_t) n); - uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000); - cli_print(cli, "File size %li", filesize); + if (uart_receive_bytes(STM_UART_MGMT, (void *) &filesize, 4, 1000) != HAL_OK) { + cli_print(cli, "Receive timed out"); + return CLI_ERROR; + } + + cli_print(cli, "Send %li bytes of data", filesize); while (filesize) { - if (filesize < n) { - n = filesize; - } + /* By initializing buf to the same value that erased flash has (0xff), we don't + * have to try and be smart when writing the last page of data to a flash memory. + */ + memset(buf, 0xff, len); - if (uart_receive_bytes(STM_UART_MGMT, (void *) &buf, n, 1000) != HAL_OK) { + if (filesize < n) n = filesize; + + if (uart_receive_bytes(STM_UART_MGMT, (void *) buf, n, 1000) != HAL_OK) { cli_print(cli, "Receive timed out"); return CLI_ERROR; } filesize -= n; my_crc = update_crc(my_crc, buf, n); + + /* After reception of a chunk but before ACKing we have "all" the time in the world to + * calculate CRC and invoke the data_callback. + */ + if (data_callback != NULL && ! data_callback(buf, (size_t) n)) { + cli_print(cli, "Data processing failed"); + return CLI_OK; + } + counter++; uart_send_bytes(STM_UART_MGMT, (void *) &counter, 4); } cli_print(cli, "Send CRC-32"); uart_receive_bytes(STM_UART_MGMT, (void *) &crc, 4, 1000); - cli_print(cli, "CRC-32 %li", crc); + cli_print(cli, "CRC-32 0x%x, calculated CRC 0x%x", (unsigned int) crc, (unsigned int) my_crc); if (crc == my_crc) { cli_print(cli, "CRC checksum MATCHED"); } else { @@ -80,6 +110,16 @@ int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int return CLI_OK; } +int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + uint8_t buf[FILETRANSFER_UPLOAD_CHUNK_SIZE]; + + demo_crc = 0; + cli_receive_data(cli, &buf[0], sizeof(buf), _count_bytes_callback); + cli_print(cli, "Demo CRC is: %li/0x%x", demo_crc, (unsigned int) demo_crc); + return CLI_OK; +} + int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) { cli_print(cli, "\n\n\nRebooting\n\n\n"); diff --git a/projects/cli-test/mgmt-misc.h b/projects/cli-test/mgmt-misc.h index caf7024..b7eb4f4 100644 --- a/projects/cli-test/mgmt-misc.h +++ b/projects/cli-test/mgmt-misc.h @@ -38,6 +38,12 @@ #include "stm-init.h" #include + +#define FILETRANSFER_UPLOAD_CHUNK_SIZE 256 + +typedef int (*cli_data_callback)(uint8_t *, size_t); + extern void configure_cli_misc(struct cli_def *cli); +extern int cli_receive_data(struct cli_def *cli, uint8_t *buf, size_t len, cli_data_callback data_callback); #endif /* __STM32_CLI_MGMT_MISC_H */ diff --git a/stm-init.c b/stm-init.c index c8228d8..4fd9dd4 100644 --- a/stm-init.c +++ b/stm-init.c @@ -59,6 +59,9 @@ static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); static void MX_USART2_UART_Init(void); #endif +#ifdef HAL_DMA_MODULE_ENABLED +static void MX_DMA_Init(void); +#endif #ifdef HAL_I2C_MODULE_ENABLED static void MX_I2C2_Init(void); #endif @@ -87,6 +90,9 @@ void stm_init(void) fpgacfg_access_control(ALLOW_FPGA); #endif #endif +#ifdef HAL_DMA_MODULE_ENABLED + MX_DMA_Init(); +#endif #ifdef HAL_UART_MODULE_ENABLED MX_USART1_UART_Init(); MX_USART2_UART_Init(); @@ -165,6 +171,29 @@ static void MX_GPIO_Init(void) #undef gpio_output #endif + +#ifdef HAL_DMA_MODULE_ENABLED +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + + /* USER UART RX */ + HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); + /* MGMT UART RX */ + HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); +} +#endif /* HAL_DMA_MODULE_ENABLED */ + + #ifdef HAL_I2C_MODULE_ENABLED /* I2C2 init function (external RTC chip) */ void MX_I2C2_Init(void) diff --git a/stm-uart.c b/stm-uart.c index 2f3aabe..59bbbe6 100644 --- a/stm-uart.c +++ b/stm-uart.c @@ -37,8 +37,11 @@ #include -UART_HandleTypeDef huart_mgmt; -UART_HandleTypeDef huart_user; +UART_HandleTypeDef huart_mgmt; /* USART1 */ +UART_HandleTypeDef huart_user; /* USART2 */ + +DMA_HandleTypeDef hdma_usart_mgmt_rx; +DMA_HandleTypeDef hdma_usart_user_rx; #define DEFAULT_UART STM_UART_USER diff --git a/stm-uart.h b/stm-uart.h index e63aaa4..db3a045 100644 --- a/stm-uart.h +++ b/stm-uart.h @@ -48,6 +48,9 @@ enum stm_uart_port { extern UART_HandleTypeDef huart_mgmt; extern UART_HandleTypeDef huart_user; +extern DMA_HandleTypeDef hdma_usart_mgmt_rx; +extern DMA_HandleTypeDef hdma_usart_user_rx; + extern HAL_StatusTypeDef uart_send_char(uint8_t ch); extern HAL_StatusTypeDef uart_recv_char(uint8_t *cp); -- cgit v1.2.3