diff --git a/F3:F303/InterfaceBoard/debug.h b/F3:F303/InterfaceBoard/debug.h deleted file mode 100644 index 76dbace..0000000 --- a/F3:F303/InterfaceBoard/debug.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of the multiiface project. - * Copyright 2026 Edward V. Emelianov . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include "usb_dev.h" - -// debugging messages on config interface - -#ifdef EBUG -#define DBG(str) do{USB_sendstr(ICFG, __FILE__ " (L" STR(__LINE__) "): " str); newline(ICFG);}while(0) -#define DBGmesg(str) do{USB_sendstr(ICFG, str);}while(0) -#define DBGmesgn(str,n) do{USB_send(ICFG, str, n);}while(0) -#define DBGnl() newline(ICFG) -#else -#define DBG(str) -#define DBGmesg(str) -#define DBGmesgn(str,n) -#define DBGnl() -#endif - - diff --git a/F3:F303/InterfaceBoard/main.c b/F3:F303/InterfaceBoard/main.c index 583dc4c..2141933 100644 --- a/F3:F303/InterfaceBoard/main.c +++ b/F3:F303/InterfaceBoard/main.c @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +#include "Debug.h" #include "flash.h" #include "hardware.h" #include "proto.h" @@ -44,13 +45,14 @@ 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); + 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 if(!usbON) continue; usarts_process(); + DBGpri(); /*for(int i = 0; i < 6; ++i){ // just echo for first time if(!CDCready[i]) continue; int l = USB_receive(i, (uint8_t*)inbuff, MAXSTRLEN); diff --git a/F3:F303/InterfaceBoard/multiiface.bin b/F3:F303/InterfaceBoard/multiiface.bin index 7607b60..80b875d 100755 Binary files a/F3:F303/InterfaceBoard/multiiface.bin and b/F3:F303/InterfaceBoard/multiiface.bin differ diff --git a/F3:F303/InterfaceBoard/multiiface.creator.user b/F3:F303/InterfaceBoard/multiiface.creator.user index 1fa8b47..36e1fe1 100644 --- a/F3:F303/InterfaceBoard/multiiface.creator.user +++ b/F3:F303/InterfaceBoard/multiiface.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/InterfaceBoard/multiiface.files b/F3:F303/InterfaceBoard/multiiface.files index c99c82d..4102133 100644 --- a/F3:F303/InterfaceBoard/multiiface.files +++ b/F3:F303/InterfaceBoard/multiiface.files @@ -1,4 +1,5 @@ -debug.h +Debug.c +Debug.h flash.c flash.h hardware.c diff --git a/F3:F303/InterfaceBoard/usart.c b/F3:F303/InterfaceBoard/usart.c index 23ec043..cf12189 100644 --- a/F3:F303/InterfaceBoard/usart.c +++ b/F3:F303/InterfaceBoard/usart.c @@ -19,7 +19,7 @@ #include #include -#include "debug.h" +#include "Debug.h" #include "hardware.h" #include "strfunc.h" #include "usart.h" @@ -87,6 +87,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ // Assuming oversampling by 16 (default after reset). For higher baud rates you might use by 8. U->BRR = peripheral_clock / lc->dwDTERate; lc->dwDTERate = peripheral_clock / U->BRR; + DBGs("New speed: "); DBGs(u2str(lc->dwDTERate)); DBGn(); // ----- Data bits & Parity ----- uint32_t cr1 = 0; @@ -102,6 +103,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ lc->bParityType = USB_CDC_EVEN_PARITY; } } + DBGs("Parity: "); DBGch('0'+lc->bParityType); DBGn(); // Word length (M bits) depends on data bits and parity // M[1:0] encoding: 00 = 8 bits, 01 = 9 bits, 10 = 7 bits @@ -114,7 +116,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ // 7 data + 1 parity = 8 bits total -> M=00 (8-bit mode) // do nothing }else{ - // Unsupported (8 or 9 data bits with parity would be 9/10 bits total) + // 8 or 9 data bits with parity would be 9/10 bits total // Fallback to 8 data + parity cr1 |= USART_CR1_M0; lc->bDataBits = 8; // ??? need to be tested @@ -130,6 +132,7 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ lc->bDataBits = 8; } } + DBGs("Data bits: "); DBGch('0' + lc->bDataBits); DBGn(); // ----- Stop bits ----- uint32_t cr2 = 0; @@ -144,18 +147,21 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ // do nothing: default to 1 stop bit -> CR2=00 break; } + DBGs("Stop bits: "); DBGch('0'+lc->bCharFormat); DBGn(); // Write CR2 (stop bits) U->CR2 = cr2; // Enable transmitter, receiver, and interrupts (optional) - cr1 |= USART_CR1_RE; + cr1 |= USART_CR1_RE | USART_CR1_IDLEIE; // enable idle interrupt to force small portions of data into ringbuffer if(cfg->DEport){ + DBG("485 -> RX"); RX485(cfg->DEport, cfg->DEpin); cr1 |= USART_CR1_TCIE; }else cr1 |= USART_CR1_TE; // ----- DMA ----- if(cfg->dma_controller){ // DMA-driven + DBG("DMA-driven"); volatile DMA_Channel_TypeDef *T = cfg->dma_tx_channel, *R = cfg->dma_rx_channel; // Tx DMA T->CCR = 0; @@ -169,8 +175,8 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ R->CCR = DMA_CCR_MINC | DMA_CCR_EN; // | DMA_CCR_TCIE // enable U[S]ART DMA U->CR3 = USART_CR3_DMAT | USART_CR3_DMAR; - cr1 |= USART_CR1_IDLEIE; // enable idle interrupt to force small portions of data into ringbuffer }else{ + DBG("IRQ-driven"); cr1 |= USART_CR1_RXNEIE; // interrupt-driven inbufidx[ifNo] = 0; outbufidx[ifNo] = 0; @@ -183,6 +189,9 @@ void usart_config(uint8_t ifNo, usb_LineCoding *lc){ if (--tmout == 0) break; } U->ICR = 0xFFFFFFFF; // Clear flags again + TXrdy[ifNo] = 1; + DBGch('0' + ifNo); + DBG("U[S]ART configured"); } // start when received DTR @@ -192,6 +201,8 @@ void usart_start(uint8_t ifNo){ cfg->instance->CR1 |= USART_CR1_UE; NVIC_EnableIRQ(cfg->UIRQn); if(cfg->dma_controller) NVIC_EnableIRQ(cfg->DIRQn); + DBGch('0' + ifNo); + DBG("U[S]ART started"); } /** @@ -201,21 +212,16 @@ void usart_start(uint8_t ifNo){ void usart_stop(uint8_t ifNo){ if(ifNo >= USARTSNO || UC[ifNo].instance == NULL) return; const USART_Config *cfg = &UC[ifNo]; - cfg->instance->CR1 = 0; + cfg->instance->CR1 &= ~USART_CR1_UE; if(cfg->DEport) RX485(cfg->DEport, cfg->DEpin); + /* if(cfg->dma_controller){ - cfg->dma_tx_channel->CCR = 0; - cfg->dma_rx_channel->CCR = 0; NVIC_DisableIRQ(cfg->DIRQn); - }else{ - 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"); + NVIC_DisableIRQ(cfg->UIRQn); + */ + DBGch('0' + ifNo); + DBG("U[S]ART stopped"); } /** @@ -234,12 +240,11 @@ void usarts_process(){ register int l = DMARXBUFSZ - R->CNDTR; if(l){ // have some input data -> send and restart DMA if(USB_send(i, inbuffers[i], l)){ - msg("USART -> USB over DMA", i, l); + DBG("USART -> USB over DMA"); // restart DMA only in case of succesfull sent or if failed, but have ability of buffer overfull R->CMAR = (uint32_t) inbuffers[i]; R->CNDTR = DMARXBUFSZ; need2send[i] = 0; - if(cfg->DEport) TX485(cfg->DEport, cfg->DEpin); } } R->CCR |= DMA_CCR_EN; // re-enable DMA @@ -254,13 +259,14 @@ void usarts_process(){ T->CMAR = (uint32_t) outbuffers[i]; T->CNDTR = got; if(cfg->DEport){ // switch to Tx + DBG("485 -> 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[i] = 0; - msg("USB -> USART over DMA", i, got); + T->CCR |= DMA_CCR_EN; // start new transmission + DBG("USB -> USART over DMA"); } } }else{ // interrupt-driven @@ -272,7 +278,7 @@ void usarts_process(){ if(l && USB_send(i, inbuffers[i], l)){ need2send[i] = 0; inbufidx[i] = 0; - msg("USART -> USB over irq", i, l); + DBG("USART -> USB over irq"); } } U->CR1 |= USART_CR1_RXNEIE; // restore irq reaction @@ -281,6 +287,7 @@ void usarts_process(){ int got = USB_receive(i, outbuffers[i], DMATXBUFSZ); if(got > 0){ if(cfg->DEport){ // switch to Tx + DBG("485 -> TX"); TX485(cfg->DEport, cfg->DEpin); U->CR1 &= ~USART_CR1_RE; U->CR1 |= USART_CR1_TE; @@ -290,7 +297,7 @@ void usarts_process(){ TXrdy[i] = 0; U->TDR = outbuffers[i][0]; // start transmission U->CR1 |= USART_CR1_TXEIE; // enable TXE interrupt - msg("USB -> USART over irq", i, got); + DBG("USB -> USART over irq"); } } } @@ -300,8 +307,8 @@ void usarts_process(){ // 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(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){ @@ -311,15 +318,17 @@ int usart_send(uint8_t ifNo, const uint8_t *data, int len){ T->CMAR = (uint32_t) outbuffers[ifNo]; T->CNDTR = len; if(cfg->DEport){ // switch to Tx + DBG("485 -> 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; + T->CCR |= DMA_CCR_EN; // start new transmission }else{ volatile USART_TypeDef *U = cfg->instance; if(cfg->DEport){ // switch to Tx + DBG("485 -> TX"); TX485(cfg->DEport, cfg->DEpin); U->CR1 &= ~USART_CR1_RE; U->CR1 |= USART_CR1_TE; @@ -339,24 +348,32 @@ int usart_send(uint8_t ifNo, const uint8_t *data, int len){ static void usart_isr(uint8_t ifno){ const USART_Config *cfg = &UC[ifno]; volatile USART_TypeDef *U = cfg->instance; - if(U->ISR & USART_ISR_RXNE){ // got new byte + // 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 } - if(U->ISR & USART_ISR_IDLE){ // try to send collected data + // IDLE active for both DMA- and interrupt-driven transitions + 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){ // send next byte if need + 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{ + }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; @@ -373,7 +390,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(){ 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 dma2_channel5_isr(){ TXrdy[3] = 1; DMA2->IFCR = DMA_IFCR_CTCIF5; } +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; } diff --git a/F3:F303/InterfaceBoard/usb_dev.c b/F3:F303/InterfaceBoard/usb_dev.c index b08dcfd..c063fb4 100644 --- a/F3:F303/InterfaceBoard/usb_dev.c +++ b/F3:F303/InterfaceBoard/usb_dev.c @@ -17,6 +17,7 @@ #include +#include "Debug.h" #include "hardware.h" #include "ringbuffer.h" #include "usart.h" @@ -45,7 +46,7 @@ static volatile uint8_t bufovrfl[InterfacesAmount] = {0}; static uint8_t volatile rcvbuf[InterfacesAmount][USB_RXBUFSZ]; static uint8_t volatile rcvbuflen[InterfacesAmount] = {0}; // line coding -#define DEFL {115200, 0, 0, 8} +#define DEFL {9600, 0, 0, 8} usb_LineCoding lineCoding[InterfacesAmount] = {DEFL,DEFL,DEFL,DEFL,DEFL,DEFL,DEFL}; // CDC configured and ready to use volatile uint8_t CDCready[InterfacesAmount] = {0}; @@ -117,9 +118,11 @@ static void rxtx_handler(){ // SET_LINE_CODING void linecoding_handler(uint8_t ifno, usb_LineCoding *lc){ + //DBGch('0' + ifno); + //DBG("Linecoding"); lineCoding[ifno] = *lc; usart_config(ifno, &lineCoding[ifno]); // lc would be real speed! - usart_start(ifno); + usart_start(ifno); // restart again with new configuration } // clear IN/OUT buffers on connection @@ -136,10 +139,13 @@ static void clearbufs(uint8_t ifno){ // SET_CONTROL_LINE_STATE void clstate_handler(uint8_t ifno, uint16_t val){ + //DBGch('0' + ifno); + //DBG("CLSTATE"); CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected lastdsz[ifno] = -1; if(val){ clearbufs(ifno); + //usart_config(ifno, &lineCoding[ifno]); // SET_CONTROL_LINE_STATE could be without SET_LINE_CODING usart_start(ifno); }else usart_stop(ifno); // turn of USART (if it is @ this interface) } @@ -147,6 +153,8 @@ void clstate_handler(uint8_t ifno, uint16_t val){ // SEND_BREAK - disconnect interface and clear its buffers // this is a fake handler as classic CDC ACM never receives this void break_handler(uint8_t ifno){ + //DBGch('0' + ifno); + //DBG("BREAK"); CDCready[ifno] = 0; usart_stop(ifno); // turn of USART (if it is @ this interface) } @@ -176,11 +184,14 @@ 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: @@ -218,6 +229,7 @@ int USB_sendall(uint8_t 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"); uint32_t T0 = Tms; while(len){ if(Tms - T0 > DISCONN_TMOUT){ @@ -242,7 +254,10 @@ int USB_send(uint8_t ifno, const uint8_t *buf, int len){ if(lastdsz[ifno] < 0) send_next(ifno); } } - if(buf[len-1] == '\n' && lastdsz[ifno] < 0) send_next(ifno); + if(buf[len-1] == '\n' && lastdsz[ifno] < 0){ + if(ifno != ICFG) DBG("send_next"); + send_next(ifno); + } return TRUE; } @@ -263,7 +278,10 @@ int USB_putbyte(uint8_t ifno, uint8_t byte){ } } // send line if got EOL - if(byte == '\n' && lastdsz[ifno] < 0) send_next(ifno); + if(byte == '\n' && lastdsz[ifno] < 0){ + if(ifno != ICFG) DBG("send_next"); + send_next(ifno); + } return TRUE; } diff --git a/F3:F303/InterfaceBoard/version.inc b/F3:F303/InterfaceBoard/version.inc index b91822d..2f3d46b 100644 --- a/F3:F303/InterfaceBoard/version.inc +++ b/F3:F303/InterfaceBoard/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "97" -#define BUILD_DATE "2026-02-15" +#define BUILD_NUMBER "110" +#define BUILD_DATE "2026-02-16"