diff --git a/F0-nolib/usbcdc/can.c b/F0-nolib/usbcdc/can.c index 9f8b508..9b3d84d 100644 --- a/F0-nolib/usbcdc/can.c +++ b/F0-nolib/usbcdc/can.c @@ -185,7 +185,7 @@ void can_proc(){ CAN_setup(); } LED_off(LED1); -#ifdef EBUG +#if 0 static uint32_t esr, msr, tsr; uint32_t msr_now = CAN->MSR & 0xf; if(esr != CAN->ESR || msr != msr_now || tsr != CAN->TSR){ diff --git a/F0-nolib/usbcdc/main.c b/F0-nolib/usbcdc/main.c index 32a3059..8b59dde 100644 --- a/F0-nolib/usbcdc/main.c +++ b/F0-nolib/usbcdc/main.c @@ -86,6 +86,7 @@ int main(void){ if(lastT > Tms || Tms - lastT > 499){ LED_blink(LED0); lastT = Tms; + transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s } can_proc(); usb_proc(); @@ -109,6 +110,9 @@ int main(void){ if(L == 2 && txt[1] == '\n'){ L = 0; switch(_1st){ + case 'f': + transmit_tbuf(); + break; case 'B': can_send_broadcast(); break; @@ -136,6 +140,7 @@ int main(void){ break; default: // help SEND( + "'f' - flush UART buffer\n" "'B' - send broadcast dummy byte\n" "'C' - send dummy byte over CAN\n" "'G' - get CAN address\n" @@ -148,7 +153,8 @@ int main(void){ } } if(L){ // text waits for sending - while(LINE_BUSY == usart_send(txt, L)); + txt[L] = 0; + usart_send(txt); L = 0; } } diff --git a/F0-nolib/usbcdc/usart.c b/F0-nolib/usbcdc/usart.c index b00dbf7..8e1dcab 100644 --- a/F0-nolib/usbcdc/usart.c +++ b/F0-nolib/usbcdc/usart.c @@ -24,7 +24,8 @@ #include extern volatile uint32_t Tms; -static int datalen[2] = {0,0}; // received data line length (including '\n') +static volatile int idatalen[2] = {0,0}; // received data line length (including '\n') +static volatile int odatalen[2] = {0,0}; volatile int linerdy = 0, // received data ready dlen = 0, // length of data (including '\n') in current buffer @@ -33,8 +34,8 @@ volatile int linerdy = 0, // received data ready ; -int rbufno = 0; // current rbuf number -static char rbuf[UARTBUFSZ][2], tbuf[UARTBUFSZ]; // receive & transmit buffers +int rbufno = 0, tbufno = 0; // current rbuf/tbuf numbers +static char rbuf[2][UARTBUFSZI], tbuf[2][UARTBUFSZO]; // receive & transmit buffers static char *recvdata = NULL; /** @@ -51,46 +52,44 @@ int usart_getline(char **line){ return dlen; } -TXstatus usart_send(const char *str, int len){ - if(!txrdy) return LINE_BUSY; - if(len > UARTBUFSZ) return STR_TOO_LONG; +// transmit current tbuf and swap buffers +void transmit_tbuf(){ + while(!txrdy); // wait for previos buffer transmission + register int l = odatalen[tbufno]; + if(!l) return; txrdy = 0; - memcpy(tbuf, str, len); + odatalen[tbufno] = 0; #if USARTNUM == 2 DMA1_Channel4->CCR &= ~DMA_CCR_EN; - DMA1_Channel4->CNDTR = len; + DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem + DMA1_Channel4->CNDTR = l; DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission #elif USARTNUM == 1 DMA1_Channel2->CCR &= ~DMA_CCR_EN; - DMA1_Channel2->CNDTR = len; + DMA1_Channel2->CMAR = (uint32_t) tbuf[tbufno]; // mem + DMA1_Channel2->CNDTR = l; DMA1_Channel2->CCR |= DMA_CCR_EN; #else #error "Not implemented" #endif - return ALL_OK; -} - -TXstatus usart_send_blocking(const char *str, int len){ - while(!txrdy); - int i; - bufovr = 0; - for(i = 0; i < len; ++i){ - USARTX->TDR = *str++; - while(!(USARTX->ISR & USART_ISR_TXE)); - } - return ALL_OK; + tbufno = !tbufno; } void usart_putchar(const char ch){ - while(!txrdy); - USARTX->TDR = ch; - while(!(USARTX->ISR & USART_ISR_TXE)); + if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); + tbuf[tbufno][odatalen[tbufno]++] = ch; +} + +void usart_send(const char *str){ + while(*str){ + if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); + tbuf[tbufno][odatalen[tbufno]++] = *str++; + } } void newline(){ - while(!txrdy); - USARTX->TDR = '\n'; - while(!(USARTX->ISR & USART_ISR_TXE)); + usart_putchar('\n'); + transmit_tbuf(); } @@ -105,7 +104,6 @@ void usart_setup(){ GPIOA->AFR[1] = (GPIOA->AFR[1] &~GPIO_AFRH_AFRH7) | 1 << (7 * 4); // PA15 // DMA: Tx - Ch4 DMA1_Channel4->CPAR = (uint32_t) &USART2->TDR; // periph - DMA1_Channel4->CMAR = (uint32_t) tbuf; // mem DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq // Tx CNDTR set @ each transmission due to data size NVIC_SetPriority(DMA1_Channel4_5_IRQn, 3); @@ -166,22 +164,22 @@ void usart1_isr(){ #ifdef CHECK_TMOUT if(tmout && Tms >= tmout){ // set overflow flag bufovr = 1; - datalen[rbufno] = 0; + idatalen[rbufno] = 0; } tmout = Tms + TIMEOUT_MS; if(!tmout) tmout = 1; // prevent 0 #endif // read RDR clears flag uint8_t rb = USARTX->RDR; - if(datalen[rbufno] < UARTBUFSZ){ // put next char into buf - rbuf[rbufno][datalen[rbufno]++] = rb; + if(idatalen[rbufno] < UARTBUFSZI){ // put next char into buf + rbuf[rbufno][idatalen[rbufno]++] = rb; if(rb == '\n'){ // got newline - line ready linerdy = 1; - dlen = datalen[rbufno]; + dlen = idatalen[rbufno]; recvdata = rbuf[rbufno]; // prepare other buffer rbufno = !rbufno; - datalen[rbufno] = 0; + idatalen[rbufno] = 0; #ifdef CHECK_TMOUT // clear timeout at line end tmout = 0; @@ -189,7 +187,7 @@ void usart1_isr(){ } }else{ // buffer overrun bufovr = 1; - datalen[rbufno] = 0; + idatalen[rbufno] = 0; #ifdef CHECK_TMOUT tmout = 0; #endif @@ -215,12 +213,13 @@ void printu(uint32_t val){ bufa[--bpos] = bufb[i]; } } - while(LINE_BUSY == usart_send_blocking(bufa, l+bpos)); + bufa[l + bpos] = 0; + usart_send(bufa); } // print 32bit unsigned int as hex void printuhex(uint32_t val){ - SEND("0x"); + usart_send("0x"); uint8_t *ptr = (uint8_t*)&val + 3; int i, j; for(i = 0; i < 4; ++i, --ptr){ diff --git a/F0-nolib/usbcdc/usart.h b/F0-nolib/usbcdc/usart.h index 46d0553..15e9187 100644 --- a/F0-nolib/usbcdc/usart.h +++ b/F0-nolib/usbcdc/usart.h @@ -25,36 +25,36 @@ #include "hardware.h" // input and output buffers size -#define UARTBUFSZ (64) +#define UARTBUFSZI (32) +#define UARTBUFSZO (512) // timeout between data bytes #ifndef TIMEOUT_MS #define TIMEOUT_MS (1500) #endif // macro for static strings -#define SEND(str) do{}while(LINE_BUSY == usart_send_blocking(str, sizeof(str)-1)) +#define SEND(str) usart_send(str) #ifdef EBUG #define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) #else #define MSG(str) #endif - +/* typedef enum{ ALL_OK, - LINE_BUSY, - STR_TOO_LONG -} TXstatus; + LINE_BUSY +} TXstatus;*/ #define usartrx() (linerdy) #define usartovr() (bufovr) extern volatile int linerdy, bufovr, txrdy; +void transmit_tbuf(); void usart_setup(); int usart_getline(char **line); -TXstatus usart_send(const char *str, int len); -TXstatus usart_send_blocking(const char *str, int len); +void usart_send(const char *str); void newline(); void usart_putchar(const char ch); void printu(uint32_t val); diff --git a/F0-nolib/usbcdc/usb.c b/F0-nolib/usbcdc/usb.c index 8ecce6e..edf2473 100644 --- a/F0-nolib/usbcdc/usb.c +++ b/F0-nolib/usbcdc/usb.c @@ -32,69 +32,69 @@ static uint8_t buffer[64]; static uint8_t len, rcvflag = 0; static uint16_t EP1_Handler(ep_t ep){ - MSG("EP1 "); if (ep.rx_flag){ //Пришли новые данные - MSG("read"); + MSG("read\n"); EP_Read(1, buffer); - EP_WriteIRQ(1, buffer, ep.rx_cnt); + //EP_WriteIRQ(1, buffer, ep.rx_cnt); ep.status = SET_VALID_TX(ep.status); //TX ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK } else if (ep.tx_flag){ //Данные успешно переданы - MSG("write"); + MSG("write\n"); ep.status = SET_VALID_RX(ep.status); //RX в VALID ep.status = SET_STALL_TX(ep.status); //TX в STALL } - MSG("; end\n"); return ep.status; } // write handler static uint16_t EP2_Handler(ep_t ep){ - MSG("EP2 "); - if (ep.rx_flag){ //Пришли новые данные - MSG("read"); - #ifdef EBUG - printu(ep.rx_cnt); - #endif - if(ep.rx_cnt > 2){ + if(ep.rx_flag){ + MSG("RX\n"); + if(ep.rx_cnt > 0){ len = ep.rx_cnt; rcvflag = 1; EP_Read(2, buffer); + buffer[len] = 0; } - //EP_WriteIRQ(3, buffer, ep.rx_cnt); + //Так как потверждение от хоста завершает транзакцию + //то сбрасываем DTOGи + ep.status = CLEAR_DTOG_RX(ep.status); + ep.status = CLEAR_DTOG_TX(ep.status); //Так как мы ожидаем новый запрос от хоста, устанавливаем + //ep.status = SET_VALID_RX(ep.status); + ep.status = SET_STALL_TX(ep.status); + }else if (ep.tx_flag){ + MSG("TX\n"); + ep.status = KEEP_STAT_TX(ep.status); + /* //Ожидаем новый запрос, или повторное чтение данных (ошибка при передаче) + //поэтому Rx и Tx в VALID ep.status = SET_VALID_RX(ep.status); - //ep.status = SET_STALL_TX(ep.status); - //ep.status = SET_VALID_TX(ep.status); //TX - //ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK - } else - if (ep.tx_flag){ //Данные успешно переданы - MSG("write"); - ep.status = SET_VALID_RX(ep.status); //RX в VALID - ep.status = SET_STALL_TX(ep.status); //TX в STALL + ep.status = SET_STALL_TX(ep.status);*/ } - MSG("; end\n"); + ep.status = SET_VALID_RX(ep.status); return ep.status; } +/* // read handler static uint16_t EP3_Handler(ep_t ep){ MSG("EP3 "); if (ep.rx_flag){ //Пришли новые данные MSG("read"); - EP_Read(3, buffer); + //EP_Read(3, buffer); ep.status = SET_VALID_TX(ep.status); //TX ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK } else if (ep.tx_flag){ //Данные успешно переданы MSG("write"); - ep.status = SET_VALID_RX(ep.status); //RX в VALID - ep.status = SET_STALL_TX(ep.status); //TX в STALL + ep.status = SET_STALL_TX(ep.status); + //ep.status = SET_VALID_RX(ep.status); //RX в VALID + //ep.status = SET_STALL_TX(ep.status); //TX в STALL } MSG("; end\n"); return ep.status; -} +}*/ void USB_setup(){ RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB @@ -127,14 +127,15 @@ void usb_proc(){ // free: 64 128 192 256 320 384 448 512 576 640 704 // (first 192 free bytes are for EP0) EP_Init(1, EP_TYPE_INTERRUPT, 256, 320, EP1_Handler); - EP_Init(2, EP_TYPE_BULK, 384, 448, EP2_Handler); - EP_Init(3, EP_TYPE_BULK, 512, 576, EP3_Handler); + EP_Init(2, EP_TYPE_BULK, 384, 448, EP2_Handler); // out + EP_Init(3, EP_TYPE_BULK, 512, 576, EP2_Handler); // in usbON = 1; }else{ if(rcvflag){ - EP_Write(3, buffer, len); MSG("read: "); - if(len > 2) while(LINE_BUSY == usart_send((char*)&buffer[2], len-2)); + if(len) SEND((char*)buffer); + SEND("\nNow write the data back\n"); + EP_Write(3, buffer, len); rcvflag = 0; } } diff --git a/F0-nolib/usbcdc/usb_lib.c b/F0-nolib/usbcdc/usb_lib.c index 8f3e3c0..cb7b4e6 100644 --- a/F0-nolib/usbcdc/usb_lib.c +++ b/F0-nolib/usbcdc/usb_lib.c @@ -10,11 +10,13 @@ #define DEVICE_QALIFIER_SIZE_BYTE (10) #define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) +static usb_LineCoding lineCoding = {115200, 0, 0, 8}; + const uint8_t USB_DeviceDescriptor[] = { DEVICE_DESCRIPTOR_SIZE_BYTE, // bLength 0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE - 0x00, // bcdUSB_L - 0x02, // bcdUSB_H + 0x10, // bcdUSB_L - 1.10 + 0x01, // bcdUSB_H 0x00, // bDeviceClass - USB_COMM 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol @@ -24,7 +26,7 @@ const uint8_t USB_DeviceDescriptor[] = { 0x03, // idProduct_L 0x23, // idProduct_H 0x00, // bcdDevice_Ver_L - 0x01, // bcdDevice_Ver_H + 0x03, // bcdDevice_Ver_H 0x01, // iManufacturer 0x02, // iProduct 0x00, // iSerialNumber @@ -34,8 +36,8 @@ const uint8_t USB_DeviceDescriptor[] = { const uint8_t USB_DeviceQualifierDescriptor[] = { DEVICE_QALIFIER_SIZE_BYTE, //bLength 0x06, // bDescriptorType - 0x00, // bcdUSB_L - 0x02, // bcdUSB_H + 0x10, // bcdUSB_L + 0x01, // bcdUSB_H 0x00, // bDeviceClass 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol @@ -44,105 +46,11 @@ const uint8_t USB_DeviceQualifierDescriptor[] = { 0x00 // Reserved }; -#if 0 const uint8_t USB_ConfigDescriptor[] = { /*Configuration Descriptor*/ 0x09, /* bLength: Configuration Descriptor size */ 0x02, /* bDescriptorType: Configuration */ - 39, /* wTotalLength:no of returned bytes */ - 0x00, - 0x02, /* bNumInterfaces: 2 interface */ - 0x01, /* bConfigurationValue: Configuration value */ - 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ - 0x80, /* bmAttributes - Bus powered */ - 0x32, /* MaxPower 100 mA */ - - /*---------------------------------------------------------------------------*/ - - /*Interface Descriptor */ - 0x09, /* bLength: Interface Descriptor size */ - 0x04, /* bDescriptorType: Interface */ - 0x00, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x01, /* bNumEndpoints: One endpoints used */ - 0x02, /* bInterfaceClass: Communication Interface Class */ - 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x01, /* bInterfaceProtocol: Common AT commands */ - 0x00, /* iInterface: */ - - /*Header Functional Descriptor*/ - 0x05, /* bLength: Endpoint Descriptor size */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x00, /* bDescriptorSubtype: Header Func Desc */ - 0x10, /* bcdCDC: spec release number */ - 0x01, - - /*Call Management Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x01, /* bDescriptorSubtype: Call Management Func Desc */ - 0x00, /* bmCapabilities: D0+D1 */ - 0x01, /* bDataInterface: 1 */ - - /*ACM Functional Descriptor*/ - 0x04, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ - 0x02, /* bmCapabilities */ - - /*Union Functional Descriptor*/ - 0x05, /* bFunctionLength */ - 0x24, /* bDescriptorType: CS_INTERFACE */ - 0x06, /* bDescriptorSubtype: Union func desc */ - 0x00, /* bMasterInterface: Communication class interface */ - 0x01, /* bSlaveInterface0: Data Class Interface */ - - /*Endpoint 2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x81, /* bEndpointAddress IN1 */ - 0x03, /* bmAttributes: Interrupt */ - 0x08, /* wMaxPacketSize LO: */ - 0x00, /* wMaxPacketSize HI: */ - 0x10, /* bInterval: */ - /*---------------------------------------------------------------------------*/ - - /*Data class interface descriptor*/ - 0x09, /* bLength: Endpoint Descriptor size */ - 0x04, /* bDescriptorType: */ - 0x01, /* bInterfaceNumber: Number of Interface */ - 0x00, /* bAlternateSetting: Alternate setting */ - 0x02, /* bNumEndpoints: Two endpoints used */ - 0x0A, /* bInterfaceClass: CDC */ - 0x02, /* bInterfaceSubClass: */ - 0x00, /* bInterfaceProtocol: */ - 0x00, /* iInterface: */ - - /*Endpoint IN2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x82, /* bEndpointAddress IN2 */ - 0x02, /* bmAttributes: Bulk */ - 64, /* wMaxPacketSize: */ - 0x00, - 0x00, /* bInterval: ignore for Bulk transfer */ - - /*Endpoint OUT3 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x03, /* bEndpointAddress */ - 0x02, /* bmAttributes: Bulk */ - 64, /* wMaxPacketSize: */ - 0, - 0x00 /* bInterval: ignore for Bulk transfer */ -}; -#endif - -const uint8_t USB_ConfigDescriptor[] = { - /*Configuration Descriptor*/ - 0x09, /* bLength: Configuration Descriptor size */ - 0x02, /* bDescriptorType: Configuration */ - 53, /* wTotalLength:no of returned bytes */ + 39, /* wTotalLength:no of returned bytes */ 0x00, 0x01, /* bNumInterfaces: 1 interface */ 0x01, /* bConfigurationValue: Configuration value */ @@ -158,11 +66,48 @@ const uint8_t USB_ConfigDescriptor[] = { 0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* bAlternateSetting: Alternate setting */ 0x03, /* bNumEndpoints: 3 endpoints used */ - 0x02, /* bInterfaceClass: Communication Interface Class */ - 0x02, /* bInterfaceSubClass: Abstract Control Model */ - 0x01, /* bInterfaceProtocol: Common AT commands */ + //0x02, /* bInterfaceClass: Communication Interface Class */ + //0x02, /* bInterfaceSubClass: Abstract Control Model */ + //0x01, /* bInterfaceProtocol: Common AT commands */ + 0xff, + 0x00, + 0x00, 0x00, /* iInterface: */ +/////////////////////////////////////////////////// + /*Endpoint 1 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + 0x81, /* bEndpointAddress IN1 */ + 0x03, /* bmAttributes: Interrupt */ + //0x40, /* wMaxPacketSize LO: */ + //0x00, /* wMaxPacketSize HI: */ + 0x0a, + 0x00, + //0x10, /* bInterval: */ + 0x01, + /*---------------------------------------------------------------------------*/ + /*Endpoint OUT2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + 0x02, /* bEndpointAddress: OUT2 */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN3 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + 0x05, /* bDescriptorType: Endpoint */ + //0x82, /* bEndpointAddress IN2 */ + 0x83, // IN3 + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: 64 */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ +}; + +#if 0 /*Header Functional Descriptor*/ 0x05, /* bLength: Endpoint Descriptor size */ 0x24, /* bDescriptorType: CS_INTERFACE */ @@ -182,35 +127,7 @@ const uint8_t USB_ConfigDescriptor[] = { 0x24, /* bDescriptorType: CS_INTERFACE */ 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ 0x02, /* bmCapabilities */ - - /*Endpoint 1 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x81, /* bEndpointAddress IN1 */ - 0x03, /* bmAttributes: Interrupt */ - 64, /* wMaxPacketSize LO: */ - 0x00, /* wMaxPacketSize HI: */ - 0x10, /* bInterval: */ - /*---------------------------------------------------------------------------*/ - - /*Endpoint IN3 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x83, /* bEndpointAddress IN3 */ - 0x02, /* bmAttributes: Bulk */ - 64, /* wMaxPacketSize: */ - 0x00, - 0x00, /* bInterval: ignore for Bulk transfer */ - - /*Endpoint OUT2 Descriptor*/ - 0x07, /* bLength: Endpoint Descriptor size */ - 0x05, /* bDescriptorType: Endpoint */ - 0x02, /* bEndpointAddress */ - 0x02, /* bmAttributes: Bulk */ - 64, /* wMaxPacketSize: */ - 0x00, - 0x00 /* bInterval: ignore for Bulk transfer */ -}; +#endif const uint8_t USB_StringLangDescriptor[] = { STRING_LANG_DESCRIPTOR_SIZE_BYTE, //bLength @@ -219,12 +136,6 @@ const uint8_t USB_StringLangDescriptor[] = { 0x04 //wLANGID_H }; -//~ typedef struct{ - //~ uint8_t bLength; - //~ uint8_t bDescriptorType; - //~ uint16_t bString[]; -//~ } StringDescriptor; - #define _USB_STRING_(name, str) \ const struct name \ { \ @@ -242,6 +153,25 @@ _USB_STRING_(USB_StringProdDescriptor, L"TSYS01 sensors controller") usb_dev_t USB_Dev; ep_t endpoints[MAX_ENDPOINTS]; +static void EP_Readx(uint8_t number, uint8_t *buf){ + uint32_t timeout = 100000; + uint16_t status, i; + status = USB -> EPnR[number]; + status = SET_VALID_RX(status); + status = SET_NAK_TX(status); + status = KEEP_DTOG_TX(status); + status = KEEP_DTOG_RX(status); + USB -> EPnR[number] = status; + endpoints[number].rx_flag = 0; + while (!endpoints[number].rx_flag){ + if (timeout) timeout--; + else break; + } + for (i = 0; i < endpoints[number].rx_cnt; i++){ + buf[i] = endpoints[number].rx_buf[i]; + } +} + /* bmRequestType: 76543210 7 direction: 0 - host->device, 1 - device->host @@ -260,8 +190,11 @@ uint16_t Enumerate_Handler(ep_t ep){ if(packet->wLength < size) size = packet->wLength; EP_WriteIRQ(0, buf, size); } + +uint8_t _2wr = 0; + if ((ep.rx_flag) && (ep.setup_flag)){ - if (packet -> bmRequestType == 0x80){ // get device properties + if (packet -> bmRequestType == 0x80){ // standard device request (device to host) switch(packet->bRequest){ case GET_DESCRIPTOR: switch(packet->wValue){ @@ -287,23 +220,23 @@ uint16_t Enumerate_Handler(ep_t ep){ wr0(USB_DeviceQualifierDescriptor, DEVICE_QALIFIER_SIZE_BYTE); break; default: - MSG("val"); - printuhex(packet->wValue); - newline(); +SEND("UNK_DES"); +_2wr = 1; + break; } break; case GET_STATUS: EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered break; default: - MSG("req"); - printuhex(packet->bRequest); - newline(); +SEND("80:WR_REQ"); +_2wr = 1; + break; } // , ep.status = SET_NAK_RX(ep.status); ep.status = SET_VALID_TX(ep.status); - }else if(packet->bmRequestType == 0x00){ // set device properties + }else if(packet->bmRequestType == 0x00){ // standard device request (host to device) switch(packet->bRequest){ case SET_ADDRESS: // DADDR , @@ -315,16 +248,16 @@ uint16_t Enumerate_Handler(ep_t ep){ USB_Dev.USB_Status = USB_CONFIGURE_STATE; break; default: - MSG("req"); - printuhex(packet->bRequest); - newline(); +SEND("0:WR_REQ"); +_2wr = 1; + break; } // EP_WriteIRQ(0, (uint8_t *)0, 0); // , ep.status = SET_NAK_RX(ep.status); ep.status = SET_VALID_TX(ep.status); - }else if(packet -> bmRequestType == 0x02){ + }else if(packet -> bmRequestType == 0x02){ // standard endpoint request (host to device) if (packet->bRequest == CLEAR_FEATURE){ // EP_WriteIRQ(0, (uint8_t *)0, 0); @@ -332,13 +265,76 @@ uint16_t Enumerate_Handler(ep_t ep){ ep.status = SET_NAK_RX(ep.status); ep.status = SET_VALID_TX(ep.status); }else{ - MSG("req"); - printuhex(packet->bRequest); - newline(); +SEND("02:WR_REQ"); +_2wr = 1; } + }else if((packet->bmRequestType & VENDOR_MASK_REQUEST) == VENDOR_MASK_REQUEST){ // vendor request +SEND("vendor "); + if(packet->bmRequestType & 0x80){ // read +SEND("read: "); + uint8_t c = '?'; + EP_WriteIRQ(0, &c, 1); + }else{ // write +SEND("write: "); + EP_WriteIRQ(0, (uint8_t *)0, 0); + } +printuhex(packet->wValue); +_2wr = 1; + ep.status = SET_NAK_RX(ep.status); + ep.status = SET_VALID_TX(ep.status); + }else if((packet->bmRequestType & 0x7f) == CONTROL_REQUEST_TYPE){ // control request +_2wr = 1; + //usb_LineCoding c; + //uint8_t lbuf[10]; + //usb_cdc_notification *notif = (usb_cdc_notification*) lbuf; + switch(packet->bRequest){ + case GET_LINE_CODING: +SEND("GET_LINE_CODING"); + EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); + break; + case SET_LINE_CODING: +SEND("SET_LINE_CODING"); + EP_Readx(0, (uint8_t*)&lineCoding); +printuhex(lineCoding.dwDTERate); + //EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); + //memcpy(&c, endpoints[0].rx_buf, sizeof(usb_LineCoding)); +/*SEND("len: "); +printu(endpoints[0].rx_cnt); +printu(endpoints[0].rx_buf[6]); +SEND(", want baudrate: "); printuhex(c.dwDTERate); +SEND(", charFormat: "); printu(c.bCharFormat); +SEND(", parityType: "); printu(c.bParityType); +SEND(", dataBits: "); printu(c.bDataBits);*/ + break; + case SET_CONTROL_LINE_STATE: +SEND("SET_CONTROL_LINE_STATE"); + /* + * This Linux cdc_acm driver requires this to be implemented + * even though it's optional in the CDC spec, and we don't + * advertise it in the ACM functional descriptor. + */ + /* We echo signals back to host as notification. * + notif->bmRequestType = CONTROL_REQUEST_TYPE | 0x80; + notif->bNotificationType = SET_LINE_CODING; + notif->wValue = 0; + notif->wIndex = 0; + notif->wLength = 2; + lbuf[8] = packet->wValue & 3; + lbuf[9] = 0; + EP_WriteIRQ(3, lbuf, 10);*/ + //EP_WriteIRQ(0, (uint8_t *)0, 0); + break; + case SEND_BREAK: +SEND("SEND_BREAK"); + break; + default: +SEND("undef control req"); + } + if((packet->bmRequestType & 0x80) == 0) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + ep.status = SET_NAK_RX(ep.status); + ep.status = SET_VALID_TX(ep.status); } - } else - if (ep.rx_flag){ // + } else if (ep.rx_flag){ // // // DTOG ep.status = CLEAR_DTOG_RX(ep.status); @@ -346,8 +342,7 @@ uint16_t Enumerate_Handler(ep_t ep){ // , ep.status = SET_VALID_RX(ep.status); ep.status = SET_STALL_TX(ep.status); - } else - if (ep.tx_flag){ // + } else if (ep.tx_flag){ // // if ((USB -> DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ // @@ -363,6 +358,21 @@ uint16_t Enumerate_Handler(ep_t ep){ ep.status = SET_VALID_RX(ep.status); ep.status = SET_VALID_TX(ep.status); } +if(_2wr){ + usart_putchar(' '); + if (ep.rx_flag) usart_putchar('r'); + else usart_putchar('t'); + printu(packet->wLength); + if(ep.setup_flag) usart_putchar('s'); + usart_putchar(' '); + usart_putchar('R'); + printu(packet->bRequest); + usart_putchar('V'); + printu(packet->wValue); + usart_putchar('T'); + printu(packet->bmRequestType); + usart_putchar('\n'); +} // ep.status EPnR // return ep.status; diff --git a/F0-nolib/usbcdc/usb_lib.h b/F0-nolib/usbcdc/usb_lib.h index eb45e85..605e421 100644 --- a/F0-nolib/usbcdc/usb_lib.h +++ b/F0-nolib/usbcdc/usb_lib.h @@ -5,7 +5,7 @@ #include "usb_defs.h" // -#define MAX_ENDPOINTS 2 +#define MAX_ENDPOINTS 4 // bRequest, standard; for bmRequestType == 0x80 #define GET_STATUS 0x00 #define GET_DESCRIPTOR 0x06 @@ -21,6 +21,14 @@ #define SET_INTERFACE 0x0B // #define SYNC_FRAME 0x0C // +// vendor +#define VENDOR_MASK_REQUEST 0x40 +#define VENDOR_READ_REQUEST_TYPE 0xc0 +#define VENDOR_WRITE_REQUEST_TYPE 0x40 +#define VENDOR_REQUEST 0x01 + +#define CONTROL_REQUEST_TYPE 0x21 + // Class-Specific Control Requests #define SEND_ENCAPSULATED_COMMAND 0x00 #define GET_ENCAPSULATED_RESPONSE 0x01 @@ -32,6 +40,10 @@ #define SET_CONTROL_LINE_STATE 0x22 #define SEND_BREAK 0x23 +// control line states +#define CONTROL_DTR 0x01 +#define CONTROL_RTS 0x02 + /* Line Coding Structure from CDC spec 6.2.13 struct usb_cdc_line_coding { __le32 dwDTERate; @@ -112,7 +124,30 @@ typedef struct __ep_t{ typedef struct { uint8_t USB_Status; uint16_t USB_Addr; -} usb_dev_t; +}usb_dev_t; + +typedef struct { + uint32_t dwDTERate; + uint8_t bCharFormat; + #define USB_CDC_1_STOP_BITS 0 + #define USB_CDC_1_5_STOP_BITS 1 + #define USB_CDC_2_STOP_BITS 2 + uint8_t bParityType; + #define USB_CDC_NO_PARITY 0 + #define USB_CDC_ODD_PARITY 1 + #define USB_CDC_EVEN_PARITY 2 + #define USB_CDC_MARK_PARITY 3 + #define USB_CDC_SPACE_PARITY 4 + uint8_t bDataBits; +} __attribute__ ((packed)) usb_LineCoding; + +typedef struct { + uint8_t bmRequestType; + uint8_t bNotificationType; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__ ((packed)) usb_cdc_notification; // USB void USB_Init();