From 8bbc2e60f81cee49480788087c0a6d5b61f1b041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sun, 9 Feb 2020 19:13:37 +0100 Subject: [PATCH] Update Firmware with features: * Shellmatta implemented using UART * Version string implemented * Increased heap size * Add shellmatta printf support --- stm-firmware/Makefile | 10 +- stm-firmware/include/shell.h | 13 ++ stm-firmware/include/stm32-gpio-macros.h | 1 + stm-firmware/include/uart/dma-ring-buffer.h | 20 +++ stm-firmware/include/uart/uart.h | 52 +++++-- stm-firmware/main.c | 19 ++- stm-firmware/shell.c | 139 +++++++++++++++++ stm-firmware/stm32f407vet6_flash.ld | 4 +- stm-firmware/uart/dma-ring-buffer.c | 91 +++++++++++ stm-firmware/uart/uart.c | 158 ++++++++++++++------ 10 files changed, 448 insertions(+), 59 deletions(-) create mode 100644 stm-firmware/include/shell.h create mode 100644 stm-firmware/shell.c diff --git a/stm-firmware/Makefile b/stm-firmware/Makefile index 027e3d2..18a18cc 100644 --- a/stm-firmware/Makefile +++ b/stm-firmware/Makefile @@ -3,7 +3,7 @@ #Compiler: arm-none-eabi ##################################################################################### #Add Files and Folders below######################################################### -CFILES = main.c syscalls.c uart/uart.c cmsis_boot/system_stm32f4xx.c systick.c +CFILES = main.c syscalls.c cmsis_boot/system_stm32f4xx.c systick.c ASFILES = boot/startup_stm32f4xx.S INCLUDEPATH = -Icmsis -Iinclude @@ -15,6 +15,9 @@ LIBRARIES = # -larm_cortexM4lf_math DEFINES = -DSTM32F407xx -DSTM32F4XX -DARM_MATH_CM4 -DHSE_VALUE=8000000UL mapfile = memory-mapping +GIT_VER := $(shell git describe --always --dirty --tags) +DEFINES += -DGIT_VER=$(GIT_VER) + ifneq ($(VERBOSE),true) QUIET=@ else @@ -25,13 +28,14 @@ endif CFILES += adc-meas.c # Shellmatta -CFILES += shellmatta/src/shellmatta.c shellmatta/src/shellmatta_autocomplete.c shellmatta/src/shellmatta_escape.c shellmatta/src/shellmatta_history.c shellmatta/src/shellmatta_utils.c +CFILES += shellmatta/src/shellmatta.c shellmatta/src/shellmatta_autocomplete.c shellmatta/src/shellmatta_escape.c shellmatta/src/shellmatta_history.c shellmatta/src/shellmatta_utils.c shell.c INCLUDEPATH += -Ishellmatta/api -DEFINES += -DSHELLMATTA_STRIP_PRINTF +# DEFINES += -DSHELLMATTA_STRIP_PRINTF # RCC Manager CFILES += clock-enable-manager.c +CFILES += uart/uart.c uart/dma-ring-buffer.c #TODO ################################################################################### diff --git a/stm-firmware/include/shell.h b/stm-firmware/include/shell.h new file mode 100644 index 0000000..e6e872d --- /dev/null +++ b/stm-firmware/include/shell.h @@ -0,0 +1,13 @@ +#ifndef __SHELL_H__ +#define __SHELL_H__ + +#include +#include + +shellmatta_handle_t shell_init(void); + +void shell_handle_input(shellmatta_handle_t shell, const char *data, size_t len); + +void shell_print_string(shellmatta_handle_t shell, const char *string); + +#endif /* __SHELL_H__ */ diff --git a/stm-firmware/include/stm32-gpio-macros.h b/stm-firmware/include/stm32-gpio-macros.h index ee35600..3164286 100644 --- a/stm-firmware/include/stm32-gpio-macros.h +++ b/stm-firmware/include/stm32-gpio-macros.h @@ -1,6 +1,7 @@ #ifndef __STM32GPIOMACROS_H__ #define __STM32GPIOMACROS_H__ +#define MODER_DELETE(pin) ~(0x3U << (pin * 2)) #define OUTPUT(pin) (0x01U << (pin * 2)) #define PULLUP(pin) (0x1U << (pin* 2)) #define ALTFUNC(pin) ((0x2) << (pin * 2)) diff --git a/stm-firmware/include/uart/dma-ring-buffer.h b/stm-firmware/include/uart/dma-ring-buffer.h index 4b4bb93..7229573 100644 --- a/stm-firmware/include/uart/dma-ring-buffer.h +++ b/stm-firmware/include/uart/dma-ring-buffer.h @@ -1,4 +1,24 @@ #ifndef __DMA_RING_BUFFER_H__ #define __DMA_RING_BUFFER_H__ +#include +#include +#include + +struct dma_ring_buffer { + char *data_ptr; + size_t buffer_count; + DMA_Stream_TypeDef *dma; + size_t get_idx; + uint8_t base_dma_id; +}; + +int dma_ring_buffer_initialize(struct dma_ring_buffer *dma_buffer, uint8_t base_dma_id, DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count, char *data_buffer, void *src_reg, uint8_t dma_trigger_channel); +int dma_ring_buffer_get_data(struct dma_ring_buffer *buff, const char **data_buff, size_t *len); + +void dma_ring_buffer_stop(struct dma_ring_buffer *buff); + #endif /* __DMA_RING_BUFFER_H__ */ + + + diff --git a/stm-firmware/include/uart/uart.h b/stm-firmware/include/uart/uart.h index 1a57902..c3934a6 100644 --- a/stm-firmware/include/uart/uart.h +++ b/stm-firmware/include/uart/uart.h @@ -1,17 +1,51 @@ -/* - * uart.h - * - * Created on: Dec 15, 2014 - * Author: shino-chan - */ +#include +#include #ifndef UART_UART_H_ #define UART_UART_H_ +#define UART_RECEIVE_DMA_STREAM + +#define UART_SEND_DMA_STREAM + +#define UART_PORT_RCC_MASK RCC_AHB1ENR_GPIOAEN + +#define UART_PORT GPIOA + +#define UART_PERIPH USART1 +#define UART_RCC_MASK RCC_APB2ENR_USART1EN + +#define UART_RX_PIN 10 +#define UART_TX_PIN 9 +#define UART_RX_PIN_ALTFUNC 7 +#define UART_TX_PIN_ALTFUNC 7 + +/* UART_DIV is 45.5625 => 115200 @ 84 MHz */ +#define UART_DIV_FRACTION 9U /* Equals 9/16 = 0.5625 */ +#define UART_DIV_MANTISSA 45U /* Equals 45 */ + +#define UART_BRR_REG_VALUE ((UART_DIV_MANTISSA<<4) | UART_DIV_FRACTION); + void initUART(); void sendChar(char c); void sendString(char* s, int count); -#ifdef _P20N_ -void yuri(); -#endif + + +void uart_init_with_dma(); + +void uart_disable(); + +void uart_send_char(char c); + +void uart_send_array(const char *data, uint32_t len); + +void uart_send_string(char *string); + +void uart_send_array_with_dma(char *data, uint32_t len); + +void uart_send_string_with_dma(char *string); + +int uart_receive_data_with_dma(const char **data, size_t *len); + + #endif /* UART_UART_H_ */ diff --git a/stm-firmware/main.c b/stm-firmware/main.c index a842acb..759a83c 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include static void setup_nvic_priorities() { @@ -27,7 +29,12 @@ static void setup_nvic_priorities() static float pt1000_value; static volatile int pt1000_value_status; -int main() { +int main() +{ + const char *uart_input; + size_t uart_input_len; + shellmatta_handle_t shell_handle; + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_GPIOBEN)); __DSB(); @@ -40,8 +47,18 @@ int main() { //setup_dma(&adc_results, 3); adc_pt1000_setup_meas(); + uart_init_with_dma(); + + shell_handle = shell_init(); + while(1) { pt1000_value_status = adc_pt1000_get_current_resistance(&pt1000_value); + + if (uart_receive_data_with_dma(&uart_input, &uart_input_len) >= 0) { + shell_handle_input(shell_handle, uart_input, uart_input_len); + } + //systick_wait_ms(300); + } } diff --git a/stm-firmware/shell.c b/stm-firmware/shell.c new file mode 100644 index 0000000..f890523 --- /dev/null +++ b/stm-firmware/shell.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#define xstr(x) str(x) +#define str(x) #x + +#ifndef GIT_VER +#define GIT_VER "VERSION NOT SET" +#endif + +static shellmatta_instance_t shell; +static char shell_buffer[512]; +static char history_buffer[1024]; + +static shellmatta_retCode_t write_shell_callback(const char *data, uint32_t len) +{ + uart_send_array(data, len); + + return SHELLMATTA_OK; +} + +static shellmatta_retCode_t shell_cmd_ver(const shellmatta_handle_t handle, + const char *arguments, + uint32_t length) +{ + (void)arguments; + (void)length; + + shellmatta_printf(handle, "Reflow Oven Controller Firmware %s", xstr(GIT_VER)); + + return SHELLMATTA_OK; +} + +static shellmatta_retCode_t shell_cmd_pt1000_res(const shellmatta_handle_t handle, + const char *arguments, + uint32_t length) +{ + (void)arguments; + (void)length; + float resistance; + int pt1000_status; + const char *display_status; + enum adc_pt1000_error pt1000_flags; + const char *status_text[] = {"VALID", "WATCHDOG", "DATA-OVERFLOW", "UNSTABLE"}; + + + display_status = status_text[0]; + pt1000_status = adc_pt1000_get_current_resistance(&resistance); + + if (pt1000_status == 2) { + display_status = status_text[3]; + } else if (pt1000_status) { + pt1000_flags = adc_pt1000_check_error(); + if (pt1000_flags & ADC_PT1000_WATCHDOG_ERROR) + display_status = status_text[1]; + else if (pt1000_flags & ADC_PT1000_OVERFLOW) + display_status = status_text[2]; + } + + shellmatta_printf(handle, "PT1000 resistance: %.2f Ohm [%s]\r\n", resistance, display_status); + + return SHELLMATTA_OK; +} +static shellmatta_retCode_t shell_cmd_clear_error_status(const shellmatta_handle_t handle, + const char *arguments, + uint32_t length) +{ + adc_pt1000_clear_error(); + + return SHELLMATTA_OK; +} +//typedef struct shellmatta_cmd +//{ +// char *cmd; /**< command name */ +// char *cmdAlias; /**< command alias */ +// char *helpText; /**< help text to print in "help" command */ +// char *usageText; /**< usage text to print on parameter error */ +// shellmatta_cmdFct_t cmdFct; /**< pointer to the cmd callack function */ +// struct shellmatta_cmd *next; /**< pointer to next command or NULL */ +//} shellmatta_cmd_t; + +static shellmatta_cmd_t cmd[3] = { + { + .cmd = "version", + .cmdAlias = "ver", + .helpText = "Print firmware version", + .usageText = NULL, + .cmdFct = shell_cmd_ver, + .next = &cmd[1], + }, + { + .cmd = "pt1000", + .cmdAlias = "pt", + .helpText = "Get current filtered and calibrated PT1000 resistance", + .usageText = NULL, + .cmdFct = shell_cmd_pt1000_res, + .next = &cmd[2], + }, + { + .cmd = "pt1000-clear-error", + .cmdAlias = "pt-clear", + .helpText = "Clear error status of PT1000 reading", + .usageText = NULL, + .cmdFct = shell_cmd_clear_error_status, + .next = NULL, + }, +}; + +shellmatta_handle_t shell_init(void) +{ + shellmatta_handle_t handle; + shellmatta_retCode_t ret; + + ret = shellmatta_doInit(&shell, &handle, shell_buffer, sizeof(shell_buffer), history_buffer, sizeof(history_buffer), + "Enter command:\r\n", cmd, write_shell_callback); + if (ret != SHELLMATTA_OK) + handle = NULL; + + return handle; +} + + +void shell_handle_input(shellmatta_handle_t shell, const char *data, size_t len) +{ + if (!shell) + return; + + shellmatta_processData(shell, (char *)data, (uint32_t)len); +} + +void shell_print_string(shellmatta_handle_t shell, const char *string) +{ + if (!shell) + return; + + shellmatta_write(shell, (char *)string, strlen(string)); +} diff --git a/stm-firmware/stm32f407vet6_flash.ld b/stm-firmware/stm32f407vet6_flash.ld index 837227c..c1b33b8 100644 --- a/stm-firmware/stm32f407vet6_flash.ld +++ b/stm-firmware/stm32f407vet6_flash.ld @@ -36,8 +36,8 @@ ENTRY(Reset_Handler) _estack = 0x20020000; /* end of 128K RAM on AHB bus*/ /* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x1000; /* required amount of heap (DEFAULT 0) */ -_Min_Stack_Size = 0x1000 ; /* required amount of stack */ +_Min_Heap_Size = 0x1500; /* required amount of heap (DEFAULT 0) */ +_Min_Stack_Size = 0x2000 ; /* required amount of stack */ /* recommended min stack size for printf=0x2000, orig = 0x400 */ /* Specify the memory areas */ diff --git a/stm-firmware/uart/dma-ring-buffer.c b/stm-firmware/uart/dma-ring-buffer.c index 48e68d9..f8c8e92 100644 --- a/stm-firmware/uart/dma-ring-buffer.c +++ b/stm-firmware/uart/dma-ring-buffer.c @@ -1,2 +1,93 @@ #include +#include +int dma_ring_buffer_initialize(struct dma_ring_buffer *dma_buffer, uint8_t base_dma_id, DMA_Stream_TypeDef *dma_stream, size_t buffer_element_count, char *data_buffer, void* src_reg, uint8_t dma_trigger_channel) +{ + if (!dma_buffer || !dma_stream || !data_buffer || !src_reg) + return -1; + + if (dma_trigger_channel > 7) + return -3; + + dma_buffer->base_dma_id = base_dma_id; + + switch (base_dma_id) { + case 1: + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA1EN)); + break; + case 2: + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN)); + break; + default: + return -2; + break; + } + + dma_buffer->dma = dma_stream; + dma_buffer->get_idx = 0; + dma_buffer->buffer_count = buffer_element_count; + + dma_buffer->data_ptr = data_buffer; + + dma_stream->PAR = (uint32_t)src_reg; + dma_stream->M0AR = (uint32_t)data_buffer; + dma_stream->NDTR = buffer_element_count; + dma_stream->NDTR = buffer_element_count; + + dma_stream->CR |= (dma_trigger_channel<<25) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_EN; + + return 0; +} + +int dma_ring_buffer_get_data(struct dma_ring_buffer *buff, const char **data_buff, size_t *len) +{ + int ret_code = 0; + uint32_t ndtr; + size_t put_idx; + + if (!buff || !data_buff || !len) + return -1; + + + ndtr = buff->dma->NDTR; + put_idx = buff->buffer_count - ndtr; + + /* Check if wrap around */ + if (put_idx < buff->get_idx) { + *data_buff = &(buff->data_ptr[buff->get_idx]); + *len = buff->buffer_count - buff->get_idx; + buff->get_idx = 0; + ret_code = 1; + } else if (put_idx > buff->get_idx) { + *data_buff = &(buff->data_ptr[buff->get_idx]); + *len = put_idx - buff->get_idx; + buff->get_idx += *len; + } else { + /* No new data */ + *len = 0; + } + + return ret_code; +} + +void dma_ring_buffer_stop(struct dma_ring_buffer *buff) +{ + if (!buff || !buff->dma) + return; + + buff->dma->CR = 0; + buff->dma->NDTR = 0; + buff->dma->M1AR = 0; + buff->dma->FCR = 0; + + switch (buff->base_dma_id) { + case 1: + rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA1EN)); + break; + case 2: + rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(RCC_AHB1ENR_DMA2EN)); + break; + default: + break; + } +} diff --git a/stm-firmware/uart/uart.c b/stm-firmware/uart/uart.c index f3e974e..5c9cdbb 100644 --- a/stm-firmware/uart/uart.c +++ b/stm-firmware/uart/uart.c @@ -1,44 +1,114 @@ -/* - * uart.c - * - * Created on: Dec 15, 2014 - * Author: shino-chan - */ -//USART2 -//PA2 => TX -//PA3 => RX -//Alternate Function 7 -#include -#include - -void initUART() { - __DSB(); - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; - RCC->APB1ENR |= RCC_APB1ENR_USART2EN; - __DSB(); - - GPIOA->MODER |= (1<<5); - GPIOA->AFR[0] |= (7<<8); //Enable Clock - GPIOA->MODER |= (1<<5); - GPIOA->AFR[0] |= (7<<8); - asm("nop"); - asm("nop"); - asm("nop"); - USART2->BRR = 0x1117; //Baudrate 273.4375=>0x1117 9600baud bei 42MHz Periph - USART2->CR1 = USART_CR1_UE | USART_CR1_TE; - -} -void sendChar(char c) { - while(!(USART2->SR & USART_SR_TXE)); - USART2->DR = c; - -} -void sendString(char* s, int count) { - int i = 0; - for (i = 0; i < count; i++,s++) - { - if (!(*s)) - break; - sendChar(*s); - } -} +/* + * uart.c + * + * Created on: Dec 15, 2014 + * Author: shino-chan + */ +//USART2 +//PA2 => TX +//PA3 => RX +//Alternate Function 7 +#include +#include +#include +#include +#include + +static struct dma_ring_buffer ring_buff; +static char uart_rx_buffer[64]; + +void initUART() { + __DSB(); + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; + RCC->APB1ENR |= RCC_APB1ENR_USART2EN; + __DSB(); + + GPIOA->MODER |= (1<<5); + GPIOA->AFR[0] |= (7<<8); //Enable Clock + GPIOA->MODER |= (1<<5); + GPIOA->AFR[0] |= (7<<8); + asm("nop"); + asm("nop"); + asm("nop"); + USART2->BRR = 0x1117; //Baudrate 273.4375=>0x1117 9600baud bei 42MHz Periph + USART2->CR1 = USART_CR1_UE | USART_CR1_TE; + +} + +void sendChar(char c) { + while(!(USART2->SR & USART_SR_TXE)); + USART2->DR = c; + +} +void sendString(char* s, int count) { + int i = 0; + for (i = 0; i < count; i++,s++) + { + if (!(*s)) + break; + sendChar(*s); + } +} + +static inline void uart_gpio_config() +{ + rcc_manager_enable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(UART_PORT_RCC_MASK)); + UART_PORT->MODER &= MODER_DELETE(UART_TX_PIN) & MODER_DELETE(UART_RX_PIN); + UART_PORT->MODER |= ALTFUNC(UART_RX_PIN) | ALTFUNC(UART_TX_PIN); + SETAF(UART_PORT, UART_RX_PIN, UART_RX_PIN_ALTFUNC); + SETAF(UART_PORT, UART_TX_PIN, UART_TX_PIN_ALTFUNC); +} + +void uart_init_with_dma() +{ + rcc_manager_enable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(UART_RCC_MASK)); + uart_gpio_config(); + + UART_PERIPH->BRR = UART_BRR_REG_VALUE; + UART_PERIPH->CR3 = USART_CR3_DMAR | USART_CR3_DMAT; + UART_PERIPH->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; + + dma_ring_buffer_initialize(&ring_buff, 2, DMA2_Stream5, sizeof(uart_rx_buffer), uart_rx_buffer, (char *)&UART_PERIPH->DR, 4); +} + +void uart_disable() +{ + UART_PERIPH->CR1 = 0; + UART_PERIPH->CR2 = 0; + UART_PERIPH->CR3 = 0; + dma_ring_buffer_stop(&ring_buff); + + rcc_manager_disable_clock(&RCC->AHB1ENR, BITMASK_TO_BITNO(UART_PORT_RCC_MASK)); + rcc_manager_disable_clock(&RCC->APB2ENR, BITMASK_TO_BITNO(UART_RCC_MASK)); +} + +void uart_send_char(char c) +{ + while(!(UART_PERIPH->SR & USART_SR_TXE)); + UART_PERIPH->DR = c; +} + +void uart_send_array(const char *data, uint32_t len) +{ + uint32_t i; + + for (i = 0; i < len; i++) + uart_send_char(data[i]); +} + +void uart_send_string(char *string) +{ + int i; + + for (i = 0; string[i] != '\0'; i++) + uart_send_char(string[i]); +} + +void uart_send_array_with_dma(char *data, uint32_t len); + +void uart_send_string_with_dma(char *string); + +int uart_receive_data_with_dma(const char **data, size_t *len) +{ + return dma_ring_buffer_get_data(&ring_buff, data, len); +}