From 68028f42a376a2c522ab4a4331a59ab6a3b7e4cc Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 17 Feb 2026 23:37:17 +0300 Subject: [PATCH] Seems like all U[S]ARTs works well. Tested on speeds up to 2Mbaud (as CH340 can). --- F3:F303/InterfaceBoard/Debug.c | 11 ++- F3:F303/InterfaceBoard/Debug.h | 1 + F3:F303/InterfaceBoard/main.c | 4 +- F3:F303/InterfaceBoard/multiiface.bin | Bin 18580 -> 18476 bytes .../InterfaceBoard/multiiface.creator.user | 2 +- F3:F303/InterfaceBoard/proto.c | 3 +- F3:F303/InterfaceBoard/ringbuffer.c | 48 ++++++++----- F3:F303/InterfaceBoard/ringbuffer.h | 1 + F3:F303/InterfaceBoard/usart.c | 66 ++++++++++++------ F3:F303/InterfaceBoard/usart.h | 7 +- F3:F303/InterfaceBoard/usb_dev.c | 20 +++--- F3:F303/InterfaceBoard/usb_dev.h | 1 + F3:F303/InterfaceBoard/version.inc | 4 +- 13 files changed, 104 insertions(+), 64 deletions(-) diff --git a/F3:F303/InterfaceBoard/Debug.c b/F3:F303/InterfaceBoard/Debug.c index b19f79a..f8ad6d4 100644 --- a/F3:F303/InterfaceBoard/Debug.c +++ b/F3:F303/InterfaceBoard/Debug.c @@ -50,13 +50,18 @@ void debug_newline_only(){ RB_write(&dbgrb, (const uint8_t*)&nl, 1); } +// print by lines until there's place in USB ringbuffer void print_debug_messages(){ if(!Config_mode) return; uint8_t rcvbuf[256]; do{ - int n = RB_readto(&dbgrb, '\n', rcvbuf, 256); - if(n == 0) break; - else if(n < 0) n = -n; // partial string: longer than 256 bytes + int l = RB_datalento(&dbgrb, '\n'); + if(l < 1) break; + int freesize = USB_sendbufspace(ICFG); + if(freesize < l) break; + if(l > 256) l = 256; + int n = RB_read(&dbgrb, rcvbuf, l); + if(n < 1) break; // empty or busy USB_send(ICFG, rcvbuf, n); }while(1); } diff --git a/F3:F303/InterfaceBoard/Debug.h b/F3:F303/InterfaceBoard/Debug.h index 02ea009..aaa797b 100644 --- a/F3:F303/InterfaceBoard/Debug.h +++ b/F3:F303/InterfaceBoard/Debug.h @@ -32,6 +32,7 @@ #else #define DBG(str) #define DBGs(str) +#define DBGch(ch) #define DBGn() #define DBGpri() #endif diff --git a/F3:F303/InterfaceBoard/main.c b/F3:F303/InterfaceBoard/main.c index 2141933..55da0c0 100644 --- a/F3:F303/InterfaceBoard/main.c +++ b/F3:F303/InterfaceBoard/main.c @@ -45,8 +45,8 @@ int main(void){ USBPU_OFF(); USB_setup(); //uint32_t ctr = Tms; - usb_LineCoding lc = {9600, 0, 0, 8}; - for(int i = 0; i < 5; ++i) usart_config(i, &lc); // configure all U[S]ARTs for default data + //usb_LineCoding lc = {9600, 0, 0, 8}; + //for(int i = 0; i < 5; ++i) usart_config(i, &lc); // configure all U[S]ARTs for default data USBPU_ON(); while(1){ // Put here code working WITOUT USB connected diff --git a/F3:F303/InterfaceBoard/multiiface.bin b/F3:F303/InterfaceBoard/multiiface.bin index 80b875d147974a6805a2d7867fd5784730e13430..9a2c9a7a935e8c707be912cc24d3a94a81650672 100755 GIT binary patch delta 7075 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 delta 7407 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 jYYJS>6u8+_;Bu$H - + EnvironmentId diff --git a/F3:F303/InterfaceBoard/proto.c b/F3:F303/InterfaceBoard/proto.c index 08317e3..ebaee10 100644 --- a/F3:F303/InterfaceBoard/proto.c +++ b/F3:F303/InterfaceBoard/proto.c @@ -95,8 +95,7 @@ static const char* erpg(const char *str){ 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); + len = usart_send(ifno, (const uint8_t*)str, len); CFGWR("sent "); CFGWR(i2str(len)); CFGWR("bytes\n"); } diff --git a/F3:F303/InterfaceBoard/ringbuffer.c b/F3:F303/InterfaceBoard/ringbuffer.c index b0ffe8e..0750be2 100644 --- a/F3:F303/InterfaceBoard/ringbuffer.c +++ b/F3:F303/InterfaceBoard/ringbuffer.c @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +#include + #include "ringbuffer.h" static int datalen(ringbuffer *b){ @@ -24,7 +26,7 @@ static int datalen(ringbuffer *b){ // stored data length int RB_datalen(ringbuffer *b){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; int l = datalen(b); b->busy = 0; @@ -32,7 +34,7 @@ int RB_datalen(ringbuffer *b){ } static int hasbyte(ringbuffer *b, uint8_t byte){ - if(b->head == b->tail) return -1; // no data in buffer + if(!b || b->head == b->tail) return -1; // no data in buffer int startidx = b->head; if(b->head > b->tail){ // for(int found = b->head; found < b->length; ++found) @@ -51,18 +53,13 @@ static int hasbyte(ringbuffer *b, uint8_t byte){ * @return index if found, -1 if none or busy */ int RB_hasbyte(ringbuffer *b, uint8_t byte){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; int ret = hasbyte(b, byte); b->busy = 0; return ret; } -// poor memcpy -static void mcpy(uint8_t *targ, const uint8_t *src, int l){ - while(l--) *targ++ = *src++; -} - // increment head or tail TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ *what += n; @@ -76,9 +73,9 @@ static int read(ringbuffer *b, uint8_t *s, int len){ int _1st = b->length - b->head; if(_1st > l) _1st = l; if(_1st > len) _1st = len; - mcpy(s, b->data + b->head, _1st); + memcpy(s, b->data + b->head, _1st); if(_1st < len && l > _1st){ - mcpy(s+_1st, b->data, l - _1st); + memcpy(s+_1st, b->data, l - _1st); incr(b, &b->head, l); return l; } @@ -94,20 +91,27 @@ static int read(ringbuffer *b, uint8_t *s, int len){ * @return bytes read or -1 if busy */ int RB_read(ringbuffer *b, uint8_t *s, int len){ - if(b->busy) return -1; + if(!b || b->busy || !s || len < 1) return -1; b->busy = 1; int r = read(b, s, len); b->busy = 0; return r; } -static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ +// length of data from current position to `byte` (including byte) +static int lento(ringbuffer *b, uint8_t byte){ int idx = hasbyte(b, byte); if(idx < 0) return 0; int partlen = idx + 1 - b->head; // now calculate length of new data portion if(idx < b->head) partlen += b->length; - if(partlen > len) return -read(b, s, len); + return partlen; +} + +static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ + int partlen = lento(b, byte); + if(!partlen) return 0; + if(partlen > len) return -1; return read(b, s, partlen); } @@ -120,21 +124,29 @@ static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ * @return amount of bytes written (negative, if lenbusy) return -1; + if(!b || b->busy || !s || len < 1) return -1; b->busy = 1; int n = readto(b, byte, s, len); b->busy = 0; return n; } +int RB_datalento(ringbuffer *b, uint8_t byte){ + if(!b || b->busy) return -1; + b->busy = 1; + int n = lento(b, byte); + b->busy = 0; + return n; +} + static int write(ringbuffer *b, const uint8_t *str, int l){ int r = b->length - 1 - datalen(b); // rest length if(l > r || !l) return 0; int _1st = b->length - b->tail; if(_1st > l) _1st = l; - mcpy(b->data + b->tail, str, _1st); + memcpy(b->data + b->tail, str, _1st); if(_1st < l){ // add another piece from start - mcpy(b->data, str+_1st, l-_1st); + memcpy(b->data, str+_1st, l-_1st); } incr(b, &b->tail, l); return l; @@ -148,7 +160,7 @@ static int write(ringbuffer *b, const uint8_t *str, int l){ * @return amount of bytes written or -1 if busy */ int RB_write(ringbuffer *b, const uint8_t *str, int l){ - if(b->busy) return -1; + if(!b || b->busy || !str || l < 1) return -1; b->busy = 1; int w = write(b, str, l); b->busy = 0; @@ -157,7 +169,7 @@ int RB_write(ringbuffer *b, const uint8_t *str, int l){ // just delete all information in buffer `b` int RB_clearbuf(ringbuffer *b){ - if(b->busy) return -1; + if(!b || b->busy) return -1; b->busy = 1; b->head = 0; b->tail = 0; diff --git a/F3:F303/InterfaceBoard/ringbuffer.h b/F3:F303/InterfaceBoard/ringbuffer.h index ed2cf95..5064755 100644 --- a/F3:F303/InterfaceBoard/ringbuffer.h +++ b/F3:F303/InterfaceBoard/ringbuffer.h @@ -38,4 +38,5 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); int RB_hasbyte(ringbuffer *b, uint8_t byte); int RB_write(ringbuffer *b, const uint8_t *str, int l); int RB_datalen(ringbuffer *b); +int RB_datalento(ringbuffer *b, uint8_t byte); int RB_clearbuf(ringbuffer *b); diff --git a/F3:F303/InterfaceBoard/usart.c b/F3:F303/InterfaceBoard/usart.c index cf12189..c1a247a 100644 --- a/F3:F303/InterfaceBoard/usart.c +++ b/F3:F303/InterfaceBoard/usart.c @@ -46,7 +46,7 @@ typedef struct { // maybe DMA1ch2 would be for SPI1Rx (or SSI should be @ SPI3), in this case USART3 would be interrupt-driven // IF1[0]: USART3 APB2 72 MHz DMA1ch2 DMA1ch3 PB14 // IF2[1]: USART1 APB1 36 MHz DMA1ch4 DMA1ch5 PB0 -// IF3[2]: USART2 APB2 72 MHz DMA1ch6 DMA1ch7 PA1 +// IF3[2]: USART2 APB2 72 MHz DMA1ch7 DMA1ch6 PA1 // IF4[3]: UART4 APB2 72 MHz DMA2ch5 DMA2ch3 // IF5[4]: UART5 APB2 72 MHz - - - interrupt-driven // IF6[5]: (CAN) @@ -54,19 +54,20 @@ typedef struct { static const USART_Config UC[USARTSNO] = { [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 = 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 = 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 }, + [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 = GPIOA, .DEpin = 1<<1 }, [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 = 36000000, .UIRQn = UART5_IRQn }, // no DMA }; // buffers for DMA or interrupt-driven data management static uint8_t inbuffers[USARTSNO][DMARXBUFSZ]; -static uint16_t inbufidx[USARTSNO] = {0}; // for interrupt-driven - index of next character (also amount of received bytes) +static uint16_t inbufidx[USARTSNO] = {0}; // for interrupt-driven - index of next character (also amount of received bytes) static uint8_t outbuffers[USARTSNO][DMATXBUFSZ]; -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 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 +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 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 +static int dma_read_idx[USARTSNO] = {0}; // start of data in DMA inbuffers // there's no way to tell recipient about overfull, so we will just "eat" spare data! @@ -172,7 +173,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ R->CPAR = (uint32_t) &U->RDR; R->CMAR = (uint32_t) inbuffers[ifNo]; R->CNDTR = DMARXBUFSZ; - R->CCR = DMA_CCR_MINC | DMA_CCR_EN; // | DMA_CCR_TCIE + R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN; // manage circular buffer in polling // enable U[S]ART DMA U->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; }else{ @@ -200,7 +201,16 @@ void usart_start(uint8_t ifNo){ const USART_Config *cfg = &UC[ifNo]; cfg->instance->CR1 |= USART_CR1_UE; NVIC_EnableIRQ(cfg->UIRQn); - if(cfg->dma_controller) NVIC_EnableIRQ(cfg->DIRQn); + if(cfg->dma_controller){ // reset Rx DMA + volatile DMA_Channel_TypeDef *R = cfg->dma_rx_channel; + dma_read_idx[ifNo] = 0; + R->CCR = 0; + R->CPAR = (uint32_t) &cfg->instance->RDR; + R->CMAR = (uint32_t) inbuffers[ifNo]; + R->CNDTR = DMARXBUFSZ; + R->CCR = DMA_CCR_MINC | DMA_CCR_CIRC | DMA_CCR_EN; + NVIC_EnableIRQ(cfg->DIRQn); + } DBGch('0' + ifNo); DBG("U[S]ART started"); } @@ -213,13 +223,11 @@ void usart_stop(uint8_t ifNo){ if(ifNo >= USARTSNO || UC[ifNo].instance == NULL) return; const USART_Config *cfg = &UC[ifNo]; cfg->instance->CR1 &= ~USART_CR1_UE; - if(cfg->DEport) RX485(cfg->DEport, cfg->DEpin); - /* if(cfg->dma_controller){ NVIC_DisableIRQ(cfg->DIRQn); } NVIC_DisableIRQ(cfg->UIRQn); - */ + if(cfg->DEport) RX485(cfg->DEport, cfg->DEpin); DBGch('0' + ifNo); DBG("U[S]ART stopped"); } @@ -234,11 +242,28 @@ void usarts_process(){ if(!(cfg->instance->CR1 & USART_CR1_UE)) continue; // USART disabled if(cfg->dma_controller){ // DMA-driven // Input data + int write_idx = DMARXBUFSZ - cfg->dma_rx_channel->CNDTR; // next symbol to be written + int available = (write_idx - dma_read_idx[i] + DMARXBUFSZ) % DMARXBUFSZ; // length of data available + if(need2send[i] && available == 0) need2send[i] = 0; + if(available >= USB_TXBUFSZ || need2send[i]){ // enough data or lonely couple of bytes + // copy data in one or two chunks (wrap handling) + if(dma_read_idx[i] + available <= DMARXBUFSZ){ // head before tail + USB_send(i, &inbuffers[i][dma_read_idx[i]], available); + }else{ // head after tail - two chunks + uint32_t first = DMARXBUFSZ - dma_read_idx[i]; + USB_send(i, &inbuffers[i][dma_read_idx[i]], first); + USB_send(i, inbuffers[i], available - first); + } + DBG("USART -> USB over DMA"); + dma_read_idx[i] = write_idx; // update read pointer + } +#if 0 if(DMARXBUFSZ - cfg->dma_rx_channel->CNDTR > DMARXBUFSZ/2 || need2send[i]){ volatile DMA_Channel_TypeDef *R = cfg->dma_rx_channel; R->CCR &= ~DMA_CCR_EN; // pause DMA input transactions register int l = DMARXBUFSZ - R->CNDTR; if(l){ // have some input data -> send and restart DMA + DBG("need"); if(USB_send(i, inbuffers[i], l)){ DBG("USART -> USB over DMA"); // restart DMA only in case of succesfull sent or if failed, but have ability of buffer overfull @@ -249,6 +274,7 @@ void usarts_process(){ } R->CCR |= DMA_CCR_EN; // re-enable DMA } +#endif // Output data if(TXrdy[i]){ // ready to send new data int got = USB_receive(i, outbuffers[i], DMATXBUFSZ); @@ -308,7 +334,7 @@ void usarts_process(){ int usart_send(uint8_t ifNo, const uint8_t *data, int len){ if(ifNo >= USARTSNO || !data || len < 1) return 0; const USART_Config *cfg = &UC[ifNo]; - if(TXrdy[ifNo] == 0 || (!cfg->instance->CR1 & USART_CR1_UE)) return -1; // busy or not active + if(TXrdy[ifNo] == 0 || !(cfg->instance->CR1 & USART_CR1_UE)) return -1; // busy or not active if(len > DMATXBUFSZ) len = DMATXBUFSZ; memcpy(outbuffers[ifNo], data, len); if(cfg->dma_controller){ @@ -350,7 +376,6 @@ static void usart_isr(uint8_t ifno){ volatile USART_TypeDef *U = cfg->instance; // for every flag we should also check if it's IRQ active if((U->ISR & USART_ISR_RXNE) && (U->CR1 & USART_CR1_RXNEIE)){ // got new byte - DBG("RXNE"); if(inbufidx[ifno] == DMARXBUFSZ) (void) U->RDR; // throw away data: buffer overfull else inbuffers[ifno][ inbufidx[ifno]++ ] = U->RDR; // put new byte into buffer } @@ -358,22 +383,17 @@ static void usart_isr(uint8_t ifno){ if(U->ISR & USART_ISR_IDLE){ // try to send collected data (DMA-driven) need2send[ifno] = 1; // seems like data portion is over - try to send it U->ICR = USART_ICR_IDLECF; - DBG("IDLE"); } if((U->ISR & USART_ISR_TXE) && (U->CR1 & USART_CR1_TXEIE)){ // send next byte if need (interrupt-driven) - DBG("TXE"); if(outbuflen[ifno] > outbufidx[ifno]){ U->TDR = outbuffers[ifno][ outbufidx[ifno]++ ]; }else if(U->CR1 & USART_CR1_TXEIE){ U->CR1 &= ~USART_CR1_TXEIE; // disable interrupt: no data to send TXrdy[ifno] = 1; - DBG("TXRDY"); } } if(U->ISR & USART_ISR_TC){ // switch RS-485 to Rx after transmission complete - DBG("TC"); if(cfg->DEport){ - DBG("485 -> RX"); RX485(cfg->DEport, cfg->DEpin); U->CR1 &= ~USART_CR1_TE; U->CR1 |= USART_CR1_RE; @@ -390,7 +410,7 @@ void uart4_exti34_isr(){ usart_isr(3); } void uart5_exti35_isr(){ usart_isr(4); } // DMA Tx interrupts (to arm ready flag) -void dma1_channel2_isr(){ DBG("DMA1 done"); TXrdy[0] = 1; DMA1->IFCR = DMA_IFCR_CTCIF2; } -void dma1_channel4_isr(){ DBG("DMA2 done"); TXrdy[1] = 1; DMA1->IFCR = DMA_IFCR_CTCIF4; } -void dma1_channel6_isr(){ DBG("DMA3 done"); TXrdy[2] = 1; DMA1->IFCR = DMA_IFCR_CTCIF6; } -void dma2_channel5_isr(){ DBG("DMA4 done"); TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; } +void dma1_channel2_isr(){ TXrdy[0] = 1; DMA1->IFCR = DMA_IFCR_CTCIF2; } +void dma1_channel4_isr(){ TXrdy[1] = 1; DMA1->IFCR = DMA_IFCR_CTCIF4; } +void dma1_channel7_isr(){ TXrdy[2] = 1; DMA1->IFCR = DMA_IFCR_CTCIF7; } +void dma2_channel5_isr(){ TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; } diff --git a/F3:F303/InterfaceBoard/usart.h b/F3:F303/InterfaceBoard/usart.h index 1ff82b6..ad25616 100644 --- a/F3:F303/InterfaceBoard/usart.h +++ b/F3:F303/InterfaceBoard/usart.h @@ -22,11 +22,8 @@ #include "usb_dev.h" // DMA linear buffers for Rx/Tx -#define DMARXBUFSZ 128 -#define DMATXBUFSZ 128 -// ringbuffers for collected data -#define USARTRXRBSZ 256 -#define USARTTXRBSZ 256 +#define DMARXBUFSZ 512 +#define DMATXBUFSZ 512 void usart_config(uint8_t ifNo, usb_LineCoding *lc); void usart_start(uint8_t ifNo); diff --git a/F3:F303/InterfaceBoard/usb_dev.c b/F3:F303/InterfaceBoard/usb_dev.c index c063fb4..d5ff457 100644 --- a/F3:F303/InterfaceBoard/usb_dev.c +++ b/F3:F303/InterfaceBoard/usb_dev.c @@ -184,14 +184,11 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ case REQ_RECIPIENT_INTERFACE: switch(req->bRequest){ case SET_LINE_CODING: - //DBG("SLC"); if(!data || !datalen) break; // wait for data - //DBG("test"); if(datalen == sizeof(usb_LineCoding)) linecoding_handler(ifno, (usb_LineCoding*)data); break; case GET_LINE_CODING: - DBG("GLC"); EP_WriteIRQ(0, (uint8_t*)&lineCoding[ifno], sizeof(lineCoding)); break; case SET_CONTROL_LINE_STATE: @@ -226,17 +223,26 @@ int USB_sendall(uint8_t ifno){ return TRUE; } +// return amount of free space in buffer +int USB_sendbufspace(uint8_t ifno){ + if(!CDCready[ifno]) return 0; + return rbout[ifno].length - RB_datalen((ringbuffer*)&rbout[ifno]); +} + // put `buf` into queue to send int USB_send(uint8_t ifno, const uint8_t *buf, int len){ - if(!buf || !CDCready[ifno] || !len) return FALSE; - if(ifno != ICFG) DBG("USB_send"); + if(!buf || !CDCready[ifno] || !len){ + return FALSE; + } uint32_t T0 = Tms; while(len){ if(Tms - T0 > DISCONN_TMOUT){ //break_handler(ifno); return FALSE; } - if(!CDCready[ifno]) return FALSE; + if(!CDCready[ifno]){ + return FALSE; + } IWDG->KR = IWDG_REFRESH; int l = RB_datalen((ringbuffer*)&rbout[ifno]); if(l < 0) continue; @@ -255,7 +261,6 @@ int USB_send(uint8_t ifno, const uint8_t *buf, int len){ } } if(buf[len-1] == '\n' && lastdsz[ifno] < 0){ - if(ifno != ICFG) DBG("send_next"); send_next(ifno); } return TRUE; @@ -279,7 +284,6 @@ int USB_putbyte(uint8_t ifno, uint8_t byte){ } // send line if got EOL if(byte == '\n' && lastdsz[ifno] < 0){ - if(ifno != ICFG) DBG("send_next"); send_next(ifno); } return TRUE; diff --git a/F3:F303/InterfaceBoard/usb_dev.h b/F3:F303/InterfaceBoard/usb_dev.h index eb9be56..3ea0e41 100644 --- a/F3:F303/InterfaceBoard/usb_dev.h +++ b/F3:F303/InterfaceBoard/usb_dev.h @@ -55,6 +55,7 @@ void linecoding_handler(uint8_t ifno, usb_LineCoding *lc); #define CFGWRn(s) do{USB_sendstr(ICFG, s); USB_putbyte(ICFG, '\n');}while(0) #define CFGn() USB_putbyte(ICFG, '\n') +int USB_sendbufspace(uint8_t ifno); int USB_sendall(uint8_t ifno); int USB_send(uint8_t ifno, const uint8_t *buf, int len); int USB_putbyte(uint8_t ifno, uint8_t byte); diff --git a/F3:F303/InterfaceBoard/version.inc b/F3:F303/InterfaceBoard/version.inc index 2f3d46b..e22d49e 100644 --- a/F3:F303/InterfaceBoard/version.inc +++ b/F3:F303/InterfaceBoard/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "110" -#define BUILD_DATE "2026-02-16" +#define BUILD_NUMBER "140" +#define BUILD_DATE "2026-02-17"