diff --git a/F0:F030,F042,F072/usbcan_gpio/flash.c b/F0:F030,F042,F072/usbcan_gpio/flash.c index 793f154..f1e5b73 100644 --- a/F0:F030,F042,F072/usbcan_gpio/flash.c +++ b/F0:F030,F042,F072/usbcan_gpio/flash.c @@ -39,12 +39,15 @@ static int write2flash(const void*, const void*, uint32_t); // 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t' const user_conf *Flash_Data = (const user_conf *)(&__varsstart); -// default pin config: all are low speed floating inputs +// default pin config +// simple FL IN #define PINEN {.enable = 1} +// USART1 @9600 with monitoring +#define U1 {.enable = 1, .mode = MODE_AF, .speed = SPEED_HIGH, .afno = 1, .af = FUNC_USART, .monitor = 1} // GPIOA, enabled: PA0-PA3, PA5-PA7, PA9, PA10 #define PACONF \ [0] = PINEN, [1] = PINEN, [2] = PINEN, [3] = PINEN, [5] = PINEN, \ -[6] = PINEN, [7] = PINEN, [9] = PINEN, [10] = PINEN +[6] = PINEN, [7] = PINEN, [9] = U1, [10] = U1 // GPIOB, enabled: PB0-PB7, PB10, PB11 #define PBCONF \ @@ -60,6 +63,7 @@ user_conf the_conf = { }, .iIlengths = {14, 16}, .pinconfig = {[0] = {PACONF}, [1] = {PBCONF}}, + .usartconfig = {.speed = 9600, .idx = 0, .RXen = 1, .TXen = 1, .textproto = 1, .monitor = 1}, }; int currentconfidx = -1; // index of current configuration diff --git a/F0:F030,F042,F072/usbcan_gpio/gpio.h b/F0:F030,F042,F072/usbcan_gpio/gpio.h index b66eef5..4d5992d 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpio.h +++ b/F0:F030,F042,F072/usbcan_gpio/gpio.h @@ -60,13 +60,14 @@ typedef enum{ } pinspeed_t; // !!! FuncNames means position of bit in funcvalues_t.flags! -enum FuncNames{ // shift 1 by this to get "canUSART" etc; not more than 7! +typedef enum FuncNames{ // shift 1 by this to get "canUSART" etc; not more than 7! FUNC_AIN = 0, FUNC_USART = 1, FUNC_SPI = 2, FUNC_I2C = 3, + FUNC_PWM = 4, FUNC_AMOUNT // just for arrays' sizes -}; +} funcnames_t; /* typedef union{ struct{ @@ -84,7 +85,7 @@ typedef struct{ pinout_t otype : 1; pinspeed_t speed : 2; uint8_t afno : 3; // alternate function number (only if mode == MODE_AF) - uint8_t af : 3; // alternate function name (`FuncNames`) + funcnames_t af : 3; // alternate function name (`FuncNames`) uint8_t monitor : 1; // monitor changes uint16_t threshold; // threshold for ADC measurement } pinconfig_t; diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp index 41611bb..054e550 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.cpp @@ -170,6 +170,7 @@ static const char* errtxt[ERR_AMOUNT] = { [ERR_WRONGLEN] = "WRONGLEN", [ERR_CANTRUN] = "CANTRUN", [ERR_BUSY] = "BUSY", + [ERR_OVERFLOW] = "OVERFLOW", }; static const char *pinhelp = @@ -357,7 +358,7 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){ curconf.pull = static_cast (pull_set); curconf.otype = static_cast (otype_set); curconf.speed = SPEED_MEDIUM; - curconf.af = func_set; + curconf.af = static_cast (func_set); curconf.monitor = monitor; if(!set_pinfunc(port, pin, &curconf)) return ERR_BADVAL; return ERR_OK; @@ -637,7 +638,7 @@ static void sendusartdata(const uint8_t *buf, int len){ SEND(str_keywords[STR_USART]); SEND(EQ); if(usart_text){ USB_send(IGPIO, curbuf, len); - if(curbuf[len-1] != '\n') NL(); + NL(); // always add newline at the end to mark real newline ("\n\n") and piece of line ("\n") }else{ NL(); hexdump(sendfun, (uint8_t*)curbuf, len); @@ -653,10 +654,7 @@ static errcodes_t cmd_USART(const char _U_ *cmd, char *args){ if(usart_text){ // add '\n' as we removed it @ parser if(setter[l-1] != '\n') setter[l++] = '\n'; } - l = usart_send((uint8_t*)setter, l); - if(l < 0) return ERR_BUSY; - else if(l == 0) return ERR_CANTRUN; - return ERR_OK; + return usart_send((uint8_t*)setter, l); } // getter: try to read int l = usart_receive(curbuf, MAXSTRLEN); if(l < 0) return ERR_CANTRUN; @@ -711,3 +709,10 @@ void GPIO_process(){ if(ans) SENDn(ans); } } + +// starting init by flash settings +void GPIO_init(){ + gpio_reinit(); + usartconf_t usc; + if(get_curusartconf(&usc)) usart_text = usc.textproto; +} diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.h b/F0:F030,F042,F072/usbcan_gpio/gpioproto.h index 2facea9..b0adede 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.h +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.h @@ -27,6 +27,7 @@ typedef enum{ ERR_WRONGLEN, // wrong message length ERR_CANTRUN, // can't run given command due to bad parameters or other ERR_BUSY, // target interface busy, try later + ERR_OVERFLOW, // string was too long -> overflow ERR_AMOUNT // amount of error codes or "send nothing" } errcodes_t; @@ -39,3 +40,4 @@ typedef enum{ #define ADC_THRES_DEFAULT 100 void GPIO_process(); +void GPIO_init(); diff --git a/F0:F030,F042,F072/usbcan_gpio/hardware.c b/F0:F030,F042,F072/usbcan_gpio/hardware.c index 45f312d..d225182 100644 --- a/F0:F030,F042,F072/usbcan_gpio/hardware.c +++ b/F0:F030,F042,F072/usbcan_gpio/hardware.c @@ -17,12 +17,12 @@ */ #include "adc.h" -#include "gpio.h" +#include "gpioproto.h" #include "hardware.h" uint8_t ledsON = 0; -TRUE_INLINE void gpio_setup(){ // setup some common GPIO +TRUE_INLINE void pins_setup(){ // setup some common GPIO // Set LEDS (PB15/PA8) as output pin_set(LED0_port, LED0_pin); // clear LEDs pin_set(LED1_port, LED1_pin); @@ -37,9 +37,9 @@ void hardware_setup(){ RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN; - gpio_setup(); - //gpio_reinit(); + pins_setup(); adc_setup(); + GPIO_init(); } void iwdg_setup(){ diff --git a/F0:F030,F042,F072/usbcan_gpio/strfunc.h b/F0:F030,F042,F072/usbcan_gpio/strfunc.h index 194d0db..c21ac44 100644 --- a/F0:F030,F042,F072/usbcan_gpio/strfunc.h +++ b/F0:F030,F042,F072/usbcan_gpio/strfunc.h @@ -37,7 +37,7 @@ #define REPOURL "https://github.com/eddyem/stm32samples/tree/master/F0:F030,F042,F072/usbcan_gpio " RLSDBG " build #" BUILD_NUMBER "@" BUILD_DATE "\n" // max string len to '\n' (including '\0') -#define MAXSTRLEN 128 +#define MAXSTRLEN 256 void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len); const char *u2str(uint32_t val); diff --git a/F0:F030,F042,F072/usbcan_gpio/usart.c b/F0:F030,F042,F072/usbcan_gpio/usart.c index 85be3a6..23b3967 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usart.c +++ b/F0:F030,F042,F072/usbcan_gpio/usart.c @@ -209,10 +209,14 @@ int usart_process(uint8_t *buf, int len){ int remained = DMA1_Channel5->CNDTR; int write_idx = DMARXBUFSZ - remained; // next symbol to be written int available = (write_idx - dma_read_idx); // length of data available + if(available < 0) available += DMARXBUFSZ; // write to the left of read + if(available == 0){ + RXrdy = 0; // clear old ready flag if got no data + return 0; + } int monitored_len = available; uint8_t locmonitor = monitor; // if `buf` not pointed, set this flag to zero - if(available < 0) available += DMARXBUFSZ; // write to the left of read - if(available){ + if(available > 0){ if(locmonitor){ if(buf && len > 0){ if(len < monitored_len) monitored_len = len; @@ -222,24 +226,32 @@ int usart_process(uint8_t *buf, int len){ if(available >= (DMARXBUFSZ/2) || RXrdy){ // enough data or lonely couple of bytes but need to show // copy data in one or two chunks (wrap handling) int wrOK = FALSE; + // check if we can write to RB `available` bytes + int canRB = TRUE; + if(!locmonitor){ + int rballow = RBin.length - 1 - RB_datalen(&RBin); + if(rballow < available) canRB = FALSE; + } if(dma_read_idx + available <= DMARXBUFSZ){ // head before tail if(locmonitor){ memcpy(buf, &inbuffer[dma_read_idx], monitored_len); ret = monitored_len; wrOK = TRUE; }else{ - if(available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE; + if(canRB && available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE; + else if(buf && len > 0) ret = RB_read(&RBin, buf, len); // ringbuffer overfull -> emerge clearing } }else{ // head after tail - two chunks int first = DMARXBUFSZ - dma_read_idx; if(locmonitor){ memcpy(buf, &inbuffer[dma_read_idx], first); - memcpy(buf, inbuffer, monitored_len - first); + memcpy(buf + first, inbuffer, monitored_len - first); ret = monitored_len; wrOK = TRUE; }else{ - if((first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) && + if(canRB && (first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) && (available - first) == RB_write(&RBin, inbuffer, available - first)) wrOK = TRUE; + else if(buf && len > 0) ret = RB_read(&RBin, buf, len); } } if(wrOK){ @@ -247,29 +259,20 @@ int usart_process(uint8_t *buf, int len){ dma_read_idx = write_idx; // update read pointer } } + }else if(available < 0){ // das ist fantastisch! + if(buf && len > 0) ret = RB_read(&RBin, buf, len); + DBG("WTF? USART's `available` < 0!!!\n"); } -#if 0 - // Output data - if(TXrdy){ // ready to send new data - here we can process RBout, if have - int got = RB_read... - if(got > 0){ // send next data portion - volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel; - T->CCR &= ~DMA_CCR_EN; - T->CMAR = (uint32_t) outbuffers[i]; - T->CNDTR = got; - TXrdy = 0; - T->CCR |= DMA_CCR_EN; // start new transmission - } - } -#endif + // we can work with RBout to send more than `usart_send` can + // here we can send next data portion return ret; } // send data buffer -int usart_send(const uint8_t *data, int len){ - if(curUSARTidx == -1 || !data || len < 1) return 0; - if(TXrdy == 0) return -1; - if(len > DMATXBUFSZ) len = DMATXBUFSZ; +errcodes_t usart_send(const uint8_t *data, int len){ + if(curUSARTidx == -1 || !data || len < 1) return ERR_CANTRUN; + if(TXrdy == 0) return ERR_BUSY; + if(len > DMATXBUFSZ) return ERR_OVERFLOW; memcpy(outbuffer, data, len); volatile DMA_Channel_TypeDef *T = DMA1_Channel4; T->CCR &= ~DMA_CCR_EN; @@ -277,7 +280,7 @@ int usart_send(const uint8_t *data, int len){ T->CNDTR = len; TXrdy = 0; T->CCR |= DMA_CCR_EN; // start new transmission - return len; + return ERR_OK; } /** diff --git a/F0:F030,F042,F072/usbcan_gpio/usart.h b/F0:F030,F042,F072/usbcan_gpio/usart.h index f5e1e77..265cad7 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usart.h +++ b/F0:F030,F042,F072/usbcan_gpio/usart.h @@ -19,12 +19,13 @@ #pragma once #include +#include "gpioproto.h" // DMA linear buffers for Rx/Tx -#define DMARXBUFSZ 128 -#define DMATXBUFSZ 128 +#define DMARXBUFSZ 192 +#define DMATXBUFSZ 192 // incoming ring buffer - only if there's a lot of data in DMA RX buffer -#define RXRBSZ 256 +#define RXRBSZ 384 #define USART_MIN_SPEED 1024 #define USART_MAX_SPEED 1000000 @@ -51,4 +52,4 @@ void get_defusartconf(usartconf_t *c); int usart_process(uint8_t *buf, int len); int usart_receive(uint8_t *buf, int len); -int usart_send(const uint8_t *data, int len); +errcodes_t usart_send(const uint8_t *data, int len); diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin index ed09300..9f8adbd 100755 Binary files a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin and b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin differ diff --git a/F0:F030,F042,F072/usbcan_gpio/version.inc b/F0:F030,F042,F072/usbcan_gpio/version.inc index 2c30622..f5e4c3d 100644 --- a/F0:F030,F042,F072/usbcan_gpio/version.inc +++ b/F0:F030,F042,F072/usbcan_gpio/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "173" +#define BUILD_NUMBER "189" #define BUILD_DATE "2026-03-14"