mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-03-20 00:30:57 +03:00
USART almost working (but hangs on long messages)
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
BINARY := usbcangpio
|
BINARY := usbcangpio
|
||||||
# MCU code
|
# MCU code
|
||||||
#MCU := F072xB
|
MCU := F072xB
|
||||||
MCU := F042x6
|
#MCU := F042x6
|
||||||
# change this linking script depending on particular MCU model,
|
# change this linking script depending on particular MCU model,
|
||||||
#LDSCRIPT := stm32f072xB.ld
|
LDSCRIPT := stm32f072x8.ld
|
||||||
LDSCRIPT := stm32f042x6.ld
|
#LDSCRIPT := stm32f042x6.ld
|
||||||
|
|
||||||
DEFINES := -DUSB2_16
|
DEFINES := -DUSB2_16
|
||||||
|
|
||||||
|
|||||||
@@ -387,8 +387,10 @@ static void CommandParser(char *txt){
|
|||||||
break;
|
break;
|
||||||
#ifdef STM32F072xB
|
#ifdef STM32F072xB
|
||||||
case 'D':
|
case 'D':
|
||||||
USB_sendstr("Go into DFU mode\n");
|
SEND("Go into DFU mode\n");
|
||||||
USB_sendall();
|
USB_sendall(ICAN);
|
||||||
|
uint32_t t = Tms;
|
||||||
|
while(Tms - t < 2000){IWDG->KR = IWDG_REFRESH;}
|
||||||
Jump2Boot();
|
Jump2Boot();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,13 +27,6 @@
|
|||||||
static uint16_t monitor_mask[2] = {0}; // pins to monitor == 1 (ONLY GPIO and ADC)
|
static uint16_t monitor_mask[2] = {0}; // pins to monitor == 1 (ONLY GPIO and ADC)
|
||||||
static uint16_t oldstates[2][16] = {0}; // previous state (16 bits - as some pins could be analog)
|
static uint16_t oldstates[2][16] = {0}; // previous state (16 bits - as some pins could be analog)
|
||||||
|
|
||||||
// strings for keywords
|
|
||||||
const char *str_keywords[] = {
|
|
||||||
#define KW(x) [STR_ ## x] = #x,
|
|
||||||
KEYWORDS
|
|
||||||
#undef KW
|
|
||||||
};
|
|
||||||
|
|
||||||
// intermediate buffer to change pin's settings by user request; after checking in will be copied to the_conf
|
// intermediate buffer to change pin's settings by user request; after checking in will be copied to the_conf
|
||||||
static pinconfig_t pinconfig[2][16] = {0};
|
static pinconfig_t pinconfig[2][16] = {0};
|
||||||
static uint8_t pinconfig_notinited = 1; // ==0 after first memcpy from the_conf to pinconfig
|
static uint8_t pinconfig_notinited = 1; // ==0 after first memcpy from the_conf to pinconfig
|
||||||
@@ -207,7 +200,8 @@ int chkpinconf(){
|
|||||||
}
|
}
|
||||||
// now check USART configuration
|
// now check USART configuration
|
||||||
if(active_usart != -1){
|
if(active_usart != -1){
|
||||||
if(chkusartconf(&UC)) ret = FALSE;
|
UC.idx = active_usart;
|
||||||
|
if(!chkusartconf(&UC)) ret = FALSE;
|
||||||
}else{
|
}else{
|
||||||
get_defusartconf(&UC); // clear global configuration
|
get_defusartconf(&UC); // clear global configuration
|
||||||
the_conf.usartconfig = UC;
|
the_conf.usartconfig = UC;
|
||||||
@@ -318,7 +312,7 @@ int gpio_reinit(){
|
|||||||
int shift4 = pin << 4;
|
int shift4 = pin << 4;
|
||||||
gpio->AFR[0] = (gpio->AFR[0] & ~(0xf << shift4)) | (cfg->afno << shift4);
|
gpio->AFR[0] = (gpio->AFR[0] & ~(0xf << shift4)) | (cfg->afno << shift4);
|
||||||
}else{
|
}else{
|
||||||
int shift4 = (pin - 8) << 4;
|
int shift4 = (pin - 8) << 2;
|
||||||
gpio->AFR[1] = (gpio->AFR[1] & ~(0xf << shift4)) | (cfg->afno << shift4);
|
gpio->AFR[1] = (gpio->AFR[1] & ~(0xf << shift4)) | (cfg->afno << shift4);
|
||||||
}
|
}
|
||||||
if(cfg->monitor && cfg->mode != MODE_AF){
|
if(cfg->monitor && cfg->mode != MODE_AF){
|
||||||
|
|||||||
@@ -99,32 +99,6 @@ typedef struct{
|
|||||||
} spiconfig_t;
|
} spiconfig_t;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// strings for keywords
|
|
||||||
extern const char *str_keywords[];
|
|
||||||
#define KEYWORDS \
|
|
||||||
KW(AIN) \
|
|
||||||
KW(IN) \
|
|
||||||
KW(OUT) \
|
|
||||||
KW(AF) \
|
|
||||||
KW(PU)\
|
|
||||||
KW(PD) \
|
|
||||||
KW(FL) \
|
|
||||||
KW(PP) \
|
|
||||||
KW(OD) \
|
|
||||||
KW(USART) \
|
|
||||||
KW(SPI) \
|
|
||||||
KW(I2C) \
|
|
||||||
KW(MONITOR) \
|
|
||||||
KW(THRESHOLD) \
|
|
||||||
KW(SPEED) \
|
|
||||||
KW(TEXT)
|
|
||||||
|
|
||||||
enum{ // indexes of string keywords
|
|
||||||
#define KW(k) STR_ ## k,
|
|
||||||
KEYWORDS
|
|
||||||
#undef KW
|
|
||||||
};
|
|
||||||
|
|
||||||
int is_disabled(uint8_t port, uint8_t pin);
|
int is_disabled(uint8_t port, uint8_t pin);
|
||||||
int chkpinconf();
|
int chkpinconf();
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ extern "C"{
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "gpioproto.h"
|
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "gpioproto.h"
|
#include "gpioproto.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
@@ -36,6 +35,10 @@ extern "C"{
|
|||||||
|
|
||||||
extern volatile uint32_t Tms;
|
extern volatile uint32_t Tms;
|
||||||
|
|
||||||
|
static uint8_t curbuf[MAXSTRLEN]; // buffer for receiving data from USART etc
|
||||||
|
|
||||||
|
static uint8_t usart_text = 0; // ==1 for text USART proto
|
||||||
|
|
||||||
// TODO: add analog threshold!
|
// TODO: add analog threshold!
|
||||||
|
|
||||||
// list of all commands and handlers
|
// list of all commands and handlers
|
||||||
@@ -56,9 +59,8 @@ extern volatile uint32_t Tms;
|
|||||||
COMMAND(setiface, "set/get name of interface x (0 - CAN, 1 - GPIO)") \
|
COMMAND(setiface, "set/get name of interface x (0 - CAN, 1 - GPIO)") \
|
||||||
COMMAND(storeconf, "save config to flash") \
|
COMMAND(storeconf, "save config to flash") \
|
||||||
COMMAND(time, "show current time (ms)") \
|
COMMAND(time, "show current time (ms)") \
|
||||||
COMMAND(vdd, "get approx Vdd value (V*100)")
|
COMMAND(vdd, "get approx Vdd value (V*100)") \
|
||||||
|
COMMAND(USART, "Read USART data or send (USART=hex)")
|
||||||
// COMMAND(USART, "Read USART data or send (USART=hex)")
|
|
||||||
// COMMAND(usartconf, "set USART params (e.g. usartconf=115200 8N1)")
|
// COMMAND(usartconf, "set USART params (e.g. usartconf=115200 8N1)")
|
||||||
// COMMAND(SPI, "Read SPI data or send (SPI=hex)")
|
// COMMAND(SPI, "Read SPI data or send (SPI=hex)")
|
||||||
// COMMAND(spiconf, "set SPI params")
|
// COMMAND(spiconf, "set SPI params")
|
||||||
@@ -99,7 +101,42 @@ enum MiscValues{
|
|||||||
MISC_MONITOR = 1,
|
MISC_MONITOR = 1,
|
||||||
MISC_THRESHOLD,
|
MISC_THRESHOLD,
|
||||||
MISC_SPEED,
|
MISC_SPEED,
|
||||||
MISC_TEXT
|
MISC_TEXT,
|
||||||
|
MISC_BIN
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: add HEX input?
|
||||||
|
|
||||||
|
#define KEYWORDS \
|
||||||
|
KW(AIN) \
|
||||||
|
KW(IN) \
|
||||||
|
KW(OUT) \
|
||||||
|
KW(AF) \
|
||||||
|
KW(PU)\
|
||||||
|
KW(PD) \
|
||||||
|
KW(FL) \
|
||||||
|
KW(PP) \
|
||||||
|
KW(OD) \
|
||||||
|
KW(USART) \
|
||||||
|
KW(SPI) \
|
||||||
|
KW(I2C) \
|
||||||
|
KW(MONITOR) \
|
||||||
|
KW(THRESHOLD) \
|
||||||
|
KW(SPEED) \
|
||||||
|
KW(TEXT) \
|
||||||
|
KW(BIN) \
|
||||||
|
|
||||||
|
enum{ // indexes of string keywords
|
||||||
|
#define KW(k) STR_ ## k,
|
||||||
|
KEYWORDS
|
||||||
|
#undef KW
|
||||||
|
};
|
||||||
|
|
||||||
|
// strings for keywords
|
||||||
|
static const char *str_keywords[] = {
|
||||||
|
#define KW(x) [STR_ ## x] = #x,
|
||||||
|
KEYWORDS
|
||||||
|
#undef KW
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Keyword keywords[] = {
|
static const Keyword keywords[] = {
|
||||||
@@ -120,17 +157,19 @@ static const Keyword keywords[] = {
|
|||||||
KEY(THRESHOLD, GROUP_MISC, MISC_THRESHOLD)
|
KEY(THRESHOLD, GROUP_MISC, MISC_THRESHOLD)
|
||||||
KEY(SPEED, GROUP_MISC, MISC_SPEED)
|
KEY(SPEED, GROUP_MISC, MISC_SPEED)
|
||||||
KEY(TEXT, GROUP_MISC, MISC_TEXT)
|
KEY(TEXT, GROUP_MISC, MISC_TEXT)
|
||||||
|
KEY(BIN, GROUP_MISC, MISC_BIN)
|
||||||
#undef K
|
#undef K
|
||||||
};
|
};
|
||||||
#define NUM_KEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
|
#define NUM_KEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
|
||||||
|
|
||||||
static const char* errtxt[ERR_AMOUNT] = {
|
static const char* errtxt[ERR_AMOUNT] = {
|
||||||
[ERR_OK] = "OK",
|
[ERR_OK] = "OK",
|
||||||
[ERR_BADCMD] = "BADCMD",
|
[ERR_BADCMD] = "BADCMD",
|
||||||
[ERR_BADPAR] = "BADPAR",
|
[ERR_BADPAR] = "BADPAR",
|
||||||
[ERR_BADVAL] = "BADVAL",
|
[ERR_BADVAL] = "BADVAL",
|
||||||
[ERR_WRONGLEN] = "WRONGLEN",
|
[ERR_WRONGLEN] = "WRONGLEN",
|
||||||
[ERR_CANTRUN] = "CANTRUN",
|
[ERR_CANTRUN] = "CANTRUN",
|
||||||
|
[ERR_BUSY] = "BUSY",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *pinhelp =
|
static const char *pinhelp =
|
||||||
@@ -141,6 +180,9 @@ static const char *pinhelp =
|
|||||||
" FUNC: USART or SPI (enable alternate function and configure peripheal)\n"
|
" FUNC: USART or SPI (enable alternate function and configure peripheal)\n"
|
||||||
" MISC: MONITOR - send data by USB as only state changed\n"
|
" MISC: MONITOR - send data by USB as only state changed\n"
|
||||||
" THRESHOLD (ADC only) - monitoring threshold, ADU\n"
|
" THRESHOLD (ADC only) - monitoring threshold, ADU\n"
|
||||||
|
" SPEED - interface speed/frequency\n"
|
||||||
|
" TEXT - USART means data as text ('\n'-separated strings)\n"
|
||||||
|
" BIN - USART means data as binary (output: HEX)\n"
|
||||||
"\n"
|
"\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -197,7 +239,10 @@ static bool argsvals(char *args, int32_t *parno, int32_t *parval){
|
|||||||
// `PAx = ` also printed there
|
// `PAx = ` also printed there
|
||||||
static void pin_getter(uint8_t port, uint8_t pin){
|
static void pin_getter(uint8_t port, uint8_t pin){
|
||||||
int16_t val = pin_in(port, pin);
|
int16_t val = pin_in(port, pin);
|
||||||
if(val < 0) SENDn(errtxt[ERR_CANTRUN]);
|
if(val < 0){
|
||||||
|
SENDn(errtxt[ERR_CANTRUN]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
SEND(port == 0 ? "PA" : "PB"); SEND(u2str((uint32_t)pin)); SEND(EQ);
|
SEND(port == 0 ? "PA" : "PB"); SEND(u2str((uint32_t)pin)); SEND(EQ);
|
||||||
SENDn(u2str((uint32_t)val));
|
SENDn(u2str((uint32_t)val));
|
||||||
}
|
}
|
||||||
@@ -284,6 +329,9 @@ static errcodes_t pin_setter(uint8_t port, uint8_t pin, char *setter){
|
|||||||
case MISC_TEXT: // what to do, if textproto is set, but user wants binary?
|
case MISC_TEXT: // what to do, if textproto is set, but user wants binary?
|
||||||
UsartConf.textproto = 1;
|
UsartConf.textproto = 1;
|
||||||
break;
|
break;
|
||||||
|
case MISC_BIN: // clear text flag
|
||||||
|
UsartConf.textproto = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -342,7 +390,13 @@ static errcodes_t cmd_PB(const char *cmd, char *args){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static errcodes_t cmd_reinit(const char _U_ *cmd, char _U_ *args){
|
static errcodes_t cmd_reinit(const char _U_ *cmd, char _U_ *args){
|
||||||
if(gpio_reinit()) return ERR_OK;
|
if(gpio_reinit()){
|
||||||
|
usartconf_t UC;
|
||||||
|
if(get_curusartconf(&UC)){
|
||||||
|
usart_text = UC.textproto;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
SEND("Can't reinit: check your configuration!\n");
|
SEND("Can't reinit: check your configuration!\n");
|
||||||
return ERR_AMOUNT;
|
return ERR_AMOUNT;
|
||||||
}
|
}
|
||||||
@@ -573,6 +627,44 @@ static errcodes_t cmd_help(const char _U_ *cmd, char _U_ *args){
|
|||||||
return ERR_AMOUNT;
|
return ERR_AMOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sendfun(const char *s){
|
||||||
|
if(!s) return 0;
|
||||||
|
return USB_sendstr(IGPIO, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sendusartdata(const uint8_t *buf, int len){
|
||||||
|
if(!buf || len < 1) return;
|
||||||
|
SEND(str_keywords[STR_USART]); SEND(EQ);
|
||||||
|
if(usart_text){
|
||||||
|
USB_send(IGPIO, curbuf, len);
|
||||||
|
if(curbuf[len-1] != '\n') NL();
|
||||||
|
}else{
|
||||||
|
NL();
|
||||||
|
hexdump(sendfun, (uint8_t*)curbuf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcodes_t cmd_USART(const char _U_ *cmd, char *args){
|
||||||
|
if(!args) return ERR_BADVAL;
|
||||||
|
char *setter = splitargs(args, NULL);
|
||||||
|
if(setter){
|
||||||
|
DBG("Try to send over USART\n");
|
||||||
|
int l = strlen(setter);
|
||||||
|
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;
|
||||||
|
} // getter: try to read
|
||||||
|
int l = usart_receive(curbuf, MAXSTRLEN);
|
||||||
|
if(l < 0) return ERR_CANTRUN;
|
||||||
|
if(l > 0) sendusartdata(curbuf, l);
|
||||||
|
// or silence: nothing to read
|
||||||
|
return ERR_AMOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr uint32_t hash(const char* str, uint32_t h = 0){
|
constexpr uint32_t hash(const char* str, uint32_t h = 0){
|
||||||
return *str ? hash(str + 1, h + ((h << 7) ^ *str)) : h;
|
return *str ? hash(str + 1, h + ((h << 7) ^ *str)) : h;
|
||||||
}
|
}
|
||||||
@@ -599,9 +691,8 @@ static const char *CommandParser(char *str){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GPIO_process(){
|
void GPIO_process(){
|
||||||
char inbuff[MAXSTRLEN];
|
int l;
|
||||||
int l = RECV(inbuff, MAXSTRLEN);
|
// TODO: check SPI/I2C etc
|
||||||
// TODO: check SPI/USART/I2C
|
|
||||||
for(uint8_t port = 0; port < 2; ++port){
|
for(uint8_t port = 0; port < 2; ++port){
|
||||||
uint16_t alert = gpio_alert(port);
|
uint16_t alert = gpio_alert(port);
|
||||||
if(alert == 0) continue;
|
if(alert == 0) continue;
|
||||||
@@ -610,11 +701,13 @@ void GPIO_process(){
|
|||||||
if(alert & pinmask) pin_getter(port, i);
|
if(alert & pinmask) pin_getter(port, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
usart_process(NULL, 0);
|
l = usart_process(curbuf, MAXSTRLEN);
|
||||||
|
if(l > 0) sendusartdata(curbuf, l);
|
||||||
|
l = RECV((char*)curbuf, MAXSTRLEN);
|
||||||
if(l == 0) return;
|
if(l == 0) return;
|
||||||
if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n");
|
if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n");
|
||||||
else{
|
else{
|
||||||
const char *ans = CommandParser(inbuff);
|
const char *ans = CommandParser((char*)curbuf);
|
||||||
if(ans) SENDn(ans);
|
if(ans) SENDn(ans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ typedef enum{
|
|||||||
ERR_BADVAL, // wrong value (for setter)
|
ERR_BADVAL, // wrong value (for setter)
|
||||||
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_AMOUNT // amount of error codes or "send nothing"
|
ERR_AMOUNT // amount of error codes or "send nothing"
|
||||||
} errcodes_t;
|
} errcodes_t;
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ TRUE_INLINE void gpio_setup(){ // setup some common GPIO
|
|||||||
|
|
||||||
void hardware_setup(){
|
void hardware_setup(){
|
||||||
// enable all active GPIO clocking
|
// enable all active GPIO clocking
|
||||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_DMA1EN;
|
||||||
RCC->APB1ENR |= RCC_APB2ENR_USART1EN;
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGEN;
|
||||||
RCC->APB2ENR |= RCC_APB1ENR_USART2EN;
|
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
||||||
gpio_setup();
|
gpio_setup();
|
||||||
//gpio_reinit();
|
//gpio_reinit();
|
||||||
adc_setup();
|
adc_setup();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ void sys_tick_handler(void){
|
|||||||
int main(void){
|
int main(void){
|
||||||
sysreset();
|
sysreset();
|
||||||
SysTick_Config(6000, 1);
|
SysTick_Config(6000, 1);
|
||||||
|
StartHSE();
|
||||||
flashstorage_init();
|
flashstorage_init();
|
||||||
hardware_setup();
|
hardware_setup();
|
||||||
USB_setup();
|
USB_setup();
|
||||||
|
|||||||
@@ -32,8 +32,8 @@
|
|||||||
static uint8_t inbuffer[DMARXBUFSZ]; // DMA in buffer
|
static uint8_t inbuffer[DMARXBUFSZ]; // DMA in buffer
|
||||||
static uint8_t rbbuffer[RXRBSZ]; // for in ringbuffer
|
static uint8_t rbbuffer[RXRBSZ]; // for in ringbuffer
|
||||||
static uint8_t outbuffer[DMATXBUFSZ]; // DMA out buffer
|
static uint8_t outbuffer[DMATXBUFSZ]; // DMA out buffer
|
||||||
static uint8_t TXrdy = 1; // TX DMA ready
|
static volatile uint8_t TXrdy = 1; // TX DMA ready
|
||||||
static uint8_t RXrdy = 0; // == 1 when got IDLE or '\n' (only when `monitoring` is on
|
static volatile uint8_t RXrdy = 0; // == 1 when got IDLE or '\n' (only when `monitoring` is on
|
||||||
static uint8_t textformat = 0; // out by '\n'-terminated lines
|
static uint8_t textformat = 0; // out by '\n'-terminated lines
|
||||||
static uint8_t monitor = 0; // monitor USART rx
|
static uint8_t monitor = 0; // monitor USART rx
|
||||||
static int dma_read_idx = 0; // start of data in DMA inbuffers
|
static int dma_read_idx = 0; // start of data in DMA inbuffers
|
||||||
@@ -108,18 +108,19 @@ int usart_config(usartconf_t *uc){
|
|||||||
// Assuming oversampling by 16 (default after reset). For higher baud rates you might use by 8.
|
// Assuming oversampling by 16 (default after reset). For higher baud rates you might use by 8.
|
||||||
U->BRR = peripheral_clock / (usartconfig.speed);
|
U->BRR = peripheral_clock / (usartconfig.speed);
|
||||||
usartconfig.speed= peripheral_clock / U->BRR; // fix for real speed
|
usartconfig.speed= peripheral_clock / U->BRR; // fix for real speed
|
||||||
uint32_t cr1 = 0;
|
uint32_t cr1 = 0, cr3 = 0;
|
||||||
// format: 8N1, so CR2 used only for character match (if need)
|
|
||||||
if(usartconfig.monitor){
|
|
||||||
if(usartconfig.textproto){
|
|
||||||
U->CR2 = USART_CR2_ADD_VAL('\n');
|
|
||||||
cr1 |= USART_CR1_CMIE;
|
|
||||||
}else cr1 |= USART_CR1_IDLEIE; // monitor binary data by IDLE flag
|
|
||||||
}
|
|
||||||
textformat = usartconfig.textproto;
|
textformat = usartconfig.textproto;
|
||||||
monitor = usartconfig.monitor;
|
monitor = usartconfig.monitor;
|
||||||
// Enable transmitter, receiver, and interrupts (optional)
|
// Enable transmitter, receiver, and interrupts (optional)
|
||||||
if(usartconfig.RXen) cr1 |= USART_CR1_RE;
|
if(usartconfig.RXen){
|
||||||
|
cr1 |= USART_CR1_RE;
|
||||||
|
cr3 |= USART_CR3_DMAR;
|
||||||
|
// format: 8N1, so CR2 used only for character match (if need)
|
||||||
|
if(usartconfig.textproto){
|
||||||
|
U->CR2 = USART_CR2_ADD_VAL('\n'); // buffer text data by EOL
|
||||||
|
cr1 |= USART_CR1_CMIE;
|
||||||
|
}else cr1 |= USART_CR1_IDLEIE; // buffer binary data by IDLE flag
|
||||||
|
}
|
||||||
if(usartconfig.TXen){
|
if(usartconfig.TXen){
|
||||||
cr1 |= USART_CR1_TE;
|
cr1 |= USART_CR1_TE;
|
||||||
// DMA Tx
|
// DMA Tx
|
||||||
@@ -127,9 +128,11 @@ int usart_config(usartconf_t *uc){
|
|||||||
T->CCR = 0;
|
T->CCR = 0;
|
||||||
T->CPAR = (uint32_t) &U->TDR;
|
T->CPAR = (uint32_t) &U->TDR;
|
||||||
T->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;
|
T->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE;
|
||||||
|
cr3 |= USART_CR3_DMAT;
|
||||||
}
|
}
|
||||||
// Main config
|
// Main config
|
||||||
U->CR1 = cr1;
|
U->CR1 = cr1;
|
||||||
|
U->CR3 = cr3;
|
||||||
curUSARTidx = No;
|
curUSARTidx = No;
|
||||||
// all OK -> copy to global config
|
// all OK -> copy to global config
|
||||||
the_conf.usartconfig = usartconfig;
|
the_conf.usartconfig = usartconfig;
|
||||||
@@ -140,26 +143,21 @@ int usart_config(usartconf_t *uc){
|
|||||||
int usart_start(){
|
int usart_start(){
|
||||||
if(curUSARTidx == -1) return FALSE;
|
if(curUSARTidx == -1) return FALSE;
|
||||||
volatile USART_TypeDef *U = Usarts[curUSARTidx];
|
volatile USART_TypeDef *U = Usarts[curUSARTidx];
|
||||||
if(monitor) NVIC_EnableIRQ(UIRQs[curUSARTidx]);
|
NVIC_EnableIRQ(UIRQs[curUSARTidx]); // copy to ring buffer after each '\n' in text mode or IDLE in binary
|
||||||
NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
|
NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
|
||||||
// reset Rx DMA
|
// reset Rx DMA
|
||||||
if(U->CR1 & USART_CR1_RE){
|
if(U->CR1 & USART_CR1_RE){
|
||||||
volatile DMA_Channel_TypeDef *R = DMA1_Channel5;
|
volatile DMA_Channel_TypeDef *R = DMA1_Channel5;
|
||||||
dma_read_idx = 0;
|
dma_read_idx = 0;
|
||||||
R->CCR = 0;
|
R->CCR = 0;
|
||||||
R->CPAR = (uint32_t) U->RDR;
|
RB_clearbuf(&RBin);
|
||||||
|
R->CPAR = (uint32_t) &U->RDR;
|
||||||
R->CMAR = (uint32_t) inbuffer;
|
R->CMAR = (uint32_t) inbuffer;
|
||||||
R->CNDTR = DMARXBUFSZ;
|
R->CNDTR = DMARXBUFSZ;
|
||||||
R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN;
|
R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN;
|
||||||
RB_clearbuf(&RBin);
|
|
||||||
}
|
}
|
||||||
U->CR1 |= USART_CR1_UE; // enable USARTx
|
U->CR1 |= USART_CR1_UE; // enable USARTx
|
||||||
U->ICR = 0xFFFFFFFF; // Clear flags
|
U->ICR = 0xFFFFFFFF; // Clear flags
|
||||||
// Wait for the idle frame to complete (optional)
|
|
||||||
uint32_t tmout = 16000000;
|
|
||||||
while(!(U->ISR & USART_ISR_TC)){
|
|
||||||
if (--tmout == 0) break;
|
|
||||||
}
|
|
||||||
TXrdy = 1;
|
TXrdy = 1;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -208,33 +206,36 @@ int usart_process(uint8_t *buf, int len){
|
|||||||
if(curUSARTidx == -1 || !(Usarts[curUSARTidx]->CR1 & USART_CR1_UE)) return -1; // none activated or started
|
if(curUSARTidx == -1 || !(Usarts[curUSARTidx]->CR1 & USART_CR1_UE)) return -1; // none activated or started
|
||||||
int ret = 0; // returned value
|
int ret = 0; // returned value
|
||||||
// Input data
|
// Input data
|
||||||
int write_idx = DMARXBUFSZ - DMA1_Channel5->CNDTR; // next symbol to be written
|
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
|
int available = (write_idx - dma_read_idx); // length of data available
|
||||||
|
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 < 0) available += DMARXBUFSZ; // write to the left of read
|
||||||
if(available){
|
if(available){
|
||||||
if(RXrdy){
|
if(locmonitor){
|
||||||
if(buf && len > 0){
|
if(buf && len > 0){
|
||||||
if(len < available) available = len;
|
if(len < monitored_len) monitored_len = len;
|
||||||
}else RXrdy = 0;
|
}else locmonitor = 0;
|
||||||
}
|
}
|
||||||
// TODO: force copying data to "async" buffer in case of overflow danger
|
// TODO: force copying data to "async" buffer in case of overflow danger
|
||||||
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;
|
||||||
if(dma_read_idx + available <= DMARXBUFSZ){ // head before tail
|
if(dma_read_idx + available <= DMARXBUFSZ){ // head before tail
|
||||||
if(RXrdy){
|
if(locmonitor){
|
||||||
memcpy(buf, &inbuffer[dma_read_idx], available);
|
memcpy(buf, &inbuffer[dma_read_idx], monitored_len);
|
||||||
ret = available;
|
ret = monitored_len;
|
||||||
wrOK = TRUE;
|
wrOK = TRUE;
|
||||||
}else{
|
}else{
|
||||||
if(available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE;
|
if(available == RB_write(&RBin, &inbuffer[dma_read_idx], available)) wrOK = TRUE;
|
||||||
}
|
}
|
||||||
}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(RXrdy){
|
if(locmonitor){
|
||||||
memcpy(buf, &inbuffer[dma_read_idx], first);
|
memcpy(buf, &inbuffer[dma_read_idx], first);
|
||||||
memcpy(buf, inbuffer, available - first);
|
memcpy(buf, inbuffer, monitored_len - first);
|
||||||
ret = available;
|
ret = monitored_len;
|
||||||
wrOK = TRUE;
|
wrOK = TRUE;
|
||||||
}else{
|
}else{
|
||||||
if((first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) &&
|
if((first == RB_write(&RBin, &inbuffer[dma_read_idx], first)) &&
|
||||||
@@ -297,9 +298,9 @@ static void usart_isr(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dma1_channel4_5_isr(){ // TX ready, channel5
|
void dma1_channel4_5_isr(){ // TX ready, channel5
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF5){
|
if(DMA1->ISR & DMA_ISR_TCIF4){
|
||||||
TXrdy = 1;
|
TXrdy = 1;
|
||||||
DMA1->IFCR = DMA_IFCR_CTCIF5;
|
DMA1->IFCR = DMA_IFCR_CTCIF4;
|
||||||
DMA1_Channel4->CCR &= ~DMA_CCR_EN; // disable DMA channel until next send
|
DMA1_Channel4->CCR &= ~DMA_CCR_EN; // disable DMA channel until next send
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 18.0.2, 2026-03-13T00:12:36. -->
|
<!-- Written by QtCreator 18.0.2, 2026-03-14T01:13:52. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "156"
|
#define BUILD_NUMBER "173"
|
||||||
#define BUILD_DATE "2026-03-12"
|
#define BUILD_DATE "2026-03-14"
|
||||||
|
|||||||
Reference in New Issue
Block a user