diff --git a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user index 1ffe426..2bc265d 100644 --- a/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user +++ b/F0:F030,F042,F072/usbcan_gpio/usbcangpio.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -155,6 +155,7 @@ true 0 true + 2 @@ -190,6 +191,7 @@ true 0 true + 2 diff --git a/F1:F103/BISS_C_encoders/Makefile b/F1:F103/BISS_C_encoders/Makefile index 8496007..3aa2506 100644 --- a/F1:F103/BISS_C_encoders/Makefile +++ b/F1:F103/BISS_C_encoders/Makefile @@ -6,4 +6,4 @@ LDSCRIPT ?= stm32f103xB.ld DEFINES := -DSTM32F10X_MD include ../makefile.f1 -include ../makefile.stm32 +include ../../makefile.stm32 diff --git a/F1:F103/BISS_C_encoders/encoders.bin b/F1:F103/BISS_C_encoders/encoders.bin index efe98a1..0068880 100755 Binary files a/F1:F103/BISS_C_encoders/encoders.bin and b/F1:F103/BISS_C_encoders/encoders.bin differ diff --git a/F1:F103/BISS_C_encoders/encoders.creator.user b/F1:F103/BISS_C_encoders/encoders.creator.user index 32c15f4..df0650b 100644 --- a/F1:F103/BISS_C_encoders/encoders.creator.user +++ b/F1:F103/BISS_C_encoders/encoders.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -154,6 +154,7 @@ true 0 true + 2 @@ -189,6 +190,7 @@ true 0 true + 2 diff --git a/F1:F103/BISS_C_encoders/flash.h b/F1:F103/BISS_C_encoders/flash.h index 2a8266a..6177fe7 100644 --- a/F1:F103/BISS_C_encoders/flash.h +++ b/F1:F103/BISS_C_encoders/flash.h @@ -47,8 +47,8 @@ typedef struct{ typedef struct __attribute__((packed, aligned(4))){ uint16_t userconf_sz; // "magick number" uint16_t send232_interval; // interval (ms) of sending data to SSII over RS-232 (or 0 - not to send) - uint16_t iInterface[bTotNumEndpoints][MAX_IINTERFACE_SZ]; // hryunikod! - uint8_t iIlengths[bTotNumEndpoints]; + uint16_t iInterface[InterfacesAmount][MAX_IINTERFACE_SZ]; // hryunikod! + uint8_t iIlengths[InterfacesAmount]; uint8_t encbits; // encoder bits: 26 or 32 uint8_t encbufsz; // encoder buffer size (up to ENCODER_BUFSZ_MAX) uint8_t minzeros; // min/max zeros in preamble when searching start of record diff --git a/F1:F103/BISS_C_encoders/main.c b/F1:F103/BISS_C_encoders/main.c index 5a3f87a..f6ac060 100644 --- a/F1:F103/BISS_C_encoders/main.c +++ b/F1:F103/BISS_C_encoders/main.c @@ -124,7 +124,7 @@ static void proc_enc(uint8_t idx){ int main(){ uint32_t lastT = 0, usartT = 0; - uint8_t oldCDCready[bTotNumEndpoints] = {0}; + uint8_t oldCDCready[InterfacesAmount] = {0}; StartHSE(); flashstorage_init(); hw_setup(); @@ -148,7 +148,7 @@ int main(){ else if(l) parse_cmd(inbuff); // check if interface connected/disconnected // (we CAN'T do much debug output in interrupt functions like linecoding_handler etc, so do it here) - for(int i = 1; i < bTotNumEndpoints; ++i){ + for(int i = 1; i < InterfacesAmount; ++i){ if(oldCDCready[i] != CDCready[i]){ CMDWR("Interface "); CMDWR(u2str(i)); diff --git a/F1:F103/BISS_C_encoders/proto.c b/F1:F103/BISS_C_encoders/proto.c index b096ddb..0438baa 100644 --- a/F1:F103/BISS_C_encoders/proto.c +++ b/F1:F103/BISS_C_encoders/proto.c @@ -133,7 +133,7 @@ static errcode_e sendenc(cmd_e idx, char *par){ } static errcode_e setiface(cmd_e idx, char *par){ - if(idx < C_setiface1 || idx >= C_setiface1 + bTotNumEndpoints) return ERR_BADCMD; + if(idx < C_setiface1 || idx >= C_setiface1 + InterfacesAmount) return ERR_BADCMD; idx -= C_setiface1; // now it is an index of iIlengths if(par && *par){ int l = strlen(par); @@ -364,7 +364,7 @@ static errcode_e dumpconf(cmd_e _U_ idx, char _U_ *par){ CMDWR("userconf_sz="); CMDWR(u2str(the_conf.userconf_sz)); CMDWR("\ncurrentconfidx="); CMDWR(i2str(currentconfidx)); CMDn(); - for(int i = 0; i < bTotNumEndpoints; ++i) + for(int i = 0; i < InterfacesAmount; ++i) setiface(C_setiface1 + i, NULL); setboolpar(C_autom, NULL); setuintpar(C_amperiod, NULL); diff --git a/F1:F103/BISS_C_encoders/ringbuffer.c b/F1:F103/BISS_C_encoders/ringbuffer.c index d444ec6..bc2af8d 100644 --- a/F1:F103/BISS_C_encoders/ringbuffer.c +++ b/F1:F103/BISS_C_encoders/ringbuffer.c @@ -15,9 +15,12 @@ * along with this program. If not, see . */ -#include // memcpy +#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); @@ -25,6 +28,8 @@ static int datalen(ringbuffer *b){ // stored data length int RB_datalen(ringbuffer *b){ + 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); @@ -52,17 +57,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){ + CHK(b); if(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){ @@ -77,10 +78,8 @@ 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; @@ -97,6 +96,9 @@ 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){ + 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); @@ -104,13 +106,20 @@ int RB_read(ringbuffer *b, uint8_t *s, int len){ 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); } @@ -118,27 +127,45 @@ static int readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ * @brief RB_readto fill array `s` with data until byte `byte` (with it) * @param b - ringbuffer * @param byte - check byte - * @param s - buffer to write data - * @param len - length of `s` + * @param s - buffer to write data or NULL to clear data + * @param len - length of `s` or 0 to clear data * @return amount of bytes written (negative, if lenbusy) return -1; b->busy = 1; - int n = readto(b, byte, s, len); + int n = 0; + if(s && len > 0){ + n = readto(b, byte, s, len); + }else{ + incr(b, &b->head, lento(b, byte)); // just throw data out + } b->busy = 0; return n; } +int RB_datalento(ringbuffer *b, uint8_t byte){ + CHK(b); + if(0 == datalen(b)) return 0; + if(b->busy) return -1; + b->busy = 1; + int n = lento(b, byte); + b->busy = 0; + return n; +} + +// if l < rest of buffer, truncate and return actually written bytes 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; + if(r < 1) return 0; + if(l > r) l = r; 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); @@ -153,6 +180,9 @@ 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){ + 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); @@ -162,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){ + 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/F1:F103/BISS_C_encoders/ringbuffer.h b/F1:F103/BISS_C_encoders/ringbuffer.h index 5643b5a..e7312bb 100644 --- a/F1:F103/BISS_C_encoders/ringbuffer.h +++ b/F1:F103/BISS_C_encoders/ringbuffer.h @@ -17,6 +17,8 @@ #pragma once +#include + #if defined STM32F0 #include #elif defined STM32F1 @@ -25,14 +27,12 @@ #include #endif -#include - typedef struct{ uint8_t *data; // data buffer const int length; // its length int head; // head index int tail; // tail index - volatile atomic_int busy; // == TRUE if buffer is busy now + volatile int busy; // == TRUE if buffer is busy now } ringbuffer; int RB_read(ringbuffer *b, uint8_t *s, int len); @@ -40,4 +40,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/F1:F103/BISS_C_encoders/usb_descr.c b/F1:F103/BISS_C_encoders/usb_descr.c index fd1688d..233d5af 100644 --- a/F1:F103/BISS_C_encoders/usb_descr.c +++ b/F1:F103/BISS_C_encoders/usb_descr.c @@ -20,11 +20,6 @@ #include "flash.h" #include "usb_descr.h" -#undef DBG -#define DBG(x) -#undef DBGs -#define DBGs(x) - // low/high for uint16_t #define L16(x) (x & 0xff) #define H16(x) (x >> 8) @@ -63,7 +58,7 @@ static const uint8_t USB_DeviceQualifierDescriptor[] = { 0 // Reserved }; -#define wTotalLength (USB_DT_CONFIG_SIZE + bTotNumEndpoints * 66) +#define wTotalLength (USB_DT_CONFIG_SIZE + (bTotNumEndpoints * 66)) /* * _1stI - number of first interface @@ -166,7 +161,7 @@ static const uint8_t USB_ConfigDescriptor[] = { //const uint8_t HID_ReportDescriptor[]; _USB_LANG_ID_(LD, LANG_US); -_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(SD, u"0.0.2"); _USB_STRING_(MD, u"eddy@sao.ru"); _USB_STRING_(PD, u"USB BISS-C encoders controller"); @@ -177,7 +172,7 @@ typedef struct{ uint8_t bDescriptorType; uint16_t bString[MAX_IINTERFACE_SZ]; }iidescr_t; -static iidescr_t iids[bTotNumEndpoints] = { +static iidescr_t iids[InterfacesAmount] = { _USB_IIDESCR_(u"encoder_cmd"), _USB_IIDESCR_(u"encoder_X"), _USB_IIDESCR_(u"encoder_Y"), @@ -197,12 +192,8 @@ static void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ if(askedsize < size) size = askedsize; // shortened request if(size < USB_EP0BUFSZ){ EP_WriteIRQ(0, buf, size); - DBG("short wr0"); - DBGs(uhex2str(size)); return; } - DBG("long wr0"); - DBGs(uhex2str(size)); while(size){ uint16_t l = size; if(l > USB_EP0BUFSZ) l = USB_EP0BUFSZ; @@ -215,7 +206,7 @@ static void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ // keep DTOGs, clear CTR_RX,TX, set TX VALID, leave stat_Rx USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX|USB_EPnR_STAT_RX)) ^ USB_EPnR_STAT_TX; - uint32_t ctr = 10000; + uint32_t ctr = 1000000; while(--ctr && (USB->ISTR & USB_ISTR_CTR) == 0){IWDG->KR = IWDG_REFRESH;}; if((USB->ISTR & USB_ISTR_CTR) == 0){ return; @@ -229,42 +220,32 @@ void get_descriptor(config_pack_t *pack){ uint8_t descrtype = pack->wValue >> 8, descridx = pack->wValue & 0xff; switch(descrtype){ - case DEVICE_DESCRIPTOR: - DBG("DEVICE_DESCRIPTOR"); - wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor), pack->wLength); - break; - case CONFIGURATION_DESCRIPTOR: - DBG("CONFIGURATION_DESCRIPTOR"); - wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor), pack->wLength); - break; - case STRING_DESCRIPTOR: - DBG("STRING_DESCRIPTOR"); - if(descridx < iDESCR_AMOUNT){ - wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx]), pack->wLength); - DBGs(uhex2str(descridx)); - }else{ - EP_WriteIRQ(0, NULL, 0); - DBG("Wrong index"); - DBGs(uhex2str(descridx)); - } - break; - case DEVICE_QUALIFIER_DESCRIPTOR: - DBG("DEVICE_QUALIFIER_DESCRIPTOR"); - wr0(USB_DeviceQualifierDescriptor, sizeof(USB_DeviceQualifierDescriptor), pack->wLength); - break; - /* case HID_REPORT_DESCRIPTOR: - wr0(HID_ReportDescriptor, sizeof(HID_ReportDescriptor), pack->wLength); - break;*/ - default: - break; + case DEVICE_DESCRIPTOR: + wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor), pack->wLength); + break; + case CONFIGURATION_DESCRIPTOR: + wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor), pack->wLength); + break; + case STRING_DESCRIPTOR: + if(descridx < iDESCR_AMOUNT){ + wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx]), pack->wLength); + }else{ + EP_WriteIRQ(0, NULL, 0); + } + break; + case DEVICE_QUALIFIER_DESCRIPTOR: + wr0(USB_DeviceQualifierDescriptor, sizeof(USB_DeviceQualifierDescriptor), pack->wLength); + break; + default: + break; } } // change values of iInterface by content of global config void setup_interfaces(){ - for(int i = 0; i < bTotNumEndpoints; ++i){ + for(int i = 0; i < InterfacesAmount; ++i){ if(the_conf.iIlengths[i]){ - iids[i].bLength = the_conf.iIlengths[i]; + iids[i].bLength = the_conf.iIlengths[i] + 2; // +2 - for bLength and bDescriptorType memcpy(iids[i].bString, the_conf.iInterface[i], the_conf.iIlengths[i]); } iids[i].bDescriptorType = 0x03; diff --git a/F1:F103/BISS_C_encoders/usb_descr.h b/F1:F103/BISS_C_encoders/usb_descr.h index 8c0ffd2..6654d70 100644 --- a/F1:F103/BISS_C_encoders/usb_descr.h +++ b/F1:F103/BISS_C_encoders/usb_descr.h @@ -32,8 +32,16 @@ #define bNumConfigurations 1 // amount of interfaces and endpoints (except 0) used -#define bNumInterfaces 6 -#define bTotNumEndpoints 3 +#define InterfacesAmount 3 +// EP number of interface +#define EPNO(i) (i + 1) +// interface number of EPno +#define IFNO(e) (e - 1) + +// amount of interfaces (including virtual) except 0 +#define bNumInterfaces (2*InterfacesAmount) +// amount of endpoints used +#define bTotNumEndpoints (1+InterfacesAmount) // powered #define BusPowered (1<<7) diff --git a/F1:F103/BISS_C_encoders/usb_dev.c b/F1:F103/BISS_C_encoders/usb_dev.c index b61aea8..c420d2a 100644 --- a/F1:F103/BISS_C_encoders/usb_dev.c +++ b/F1:F103/BISS_C_encoders/usb_dev.c @@ -38,56 +38,41 @@ #define CONTROL_DTR 0x01 #define CONTROL_RTS 0x02 -// It's good to use debug here ONLY to debug into USART! -// never try to debug USB into USB!!! -#undef DBG -#define DBG(x) -#undef DBGs -#define DBGs(x) - extern volatile uint32_t Tms; // inbuf overflow when receiving -static volatile uint8_t bufovrfl[bTotNumEndpoints] = {0}; +static volatile uint8_t bufovrfl[InterfacesAmount] = {0}; // receive buffer: hold data until chkin() call -static uint8_t volatile rcvbuf[bTotNumEndpoints][USB_RXBUFSZ]; -static uint8_t volatile rcvbuflen[bTotNumEndpoints] = {0}; +static uint8_t volatile rcvbuf[InterfacesAmount][USB_RXBUFSZ] __attribute__((aligned(4))); +static uint8_t volatile rcvbuflen[InterfacesAmount] = {0}; // line coding #define DEFLC {115200, 0, 0, 8} -static usb_LineCoding lineCoding[bTotNumEndpoints] = {DEFLC, DEFLC, DEFLC}; +static usb_LineCoding lineCoding[InterfacesAmount] = {DEFLC, DEFLC, DEFLC}; // CDC configured and ready to use -volatile uint8_t CDCready[bTotNumEndpoints] = {0}; +volatile uint8_t CDCready[InterfacesAmount] = {0}; // ring buffers for incoming and outgoing data -static uint8_t obuf[bTotNumEndpoints][RBOUTSZ], ibuf[bTotNumEndpoints][RBINSZ]; +static uint8_t obuf[InterfacesAmount][RBOUTSZ], ibuf[InterfacesAmount][RBINSZ]; #define OBUF(N) {.data = obuf[N], .length = RBOUTSZ, .head = 0, .tail = 0} -static volatile ringbuffer rbout[bTotNumEndpoints] = {OBUF(0), OBUF(1), OBUF(2)}; +static volatile ringbuffer rbout[InterfacesAmount] = {OBUF(0), OBUF(1), OBUF(2)}; #define IBUF(N) {.data = ibuf[N], .length = RBINSZ, .head = 0, .tail = 0} -static volatile ringbuffer rbin[bTotNumEndpoints] = {IBUF(0), IBUF(1), IBUF(2)}; +static volatile ringbuffer rbin[InterfacesAmount] = {IBUF(0), IBUF(1), IBUF(2)}; // last send data size (<0 if USB transfer ready) -static volatile int lastdsz[bTotNumEndpoints] = {-1, -1, -1}; +static volatile int lastdsz[InterfacesAmount] = {-1, -1, -1}; +// check incoming data and set ACK if need static void chkin(uint8_t ifno){ - static int ovrflctr = 0; // "antistall" counter if(bufovrfl[ifno]) return; // allow user to know that previous buffer was overflowed and cleared if(!rcvbuflen[ifno]) return; int w = RB_write((ringbuffer*)&rbin[ifno], (uint8_t*)rcvbuf[ifno], rcvbuflen[ifno]); - if(w < 0){ // buffer busy - DBG("Can't write into buffer: busy"); + if(w < 0){ return; - }else if(w == 0){ // no enough space or (WTF) incoming string larger than buffer size - if(rcvbuflen[ifno] > rbin[ifno].length || ++ovrflctr > 9999){ - bufovrfl[ifno] = 1; // real overflow in case if ringbuffer's size less than USB buffer - ovrflctr = 0; - }else{ - return; // not enough space - } } - DBG("Put data into buffer"); + if(w != rcvbuflen[ifno]) bufovrfl[ifno] = 1; rcvbuflen[ifno] = 0; - uint16_t status = KEEP_DTOG(USB->EPnR[1+ifno]); // don't change DTOG - USB->EPnR[1+ifno] = (status & ~(USB_EPnR_STAT_TX|USB_EPnR_CTR_RX)) ^ USB_EPnR_STAT_RX; // prepare to get next data portion + uint16_t status = KEEP_DTOG(USB->EPnR[EPNO(ifno)]); // don't change DTOG + USB->EPnR[EPNO(ifno)] = (status & ~(USB_EPnR_STAT_TX|USB_EPnR_CTR_RX)) ^ USB_EPnR_STAT_RX; // prepare to get next data portion } // called from transmit EP to send next data portion or by user - when new transmission starts @@ -100,97 +85,83 @@ static void send_next(uint8_t ifno){ } if(buflen == 0){ if(lastdsz[ifno] == USB_TXBUFSZ){ - EP_Write(1+ifno, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + EP_Write(EPNO(ifno), NULL, 0); // send ZLP after 64 bits packet when nothing more to send lastdsz[ifno] = 0; }else lastdsz[ifno] = -1; // OK. User can start sending data return; }else if(buflen < 0){ - DBG("Buff busy"); lastdsz[ifno] = -1; return; } - DBG("Got data in buf"); - DBGs(uhex2str(buflen)); - DBGs(uhex2str(ifno)); - EP_Write(1+ifno, (uint8_t*)usbbuff, buflen); + EP_Write(EPNO(ifno), (uint8_t*)usbbuff, buflen); lastdsz[ifno] = buflen; } // data IN/OUT handler static void rxtx_handler(){ - uint8_t epno = (USB->ISTR & USB_ISTR_EPID), ifno = epno - 1; - DBG("rxtx_handler"); - DBGs(uhex2str(ifno)); - if(epno > bTotNumEndpoints){ - DBG("wrong ifno"); + uint8_t epno = (USB->ISTR & USB_ISTR_EPID), ifno = IFNO(epno); + if(ifno > InterfacesAmount-1){ return; } uint16_t epstatus = KEEP_DTOG(USB->EPnR[epno]); if(RX_FLAG(epstatus)){ // receive data - DBG("Got data"); if(rcvbuflen[ifno]){ bufovrfl[ifno] = 1; // lost last data rcvbuflen[ifno] = 0; - DBG("OVERFULL"); } rcvbuflen[ifno] = EP_Read(epno, (uint8_t*)rcvbuf[ifno]); - DBGs(uhex2str(rcvbuflen[ifno])); USB->EPnR[epno] = epstatus & ~(USB_EPnR_CTR_RX | USB_EPnR_STAT_RX | USB_EPnR_STAT_TX); // keep RX in STALL state until read data chkin(ifno); // try to write current data into RXbuf if it's not busy }else{ // tx successfull - DBG("Tx OK"); USB->EPnR[epno] = (epstatus & ~(USB_EPnR_CTR_TX | USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; send_next(ifno); } } -// weak handlers: change them somewhere else if you want to setup USART -// SET_LINE_CODING -void WEAK linecoding_handler(uint8_t ifno, usb_LineCoding *lc){ - lineCoding[ifno] = *lc; - DBG("linecoding_handler"); - DBGs(uhex2str(ifno)); -} - -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; } - rcvbuflen[ifno] = 0; +} + +// SET_LINE_CODING +void linecoding_handler(uint8_t ifno, usb_LineCoding *lc){ + lineCoding[ifno] = *lc; } // SET_CONTROL_LINE_STATE -void WEAK clstate_handler(uint8_t ifno, uint16_t val){ - DBG("clstate_handler"); - DBGs(uhex2str(ifno)); - DBGs(uhex2str(val)); - if(val) clearbufs(ifno); // clear buffers on connect +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){ + clearRbuf(ifno); + clearTbuf(ifno); + EP_reset(EPNO(ifno)); + } } // SEND_BREAK - disconnect interface and clear its buffers -void WEAK break_handler(uint8_t ifno){ +// this is a fake handler as classic CDC ACM never receives this +void break_handler(uint8_t ifno){ CDCready[ifno] = 0; - DBG("break_handler()"); - DBGs(uhex2str(ifno)); } -// USB is configured: setup endpoints +// Interface is configured: setup endpoints void set_configuration(){ - DBG("set_configuration()"); - for(int i = 0; i < bTotNumEndpoints; ++i){ + for(int i = 0; i < InterfacesAmount; ++i){ IWDG->KR = IWDG_REFRESH; - int r = EP_Init(1+i, EP_TYPE_BULK, USB_TXBUFSZ, USB_RXBUFSZ, rxtx_handler); + int r = EP_Init(EPNO(i), EP_TYPE_BULK, USB_TXBUFSZ, USB_RXBUFSZ, rxtx_handler); if(r){ - DBG("Can't init EP"); - DBGs(uhex2str(i)); - DBGs(uhex2str(r)); + // OOPS, can't init EP. What to do? Cry? + break; } } } @@ -200,45 +171,33 @@ void usb_class_request(config_pack_t *req, uint8_t *data, uint16_t datalen){ uint8_t recipient = REQUEST_RECIPIENT(req->bmRequestType); uint8_t dev2host = (req->bmRequestType & 0x80) ? 1 : 0; uint8_t ifno = req->wIndex >> 1; - if(ifno > bTotNumEndpoints-1 && ifno != 0xff){ - DBG("wrong ifno"); + if(ifno > InterfacesAmount-1){ // wrong interface number + EP_WriteIRQ(0, NULL, 0); return; } - DBG("usb_class_request"); - DBGs(uhex2str(req->bRequest)); switch(recipient){ - case REQ_RECIPIENT_INTERFACE: - switch(req->bRequest){ - case SET_LINE_CODING: - DBG("SET_LINE_CODING"); - if(!data || !datalen) break; // wait for data - if(datalen == sizeof(usb_LineCoding)) - linecoding_handler(ifno, (usb_LineCoding*)data); - break; - case GET_LINE_CODING: - DBG("GET_LINE_CODING"); - EP_WriteIRQ(0, (uint8_t*)&lineCoding[ifno], sizeof(lineCoding)); - break; - case SET_CONTROL_LINE_STATE: - DBG("SET_CONTROL_LINE_STATE"); - clstate_handler(ifno, req->wValue); - break; - case SEND_BREAK: - DBG("SEND_BREAK"); - break_handler(ifno); - break; - default: - DBG("Wrong"); - DBGs(uhex2str(req->bRequest)); - DBGs(uhex2str(datalen)); - } + case REQ_RECIPIENT_INTERFACE: + switch(req->bRequest){ + case SET_LINE_CODING: + if(!data || !datalen) break; // wait for data + if(datalen == sizeof(usb_LineCoding)) + linecoding_handler(ifno, (usb_LineCoding*)data); + break; + case GET_LINE_CODING: + EP_WriteIRQ(0, (uint8_t*)&lineCoding[ifno], sizeof(lineCoding)); + break; + case SET_CONTROL_LINE_STATE: + clstate_handler(ifno, req->wValue); + break; + case SEND_BREAK: + break_handler(ifno); + break; + default: // WTF? + break; + } break; - default: - DBG("Wrong"); - DBGs(uhex2str(recipient)); - DBGs(uhex2str(datalen)); - DBGs(uhex2str(req->bRequest)); - if(dev2host) EP_WriteIRQ(0, NULL, 0); + default: // WTF? + if(dev2host) EP_WriteIRQ(0, NULL, 0); } if(!dev2host) EP_WriteIRQ(0, NULL, 0); } @@ -248,7 +207,6 @@ int USB_sendall(uint8_t ifno){ uint32_t T0 = Tms; while(lastdsz[ifno] > 0){ if(Tms - T0 > DISCONN_TMOUT){ - break_handler(ifno); return FALSE; } if(!CDCready[ifno]) return FALSE; @@ -257,17 +215,25 @@ 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; - 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; @@ -285,7 +251,9 @@ 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){ + send_next(ifno); + } return TRUE; } @@ -295,7 +263,6 @@ int USB_putbyte(uint8_t ifno, uint8_t byte){ uint32_t T0 = Tms; while((l = RB_write((ringbuffer*)&rbout[ifno], &byte, 1)) != 1){ if(Tms - T0 > DISCONN_TMOUT){ - break_handler(ifno); return FALSE; } if(!CDCready[ifno]) return FALSE; @@ -306,7 +273,9 @@ 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){ + send_next(ifno); + } return TRUE; } @@ -317,6 +286,10 @@ int USB_sendstr(uint8_t ifno, const char *string){ return USB_send(ifno, (const uint8_t*)string, len); } +int USB_rcvlen(uint8_t ifno){ + return RB_datalen((ringbuffer*)&rbin[ifno]); +} + /** * @brief USB_receive - get binary data from receiving ring-buffer * @param buf (i) - buffer for received data @@ -324,17 +297,15 @@ int USB_sendstr(uint8_t ifno, const char *string){ * @return amount of received bytes (negative, if overfull happened) */ 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]){ - DBG("Buffer overflow"); - DBGs(uhex2str(ifno)); - while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); // run watchdog in case of problems + clearRbuf(ifno); bufovrfl[ifno] = 0; return -1; } int sz = RB_read((ringbuffer*)&rbin[ifno], buf, len); if(sz < 0) return 0; // buffer in writting state - DBG("usb read"); return sz; } @@ -345,24 +316,22 @@ int USB_receive(uint8_t ifno, uint8_t *buf, int len){ * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) */ 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; } int l = RB_readto((ringbuffer*)&rbin[ifno], '\n', (uint8_t*)buf, len); if(l < 1){ - //if(rbin[ifno].length < 1 + RB_datalen((ringbuffer*)&rbin[ifno])){ // buffer is full but no '\n' found - if(RB_datalen((ringbuffer*)&rbin[ifno]) >= len){ - CMDWRn("OVERFULL!"); - while(1 != RB_clearbuf((ringbuffer*)&rbin[ifno])); + 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 + clearRbuf(ifno); return -1; } return 0; } - if(l == 0) return 0; buf[l-1] = 0; // replace '\n' with strend return l; } - diff --git a/F1:F103/BISS_C_encoders/usb_dev.h b/F1:F103/BISS_C_encoders/usb_dev.h index 7308630..064f473 100644 --- a/F1:F103/BISS_C_encoders/usb_dev.h +++ b/F1:F103/BISS_C_encoders/usb_dev.h @@ -40,14 +40,14 @@ typedef struct { uint8_t bDataBits; } __attribute__ ((packed)) usb_LineCoding; -extern volatile uint8_t CDCready[bTotNumEndpoints]; +extern volatile uint8_t CDCready[InterfacesAmount]; void break_handler(uint8_t ifno); void clstate_handler(uint8_t ifno, uint16_t val); void linecoding_handler(uint8_t ifno, usb_LineCoding *lc); // as ugly CDC have no BREAK after disconnected client in non-canonical mode, we should use timeout - more than 2ms -#define DISCONN_TMOUT (1000) +#define DISCONN_TMOUT (2) // sizes of ringbuffers for outgoing and incoming data #define RBOUTSZ (512) @@ -69,9 +69,11 @@ void linecoding_handler(uint8_t ifno, usb_LineCoding *lc); #define DBGs(s) #endif +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); int USB_sendstr(uint8_t ifno, const char *string); +int USB_rcvlen(uint8_t ifno); int USB_receive(uint8_t ifno, uint8_t *buf, int len); int USB_receivestr(uint8_t ifno, char *buf, int len); diff --git a/F1:F103/BISS_C_encoders/usb_lib.c b/F1:F103/BISS_C_encoders/usb_lib.c index 2779402..8ed4e0e 100644 --- a/F1:F103/BISS_C_encoders/usb_lib.c +++ b/F1:F103/BISS_C_encoders/usb_lib.c @@ -20,15 +20,10 @@ #include "usb_descr.h" #include "usb_dev.h" -#undef DBG -#define DBG(x) -#undef DBGs -#define DBGs(x) - static ep_t endpoints[STM32ENDPOINTS]; static uint16_t USB_Addr = 0; -static uint8_t setupdatabuf[EP0DATABUF_SIZE]; +static uint8_t setupdatabuf[EP0DATABUF_SIZE] __attribute__((aligned(4))); static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; volatile uint8_t usbON = 0; // device is configured and active @@ -37,20 +32,15 @@ static inline void std_d2h_req(){ uint16_t st = 0; switch(setup_packet->bRequest){ case GET_DESCRIPTOR: - DBG("GET_DESCRIPTOR"); get_descriptor(setup_packet); break; case GET_STATUS: - DBG("GET_STATUS"); EP_WriteIRQ(0, (uint8_t *)&st, 2); // send status: Bus Powered break; case GET_CONFIGURATION: - DBG("GET_CONFIGURATION"); EP_WriteIRQ(0, (uint8_t*)&configuration, 1); break; default: - DBG("Wrong"); - DBGs(uhex2str(setup_packet->bRequest)); EP_WriteIRQ(0, NULL, 0); break; } @@ -59,21 +49,16 @@ static inline void std_d2h_req(){ static inline void std_h2d_req(){ switch(setup_packet->bRequest){ case SET_ADDRESS: - DBG("SET_ADDRESS"); // new address will be assigned later - after acknowlegement or request to host USB_Addr = setup_packet->wValue; - DBGs(uhex2str(USB_Addr)); break; case SET_CONFIGURATION: - DBG("SET_CONFIGURATION"); // Now device configured configuration = setup_packet->wValue; set_configuration(); usbON = 1; break; default: - DBG("Wrong"); - DBGs(uhex2str(setup_packet->bRequest)); break; } } @@ -83,7 +68,6 @@ void WEAK usb_standard_request(){ uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; switch(recipient){ case REQ_RECIPIENT_DEVICE: - DBG("REQ_RECIPIENT_DEVICE"); if(dev2host){ std_d2h_req(); }else{ @@ -91,49 +75,34 @@ void WEAK usb_standard_request(){ } break; case REQ_RECIPIENT_INTERFACE: - DBG("REQ_RECIPIENT_INTERFACE"); if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ get_descriptor(setup_packet); } break; case REQ_RECIPIENT_ENDPOINT: - DBG("REQ_RECIPIENT_ENDPOINT"); if(setup_packet->bRequest == CLEAR_FEATURE){ - }else{ - DBG("Wrong"); - } + }else{ /* wrong */ } break; default: - DBG("Wrong"); - DBGs(uhex2str(recipient)); break; } if(!dev2host) EP_WriteIRQ(0, NULL, 0); } void WEAK usb_class_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ - DBG("REQ_TYPE_CLASS"); switch(req->bRequest){ case GET_INTERFACE: - DBG("GI"); break; case SET_CONFIGURATION: // set featuring by req->wValue - DBG("SC"); break; default: - DBG("Wrong"); - DBGs(uhex2str(req->bmRequestType)); - DBGs(uhex2str(req->bRequest)); - DBGs(uhex2str(req->wIndex)); - DBGs(uhex2str(req->wLength)); - DBGs(uhex2str(req->wValue)); + break; } if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev EP_WriteIRQ(0, NULL, 0); } void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t _U_ datalen){ - DBG("vendor"); if(0 == (setup_packet->bmRequestType & 0x80)) // host2dev EP_WriteIRQ(0, NULL, 0); } @@ -149,18 +118,16 @@ bmRequestType: 76543210 */ static void EP0_Handler(){ uint8_t ep0dbuflen = 0; - uint8_t ep0databuf[EP0DATABUF_SIZE]; + uint8_t ep0databuf[EP0DATABUF_SIZE] __attribute__((aligned(4))); uint16_t epstatus = KEEP_DTOG(USB->EPnR[0]); // EP0R on input -> return this value after modifications int rxflag = RX_FLAG(epstatus); - if(rxflag){ DBG("EP0_Handler"); } // check direction if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack - DBG("USB_EPnR_SETUP"); EP_Read(0, setupdatabuf); // interrupt handler will be called later }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf - if(endpoints[0].rx_cnt){ DBG("data"); DBGs(uhex2str(endpoints[0].rx_cnt));} + //if(endpoints[0].rx_cnt){ } ep0dbuflen = EP_Read(0, ep0databuf); } } @@ -169,23 +136,16 @@ static void EP0_Handler(){ switch(reqtype){ case REQ_TYPE_STANDARD: if(SETUP_FLAG(epstatus)){ - DBG("REQ_TYPE_STANDARD"); usb_standard_request(); - }else{ - DBG("REQ_TYPE_STANDARD without SETUP_FLAG"); - } + }else{ } break; case REQ_TYPE_CLASS: - DBG("REQ_TYPE_CLASS"); usb_class_request(setup_packet, ep0databuf, ep0dbuflen); break; case REQ_TYPE_VENDOR: - DBG("REQ_TYPE_VENDOR"); usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); break; default: - DBG("Wrong"); - DBGs(uhex2str(reqtype)); EP_WriteIRQ(0, NULL, 0); break; } @@ -195,8 +155,6 @@ static void EP0_Handler(){ if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ USB->DADDR = USB_DADDR_EF | USB_Addr; usbON = 0; - DBG("Enum"); - DBGs(uhex2str(USB_Addr)); } } //epstatus = KEEP_DTOG(USB->EPnR[0]); @@ -214,9 +172,14 @@ static void EP0_Handler(){ */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ if(size > endpoints[number].txbufsz) size = endpoints[number].txbufsz; +#ifndef USB32 uint16_t N2 = (size + 1) >> 1; // the buffer is 16-bit, so we should copy data as it would be uint16_t uint16_t *buf16 = (uint16_t *)buf; +#else + int N4 = (size + 3) >> 2; + uint32_t *buf32 = (uint32_t *)buf; +#endif #if defined USB1_16 // very bad: what if `size` is odd? uint32_t *out = (uint32_t *)endpoints[number].tx_buf; @@ -225,13 +188,19 @@ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ } #elif defined USB2_16 // use memcpy instead? - for(int i = 0; i < N2; i++){ + for(int i = 0; i < N2; ++i){ endpoints[number].tx_buf[i] = buf16[i]; } +#elif defined USB32 + for(int i = 0; i < N4; ++i) endpoints[number].tx_buf[i] = buf32[i]; #else -#error "Define USB1_16 or USB2_16" +#error "Define USB1_16 / USB2_16 / USB32" #endif +#ifndef USB32 USB_BTABLE->EP[number].USB_COUNT_TX = size; +#else + USB_BTABLE->EP[number].USB_ADDR_COUNT_TX = (USB_BTABLE->EP[number].USB_ADDR_COUNT_TX & 0xffff) | (size << 16); +#endif } /** @@ -266,8 +235,12 @@ int EP_Read(uint8_t number, uint8_t *buf){ // use memcpy instead? for(int i = 0; i < sz; ++i) buf[i] = endpoints[number].rx_buf[i]; +#elif defined USB32 + uint32_t *u32buf = (uint32_t*) buf; + int N4 = (sz + 3) >> 2; + for(int i = 0; i < N4; ++i) u32buf[i] = endpoints[number].rx_buf[i]; #else -#error "Define USB1_16 or USB2_16" +#error "Define USB1_16 / USB2_16 / USB32" #endif return sz; } @@ -284,11 +257,16 @@ static uint16_t lastaddr = LASTADDR_DEFAULT; * @return 0 if all OK */ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)){ +#ifdef STM32G0 + // in STM32G0 all buffers should be aligned by 32 bits + if(txsz & 3) txsz = ((txsz >> 2)+1) << 2; + if(rxsz & 3) rxsz = ((rxsz >> 2)+1) << 2; +#endif if(number >= STM32ENDPOINTS) return 4; // out of configured amount if(txsz > USB_BTABLE_SIZE/ACCESSZ || rxsz > USB_BTABLE_SIZE/ACCESSZ) return 1; // buffer too large if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE/ACCESSZ) return 2; // out of btable USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); - USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; + USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX; if(rxsz & 1) return 3; // wrong rx buffer size uint16_t countrx = 0; if(rxsz < 64) countrx = rxsz / 2; @@ -296,25 +274,49 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f if(rxsz & 0x1f) return 3; // should be multiple of 32 countrx = 31 + rxsz / 32; } - USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; +#ifdef USB32 + endpoints[number].tx_buf = (uint32_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); +#else endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); +#endif endpoints[number].txbufsz = txsz; - lastaddr += txsz; +#ifdef USB32 + USB_BTABLE->EP[number].USB_ADDR_COUNT_TX = (uint32_t) lastaddr; +#else + USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; USB_BTABLE->EP[number].USB_COUNT_TX = 0; - USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; +#endif + lastaddr += txsz; +#ifdef USB32 + endpoints[number].rx_buf = (uint32_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + USB_BTABLE->EP[number].USB_ADDR_COUNT_RX = (uint32_t) lastaddr | countrx << 26; +#else endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); - lastaddr += rxsz; + USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; +#endif + lastaddr += rxsz; endpoints[number].func = func; return 0; } +// refresh EP after interface reconnected +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 void USB_IRQ(){ uint32_t CNTR = USB->CNTR; USB->CNTR = 0; - if(USB->ISTR & USB_ISTR_RESET){ - DBG("USB_ISTR_RESET"); + uint32_t istr = USB->ISTR; + if(istr & USB_ISTR_RESET){ usbON = 0; // Reinit registers CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM; @@ -323,45 +325,56 @@ void USB_IRQ(){ lastaddr = LASTADDR_DEFAULT; // clear address, leave only enable bit USB->DADDR = USB_DADDR_EF; - USB->ISTR = ~USB_ISTR_RESET; + //USB->ISTR = ~(USB_ISTR_RESET); // clear all flags if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0BUFSZ, USB_EP0BUFSZ, EP0_Handler)){ - DBG("Can't init EP0"); return; }; } - if(USB->ISTR & USB_ISTR_CTR){ + if(istr & USB_ISTR_CTR){ // EP number - uint8_t n = USB->ISTR & USB_ISTR_EPID; + uint8_t n = istr & USB_ISTR_EPID; + if (istr & USB_ISTR_DIR){ // OUT + }else{ // IN + } // copy received bytes amount - endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter + endpoints[n].rx_cnt = +#ifdef USB32 + (USB_BTABLE->EP[n].USB_ADDR_COUNT_RX >> 16) & 0x3FF; +#else + USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter +#endif // call EP handler if(endpoints[n].func) endpoints[n].func(); } - if(USB->ISTR & USB_ISTR_WKUP){ // wakeup - DBG("USB_ISTR_WKUP"); -#ifndef STM32F0 - CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM); // clear suspend flags -#else + if(istr & USB_ISTR_WKUP){ // wakeup +#if defined STM32F0 CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM); -#endif - USB->ISTR = ~USB_ISTR_WKUP; - } - if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep - DBG("USB_ISTR_SUSP"); - usbON = 0; -#ifndef STM32F0 - CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM; +#elif defined STM32G0 + CNTR &= ~(USB_CNTR_SUSPEN | USB_CNTR_PDWN | USB_CNTR_WKUPM); #else + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM); // clear suspend flags +#endif + //USB->ISTR = ~USB_ISTR_WKUP; + } + if(istr & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + usbON = 0; +#if defined STM32F0 CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM; +#elif defined STM32G0 + CNTR |= USB_CNTR_SUSPEN | USB_CNTR_WKUPM; +#else + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM; #endif CNTR &= ~(USB_CNTR_SUSPM); - USB->ISTR = ~USB_ISTR_SUSP; + //USB->ISTR = ~USB_ISTR_SUSP; } + USB->ISTR = 0; // clear all flags USB->CNTR = CNTR; // rewoke interrupts } // here we suppose that all PIN settings done in hw_setup earlier void USB_setup(){ + lastaddr = LASTADDR_DEFAULT; // clear last address settings #if defined STM32F3 NVIC_DisableIRQ(USB_LP_IRQn); // remap USB LP & Wakeup interrupts to 75 and 76 - works only on pure F303 @@ -371,6 +384,7 @@ void USB_setup(){ NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); #elif defined STM32F0 + // All is clocking from HSI48 NVIC_DisableIRQ(USB_IRQn); RCC->APB1ENR |= RCC_APB1ENR_CRSEN; RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB @@ -383,16 +397,33 @@ void USB_setup(){ CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only RCC->CFGR |= RCC_CFGR_SW; +#elif defined STM32G0 + NVIC_DisableIRQ(USB_UCPD1_2_IRQn); + PWR->CR2 |= PWR_CR2_USV; // enable USB powering + //RCC->APBENR2 |= RCC_APBENR2_SYSCFGEN; // enable tacting of SYSCFG + // independent clocking of USB from HSI48 + RCC->CR |= RCC_CR_HSI48ON; + uint32_t tmout = 16000000; + while(!(RCC->CR & RCC_CR_HSI48RDY)) if(--tmout == 0) break; + RCC->CCIPR2 &= ~RCC_CCIPR2_USBSEL; // select HSI48 for USB + RCC->APBENR1 |= RCC_APBENR1_CRSEN; // CRS clocking + CRS->CFGR = (31LL << CRS_CFGR_FELIM_Pos) | // tolerance (usually 31) + (48000LL / 1LL - 1LL) << CRS_CFGR_RELOAD_Pos | // 48MHz / 1kHZ (SOF) + CRS_CFGR_SYNCSRC_1; // USB SOF as sync source (0x2) + CRS->CR |= CRS_CR_AUTOTRIMEN | CRS_CR_CEN; // Enable autotrim and turn on Clock Recovery System + RCC->APBENR1 |= RCC_APBENR1_USBEN; #endif +#ifndef STM32G0 RCC->APB1ENR |= RCC_APB1ENR_USBEN; - //?? USB->CNTR = USB_CNTR_FRES; // Force USB Reset - for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms - USB->CNTR = 0; USB->BTABLE = 0; +#else + USB->CNTR = USB_CNTR_USBRST; +#endif + for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms + USB->CNTR = USB_CNTR_RESETM; // allow only reset interrupts USB->DADDR = 0; USB->ISTR = 0; - USB->CNTR = USB_CNTR_RESETM; // allow only reset interrupts #if defined STM32F3 NVIC_EnableIRQ(USB_LP_IRQn); #elif defined STM32F1 @@ -400,8 +431,11 @@ void USB_setup(){ #elif defined STM32F0 USB->BCDR |= USB_BCDR_DPPU; NVIC_EnableIRQ(USB_IRQn); +#elif defined STM32G0 + USB->BCDR |= USB_BCDR_DPPU; // turn ON DP pullup + NVIC_EnableIRQ(USB_UCPD1_2_IRQn); #endif - setup_interfaces(); + setup_interfaces(); // refresh interfaces' names } @@ -411,4 +445,6 @@ void usb_lp_isr() __attribute__ ((alias ("USB_IRQ"))); void usb_lp_can_rx0_isr() __attribute__ ((alias ("USB_IRQ"))); #elif defined STM32F0 void usb_isr() __attribute__ ((alias ("USB_IRQ"))); +#elif defined STM32G0 +void usb_ucpd1_2_isr() __attribute__ ((alias ("USB_IRQ"))); #endif diff --git a/F1:F103/BISS_C_encoders/usb_lib.h b/F1:F103/BISS_C_encoders/usb_lib.h index c6e70b0..1dfb3a8 100644 --- a/F1:F103/BISS_C_encoders/usb_lib.h +++ b/F1:F103/BISS_C_encoders/usb_lib.h @@ -19,6 +19,10 @@ #include #include +#ifndef _U_ +#define _U_ __attribute__((unused)) +#endif + /****************************************************************** * Hardware registers etc * *****************************************************************/ @@ -30,6 +34,8 @@ #define USB_BASE ((uint32_t)0x40005C00) #elif defined STM32F3 #include +#elif defined STM32G0 +#include #endif // max endpoints number @@ -38,14 +44,16 @@ * Buffers size definition **/ -// F0 - USB2_16; F1 - USB1_16; F3 - 1/2 depending on series -#if !defined USB1_16 && !defined USB2_16 +// F0 - USB2_16; F1 - USB1_16; F3 - 1/2 depending on series; G0 - USB32 +#if !defined USB1_16 && !defined USB2_16 && !defined USB32 #if defined STM32F0 #define USB2_16 #elif defined STM32F1 #define USB1_16 +#elif defined STM32G0 +#define USB32 #else -#error "Can't determine USB1_16 or USB2_16, define by hands" +#error "Can't determine USB1_16/USB2_16/USB32, define by hands" #endif #endif @@ -59,8 +67,8 @@ #if defined STM32F0 #define USB_BTABLE_SIZE 1024 #elif defined STM32F3 -#define USB_BTABLE_SIZE 512 -#warning "Please, check real buffer size due to docs" +#define USB_BTABLE_SIZE 1024 +//#warning "Please, check real buffer size due to docs" #else #error "define STM32F0 or STM32F3" #endif @@ -68,16 +76,21 @@ #if defined STM32F0 #define USB_BTABLE_SIZE 768 #elif defined STM32F3 -#define USB_BTABLE_SIZE 512 -#warning "Please, check real buffer size due to docs" +#define USB_BTABLE_SIZE 768 +#elif defined STM32G0 +#define USB_BTABLE_SIZE 2048 +//#warning "Please, check real buffer size due to docs" #else // STM32F103: 1024 bytes but with 32-bit addressing #define USB_BTABLE_SIZE 1024 #endif #endif // NOCAN // first 64 bytes of USB_BTABLE are registers! - +#ifndef STM32G0 #define USB_BTABLE_BASE 0x40006000 +#else +#define USB_BTABLE_BASE 0x40009800 +#endif #define USB ((USB_TypeDef *) USB_BASE) #ifdef USB_BTABLE @@ -120,8 +133,12 @@ typedef struct { __IO uint32_t ISTR; __IO uint32_t FNR; __IO uint32_t DADDR; +#ifndef USB32 __IO uint32_t BTABLE; -#ifdef STM32F0 +#else + __IO uint32_t RESERVED1; // there's no BTABLE register in STM32G0 +#endif +#if defined STM32F0 || defined USB32 __IO uint32_t LPMCSR; __IO uint32_t BCDR; #endif @@ -135,16 +152,19 @@ typedef struct{ __IO uint16_t USB_ADDR_RX; __IO uint16_t USB_COUNT_RX; #define ACCESSZ (1) -#define BUFTYPE uint8_t #elif defined USB1_16 __IO uint32_t USB_ADDR_TX; __IO uint32_t USB_COUNT_TX; __IO uint32_t USB_ADDR_RX; __IO uint32_t USB_COUNT_RX; #define ACCESSZ (2) -#define BUFTYPE uint16_t +#elif defined USB32 + // 32-bit registers: addr & count in one! + __IO uint32_t USB_ADDR_COUNT_TX; + __IO uint32_t USB_ADDR_COUNT_RX; +#define ACCESSZ (1) #else -#error "Define USB1_16 or USB2_16" +#error "Define USB1_16 (16 bits over 32bit register), USB2_16 (16 bits over 16 bit register) or USB32 (32 bist over 32 bit register)" #endif } USB_EPDATA_TypeDef; @@ -303,9 +323,17 @@ typedef struct { // endpoints state typedef struct{ +#ifdef USB32 + uint32_t *tx_buf; // transmission buffer address +#else uint16_t *tx_buf; // transmission buffer address +#endif uint16_t txbufsz; // transmission buffer size +#ifdef USB32 + uint32_t *rx_buf; // reception buffer address +#else uint8_t *rx_buf; // reception buffer address +#endif void (*func)(); // endpoint action function unsigned rx_cnt : 10; // received data counter } ep_t; @@ -317,6 +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 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/F1:F103/BISS_C_encoders/version.inc b/F1:F103/BISS_C_encoders/version.inc index ebc3fa9..b4b67d4 100644 --- a/F1:F103/BISS_C_encoders/version.inc +++ b/F1:F103/BISS_C_encoders/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "144" -#define BUILD_DATE "2026-02-13" +#define BUILD_NUMBER "147" +#define BUILD_DATE "2026-03-23"