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'
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

View File

@@ -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;

View File

@@ -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 <pinpull_t> (pull_set);
curconf.otype = static_cast <pinout_t> (otype_set);
curconf.speed = SPEED_MEDIUM;
curconf.af = func_set;
curconf.af = static_cast <funcnames_t> (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;
}

View File

@@ -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();

View File

@@ -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(){

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"
// 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);

View File

@@ -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;
}
/**

View File

@@ -19,12 +19,13 @@
#pragma once
#include <stdint.h>
#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);

View File

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