mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-03-20 00:30:57 +03:00
OK, USART works, maybe add HEX input?
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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(){
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Binary file not shown.
@@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "173"
|
#define BUILD_NUMBER "189"
|
||||||
#define BUILD_DATE "2026-03-14"
|
#define BUILD_DATE "2026-03-14"
|
||||||
|
|||||||
Reference in New Issue
Block a user