diff --git a/F1:F103/USB_NEW_concept/main.c b/F1:F103/USB_NEW_concept/main.c index cc3afe1..0ab0398 100644 --- a/F1:F103/USB_NEW_concept/main.c +++ b/F1:F103/USB_NEW_concept/main.c @@ -17,6 +17,9 @@ */ #include "hardware.h" +#ifdef EBUG +#include "usart.h" +#endif #include "usb_dev.h" volatile uint32_t Tms = 0; @@ -29,12 +32,16 @@ void sys_tick_handler(void){ #define STRLEN (256) int main(void){ - char inbuff[RBINSZ+1]; + char inbuff[RBINSZ]; uint32_t lastT = 0; StartHSE(); hw_setup(); USBPU_OFF(); SysTick_Config(72000); +#ifdef EBUG + usart_setup(); + uint32_t tt = 0; +#endif USB_setup(); #ifndef EBUG iwdg_setup(); @@ -42,10 +49,18 @@ int main(void){ USBPU_ON(); while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog - if(lastT > Tms || Tms - lastT > 499){ + if(Tms - lastT > 499){ LED_blink(LED0); lastT = Tms; } +#ifdef EBUG + if(Tms != tt){ + __disable_irq(); + usart_transmit(); + tt = Tms; + __enable_irq(); + } +#endif int l = USB_receivestr(inbuff, RBINSZ); if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); else if(l){ diff --git a/F1:F103/USB_NEW_concept/openocd.cfg b/F1:F103/USB_NEW_concept/openocd.cfg new file mode 100644 index 0000000..18ecde1 --- /dev/null +++ b/F1:F103/USB_NEW_concept/openocd.cfg @@ -0,0 +1,4 @@ +set FLASH_SIZE 0x20000 + +source [find interface/stlink-v2-1.cfg] +source [find target/stm32f1x.cfg] diff --git a/F1:F103/USB_NEW_concept/ringbuffer.c b/F1:F103/USB_NEW_concept/ringbuffer.c index 8d8d6ca..b0ffe8e 100644 --- a/F1:F103/USB_NEW_concept/ringbuffer.c +++ b/F1:F103/USB_NEW_concept/ringbuffer.c @@ -129,8 +129,7 @@ int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len){ static int write(ringbuffer *b, const uint8_t *str, int l){ int r = b->length - 1 - datalen(b); // rest length - if(l > r) l = r; - if(!l) return 0; + if(l > r || !l) return 0; int _1st = b->length - b->tail; if(_1st > l) _1st = l; mcpy(b->data + b->tail, str, _1st); diff --git a/F1:F103/USB_NEW_concept/someusb.bin b/F1:F103/USB_NEW_concept/someusb.bin new file mode 100755 index 0000000..b14a40c Binary files /dev/null and b/F1:F103/USB_NEW_concept/someusb.bin differ diff --git a/F1:F103/USB_NEW_concept/someusb.creator.user b/F1:F103/USB_NEW_concept/someusb.creator.user index 8f45bb0..ce72e08 100644 --- a/F1:F103/USB_NEW_concept/someusb.creator.user +++ b/F1:F103/USB_NEW_concept/someusb.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -98,7 +98,6 @@ 0 0 - /Big/Data/00__Electronics/STM32/F1-nolib/I2C_tiny diff --git a/F1:F103/USB_NEW_concept/someusb.files b/F1:F103/USB_NEW_concept/someusb.files index c1b4596..6f277ab 100644 --- a/F1:F103/USB_NEW_concept/someusb.files +++ b/F1:F103/USB_NEW_concept/someusb.files @@ -3,6 +3,8 @@ hardware.h main.c ringbuffer.c ringbuffer.h +usart.c +usart.h usb_descr.c usb_descr.h usb_lib.c diff --git a/F1:F103/USB_NEW_concept/usart.c b/F1:F103/USB_NEW_concept/usart.c new file mode 100644 index 0000000..fa97a75 --- /dev/null +++ b/F1:F103/USB_NEW_concept/usart.c @@ -0,0 +1,122 @@ +/* + * usart.c + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include + +#include "stm32f1.h" +#include "usart.h" +#include "ringbuffer.h" + +extern volatile uint32_t Tms; +static uint8_t buf[UARTBUFSZO], txbuf[UARTBUFSZO]; +static ringbuffer ringbuf = {.data = buf, .length = UARTBUFSZO}; + +static volatile int usart_txrdy = 1; // transmission done + +// transmit current tbuf +void usart_transmit(){ + if(RB_hasbyte(&ringbuf, '\n') < 0 || !usart_txrdy) return; + int L = 0, l = 0; + do{ + l = RB_readto(&ringbuf, '\n', txbuf + L, UARTBUFSZO - L); + if(l > 0) L += l; + }while(l > 0 && L < UARTBUFSZO); + if(L < 1) return; + usart_txrdy = 0; + if(L < UARTBUFSZO-1){ + txbuf[L++] = '$'; txbuf[L++] = '\n'; + } + DMA1_Channel4->CCR &= ~DMA_CCR_EN; + DMA1_Channel4->CMAR = (uint32_t) txbuf; // mem + DMA1_Channel4->CNDTR = L; + DMA1_Channel4->CCR |= DMA_CCR_EN; +} + +void usart_putchar(const char ch){ + RB_write(&ringbuf, (const uint8_t*)&ch, 1); +} + +void usart_send(const char *str){ + int l = strlen(str); + RB_write(&ringbuf, (const uint8_t*)str, l); +} + +/* + * USART speed: baudrate = Fck/(USARTDIV) + * USARTDIV stored in USART->BRR + * + * for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271 + * 9600: BRR = 7500 (0x1D4C) + */ + +void usart_setup(){ + uint32_t tmout = 16000000; + // PA9 - Tx, PA10 - Rx + RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + GPIOA->CRH |= CRH(9, CNF_AFPP|MODE_NORMAL) | CRH(10, CNF_FLINPUT|MODE_INPUT); + + // USART1 Tx DMA - Channel4 (Rx - channel 5) + DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph + 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_IRQn, 3); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); + NVIC_SetPriority(USART1_IRQn, 0); + // setup usart1 + USART1->BRR = 72000000 / 4000000; + USART1->CR1 = USART_CR1_TE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART + while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission + USART1->SR = 0; // clear flags + USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ + USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx +} + + +void dma1_channel4_isr(){ + if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx + DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag + usart_txrdy = 1; + } +} + + + +char *uhex2str(uint32_t val){ + static char abuf[12] = "0x"; + int npos = 2; + uint8_t *ptr = (uint8_t*)&val + 3; + int8_t i, j, z=1; + for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) abuf[npos++] = half + '0'; + else abuf[npos++] = half - 10 + 'a'; + } + } + abuf[npos] = 0; + return abuf; +} diff --git a/F1:F103/USB_NEW_concept/usart.h b/F1:F103/USB_NEW_concept/usart.h new file mode 100644 index 0000000..f7bc03f --- /dev/null +++ b/F1:F103/USB_NEW_concept/usart.h @@ -0,0 +1,45 @@ +/* + * usart.h + * + * Copyright 2018 Edward V. Emelianoff + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once + +#include + +#define UARTBUFSZO (1024) + +// macro for static strings +#define USEND(str) usart_send(str) + +#ifdef EBUG +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) +#define DBG(str) do{usart_send(__FILE__ " (L" STR(__LINE__) "): " str); usart_putchar('\n');}while(0) +#define DBGs(str) do{usart_send(str); usart_putchar('\n');}while(0) +#else +#define DBG(s) +#define DBGs(s) +#endif + +void usart_transmit(); +void usart_setup(); +void usart_send(const char *str); +void usart_putchar(const char ch); +char *uhex2str(uint32_t val); diff --git a/F1:F103/USB_NEW_concept/usb_descr.c b/F1:F103/USB_NEW_concept/usb_descr.c index a21a3a7..cb55877 100644 --- a/F1:F103/USB_NEW_concept/usb_descr.c +++ b/F1:F103/USB_NEW_concept/usb_descr.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include "usart.h" #include "usb_descr.h" // low/high for uint16_t @@ -26,7 +27,7 @@ const uint8_t USB_DeviceDescriptor[] = { USB_DT_DEVICE, // bDescriptorType L16(bcdUSB), // bcdUSB_L H16(bcdUSB), // bcdUSB_H - USB_CLASS_VENDOR_SPEC, // bDeviceClass + USB_CLASS_PER_INTERFACE, // bDeviceClass bDeviceSubClass, // bDeviceSubClass bDeviceProtocol, // bDeviceProtocol USB_EP0BUFSZ, // bMaxPacketSize @@ -47,7 +48,7 @@ const uint8_t USB_DeviceQualifierDescriptor[] = { USB_DT_QUALIFIER, // bDescriptorType L16(bcdUSB), // bcdUSB_L H16(bcdUSB), // bcdUSB_H - USB_CLASS_VENDOR_SPEC, // bDeviceClass + USB_CLASS_PER_INTERFACE, // bDeviceClass bDeviceSubClass, // bDeviceSubClass bDeviceProtocol, // bDeviceProtocol USB_EP0BUFSZ, // bMaxPacketSize0 @@ -58,52 +59,52 @@ const uint8_t USB_DeviceQualifierDescriptor[] = { #define wTotalLength (USB_DT_CONFIG_SIZE + (bNumInterfaces * USB_DT_INTERFACE_SIZE) + (bTotNumEndpoints * USB_DT_ENDPOINT_SIZE)) const uint8_t USB_ConfigDescriptor[] = { - /* Configuration Descriptor*/ - USB_DT_CONFIG_SIZE, /* bLength: Configuration Descriptor size */ - USB_DT_CONFIG, /* bDescriptorType: Configuration */ - L16(wTotalLength), /* wTotalLength.L :no of returned bytes */ - H16(wTotalLength), /* wTotalLength.H */ - bNumInterfaces, /* bNumInterfaces */ - 1, /* bConfigurationValue: Current configuration value */ - 0, /* iConfiguration: Index of string descriptor describing the configuration or 0 */ - BusPowered, /* bmAttributes - Bus powered */ - 100, /* MaxPower in 2mA units */ - /*---------------------------------------------------------------------------*/ - /* Interface Descriptor */ - USB_DT_INTERFACE_SIZE, /* bLength: Interface Descriptor size */ - USB_DT_INTERFACE, /* bDescriptorType: Interface */ - 0, /* bInterfaceNumber: Number of Interface */ - 0, /* bAlternateSetting: Alternate setting */ - 3, /* bNumEndpoints */ - USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */ - 0, /* bInterfaceSubClass */ - 0, /* bInterfaceProtocol */ - iINTERFACE_DESCR1, /* iInterface: */ - /*---------------------------------------------------------------------------*/ - /* Endpoint 1 Descriptor */ - USB_DT_ENDPOINT_SIZE, /* bLength: Endpoint Descriptor size */ - USB_DT_ENDPOINT, /* bDescriptorType: Endpoint */ - 0x81, /* bEndpointAddress IN1 */ - EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt */ - L16(USB_EP1BUFSZ), /* wMaxPacketSize LO */ - H16(USB_EP1BUFSZ), /* wMaxPacketSize HI */ - 0x01, /* bInterval: 1ms */ - /* Endpoint OUT2 Descriptor */ - USB_DT_ENDPOINT_SIZE, /* bLength: Endpoint Descriptor size */ - USB_DT_ENDPOINT, /* bDescriptorType: Endpoint */ - 0x02, /* bEndpointAddress: OUT2 */ - EP_TYPE_BULK, /* bmAttributes: Bulk */ - L16(USB_RXBUFSZ), /* wMaxPacketSize LO */ - H16(USB_RXBUFSZ), /* wMaxPacketSize HI */ - 0, /* bInterval: ignore for Bulk transfer */ - /*Endpoint IN3 Descriptor*/ - USB_DT_ENDPOINT_SIZE, /* bLength: Endpoint Descriptor size */ - USB_DT_ENDPOINT, /* bDescriptorType: Endpoint */ - 0x83, /* bEndpointAddress: IN3 */ - EP_TYPE_BULK, /* bmAttributes: Bulk */ - L16(USB_TXBUFSZ), /* wMaxPacketSize LO */ - H16(USB_TXBUFSZ), /* wMaxPacketSize HI */ - 0, /* bInterval: ignore for Bulk transfer */ + // Configuration Descriptor + USB_DT_CONFIG_SIZE, // bLength: Configuration Descriptor size + USB_DT_CONFIG, // bDescriptorType: Configuration + L16(wTotalLength), // wTotalLength.L :no of returned bytes + H16(wTotalLength), // wTotalLength.H + bNumInterfaces, // bNumInterfaces + 1, // bConfigurationValue: Current configuration value + 0, // iConfiguration: Index of string descriptor describing the configuration or 0 + BusPowered, // bmAttributes - Bus powered + 50, // MaxPower in 2mA units + //--------------------------------------------------------------------------- + // Interface Descriptor + USB_DT_INTERFACE_SIZE, // bLength: Interface Descriptor size + USB_DT_INTERFACE, // bDescriptorType: Interface + 0, // bInterfaceNumber: Number of Interface + 0, // bAlternateSetting: Alternate setting + 3, // bNumEndpoints + USB_CLASS_VENDOR_SPEC, // bInterfaceClass + 0, // bInterfaceSubClass + 0, // bInterfaceProtocol + iINTERFACE_DESCR1, // iInterface: + //--------------------------------------------------------------------------- + // Endpoint 1 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x81, // bEndpointAddress IN1 + USB_BM_ATTR_INTERRUPT, // bmAttributes: Interrupt + L16(USB_EP1BUFSZ), // wMaxPacketSize LO + H16(USB_EP1BUFSZ), // wMaxPacketSize HI + 0x01, // bInterval: 1ms + // Endpoint OUT2 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x02, // bEndpointAddress: OUT2 + USB_BM_ATTR_BULK, // bmAttributes: Bulk + L16(USB_RXBUFSZ), // wMaxPacketSize LO + H16(USB_RXBUFSZ), // wMaxPacketSize HI + 0, // bInterval: ignore for Bulk transfer + //Endpoint IN3 Descriptor + USB_DT_ENDPOINT_SIZE, // bLength: Endpoint Descriptor size + USB_DT_ENDPOINT, // bDescriptorType: Endpoint + 0x83, // bEndpointAddress: IN3 + USB_BM_ATTR_BULK, // bmAttributes: Bulk + L16(USB_TXBUFSZ), // wMaxPacketSize LO + H16(USB_TXBUFSZ), // wMaxPacketSize HI + 0, // bInterval: ignore for Bulk transfer }; //const uint8_t HID_ReportDescriptor[]; @@ -114,7 +115,7 @@ _USB_STRING_(MD, u"eddy@sao.ru"); _USB_STRING_(PD, u"USB-Serial Controller"); _USB_STRING_(ID, u"USB-STM32"); -const void* const StringDescriptor[iDESCR_AMOUNT] = { +static const void* const StringDescriptor[iDESCR_AMOUNT] = { [iLANGUAGE_DESCR] = &LD, [iMANUFACTURER_DESCR] = &MD, [iPRODUCT_DESCR] = &PD, @@ -125,9 +126,11 @@ const void* const StringDescriptor[iDESCR_AMOUNT] = { void wr0(const uint8_t *buf, uint16_t size, uint16_t askedsize){ if(askedsize < size) size = askedsize; // shortened request if(size < USB_EP0BUFSZ){ + //DBG("short wr0"); EP_WriteIRQ(0, buf, size); return; } + //DBG("long wr0"); while(size){ uint16_t l = size; if(l > USB_EP0BUFSZ) l = USB_EP0BUFSZ; @@ -155,16 +158,20 @@ void get_descriptor(config_pack_t *pack){ 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); else EP_WriteIRQ(0, NULL, 0); break; case DEVICE_QUALIFIER_DESCRIPTOR: + //DBG("DEVICE_QUALIFIER_DESCRIPTOR"); wr0(USB_DeviceQualifierDescriptor, sizeof(USB_DeviceQualifierDescriptor), pack->wLength); break; /* case HID_REPORT_DESCRIPTOR: diff --git a/F1:F103/USB_NEW_concept/usb_descr.h b/F1:F103/USB_NEW_concept/usb_descr.h index c842e9c..2e15f25 100644 --- a/F1:F103/USB_NEW_concept/usb_descr.h +++ b/F1:F103/USB_NEW_concept/usb_descr.h @@ -25,14 +25,16 @@ #define bcdUSB 0x0110 #define bDeviceSubClass 0x00 #define bDeviceProtocol 0x00 -#define idVendor 0x0403 -#define idProduct 0xc631 -#define bcdDevice_Ver 0x0205 +//#define idVendor 0x0483 +//#define idProduct 0x3748 +#define idVendor 0x067b +#define idProduct 0x2303 +#define bcdDevice_Ver 0x0300 #define bNumConfigurations 1 // amount of interfaces and endpoints (except 0) used #define bNumInterfaces 1 -#define bTotNumEndpoints 1 +#define bTotNumEndpoints 3 // powered #define BusPowered (1<<7) diff --git a/F1:F103/USB_NEW_concept/usb_dev.c b/F1:F103/USB_NEW_concept/usb_dev.c index e0fd5c5..2428257 100644 --- a/F1:F103/USB_NEW_concept/usb_dev.c +++ b/F1:F103/USB_NEW_concept/usb_dev.c @@ -19,6 +19,7 @@ #include #include "ringbuffer.h" +#include "usart.h" #include "usb_descr.h" #include "usb_dev.h" @@ -57,6 +58,7 @@ static volatile int lastdsz = 0; static void EP1_Handler(){ uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + DBG("EP1_Handler"); if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX else epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX); // clear CTR @@ -116,19 +118,23 @@ static void receive_Handler(){ // EP2OUT // SET_LINE_CODING void WEAK linecoding_handler(usb_LineCoding *lc){ lineCoding = *lc; + DBG("linecoding_handler"); } // SET_CONTROL_LINE_STATE void WEAK clstate_handler(uint16_t _U_ val){ + DBG("clstate_handler"); } // SEND_BREAK void WEAK break_handler(){ + DBG("break_handler()"); } // USB is configured: setup endpoints void set_configuration(){ + DBG("set_configuration()"); EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data @@ -142,30 +148,58 @@ 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("SET_LINE_CODING"); if(!data || !datalen) break; // wait for data if(datalen == sizeof(usb_LineCoding)) linecoding_handler((usb_LineCoding*)data); + CDCready = 1; break; case GET_LINE_CODING: + DBG("GET_LINE_CODING"); EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); break; case SET_CONTROL_LINE_STATE: + DBG("SET_CONTROL_LINE_STATE"); CDCready = 1; clstate_handler(req->wValue); break; case SEND_BREAK: + DBG("SEND_BREAK"); CDCready = 0; break_handler(); break; default: - break; + DBG("Wrong"); + DBGs(uhex2str(req->bRequest)); + DBGs(uhex2str(datalen)); } break; default: + DBG("Wrong"); + DBGs(uhex2str(recipient)); + DBGs(uhex2str(datalen)); + DBGs(uhex2str(req->bRequest)); if(dev2host) EP_WriteIRQ(0, NULL, 0); } } +#if 0 + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_write(serial, 0x0404, 0); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_read(serial, 0x8383, buf); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_write(serial, 0x0404, 1); + pl2303_vendor_read(serial, 0x8484, buf); + pl2303_vendor_read(serial, 0x8383, buf); + pl2303_vendor_write(serial, 0, 1); + pl2303_vendor_write(serial, 1, 0); + if (spriv->quirks & PL2303_QUIRK_LEGACY) + pl2303_vendor_write(serial, 2, 0x24); + else + pl2303_vendor_write(serial, 2, 0x44); +#endif + // Vendor request for PL2303 void usb_vendor_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ datalen){ uint8_t c; @@ -184,13 +218,17 @@ void usb_vendor_request(config_pack_t *req, uint8_t _U_ *data, uint16_t _U_ data c = 0; } EP_WriteIRQ(0, &c, 1); + DBG("Vendor read"); }else{ // write ZLP EP_WriteIRQ(0, NULL, 0); + DBG("Vendor write"); } + DBGs(uhex2str(req->bRequest)); + DBGs(uhex2str(req->wValue)); + DBGs(uhex2str(req->wLength)); + DBGs(uhex2str(datalen)); } - - // blocking send full content of ring buffer int USB_sendall(){ while(lastdsz > 0){ @@ -202,6 +240,7 @@ int USB_sendall(){ // put `buf` into queue to send int USB_send(const uint8_t *buf, int len){ if(!buf || !CDCready || !len) return FALSE; + DBG("send"); while(len){ int a = RB_write((ringbuffer*)&rbout, buf, len); if(a > 0){ @@ -241,12 +280,14 @@ int USB_sendstr(const char *string){ int USB_receive(uint8_t *buf, int len){ chkin(); if(bufovrfl){ + DBG("Buffer overflow"); while(1 != RB_clearbuf((ringbuffer*)&rbin)); bufovrfl = 0; return -1; } int sz = RB_read((ringbuffer*)&rbin, buf, len); if(sz < 0) return 0; // buffer in writting state + DBG("usb read"); return sz; } diff --git a/F1:F103/USB_NEW_concept/usb_dev.h b/F1:F103/USB_NEW_concept/usb_dev.h index 163dc6d..075b7a7 100644 --- a/F1:F103/USB_NEW_concept/usb_dev.h +++ b/F1:F103/USB_NEW_concept/usb_dev.h @@ -47,15 +47,6 @@ void linecoding_handler(usb_LineCoding *lc); #define newline() USB_putbyte('\n') #define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) -#define STR_HELPER(s) #s -#define STR(s) STR_HELPER(s) - -#ifdef EBUG -#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0) -#else -#define DBG(str) -#endif - int USB_sendall(); int USB_send(const uint8_t *buf, int len); int USB_putbyte(uint8_t byte); diff --git a/F1:F103/USB_NEW_concept/usb_lib.c b/F1:F103/USB_NEW_concept/usb_lib.c index a4cf454..1c81afd 100644 --- a/F1:F103/USB_NEW_concept/usb_lib.c +++ b/F1:F103/USB_NEW_concept/usb_lib.c @@ -16,10 +16,16 @@ */ #include +#include "usart.h" #include "usb_lib.h" #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; @@ -35,15 +41,20 @@ 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)); break; } } @@ -51,16 +62,21 @@ 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; } } @@ -71,6 +87,7 @@ void WEAK usb_standard_request(){ uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); switch(recipient){ case REQ_RECIPIENT_DEVICE: + DBG("REQ_RECIPIENT_DEVICE"); if(dev2host){ std_d2h_req(); return; @@ -80,42 +97,52 @@ void WEAK usb_standard_request(){ } break; case REQ_RECIPIENT_INTERFACE: + DBG("REQ_RECIPIENT_INTERFACE"); switch(reqtype){ case REQ_TYPE_STANDARD: + DBG("REQ_TYPE_STANDARD"); if(dev2host && setup_packet->bRequest == GET_DESCRIPTOR){ get_descriptor(setup_packet); }else EP_WriteIRQ(0, NULL, 0); break; case REQ_TYPE_CLASS: + DBG("REQ_TYPE_CLASS"); if(setup_packet->bRequest == GET_INTERFACE){ EP_WriteIRQ(0, NULL, 0); - }/*else if (setup_packet->bRequest == SET_FEAUTRE){ + }else{ DBG("Wrong"); } + /*else if (setup_packet->bRequest == SET_FEAUTRE){ //set_featuring = 1; }*/ break; default: + DBG("Wrong"); + DBGs(uhex2str(reqtype)); if(dev2host) EP_WriteIRQ(0, NULL, 0); break; } break; case REQ_RECIPIENT_ENDPOINT: + DBG("REQ_RECIPIENT_ENDPOINT"); if(setup_packet->bRequest == CLEAR_FEATURE){ EP_WriteIRQ(0, NULL, 0); }else{ - //EP_WriteIRQ(0, (const uint8_t*)"epr", 4); + DBG("Wrong"); } break; default: - //EP_WriteIRQ(0, (const uint8_t*)"epd", 4); + DBG("Wrong"); + DBGs(uhex2str(recipient)); break; } } void WEAK usb_class_request(config_pack_t _U_ *req, uint8_t _U_ *data, uint16_t _U_ datalen){ + DBG("weak"); EP_WriteIRQ(0, NULL, 0); } -void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t datalen){ +void WEAK usb_vendor_request(config_pack_t _U_ *packet, uint8_t _U_ *data, uint16_t _U_ datalen){ + DBG("weak"); EP_WriteIRQ(0, NULL, 0); } @@ -131,33 +158,53 @@ bmRequestType: 76543210 static void EP0_Handler(){ uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications uint8_t reqtype = REQUEST_TYPE(setup_packet->bmRequestType); - //char x[] = "EP0Hx"; int rxflag = RX_FLAG(epstatus); + 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");} + ep0dbuflen = EP_Read(0, ep0databuf); + } + } if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ case REQ_TYPE_STANDARD: + DBG("REQ_TYPE_STANDARD"); usb_standard_request(); break; case REQ_TYPE_CLASS: + DBG("REQ_TYPE_CLASS"); usb_class_request(setup_packet, NULL, 0); break; case REQ_TYPE_VENDOR: + DBG("REQ_TYPE_VENDOR"); usb_vendor_request(setup_packet, NULL, 0); break; default: - //x[4] = reqtype; - //EP_WriteIRQ(0, (const uint8_t*)x, 5); + DBG("Wrong"); + DBGs(uhex2str(reqtype)); + EP_WriteIRQ(0, NULL, 0); break; } }else if(rxflag){ // got data over EP0 or host acknowlegement if(ep0dbuflen){ switch(reqtype){ case REQ_TYPE_CLASS: + DBG("REQ_TYPE_CLASS"); usb_class_request(setup_packet, ep0databuf, ep0dbuflen); break; - case REQ_TYPE_VENDOR: + case REQ_TYPE_VENDOR: + DBG("REQ_TYPE_VENDOR"); usb_vendor_request(setup_packet, ep0databuf, ep0dbuflen); break; + default: + DBG("Wrong"); + DBGs(uhex2str(reqtype)); } ep0dbuflen = 0; } @@ -166,6 +213,8 @@ 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]); @@ -253,11 +302,18 @@ 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)){ + /*DBG("num, type, txsz, rxsz"); + DBGs(uhex2str(number)); + DBGs(uhex2str(type)); + DBGs(uhex2str(txsz)); + DBGs(uhex2str(rxsz));*/ if(number >= STM32ENDPOINTS) return 4; // out of configured amount if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) 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; + /*DBG("EPnR="); + DBGs(uhex2str(USB->EPnR[number]));*/ if(rxsz & 1 || rxsz > USB_BTABLE_SIZE) return 3; // wrong rx buffer size uint16_t countrx = 0; if(rxsz < 64) countrx = rxsz / 2; @@ -265,78 +321,83 @@ 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; } + //DBG("addrtx, txbuf, txbufsz"); USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); endpoints[number].txbufsz = txsz; + /*DBGs(uhex2str(USB_BTABLE->EP[number].USB_ADDR_TX)); + DBGs(uhex2str((uint32_t)endpoints[number].tx_buf)); + DBGs(uhex2str(endpoints[number].txbufsz));*/ lastaddr += txsz; USB_BTABLE->EP[number].USB_COUNT_TX = 0; USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + /*DBG("Adrrx, rxbuf"); + DBGs(uhex2str(USB_BTABLE->EP[number].USB_ADDR_RX)); + DBGs(uhex2str((uint32_t)endpoints[number].rx_buf));*/ lastaddr += rxsz; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; + /*DBG("countrx"); + DBGs(uhex2str(USB_BTABLE->EP[number].USB_COUNT_RX));*/ endpoints[number].func = func; return 0; } // standard IRQ handler void USB_IRQ(){ + /*DBG("USB_IRQ"); + DBGs(uhex2str(USB->ISTR));*/ + uint32_t CNTR = USB->CNTR; + USB->CNTR = 0; if(USB->ISTR & USB_ISTR_RESET){ + DBG("USB_ISTR_RESET"); usbON = 0; // Reinit registers - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM; // Endpoint 0 - CONTROL // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! lastaddr = LASTADDR_DEFAULT; // clear address, leave only enable bit USB->DADDR = USB_DADDR_EF; if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0BUFSZ, USB_EP0BUFSZ, EP0_Handler)){ + DBG("Can't init EP0"); return; - } - USB->ISTR = ~USB_ISTR_RESET; + }; } if(USB->ISTR & USB_ISTR_CTR){ + DBG("USB_ISTR_CTR"); // EP number uint8_t n = USB->ISTR & USB_ISTR_EPID; - // copy status register - uint16_t epstatus = USB->EPnR[n]; // copy received bytes amount endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter - // 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(n == 0){ // control endpoint - if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack - EP_Read(0, setupdatabuf); - // interrupt handler will be called later - }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf - ep0dbuflen = EP_Read(0, ep0databuf); - } - } - } // call EP handler if(endpoints[n].func) endpoints[n].func(endpoints[n]); } + 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 + CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM); +#endif + } if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + DBG("USB_ISTR_SUSP"); usbON = 0; #ifndef STM32F0 - USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE; + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE | USB_CNTR_WKUPM; #else - USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE; + CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE | USB_CNTR_WKUPM; #endif - USB->ISTR = ~USB_ISTR_SUSP; - } - if(USB->ISTR & USB_ISTR_WKUP){ // wakeup -#ifndef STM32F0 - USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags -#else - USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE); -#endif - USB->ISTR = ~USB_ISTR_WKUP; + CNTR &= ~(USB_CNTR_SUSPM); } + 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(){ + DBG(">\n>\n>\nUSB_setup"); #if defined STM32F3 NVIC_DisableIRQ(USB_LP_IRQn); // remap USB LP & Wakeup interrupts to 75 and 76 - works only on pure F303 @@ -367,7 +428,7 @@ void USB_setup(){ USB->BTABLE = 0; USB->DADDR = 0; USB->ISTR = 0; - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts + USB->CNTR = USB_CNTR_RESETM; // allow only reset interrupts #if defined STM32F3 NVIC_EnableIRQ(USB_LP_IRQn); #elif defined STM32F1 @@ -376,6 +437,7 @@ void USB_setup(){ USB->BCDR |= USB_BCDR_DPPU; NVIC_EnableIRQ(USB_IRQn); #endif + DBG("USB ready"); } diff --git a/F1:F103/USB_NEW_concept/usb_lib.h b/F1:F103/USB_NEW_concept/usb_lib.h index 2c947c9..9fa7897 100644 --- a/F1:F103/USB_NEW_concept/usb_lib.h +++ b/F1:F103/USB_NEW_concept/usb_lib.h @@ -247,12 +247,19 @@ typedef struct{ #define DEVICE_QUALIFIER_DESCRIPTOR 0x06 #define HID_REPORT_DESCRIPTOR 0x2200 -// EP types +// EP types for EP_init #define EP_TYPE_BULK 0x00 #define EP_TYPE_CONTROL 0x01 #define EP_TYPE_ISO 0x02 #define EP_TYPE_INTERRUPT 0x03 +// EP types for descriptors +#define USB_BM_ATTR_CONTROL 0x00 +#define USB_BM_ATTR_ISO 0x01 +#define USB_BM_ATTR_BULK 0x02 +#define USB_BM_ATTR_INTERRUPT 0x03 + + /****************************************************************** * Other stuff * *****************************************************************/