From fb8b93b0fee19bf11d2260b7b139aef019e37e3b Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Sat, 7 Mar 2026 14:37:42 +0300 Subject: [PATCH] usbcan_gpio: both USB interfaces works; start adding GPIO functions --- F0:F030,F042,F072/usbcan_gpio/Makefile | 3 ++ F0:F030,F042,F072/usbcan_gpio/gpioproto.c | 7 ++-- F0:F030,F042,F072/usbcan_gpio/ringbuffer.c | 34 ++++++++++++++----- F0:F030,F042,F072/usbcan_gpio/usb_dev.c | 17 ++++++---- F0:F030,F042,F072/usbcan_gpio/usb_lib.c | 12 ++++--- F0:F030,F042,F072/usbcan_gpio/usb_lib.h | 2 +- F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin | Bin 22632 -> 22860 bytes F0:F030,F042,F072/usbcan_gpio/version.inc | 2 +- F3:F303/InterfaceBoard/TODO | 1 + 9 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 F3:F303/InterfaceBoard/TODO diff --git a/F0:F030,F042,F072/usbcan_gpio/Makefile b/F0:F030,F042,F072/usbcan_gpio/Makefile index 3607fae..12e87d8 100644 --- a/F0:F030,F042,F072/usbcan_gpio/Makefile +++ b/F0:F030,F042,F072/usbcan_gpio/Makefile @@ -10,3 +10,6 @@ DEFINES := -DUSB2_16 include ../makefile.f0 include ../../makefile.stm32 + +$(OBJDIR)/gpioproto.o: gpioproto.c $(VERSION_FILE) +$(OBJDIR)/canproto.o: canproto.c $(VERSION_FILE) diff --git a/F0:F030,F042,F072/usbcan_gpio/gpioproto.c b/F0:F030,F042,F072/usbcan_gpio/gpioproto.c index afcbda2..b76d98f 100644 --- a/F0:F030,F042,F072/usbcan_gpio/gpioproto.c +++ b/F0:F030,F042,F072/usbcan_gpio/gpioproto.c @@ -104,7 +104,9 @@ static const char *cmd_parser(char *buf){ case 'i': return setiface(buf); default: - return buf-1; // echo wrong data + // echo wrong data with terminating '\n' + SENDn(buf-1); + return NULL; } } // "short" commands @@ -138,8 +140,9 @@ static const char *cmd_parser(char *buf){ void GPIO_process(){ char inbuff[MAXSTRLEN]; int l = RECV(inbuff, MAXSTRLEN); + if(l == 0) return; if(l < 0) SEND("ERROR: USB buffer overflow or string was too long\n"); - else if(l){ + else{ const char *ans = cmd_parser(inbuff); if(ans) SEND(ans); } diff --git a/F0:F030,F042,F072/usbcan_gpio/ringbuffer.c b/F0:F030,F042,F072/usbcan_gpio/ringbuffer.c index 24c8b61..389c9e7 100644 --- a/F0:F030,F042,F072/usbcan_gpio/ringbuffer.c +++ b/F0:F030,F042,F072/usbcan_gpio/ringbuffer.c @@ -19,6 +19,8 @@ #include #include "ringbuffer.h" +#define CHK(b) do{if(!b) return -1;}while(0) + static int datalen(ringbuffer *b){ if(b->tail >= b->head) return (b->tail - b->head); else return (b->length - b->head + b->tail); @@ -26,7 +28,9 @@ static int datalen(ringbuffer *b){ // stored data length int RB_datalen(ringbuffer *b){ - if(!b || b->busy) return -1; + CHK(b); + if(0 == datalen(b)) return 0; // don't block for empty RO operations + if(b->busy) return -1; b->busy = 1; int l = datalen(b); b->busy = 0; @@ -34,7 +38,7 @@ int RB_datalen(ringbuffer *b){ } static int hasbyte(ringbuffer *b, uint8_t byte){ - if(!b || b->head == b->tail) return -1; // no data in buffer + if(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) @@ -53,7 +57,8 @@ 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 || b->busy) return -1; + CHK(b); + if(b->busy) return -1; b->busy = 1; int ret = hasbyte(b, byte); b->busy = 0; @@ -91,7 +96,10 @@ 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 || b->busy || !s || len < 1) return -1; + CHK(b); + if(!s || len < 1) return -1; + if(0 == datalen(b)) return 0; + if(b->busy) return -1; b->busy = 1; int r = read(b, s, len); b->busy = 0; @@ -124,7 +132,10 @@ static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ * @return amount of bytes written (negative, if lenbusy) return -1; + CHK(b); + if(!s || len < 1) return -1; + if(0 == datalen(b)) return 0; + if(b->busy) return -1; b->busy = 1; int n = 0; if(s && len > 0){ @@ -137,7 +148,9 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ } int RB_datalento(ringbuffer *b, uint8_t byte){ - if(!b || b->busy) return -1; + CHK(b); + if(0 == datalen(b)) return 0; + if(b->busy) return -1; b->busy = 1; int n = lento(b, byte); b->busy = 0; @@ -167,7 +180,10 @@ 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 || b->busy || !str || l < 1) return -1; + CHK(b); + if(!str || l < 1) return -1; + if(b->length - datalen(b) < 2) return 0; + if(b->busy) return -1; b->busy = 1; int w = write(b, str, l); b->busy = 0; @@ -176,10 +192,12 @@ 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 || b->busy) return -1; + CHK(b); + if(b->busy) return -1; b->busy = 1; b->head = 0; b->tail = 0; + bzero(b->data, b->length); b->busy = 0; return 1; } diff --git a/F0:F030,F042,F072/usbcan_gpio/usb_dev.c b/F0:F030,F042,F072/usbcan_gpio/usb_dev.c index 249db9f..6d015cf 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usb_dev.c +++ b/F0:F030,F042,F072/usbcan_gpio/usb_dev.c @@ -119,13 +119,15 @@ static void rxtx_handler(){ } } -// clear IN/OUT buffers on connection -static void clearbufs(uint8_t ifno){ +static void clearRbuf(uint8_t ifno){ uint32_t T0 = Tms; while(Tms - T0 < 10){ // wait no more than 10ms if(1 == RB_clearbuf((ringbuffer*)&rbin[ifno])) break; } - T0 = Tms; +} + +static void clearTbuf(uint8_t ifno){ + uint32_t T0 = Tms; while(Tms - T0 < 10){ if(1 == RB_clearbuf((ringbuffer*)&rbout[ifno])) break; } @@ -144,7 +146,8 @@ void clstate_handler(uint8_t ifno, uint16_t val){ CDCready[ifno] = val; // CONTROL_DTR | CONTROL_RTS -> interface connected; 0 -> disconnected lastdsz[ifno] = -1; if(val){ - clearbufs(ifno); + clearRbuf(ifno); + clearTbuf(ifno); EP_reset(EPNO(ifno)); // usart_start(ifno); }//else usart_stop(ifno); // turn of USART (if it is @ this interface) @@ -306,7 +309,7 @@ int USB_receive(uint8_t ifno, uint8_t *buf, int len){ if(!CDCready[ifno]) return 0; chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy if(bufovrfl[ifno]){ - while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); // run watchdog in case of problems + clearRbuf(ifno); bufovrfl[ifno] = 0; return -1; } @@ -325,7 +328,7 @@ int USB_receivestr(uint8_t ifno, char *buf, int len){ if(!CDCready[ifno]) return 0; chkin(ifno); // rxtx_handler could leave last message unwritten if buffer was busy if(bufovrfl[ifno]){ - while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); + clearRbuf(ifno); bufovrfl[ifno] = 0; return -1; } @@ -333,7 +336,7 @@ int USB_receivestr(uint8_t ifno, char *buf, int len){ if(l < 1){ if((rbin[ifno].length <= RB_datalen((ringbuffer*)&rbin[ifno]) + 1) || (RB_datalento((ringbuffer*)&rbin[ifno], '\n') > len - 1)){ // buffer is full but no '\n' found or string too long - while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); + clearRbuf(ifno); return -1; } return 0; diff --git a/F0:F030,F042,F072/usbcan_gpio/usb_lib.c b/F0:F030,F042,F072/usbcan_gpio/usb_lib.c index 3bdfd8c..8ed4e0e 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usb_lib.c +++ b/F0:F030,F042,F072/usbcan_gpio/usb_lib.c @@ -301,10 +301,14 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f } // refresh EP after interface reconnected -void EP_reset(uint8_t number){ - if(number >= STM32ENDPOINTS) return; - USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX; - USB_BTABLE->EP[number].USB_COUNT_TX = 0; +void EP_reset(uint8_t epno){ + if(epno >= STM32ENDPOINTS) return; + // keep DTOGs (don't write 1 to them), clear CTR (write 0 to them) + // and set STAT to VALID (write 1 where was 0) + uint16_t epstatus = KEEP_DTOG(USB->EPnR[epno]); + USB->EPnR[epno] = (epstatus & ~(USB_EPnR_CTR_TX|USB_EPnR_CTR_RX)) ^ + (USB_EPnR_STAT_RX | USB_EPnR_STAT_TX); + USB_BTABLE->EP[epno].USB_COUNT_TX = 0; } // standard IRQ handler diff --git a/F0:F030,F042,F072/usbcan_gpio/usb_lib.h b/F0:F030,F042,F072/usbcan_gpio/usb_lib.h index 18ede16..1dfb3a8 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usb_lib.h +++ b/F0:F030,F042,F072/usbcan_gpio/usb_lib.h @@ -345,7 +345,7 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); int EP_Read(uint8_t number, uint8_t *buf); -void EP_reset(uint8_t number); +void EP_reset(uint8_t epno); // could be [re]defined in usb_dev.c extern void usb_class_request(config_pack_t *packet, uint8_t *data, uint16_t datalen); diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.bin index 8716eef70317be27aa40bdc89dd3772eec487b52..1a75ca53657320d8c0282a8dcc4ed227ec3e1a55 100755 GIT binary patch delta 4966 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 dXh1W