OK, USART works, maybe add HEX input?

This commit is contained in:
Edward Emelianov
2026-03-14 22:46:28 +03:00
parent 65c9ae34bc
commit 57a44f1c66
10 changed files with 61 additions and 45 deletions

View File

@@ -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' // '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); 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} #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 // GPIOA, enabled: PA0-PA3, PA5-PA7, PA9, PA10
#define PACONF \ #define PACONF \
[0] = PINEN, [1] = PINEN, [2] = PINEN, [3] = PINEN, [5] = PINEN, \ [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 // GPIOB, enabled: PB0-PB7, PB10, PB11
#define PBCONF \ #define PBCONF \
@@ -60,6 +63,7 @@ user_conf the_conf = {
}, },
.iIlengths = {14, 16}, .iIlengths = {14, 16},
.pinconfig = {[0] = {PACONF}, [1] = {PBCONF}}, .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 int currentconfidx = -1; // index of current configuration

View File

@@ -60,13 +60,14 @@ typedef enum{
} pinspeed_t; } pinspeed_t;
// !!! FuncNames means position of bit in funcvalues_t.flags! // !!! 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_AIN = 0,
FUNC_USART = 1, FUNC_USART = 1,
FUNC_SPI = 2, FUNC_SPI = 2,
FUNC_I2C = 3, FUNC_I2C = 3,
FUNC_PWM = 4,
FUNC_AMOUNT // just for arrays' sizes FUNC_AMOUNT // just for arrays' sizes
}; } funcnames_t;
/* /*
typedef union{ typedef union{
struct{ struct{
@@ -84,7 +85,7 @@ typedef struct{
pinout_t otype : 1; pinout_t otype : 1;
pinspeed_t speed : 2; pinspeed_t speed : 2;
uint8_t afno : 3; // alternate function number (only if mode == MODE_AF) 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 uint8_t monitor : 1; // monitor changes
uint16_t threshold; // threshold for ADC measurement uint16_t threshold; // threshold for ADC measurement
} pinconfig_t; } pinconfig_t;

View File

@@ -170,6 +170,7 @@ static const char* errtxt[ERR_AMOUNT] = {
[ERR_WRONGLEN] = "WRONGLEN", [ERR_WRONGLEN] = "WRONGLEN",
[ERR_CANTRUN] = "CANTRUN", [ERR_CANTRUN] = "CANTRUN",
[ERR_BUSY] = "BUSY", [ERR_BUSY] = "BUSY",
[ERR_OVERFLOW] = "OVERFLOW",
}; };
static const char *pinhelp = 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 <pinpull_t> (pull_set); curconf.pull = static_cast <pinpull_t> (pull_set);
curconf.otype = static_cast <pinout_t> (otype_set); curconf.otype = static_cast <pinout_t> (otype_set);
curconf.speed = SPEED_MEDIUM; curconf.speed = SPEED_MEDIUM;
curconf.af = func_set; curconf.af = static_cast <funcnames_t> (func_set);
curconf.monitor = monitor; curconf.monitor = monitor;
if(!set_pinfunc(port, pin, &curconf)) return ERR_BADVAL; if(!set_pinfunc(port, pin, &curconf)) return ERR_BADVAL;
return ERR_OK; return ERR_OK;
@@ -637,7 +638,7 @@ static void sendusartdata(const uint8_t *buf, int len){
SEND(str_keywords[STR_USART]); SEND(EQ); SEND(str_keywords[STR_USART]); SEND(EQ);
if(usart_text){ if(usart_text){
USB_send(IGPIO, curbuf, len); 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{ }else{
NL(); NL();
hexdump(sendfun, (uint8_t*)curbuf, len); 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(usart_text){ // add '\n' as we removed it @ parser
if(setter[l-1] != '\n') setter[l++] = '\n'; if(setter[l-1] != '\n') setter[l++] = '\n';
} }
l = usart_send((uint8_t*)setter, l); return usart_send((uint8_t*)setter, l);
if(l < 0) return ERR_BUSY;
else if(l == 0) return ERR_CANTRUN;
return ERR_OK;
} // getter: try to read } // getter: try to read
int l = usart_receive(curbuf, MAXSTRLEN); int l = usart_receive(curbuf, MAXSTRLEN);
if(l < 0) return ERR_CANTRUN; if(l < 0) return ERR_CANTRUN;
@@ -711,3 +709,10 @@ void GPIO_process(){
if(ans) SENDn(ans); 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;
}

View File

@@ -27,6 +27,7 @@ typedef enum{
ERR_WRONGLEN, // wrong message length ERR_WRONGLEN, // wrong message length
ERR_CANTRUN, // can't run given command due to bad parameters or other ERR_CANTRUN, // can't run given command due to bad parameters or other
ERR_BUSY, // target interface busy, try later ERR_BUSY, // target interface busy, try later
ERR_OVERFLOW, // string was too long -> overflow
ERR_AMOUNT // amount of error codes or "send nothing" ERR_AMOUNT // amount of error codes or "send nothing"
} errcodes_t; } errcodes_t;
@@ -39,3 +40,4 @@ typedef enum{
#define ADC_THRES_DEFAULT 100 #define ADC_THRES_DEFAULT 100
void GPIO_process(); void GPIO_process();
void GPIO_init();

View File

@@ -17,12 +17,12 @@
*/ */
#include "adc.h" #include "adc.h"
#include "gpio.h" #include "gpioproto.h"
#include "hardware.h" #include "hardware.h"
uint8_t ledsON = 0; 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 // Set LEDS (PB15/PA8) as output
pin_set(LED0_port, LED0_pin); // clear LEDs pin_set(LED0_port, LED0_pin); // clear LEDs
pin_set(LED1_port, LED1_pin); 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->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
gpio_setup(); pins_setup();
//gpio_reinit();
adc_setup(); adc_setup();
GPIO_init();
} }
void iwdg_setup(){ void iwdg_setup(){

View File

@@ -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" #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') // 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); void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
const char *u2str(uint32_t val); const char *u2str(uint32_t val);

View File

@@ -209,10 +209,14 @@ int usart_process(uint8_t *buf, int len){
int remained = DMA1_Channel5->CNDTR; int remained = DMA1_Channel5->CNDTR;
int write_idx = DMARXBUFSZ - remained; // next symbol to be written int write_idx = DMARXBUFSZ - remained; // next symbol to be written
int available = (write_idx - dma_read_idx); // length of data available 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; int monitored_len = available;
uint8_t locmonitor = monitor; // if `buf` not pointed, set this flag to zero 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 > 0){
if(available){
if(locmonitor){ if(locmonitor){
if(buf && len > 0){ if(buf && len > 0){
if(len < monitored_len) monitored_len = len; 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 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) // copy data in one or two chunks (wrap handling)
int wrOK = FALSE; 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(dma_read_idx + available <= DMARXBUFSZ){ // head before tail
if(locmonitor){ if(locmonitor){
memcpy(buf, &inbuffer[dma_read_idx], monitored_len); memcpy(buf, &inbuffer[dma_read_idx], monitored_len);
ret = monitored_len; ret = monitored_len;
wrOK = TRUE; wrOK = TRUE;
}else{ }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 }else{ // head after tail - two chunks
int first = DMARXBUFSZ - dma_read_idx; int first = DMARXBUFSZ - dma_read_idx;
if(locmonitor){ if(locmonitor){
memcpy(buf, &inbuffer[dma_read_idx], first); memcpy(buf, &inbuffer[dma_read_idx], first);
memcpy(buf, inbuffer, monitored_len - first); memcpy(buf + first, inbuffer, monitored_len - first);
ret = monitored_len; ret = monitored_len;
wrOK = TRUE; wrOK = TRUE;
}else{ }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; (available - first) == RB_write(&RBin, inbuffer, available - first)) wrOK = TRUE;
else if(buf && len > 0) ret = RB_read(&RBin, buf, len);
} }
} }
if(wrOK){ if(wrOK){
@@ -247,29 +259,20 @@ int usart_process(uint8_t *buf, int len){
dma_read_idx = write_idx; // update read pointer 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 // we can work with RBout to send more than `usart_send` can
// Output data // here we can send next data portion
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
return ret; return ret;
} }
// send data buffer // send data buffer
int usart_send(const uint8_t *data, int len){ errcodes_t usart_send(const uint8_t *data, int len){
if(curUSARTidx == -1 || !data || len < 1) return 0; if(curUSARTidx == -1 || !data || len < 1) return ERR_CANTRUN;
if(TXrdy == 0) return -1; if(TXrdy == 0) return ERR_BUSY;
if(len > DMATXBUFSZ) len = DMATXBUFSZ; if(len > DMATXBUFSZ) return ERR_OVERFLOW;
memcpy(outbuffer, data, len); memcpy(outbuffer, data, len);
volatile DMA_Channel_TypeDef *T = DMA1_Channel4; volatile DMA_Channel_TypeDef *T = DMA1_Channel4;
T->CCR &= ~DMA_CCR_EN; T->CCR &= ~DMA_CCR_EN;
@@ -277,7 +280,7 @@ int usart_send(const uint8_t *data, int len){
T->CNDTR = len; T->CNDTR = len;
TXrdy = 0; TXrdy = 0;
T->CCR |= DMA_CCR_EN; // start new transmission T->CCR |= DMA_CCR_EN; // start new transmission
return len; return ERR_OK;
} }
/** /**

View File

@@ -19,12 +19,13 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "gpioproto.h"
// DMA linear buffers for Rx/Tx // DMA linear buffers for Rx/Tx
#define DMARXBUFSZ 128 #define DMARXBUFSZ 192
#define DMATXBUFSZ 128 #define DMATXBUFSZ 192
// incoming ring buffer - only if there's a lot of data in DMA RX buffer // 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_MIN_SPEED 1024
#define USART_MAX_SPEED 1000000 #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_process(uint8_t *buf, int len);
int usart_receive(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);

View File

@@ -1,2 +1,2 @@
#define BUILD_NUMBER "173" #define BUILD_NUMBER "189"
#define BUILD_DATE "2026-03-14" #define BUILD_DATE "2026-03-14"