mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-02-28 03:44:30 +03:00
partial work for interrupt-driven
This commit is contained in:
@@ -32,6 +32,7 @@ void sys_tick_handler(void){
|
|||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
char inbuff[MAXSTRLEN+1];
|
char inbuff[MAXSTRLEN+1];
|
||||||
|
uint8_t oldcdc[InterfacesAmount] = {0};
|
||||||
if(StartHSE()){
|
if(StartHSE()){
|
||||||
SysTick_Config((uint32_t)72000); // 1ms
|
SysTick_Config((uint32_t)72000); // 1ms
|
||||||
}else{
|
}else{
|
||||||
@@ -43,26 +44,37 @@ int main(void){
|
|||||||
USBPU_OFF();
|
USBPU_OFF();
|
||||||
USB_setup();
|
USB_setup();
|
||||||
//uint32_t ctr = Tms;
|
//uint32_t ctr = Tms;
|
||||||
|
//usb_LineCoding lc = {9600, 0, 0, 8};
|
||||||
|
//for(int i = 0; i < 5; ++i) usart_config(i, &lc);
|
||||||
USBPU_ON();
|
USBPU_ON();
|
||||||
int maxno = (Config_mode) ? ICFG : InterfacesAmount;
|
|
||||||
while(1){
|
while(1){
|
||||||
// Put here code working WITOUT USB connected
|
// Put here code working WITOUT USB connected
|
||||||
if(!usbON) continue;
|
if(!usbON) continue;
|
||||||
usarts_process(); //
|
usarts_process();
|
||||||
for(int i = 0; i < maxno; ++i){ // just echo for first time
|
/*for(int i = 0; i < 6; ++i){ // just echo for first time
|
||||||
if(!CDCready[i]) continue;
|
if(!CDCready[i]) continue;
|
||||||
int l = USB_receive(i, (uint8_t*)inbuff, MAXSTRLEN);
|
int l = USB_receive(i, (uint8_t*)inbuff, MAXSTRLEN);
|
||||||
if(l) USB_send(i, (uint8_t*)inbuff, l);
|
if(l) USB_send(i, (uint8_t*)inbuff, l);
|
||||||
}
|
}*/
|
||||||
// and here is code what should run when USB connected
|
// and here is code what should run when USB connected
|
||||||
if(Config_mode && CDCready[ICFG]){
|
if(Config_mode && CDCready[ICFG]){
|
||||||
/*if(Tms - ctr > 999){
|
/*if(Tms - ctr > 4999){
|
||||||
ctr = Tms;
|
ctr = Tms;
|
||||||
CFGWR("I'm alive\n");
|
CFGWR("I'm alive\n");
|
||||||
}*/
|
}*/
|
||||||
|
for(int i = 0; i < ICFG; ++i){
|
||||||
|
if(oldcdc[i] != CDCready[i]){
|
||||||
|
CFGWR("Interface "); USB_putbyte(ICFG, '1' + i);
|
||||||
|
USB_putbyte(ICFG, ' ');
|
||||||
|
if(!CDCready[i]) CFGWR("dis");
|
||||||
|
CFGWR("connected\n");
|
||||||
|
oldcdc[i] = CDCready[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
int l = USB_receivestr(ICFG, inbuff, MAXSTRLEN);
|
int l = USB_receivestr(ICFG, inbuff, MAXSTRLEN);
|
||||||
if(l < 0) CFGWR("ERROR: USB buffer overflow or string was too long\n");
|
if(l < 0) CFGWR("ERROR: USB buffer overflow or string was too long\n");
|
||||||
else if(l){
|
else if(l){
|
||||||
|
CFGWR("PARSING...\n");
|
||||||
const char *ans = parse_cmd(inbuff);
|
const char *ans = parse_cmd(inbuff);
|
||||||
if(ans) CFGWRn(ans);
|
if(ans) CFGWRn(ans);
|
||||||
}
|
}
|
||||||
|
|||||||
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-02-14T00:56:14. -->
|
<!-- Written by QtCreator 18.0.2, 2026-02-15T23:30:45. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "strfunc.h"
|
#include "strfunc.h"
|
||||||
|
#include "usart.h"
|
||||||
#include "usb_dev.h"
|
#include "usb_dev.h"
|
||||||
#include "version.inc"
|
#include "version.inc"
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ extern volatile uint32_t Tms;
|
|||||||
|
|
||||||
const char *helpstring =
|
const char *helpstring =
|
||||||
"https://github.com/eddyem/stm32samples/tree/master/F3:F303/InterfaceBoard build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
"https://github.com/eddyem/stm32samples/tree/master/F3:F303/InterfaceBoard build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
||||||
|
"1..5x - send data over IF1..5\n"
|
||||||
"d - dump flash\n"
|
"d - dump flash\n"
|
||||||
"ix - rename interface number x (0..6)\n"
|
"ix - rename interface number x (0..6)\n"
|
||||||
"Ex - erase full storage (witout x) or only page x\n"
|
"Ex - erase full storage (witout x) or only page x\n"
|
||||||
@@ -90,11 +92,23 @@ static const char* erpg(const char *str){
|
|||||||
return sOKn;
|
return sOKn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *parse_cmd(const char *buf){
|
static void sendoverU(uint8_t ifno, char *str){
|
||||||
|
int len = strlen(str);
|
||||||
|
CFGWR("try to send "); CFGWRn(str);
|
||||||
|
str[len] = '\n';
|
||||||
|
len = usart_send(ifno, (const uint8_t*)str, len+1);
|
||||||
|
CFGWR("sent "); CFGWR(i2str(len)); CFGWR("bytes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *parse_cmd(char *buf){
|
||||||
if(!buf || !*buf) return NULL;
|
if(!buf || !*buf) return NULL;
|
||||||
if(strlen(buf) > 1){
|
if(strlen(buf) > 1){
|
||||||
// "long" commands
|
// "long" commands
|
||||||
char c = *buf++;
|
char c = *buf++;
|
||||||
|
if(c > '0' && c < '6'){
|
||||||
|
sendoverU(c - '1', buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
switch(c){
|
switch(c){
|
||||||
case 'E':
|
case 'E':
|
||||||
return erpg(buf);
|
return erpg(buf);
|
||||||
|
|||||||
@@ -32,12 +32,12 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
volatile USART_TypeDef *instance; // U[S]ARTx
|
volatile USART_TypeDef *instance; // U[S]ARTx
|
||||||
uint32_t pclk_freq; // APB1/APB2 frequency
|
uint32_t pclk_freq; // APB1/APB2 frequency
|
||||||
int16_t IRQn; // IRQ number for enable/disable (maybe 0 for DMA-driven channels)
|
int16_t UIRQn; // USART IRQ number
|
||||||
|
int16_t DIRQn; // DMA Tx IRQ number (for DMA-driven)
|
||||||
volatile DMA_TypeDef *dma_controller; // DMA1/DMA2 or NULL if not used
|
volatile DMA_TypeDef *dma_controller; // DMA1/DMA2 or NULL if not used
|
||||||
volatile DMA_Channel_TypeDef *dma_rx_channel; // e.g., DMA_Channel_5 or NULL if not used
|
volatile DMA_Channel_TypeDef *dma_rx_channel; // e.g., DMA_Channel_5 or NULL if not used
|
||||||
volatile DMA_Channel_TypeDef *dma_tx_channel; // e.g., DMA_Channel_4 or NULL if not used
|
volatile DMA_Channel_TypeDef *dma_tx_channel; // e.g., DMA_Channel_4 or NULL if not used
|
||||||
uint32_t TTCflag; // Tx transfer complete flag
|
uint32_t TTCflag; // Tx transfer complete flag
|
||||||
uint32_t RTCflag; // Rx transfer complete flag
|
|
||||||
volatile GPIO_TypeDef *DEport; // if RS485 - DE GPIO port (NULL for RS-232 or RS-422)
|
volatile GPIO_TypeDef *DEport; // if RS485 - DE GPIO port (NULL for RS-232 or RS-422)
|
||||||
uint32_t DEpin; // -//- pin
|
uint32_t DEpin; // -//- pin
|
||||||
} USART_Config;
|
} USART_Config;
|
||||||
@@ -52,11 +52,11 @@ typedef struct {
|
|||||||
// IF6[5]: (CAN)
|
// IF6[5]: (CAN)
|
||||||
// IF7[6]: (SPI)
|
// IF7[6]: (SPI)
|
||||||
static const USART_Config UC[USARTSNO] = {
|
static const USART_Config UC[USARTSNO] = {
|
||||||
[0] = {.instance = USART3, .pclk_freq = 72000000, USART3_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel3, .dma_tx_channel = DMA1_Channel2, .TTCflag = DMA_ISR_TCIF3, .RTCflag = DMA_ISR_TCIF3, .DEport = GPIOB, .DEpin = 1<<14 },
|
[0] = {.instance = USART3, .pclk_freq = 36000000, .UIRQn = USART3_IRQn, .DIRQn = DMA1_Channel2_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel3, .dma_tx_channel = DMA1_Channel2, .TTCflag = DMA_ISR_TCIF2, .DEport = GPIOB, .DEpin = 1<<14 },
|
||||||
[1] = {.instance = USART1, .pclk_freq = 36000000, USART1_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel5, .dma_tx_channel = DMA1_Channel4, .TTCflag = DMA_ISR_TCIF5, .RTCflag = DMA_ISR_TCIF4, .DEport = GPIOB, .DEpin = 1<<0 },
|
[1] = {.instance = USART1, .pclk_freq = 72000000, .UIRQn = USART1_IRQn, .DIRQn = DMA1_Channel4_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel5, .dma_tx_channel = DMA1_Channel4, .TTCflag = DMA_ISR_TCIF4, .DEport = GPIOB, .DEpin = 1<<0 },
|
||||||
[2] = {.instance = USART2, .pclk_freq = 72000000, USART2_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel6, .dma_tx_channel = DMA1_Channel7, .TTCflag = DMA_ISR_TCIF6, .RTCflag = DMA_ISR_TCIF7, .DEport = GPIOB, .DEpin = 1<<1 },
|
[2] = {.instance = USART2, .pclk_freq = 36000000, .UIRQn = USART2_IRQn, .DIRQn = DMA1_Channel7_IRQn, .dma_controller = DMA1, .dma_rx_channel = DMA1_Channel6, .dma_tx_channel = DMA1_Channel7, .TTCflag = DMA_ISR_TCIF7, .DEport = GPIOB, .DEpin = 1<<1 },
|
||||||
[3] = {.instance = UART4, .pclk_freq = 72000000, UART4_IRQn, .dma_controller = DMA2, .dma_rx_channel = DMA2_Channel3, .dma_tx_channel = DMA2_Channel5, .TTCflag = DMA_ISR_TCIF3, .RTCflag = DMA_ISR_TCIF5 },
|
[3] = {.instance = UART4, .pclk_freq = 36000000, .UIRQn = UART4_IRQn, .DIRQn = DMA2_Channel5_IRQn, .dma_controller = DMA2, .dma_rx_channel = DMA2_Channel3, .dma_tx_channel = DMA2_Channel5, .TTCflag = DMA_ISR_TCIF5 },
|
||||||
[4] = {.instance = UART5, .pclk_freq = 72000000, UART5_IRQn }, // no DMA
|
[4] = {.instance = UART5, .pclk_freq = 36000000, .UIRQn = UART5_IRQn }, // no DMA
|
||||||
};
|
};
|
||||||
|
|
||||||
// buffers for DMA or interrupt-driven data management
|
// buffers for DMA or interrupt-driven data management
|
||||||
@@ -66,13 +66,13 @@ static uint8_t outbuffers[USARTSNO][DMATXBUFSZ];
|
|||||||
static uint16_t outbufidx[USARTSNO] = {0}; // index of next char to transmit over interrupt
|
static uint16_t outbufidx[USARTSNO] = {0}; // index of next char to transmit over interrupt
|
||||||
static uint16_t outbuflen[USARTSNO] = {0}; // length of data to transmit over interrupt [equal 0 if nothing to send]
|
static uint16_t outbuflen[USARTSNO] = {0}; // length of data to transmit over interrupt [equal 0 if nothing to send]
|
||||||
static uint8_t need2send[USARTSNO] = {0}; // flags from IDLE interrupt to send data portion
|
static uint8_t need2send[USARTSNO] = {0}; // flags from IDLE interrupt to send data portion
|
||||||
|
static uint8_t TXrdy[USARTSNO] = {1,1,1,1,1}; // TX DMA ready
|
||||||
// there's no way to tell recipient about overfull, so we will just "eat" spare data!
|
// there's no way to tell recipient about overfull, so we will just "eat" spare data!
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usart_config - configure US[A]RT based on usb_LineCoding
|
* @brief usart_config - configure US[A]RT based on usb_LineCoding
|
||||||
* @param ifNo - interface index [0..6]
|
* @param ifNo - interface index [0..4]
|
||||||
* @param lc (io) - linecoding (modified to real speeds)
|
* @param lc (io) - linecoding (modified to real speeds)
|
||||||
*/
|
*/
|
||||||
void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
||||||
@@ -148,7 +148,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
|||||||
// Write CR2 (stop bits)
|
// Write CR2 (stop bits)
|
||||||
U->CR2 = cr2;
|
U->CR2 = cr2;
|
||||||
// Enable transmitter, receiver, and interrupts (optional)
|
// Enable transmitter, receiver, and interrupts (optional)
|
||||||
cr1 |= USART_CR1_RE | USART_CR1_UE;
|
cr1 |= USART_CR1_RE;
|
||||||
if(cfg->DEport){
|
if(cfg->DEport){
|
||||||
RX485(cfg->DEport, cfg->DEpin);
|
RX485(cfg->DEport, cfg->DEpin);
|
||||||
cr1 |= USART_CR1_TCIE;
|
cr1 |= USART_CR1_TCIE;
|
||||||
@@ -160,7 +160,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
|||||||
// Tx DMA
|
// Tx DMA
|
||||||
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;
|
||||||
// Rx DMA
|
// Rx DMA
|
||||||
R->CCR = 0;
|
R->CCR = 0;
|
||||||
R->CPAR = (uint32_t) &U->RDR;
|
R->CPAR = (uint32_t) &U->RDR;
|
||||||
@@ -171,10 +171,9 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
|||||||
U->CR3 = USART_CR3_DMAT | USART_CR3_DMAR;
|
U->CR3 = USART_CR3_DMAT | USART_CR3_DMAR;
|
||||||
cr1 |= USART_CR1_IDLEIE; // enable idle interrupt to force small portions of data into ringbuffer
|
cr1 |= USART_CR1_IDLEIE; // enable idle interrupt to force small portions of data into ringbuffer
|
||||||
}else{
|
}else{
|
||||||
cr1 |= USART_CR1_RXNEIE | USART_CR1_TXEIE; // interrupt-driven
|
cr1 |= USART_CR1_RXNEIE; // interrupt-driven
|
||||||
inbufidx[ifNo] = 0;
|
inbufidx[ifNo] = 0;
|
||||||
outbufidx[ifNo] = 0;
|
outbufidx[ifNo] = 0;
|
||||||
NVIC_EnableIRQ(cfg->IRQn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
U->CR1 = cr1;
|
U->CR1 = cr1;
|
||||||
@@ -186,6 +185,15 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){
|
|||||||
U->ICR = 0xFFFFFFFF; // Clear flags again
|
U->ICR = 0xFFFFFFFF; // Clear flags again
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start when received DTR
|
||||||
|
void usart_start(uint8_t ifNo){
|
||||||
|
if(ifNo >= USARTSNO || UC[ifNo].instance == NULL) return;
|
||||||
|
const USART_Config *cfg = &UC[ifNo];
|
||||||
|
cfg->instance->CR1 |= USART_CR1_UE;
|
||||||
|
NVIC_EnableIRQ(cfg->UIRQn);
|
||||||
|
if(cfg->dma_controller) NVIC_EnableIRQ(cfg->DIRQn);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usart_stop - turn off U[S]ART for given interface
|
* @brief usart_stop - turn off U[S]ART for given interface
|
||||||
* @param ifNo - interface number
|
* @param ifNo - interface number
|
||||||
@@ -198,11 +206,18 @@ void usart_stop(uint8_t ifNo){
|
|||||||
if(cfg->dma_controller){
|
if(cfg->dma_controller){
|
||||||
cfg->dma_tx_channel->CCR = 0;
|
cfg->dma_tx_channel->CCR = 0;
|
||||||
cfg->dma_rx_channel->CCR = 0;
|
cfg->dma_rx_channel->CCR = 0;
|
||||||
|
NVIC_DisableIRQ(cfg->DIRQn);
|
||||||
}else{
|
}else{
|
||||||
NVIC_DisableIRQ(cfg->IRQn);
|
NVIC_DisableIRQ(cfg->UIRQn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msg(const char *txt, uint8_t ifno, int l){
|
||||||
|
if(!Config_mode) return;
|
||||||
|
CFGWR("IF"); USB_putbyte(ICFG, '1' + ifno); CFGWR(": ");
|
||||||
|
CFGWR(txt); CFGWR(" ("); CFGWR(i2str(l)); CFGWR(" bytes)\n");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usarts_process - send/receive processing
|
* @brief usarts_process - send/receive processing
|
||||||
* Try to send data from output ringbuffer, check input DMA buffer and full input ringbuffer
|
* Try to send data from output ringbuffer, check input DMA buffer and full input ringbuffer
|
||||||
@@ -219,6 +234,7 @@ void usarts_process(){
|
|||||||
register int l = DMARXBUFSZ - R->CNDTR;
|
register int l = DMARXBUFSZ - R->CNDTR;
|
||||||
if(l){ // have some input data -> send and restart DMA
|
if(l){ // have some input data -> send and restart DMA
|
||||||
if(USB_send(i, inbuffers[i], l)){
|
if(USB_send(i, inbuffers[i], l)){
|
||||||
|
msg("USART -> USB over DMA", i, l);
|
||||||
// restart DMA only in case of succesfull sent or if failed, but have ability of buffer overfull
|
// restart DMA only in case of succesfull sent or if failed, but have ability of buffer overfull
|
||||||
R->CMAR = (uint32_t) inbuffers[i];
|
R->CMAR = (uint32_t) inbuffers[i];
|
||||||
R->CNDTR = DMARXBUFSZ;
|
R->CNDTR = DMARXBUFSZ;
|
||||||
@@ -229,11 +245,11 @@ void usarts_process(){
|
|||||||
R->CCR |= DMA_CCR_EN; // re-enable DMA
|
R->CCR |= DMA_CCR_EN; // re-enable DMA
|
||||||
}
|
}
|
||||||
// Output data
|
// Output data
|
||||||
if(cfg->dma_controller->ISR & cfg->RTCflag){ // ready to send new data
|
if(TXrdy[i]){ // ready to send new data
|
||||||
int got = USB_receive(i, outbuffers[i], DMATXBUFSZ);
|
int got = USB_receive(i, outbuffers[i], DMATXBUFSZ);
|
||||||
if(got > 0){ // send next data portion
|
if(got > 0){ // send next data portion
|
||||||
volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel;
|
volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel;
|
||||||
cfg->dma_controller->IFCR = cfg->RTCflag; // now we can clear TC flag (TC and CTC are the same)
|
//cfg->dma_controller->IFCR = cfg->TTCflag; // now we can clear TC flag (TC and CTC are the same)
|
||||||
T->CCR &= ~DMA_CCR_EN;
|
T->CCR &= ~DMA_CCR_EN;
|
||||||
T->CMAR = (uint32_t) outbuffers[i];
|
T->CMAR = (uint32_t) outbuffers[i];
|
||||||
T->CNDTR = got;
|
T->CNDTR = got;
|
||||||
@@ -243,6 +259,8 @@ void usarts_process(){
|
|||||||
cfg->instance->CR1 |= USART_CR1_TE;
|
cfg->instance->CR1 |= USART_CR1_TE;
|
||||||
}
|
}
|
||||||
T->CCR |= DMA_CCR_EN; // start new transmission
|
T->CCR |= DMA_CCR_EN; // start new transmission
|
||||||
|
TXrdy[i] = 0;
|
||||||
|
msg("USB -> USART over DMA", i, got);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{ // interrupt-driven
|
}else{ // interrupt-driven
|
||||||
@@ -250,16 +268,16 @@ void usarts_process(){
|
|||||||
volatile USART_TypeDef *U = cfg->instance;
|
volatile USART_TypeDef *U = cfg->instance;
|
||||||
U->CR1 &= ~USART_CR1_RXNEIE; // temporarily disable interrupt
|
U->CR1 &= ~USART_CR1_RXNEIE; // temporarily disable interrupt
|
||||||
register int l = inbufidx[i];
|
register int l = inbufidx[i];
|
||||||
if(DMARXBUFSZ - l > DMARXBUFSZ/2 || need2send[i]){
|
if(l > DMARXBUFSZ/2 || need2send[i]){
|
||||||
if(l && USB_send(i, inbuffers[i], l)){
|
if(l && USB_send(i, inbuffers[i], l)){
|
||||||
need2send[i] = 0;
|
need2send[i] = 0;
|
||||||
inbufidx[i] = 0;
|
inbufidx[i] = 0;
|
||||||
|
msg("USART -> USB over irq", i, l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
U->CR1 |= USART_CR1_RXNEIE; // restore irq reaction
|
U->CR1 |= USART_CR1_RXNEIE; // restore irq reaction
|
||||||
// output data
|
// output data
|
||||||
U->CR1 &= ~USART_CR1_TXEIE;
|
if(TXrdy[i]){
|
||||||
if(outbuflen[i] == 0){
|
|
||||||
int got = USB_receive(i, outbuffers[i], DMATXBUFSZ);
|
int got = USB_receive(i, outbuffers[i], DMATXBUFSZ);
|
||||||
if(got > 0){
|
if(got > 0){
|
||||||
if(cfg->DEport){ // switch to Tx
|
if(cfg->DEport){ // switch to Tx
|
||||||
@@ -269,14 +287,51 @@ void usarts_process(){
|
|||||||
}
|
}
|
||||||
outbufidx[i] = 1; // continue from next symbol
|
outbufidx[i] = 1; // continue from next symbol
|
||||||
outbuflen[i] = got;
|
outbuflen[i] = got;
|
||||||
|
TXrdy[i] = 0;
|
||||||
U->TDR = outbuffers[i][0]; // start transmission
|
U->TDR = outbuffers[i][0]; // start transmission
|
||||||
|
U->CR1 |= USART_CR1_TXEIE; // enable TXE interrupt
|
||||||
|
msg("USB -> USART over irq", i, got);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
U->CR1 |= USART_CR1_TXEIE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use this function only for debug purpose
|
||||||
|
int usart_send(uint8_t ifNo, const uint8_t *data, int len){
|
||||||
|
if(ifNo >= USARTSNO || !data || len < 1) return 0;
|
||||||
|
if(TXrdy[ifNo] == 0) return -1; // busy
|
||||||
|
const USART_Config *cfg = &UC[ifNo];
|
||||||
|
if(len > DMATXBUFSZ) len = DMATXBUFSZ;
|
||||||
|
memcpy(outbuffers[ifNo], data, len);
|
||||||
|
if(cfg->dma_controller){
|
||||||
|
volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel;
|
||||||
|
//cfg->dma_controller->IFCR = cfg->TTCflag; // now we can clear TC flag (TC and CTC are the same)
|
||||||
|
T->CCR &= ~DMA_CCR_EN;
|
||||||
|
T->CMAR = (uint32_t) outbuffers[ifNo];
|
||||||
|
T->CNDTR = len;
|
||||||
|
if(cfg->DEport){ // switch to Tx
|
||||||
|
TX485(cfg->DEport, cfg->DEpin);
|
||||||
|
cfg->instance->CR1 &= ~USART_CR1_RE;
|
||||||
|
cfg->instance->CR1 |= USART_CR1_TE;
|
||||||
|
}
|
||||||
|
T->CCR |= DMA_CCR_EN; // start new transmission
|
||||||
|
TXrdy[ifNo] = 0;
|
||||||
|
}else{
|
||||||
|
volatile USART_TypeDef *U = cfg->instance;
|
||||||
|
if(cfg->DEport){ // switch to Tx
|
||||||
|
TX485(cfg->DEport, cfg->DEpin);
|
||||||
|
U->CR1 &= ~USART_CR1_RE;
|
||||||
|
U->CR1 |= USART_CR1_TE;
|
||||||
|
}
|
||||||
|
outbufidx[ifNo] = 1; // continue from next symbol
|
||||||
|
outbuflen[ifNo] = len;
|
||||||
|
U->TDR = outbuffers[ifNo][0]; // start transmission
|
||||||
|
U->CR1 |= USART_CR1_TXEIE; // enable TXE interrupt
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief usart_isr - U[S]ART interrupt: IDLE (for DMA-driven) or
|
* @brief usart_isr - U[S]ART interrupt: IDLE (for DMA-driven) or
|
||||||
* @param ifno - interface index
|
* @param ifno - interface index
|
||||||
@@ -293,8 +348,11 @@ static void usart_isr(uint8_t ifno){
|
|||||||
U->ICR = USART_ICR_IDLECF;
|
U->ICR = USART_ICR_IDLECF;
|
||||||
}
|
}
|
||||||
if(U->ISR & USART_ISR_TXE){ // send next byte if need
|
if(U->ISR & USART_ISR_TXE){ // send next byte if need
|
||||||
if(outbuflen[ifno] < outbufidx[ifno]){
|
if(outbuflen[ifno] > outbufidx[ifno]){
|
||||||
U->TDR = outbuffers[ifno][ outbufidx[ifno]++ ];
|
U->TDR = outbuffers[ifno][ outbufidx[ifno]++ ];
|
||||||
|
}else{
|
||||||
|
U->CR1 &= ~USART_CR1_TXEIE; // disable interrupt: no data to send
|
||||||
|
TXrdy[ifno] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(U->ISR & USART_ISR_TC){ // switch RS-485 to Rx after transmission complete
|
if(U->ISR & USART_ISR_TC){ // switch RS-485 to Rx after transmission complete
|
||||||
@@ -307,22 +365,15 @@ static void usart_isr(uint8_t ifno){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usart1_exti25_isr(){
|
// U[S]ART interrupts (for DMA-driven - only IDLE, for interrupt-driven: RXNE and TXE)
|
||||||
usart_isr(1);
|
void usart1_exti25_isr(){ usart_isr(1); }
|
||||||
}
|
void usart2_exti26_isr(){ usart_isr(2); }
|
||||||
|
void usart3_exti28_isr(){ usart_isr(0); }
|
||||||
|
void uart4_exti34_isr(){ usart_isr(3); }
|
||||||
|
void uart5_exti35_isr(){ usart_isr(4); }
|
||||||
|
|
||||||
void usart2_exti26_isr(){
|
// DMA Tx interrupts (to arm ready flag)
|
||||||
usart_isr(2);
|
void dma1_channel2_isr(){ TXrdy[1] = 1; DMA1->IFCR = DMA_IFCR_CTCIF2; }
|
||||||
}
|
void dma1_channel4_isr(){ TXrdy[2] = 1; DMA1->IFCR = DMA_IFCR_CTCIF4; }
|
||||||
|
void dma1_channel7_isr(){ TXrdy[0] = 1; DMA1->IFCR = DMA_IFCR_CTCIF7; }
|
||||||
void usart3_exti28_isr(){
|
void dma2_channel5_isr(){ TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; }
|
||||||
usart_isr(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart4_exti34_isr(){
|
|
||||||
usart_isr(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart5_exti35_isr(){
|
|
||||||
usart_isr(4);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,9 +29,10 @@
|
|||||||
#define USARTTXRBSZ 256
|
#define USARTTXRBSZ 256
|
||||||
|
|
||||||
void usart_config(uint8_t ifNo, usb_LineCoding *lc);
|
void usart_config(uint8_t ifNo, usb_LineCoding *lc);
|
||||||
|
void usart_start(uint8_t ifNo);
|
||||||
void usart_stop(uint8_t ifNo);
|
void usart_stop(uint8_t ifNo);
|
||||||
|
|
||||||
void usarts_process();
|
void usarts_process();
|
||||||
|
|
||||||
int usart_send(uint8_t ifNo, const uint8_t *data, int len);
|
int usart_send(uint8_t ifNo, const uint8_t *data, int len);
|
||||||
int usart_receive(uint8_t ifNo, uint8_t *data, int len);
|
//int usart_receive(uint8_t ifNo, uint8_t *data, int len);
|
||||||
|
|||||||
@@ -117,8 +117,9 @@ static void rxtx_handler(){
|
|||||||
|
|
||||||
// SET_LINE_CODING
|
// SET_LINE_CODING
|
||||||
void linecoding_handler(uint8_t ifno, usb_LineCoding *lc){
|
void linecoding_handler(uint8_t ifno, usb_LineCoding *lc){
|
||||||
usart_config(ifno, lc); // lc would be real speed!
|
|
||||||
lineCoding[ifno] = *lc;
|
lineCoding[ifno] = *lc;
|
||||||
|
usart_config(ifno, &lineCoding[ifno]); // lc would be real speed!
|
||||||
|
usart_start(ifno);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear IN/OUT buffers on connection
|
// clear IN/OUT buffers on connection
|
||||||
@@ -137,8 +138,10 @@ static void clearbufs(uint8_t ifno){
|
|||||||
void clstate_handler(uint8_t ifno, uint16_t val){
|
void clstate_handler(uint8_t ifno, uint16_t val){
|
||||||
CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected
|
CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected
|
||||||
lastdsz[ifno] = -1;
|
lastdsz[ifno] = -1;
|
||||||
if(val) clearbufs(ifno);
|
if(val){
|
||||||
else usart_stop(ifno); // turn of USART (if it is @ this interface)
|
clearbufs(ifno);
|
||||||
|
usart_start(ifno);
|
||||||
|
}else usart_stop(ifno); // turn of USART (if it is @ this interface)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEND_BREAK - disconnect interface and clear its buffers
|
// SEND_BREAK - disconnect interface and clear its buffers
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "65"
|
#define BUILD_NUMBER "97"
|
||||||
#define BUILD_DATE "2026-02-15"
|
#define BUILD_DATE "2026-02-15"
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ TRUE_INLINE int StartHSE(){ // system bus 72MHz from PLL
|
|||||||
WAITWHILE(!(RCC->CR & RCC_CR_PLLRDY));
|
WAITWHILE(!(RCC->CR & RCC_CR_PLLRDY));
|
||||||
// Select PLL as system clock source
|
// Select PLL as system clock source
|
||||||
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
|
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
|
||||||
// select system clock as I2C source
|
// select system clock as I2C source (default: HSI)
|
||||||
RCC->CFGR3 |= RCC_CFGR3_I2C1SW_SYSCLK | RCC_CFGR3_I2C1SW_SYSCLK;
|
RCC->CFGR3 |= RCC_CFGR3_I2C1SW_SYSCLK | RCC_CFGR3_I2C2SW_SYSCLK;
|
||||||
// Wait till PLL is used as system clock source
|
// Wait till PLL is used as system clock source
|
||||||
WAITWHILE((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
|
WAITWHILE((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
|
||||||
SysFreq = 72000000;
|
SysFreq = 72000000;
|
||||||
|
|||||||
Reference in New Issue
Block a user