some fixes in pl2303

This commit is contained in:
eddyem 2019-04-26 14:01:40 +03:00
parent f11e5e5b4d
commit 6d50b88096
7 changed files with 257 additions and 168 deletions

View File

@ -9,8 +9,7 @@ MCU = F042x6
DEFS += -DUSARTNUM=1 DEFS += -DUSARTNUM=1
#DEFS += -DCHECK_TMOUT #DEFS += -DCHECK_TMOUT
#DEFS += -DEBUG #DEFS += -DEBUG
# change this linking script depending on particular MCU model, # change this linking script depending on particular MCU model
# for example, if you have STM32F103VBT6, you should write:
LDSCRIPT = stm32f042k.ld LDSCRIPT = stm32f042k.ld
INDEPENDENT_HEADERS= INDEPENDENT_HEADERS=
@ -60,11 +59,13 @@ CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls $(INCLUDE) CFLAGS += -Wredundant-decls $(INCLUDE)
# -Wmissing-prototypes -Wstrict-prototypes # -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -fno-common -ffunction-sections -fdata-sections CFLAGS += -fno-common -ffunction-sections -fdata-sections
#CGLAGS += -fno-stack-protector
############################################################################### ###############################################################################
# Linker flags # Linker flags
LDFLAGS += --static -nostartfiles LDFLAGS += --static -nostartfiles
#--specs=nano.specs #--specs=nano.specs
#LDFLAGS += -fno-stack-protector
LDFLAGS += -L$(LIB_DIR) LDFLAGS += -L$(LIB_DIR)
LDFLAGS += -T$(LDSCRIPT) LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map

View File

@ -22,6 +22,7 @@
#include "usart.h" #include "usart.h"
#include "usb.h" #include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#include <string.h> // memcpy
volatile uint32_t Tms = 0; volatile uint32_t Tms = 0;
@ -53,18 +54,62 @@ void iwdg_setup(){
IWDG->KR = IWDG_REFRESH; /* (6) */ IWDG->KR = IWDG_REFRESH; /* (6) */
} }
void linecoding_handler(usb_LineCoding *lc){ static usb_LineCoding new_lc;
static uint8_t lcchange = 0;
static void show_new_lc(){
SEND("got new linecoding:"); SEND("got new linecoding:");
SEND(" baudrate="); printu(lc->dwDTERate); SEND(" baudrate="); printu(new_lc.dwDTERate);
SEND(", charFormat="); printu(lc->bCharFormat); SEND(", charFormat="); printu(new_lc.bCharFormat);
SEND(", parityType="); printu(lc->bParityType); SEND(" (");
SEND(", dataBits="); printu(lc->bDataBits); switch(new_lc.bCharFormat){
case USB_CDC_1_STOP_BITS:
usart_putchar('1');
break;
case USB_CDC_1_5_STOP_BITS:
SEND("1.5");
break;
case USB_CDC_2_STOP_BITS:
usart_putchar('2');
break;
default:
usart_putchar('?');
}
SEND(" stop bits), parityType="); printu(new_lc.bParityType);
SEND(" (");
switch(new_lc.bParityType){
case USB_CDC_NO_PARITY:
SEND("no");
break;
case USB_CDC_ODD_PARITY:
SEND("odd");
break;
case USB_CDC_EVEN_PARITY:
SEND("even");
break;
case USB_CDC_MARK_PARITY:
SEND("mark");
break;
case USB_CDC_SPACE_PARITY:
SEND("space");
break;
default:
SEND("unknown");
}
SEND(" parity), dataBits="); printu(new_lc.bDataBits);
usart_putchar('\n'); usart_putchar('\n');
lcchange = 0;
}
void linecoding_handler(usb_LineCoding *lc){
memcpy(&new_lc, lc, sizeof(usb_LineCoding));
lcchange = 1;
} }
void clstate_handler(uint16_t val){ void clstate_handler(uint16_t val){
SEND("change control line state to "); SEND("change control line state to ");
printu(val); printu(val);
if(val & CONTROL_DTR) SEND(" (DTR)");
if(val & CONTROL_RTS) SEND(" (RTS)");
usart_putchar('\n'); usart_putchar('\n');
} }
@ -120,6 +165,7 @@ int main(void){
case 'L': case 'L':
USB_send("Very long test string for USB (it's length is more than 64 bytes\n" USB_send("Very long test string for USB (it's length is more than 64 bytes\n"
"This is another part of the string! Can you see all of this?\n"); "This is another part of the string! Can you see all of this?\n");
SEND("Long test sent\n");
break; break;
case 'R': case 'R':
SEND("Soft reset\n"); SEND("Soft reset\n");
@ -127,6 +173,7 @@ int main(void){
break; break;
case 'S': case 'S':
USB_send("Test string for USB\n"); USB_send("Test string for USB\n");
SEND("Short test sent\n");
break; break;
case 'W': case 'W':
SEND("Wait for reboot\n"); SEND("Wait for reboot\n");
@ -150,6 +197,9 @@ int main(void){
usart_send(txt); usart_send(txt);
L = 0; L = 0;
} }
if(lcchange){
show_new_lc();
}
} }
return 0; return 0;
} }

Binary file not shown.

View File

@ -109,7 +109,7 @@ void USB_setup(){
void usb_proc(){ void usb_proc(){
if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints
if(!usbON){ // endpoints not activated if(!usbON){ // endpoints not activated
MSG("Configured; activate other endpoints\n"); SEND("Configure endpoints\n");
// make new BULK endpoint // make new BULK endpoint
// Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features) // Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features)
EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit

View File

@ -27,18 +27,21 @@
#include <stm32f0xx.h> #include <stm32f0xx.h>
#define USB_BTABLE_BASE 0x40006000 /**
* Buffers size definition
**/
// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! // !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
#define USB_BTABLE_SIZE 1024 #define USB_BTABLE_SIZE 1024
// first 64 bytes of USB_BTABLE are registers! // first 64 bytes of USB_BTABLE are registers!
#define USB_EP0_BASEADDR 64 #define USB_EP0_BASEADDR 64
// for USB FS EP0 buffers are from 8 to 64 bytes long // for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303)
#define USB_EP0_BUFSZ 8 #define USB_EP0_BUFSZ 64
// USB transmit buffer size // USB transmit buffer size (64 for PL2303)
#define USB_TXBUFSZ 64 #define USB_TXBUFSZ 64
// USB receive buffer size // USB receive buffer size (64 for PL2303)
#define USB_RXBUFSZ 64 #define USB_RXBUFSZ 64
#define USB_BTABLE_BASE 0x40006000
#undef USB_BTABLE #undef USB_BTABLE
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) #define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
#define USB_ISTR_EPID 0x0000000F #define USB_ISTR_EPID 0x0000000F

View File

@ -26,6 +26,9 @@
#include <string.h> // memcpy #include <string.h> // memcpy
#include "usart.h" #include "usart.h"
ep_t endpoints[ENDPOINTS_NUM];
static usb_dev_t USB_Dev;
static usb_LineCoding lineCoding = {115200, 0, 0, 8}; static usb_LineCoding lineCoding = {115200, 0, 0, 8};
static config_pack_t setup_packet; static config_pack_t setup_packet;
static uint8_t ep0databuf[EP0DATABUF_SIZE]; static uint8_t ep0databuf[EP0DATABUF_SIZE];
@ -33,15 +36,23 @@ static uint8_t ep0dbuflen = 0;
usb_LineCoding getLineCoding(){return lineCoding;} usb_LineCoding getLineCoding(){return lineCoding;}
const uint8_t USB_DeviceDescriptor[] = { // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor
#define bcdUSB_L 0x10
#define bcdUSB_H 0x01
#define bDeviceClass 0
#define bDeviceSubClass 0
#define bDeviceProtocol 0
#define bNumConfigurations 1
static const uint8_t USB_DeviceDescriptor[] = {
18, // bLength 18, // bLength
0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE 0x01, // bDescriptorType - Device descriptor
0x10, // bcdUSB_L - 1.10 bcdUSB_L, // bcdUSB_L - 1.10
0x01, // bcdUSB_H bcdUSB_H, // bcdUSB_H
0x00, // bDeviceClass - USB_COMM bDeviceClass, // bDeviceClass - USB_COMM
0x00, // bDeviceSubClass bDeviceSubClass, // bDeviceSubClass
0x00, // bDeviceProtocol bDeviceProtocol, // bDeviceProtocol
0x40, // bMaxPacketSize USB_EP0_BUFSZ, // bMaxPacketSize
0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303 0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303
0x06, // idVendor_H 0x06, // idVendor_H
0x03, // idProduct_L 0x03, // idProduct_L
@ -51,23 +62,23 @@ const uint8_t USB_DeviceDescriptor[] = {
0x01, // iManufacturer 0x01, // iManufacturer
0x02, // iProduct 0x02, // iProduct
0x00, // iSerialNumber 0x00, // iSerialNumber
0x01 // bNumConfigurations bNumConfigurations // bNumConfigurations
}; };
const uint8_t USB_DeviceQualifierDescriptor[] = { static const uint8_t USB_DeviceQualifierDescriptor[] = {
10, //bLength 10, //bLength
0x06, // bDescriptorType 0x06, // bDescriptorType - Device qualifier
0x10, // bcdUSB_L bcdUSB_L, // bcdUSB_L
0x01, // bcdUSB_H bcdUSB_H, // bcdUSB_H
0x00, // bDeviceClass bDeviceClass, // bDeviceClass
0x00, // bDeviceSubClass bDeviceSubClass, // bDeviceSubClass
0x00, // bDeviceProtocol bDeviceProtocol, // bDeviceProtocol
0x40, // bMaxPacketSize0 USB_EP0_BUFSZ, // bMaxPacketSize0
0x01, // bNumConfigurations bNumConfigurations, // bNumConfigurations
0x00 // Reserved 0x00 // Reserved
}; };
const uint8_t USB_ConfigDescriptor[] = { static const uint8_t USB_ConfigDescriptor[] = {
/*Configuration Descriptor*/ /*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */ 0x09, /* bLength: Configuration Descriptor size */
0x02, /* bDescriptorType: Configuration */ 0x02, /* bDescriptorType: Configuration */
@ -122,12 +133,9 @@ const uint8_t USB_ConfigDescriptor[] = {
_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); _USB_LANG_ID_(USB_StringLangDescriptor, LANG_US);
// these descriptors are not used in PL2303 emulator! // these descriptors are not used in PL2303 emulator!
_USB_STRING_(USB_StringSerialDescriptor, u"0") _USB_STRING_(USB_StringSerialDescriptor, u"0");
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.") _USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.");
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller") _USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller");
static usb_dev_t USB_Dev;
ep_t endpoints[ENDPOINTS_NUM];
/* /*
* default handlers * default handlers
@ -149,12 +157,8 @@ void WEAK break_handler(){
// handler of vendor requests // handler of vendor requests
void WEAK vendor_handler(config_pack_t *packet){ void WEAK vendor_handler(config_pack_t *packet){
/*SEND("Vendor, reqt=");
printuhex(packet->bmRequestType);
SEND(", wval=");
printuhex(packet->wValue);
usart_putchar('\n');*/
if(packet->bmRequestType & 0x80){ // read if(packet->bmRequestType & 0x80){ // read
//SEND("Read");
uint8_t c; uint8_t c;
switch(packet->wValue){ switch(packet->wValue){
case 0x8484: case 0x8484:
@ -171,8 +175,92 @@ void WEAK vendor_handler(config_pack_t *packet){
} }
EP_WriteIRQ(0, &c, 1); EP_WriteIRQ(0, &c, 1);
}else{ // write ZLP }else{ // write ZLP
//SEND("Write");
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
/*SEND(" vendor, reqt=");
printuhex(packet->bmRequestType);
SEND(", wval=");
printuhex(packet->wValue);
usart_putchar('\n');*/
}
#ifdef EBUG
uint8_t _2wr = 0;
#define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0)
#else
#define WRITEDUMP(str)
#endif
static void wr0(const uint8_t *buf, uint16_t size){
if(setup_packet.wLength < size) size = setup_packet.wLength;
EP_WriteIRQ(0, buf, size);
}
static inline void get_descriptor(){
switch(setup_packet.wValue){
case DEVICE_DESCRIPTOR:
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
break;
case CONFIGURATION_DESCRIPTOR:
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
break;
case STRING_LANG_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE);
break;
case STRING_MAN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
break;
case STRING_PROD_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
break;
case STRING_SN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
break;
case DEVICE_QUALIFIER_DESCRIPTOR:
wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]);
break;
default:
WRITEDUMP("UNK_DES");
break;
}
}
static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured)
static inline void std_d2h_req(){
uint16_t status = 0; // bus powered
switch(setup_packet.bRequest){
case GET_DESCRIPTOR:
get_descriptor();
break;
case GET_STATUS:
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered
break;
case GET_CONFIGURATION:
WRITEDUMP("GET_CONFIGURATION");
EP_WriteIRQ(0, &configuration, 1);
break;
default:
WRITEDUMP("80:WR_REQ");
break;
}
}
static inline void std_h2d_req(){
switch(setup_packet.bRequest){
case SET_ADDRESS:
// new address will be assigned later - after acknowlegement or request to host
USB_Dev.USB_Addr = setup_packet.wValue;
break;
case SET_CONFIGURATION:
// Now device configured
USB_Dev.USB_Status = USB_CONFIGURE_STATE;
configuration = setup_packet.wValue;
break;
default:
WRITEDUMP("0:WR_REQ");
break;
}
} }
/* /*
@ -186,123 +274,70 @@ bmRequestType: 76543210
* @param ep - endpoint state * @param ep - endpoint state
* @return data written to EP0R * @return data written to EP0R
*/ */
uint16_t EP0_Handler(ep_t ep){ static uint16_t EP0_Handler(ep_t ep){
uint16_t status = 0; // bus powered
uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications
static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) uint8_t reqtype = setup_packet.bmRequestType & 0x7f;
void wr0(const uint8_t *buf, uint16_t size){ uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0;
if(setup_packet.wLength < size) size = setup_packet.wLength;
EP_WriteIRQ(0, buf, size);
}
#ifdef EBUG
uint8_t _2wr = 0;
#define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0)
#else
#define WRITEDUMP(str)
#endif
if ((ep.rx_flag) && (ep.setup_flag)){ if ((ep.rx_flag) && (ep.setup_flag)){
if (setup_packet.bmRequestType == 0x80){ // standard device request (device to host) switch(reqtype){
switch(setup_packet.bRequest){ case STANDARD_DEVICE_REQUEST_TYPE: // standard device request
case GET_DESCRIPTOR: if(dev2host){
switch(setup_packet.wValue){ std_d2h_req();
case DEVICE_DESCRIPTOR: }else{
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); std_h2d_req();
break; // send ZLP
case CONFIGURATION_DESCRIPTOR: EP_WriteIRQ(0, (uint8_t *)0, 0);
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); }
break; epstatus = SET_NAK_RX(epstatus);
case STRING_LANG_DESCRIPTOR: epstatus = SET_VALID_TX(epstatus);
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); break;
break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
case STRING_MAN_DESCRIPTOR: if (setup_packet.bRequest == CLEAR_FEATURE){
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); // send ZLP
break; EP_WriteIRQ(0, (uint8_t *)0, 0);
case STRING_PROD_DESCRIPTOR: epstatus = SET_NAK_RX(epstatus);
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); epstatus = SET_VALID_TX(epstatus);
break; }else{
case STRING_SN_DESCRIPTOR: WRITEDUMP("02:WR_REQ");
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); }
break; break;
case DEVICE_QALIFIER_DESCRIPTOR: case VENDOR_REQUEST_TYPE:
wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); vendor_handler(&setup_packet);
break; epstatus = SET_NAK_RX(epstatus);
default: epstatus = SET_VALID_TX(epstatus);
WRITEDUMP("UNK_DES"); break;
break; case CONTROL_REQUEST_TYPE:
} switch(setup_packet.bRequest){
break; case GET_LINE_CODING:
case GET_STATUS: EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered break;
break; case SET_LINE_CODING: // omit this for next stage, when data will come
case GET_CONFIGURATION: break;
WRITEDUMP("GET_CONFIGURATION"); case SET_CONTROL_LINE_STATE:
EP_WriteIRQ(0, &configuration, 1); clstate_handler(setup_packet.wValue);
break; break;
default: case SEND_BREAK:
WRITEDUMP("80:WR_REQ"); break_handler();
break; break;
} default:
epstatus = SET_NAK_RX(epstatus); WRITEDUMP("undef control req");
epstatus = SET_VALID_TX(epstatus); }
}else if(setup_packet.bmRequestType == 0x00){ // standard device request (host to device) if(!dev2host) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
switch(setup_packet.bRequest){ epstatus = SET_VALID_RX(epstatus);
case SET_ADDRESS: epstatus = SET_VALID_TX(epstatus);
// new address will be assigned later - after acknowlegement or request to host break;
USB_Dev.USB_Addr = setup_packet.wValue; default:
break;
case SET_CONFIGURATION:
// Now device configured
USB_Dev.USB_Status = USB_CONFIGURE_STATE;
configuration = setup_packet.wValue;
break;
default:
WRITEDUMP("0:WR_REQ");
break;
}
// send ZLP
EP_WriteIRQ(0, (uint8_t *)0, 0);
epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
}else if(setup_packet.bmRequestType == 0x02){ // standard endpoint request (host to device)
if (setup_packet.bRequest == CLEAR_FEATURE){
// send ZLP
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
epstatus = SET_NAK_RX(epstatus); epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus); epstatus = SET_VALID_TX(epstatus);
}else{
WRITEDUMP("02:WR_REQ");
}
}else if((setup_packet.bmRequestType & VENDOR_MASK_REQUEST) == VENDOR_MASK_REQUEST){ // vendor request
vendor_handler(&setup_packet);
epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
}else if((setup_packet.bmRequestType & 0x7f) == CONTROL_REQUEST_TYPE){ // control request
switch(setup_packet.bRequest){
case GET_LINE_CODING:
EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
break;
case SET_LINE_CODING:
break;
case SET_CONTROL_LINE_STATE:
clstate_handler(setup_packet.wValue);
break;
case SEND_BREAK:
break_handler();
break;
default:
WRITEDUMP("undef control req");
}
if((setup_packet.bmRequestType & 0x80) == 0) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
epstatus = SET_VALID_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
} }
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement }else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
if(ep.rx_cnt){ if(ep.rx_cnt){
EP_WriteIRQ(0, (uint8_t *)0, 0);
if(setup_packet.bRequest == SET_LINE_CODING){ if(setup_packet.bRequest == SET_LINE_CODING){
//WRITEDUMP("SET_LINE_CODING"); //WRITEDUMP("SET_LINE_CODING");
linecoding_handler((usb_LineCoding*)ep0databuf); linecoding_handler((usb_LineCoding*)ep0databuf);
} }
EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
// Close transaction // Close transaction
epstatus = CLEAR_DTOG_RX(epstatus); epstatus = CLEAR_DTOG_RX(epstatus);
@ -348,6 +383,7 @@ uint16_t EP0_Handler(ep_t ep){
#endif #endif
return epstatus; return epstatus;
} }
#undef WRITEDUMP
static uint16_t lastaddr = USB_EP0_BASEADDR; static uint16_t lastaddr = USB_EP0_BASEADDR;
/** /**
@ -361,6 +397,7 @@ static uint16_t lastaddr = USB_EP0_BASEADDR;
* @return 0 if all OK * @return 0 if all OK
*/ */
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){
if(number >= ENDPOINTS_NUM) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
@ -380,7 +417,7 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t
USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr;
endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr); endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr);
lastaddr += rxsz; lastaddr += rxsz;
// buffer size: Table127 of RM: BL_SIZE=1, NUM_BLOCK=1 // buffer size: Table127 of RM
USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10;
endpoints[number].func = func; endpoints[number].func = func;
return 0; return 0;
@ -388,7 +425,6 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t
// standard IRQ handler // standard IRQ handler
void usb_isr(){ void usb_isr(){
uint8_t n;
if (USB->ISTR & USB_ISTR_RESET){ if (USB->ISTR & USB_ISTR_RESET){
// Reinit registers // Reinit registers
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
@ -404,7 +440,7 @@ void usb_isr(){
} }
if(USB->ISTR & USB_ISTR_CTR){ if(USB->ISTR & USB_ISTR_CTR){
// EP number // EP number
n = USB->ISTR & USB_ISTR_EPID; uint8_t n = USB->ISTR & USB_ISTR_EPID;
// copy status register // copy status register
uint16_t epstatus = USB->EPnR[n]; uint16_t epstatus = USB->EPnR[n];
// Calculate flags // Calculate flags
@ -412,7 +448,7 @@ void usb_isr(){
endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0;
endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0; endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0;
// copy received bytes amount // copy received bytes amount
endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX; endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter
// check direction // 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(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(n == 0){ // control endpoint
@ -451,6 +487,7 @@ void usb_isr(){
*/ */
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
uint8_t i; uint8_t i;
if(size > USB_TXBUFSZ) size = USB_TXBUFSZ;
uint16_t N2 = (size + 1) >> 1; uint16_t N2 = (size + 1) >> 1;
// the buffer is 16-bit, so we should copy data as it would be uint16_t // the buffer is 16-bit, so we should copy data as it would be uint16_t
uint16_t *buf16 = (uint16_t *)buf; uint16_t *buf16 = (uint16_t *)buf;

View File

@ -32,6 +32,11 @@
// Max EP amount (EP0 + other used) // Max EP amount (EP0 + other used)
#define ENDPOINTS_NUM 4 #define ENDPOINTS_NUM 4
// bmRequestType & 0x7f
#define STANDARD_DEVICE_REQUEST_TYPE 0
#define STANDARD_ENDPOINT_REQUEST_TYPE 2
#define VENDOR_REQUEST_TYPE 0x40
#define CONTROL_REQUEST_TYPE 0x21
// bRequest, standard; for bmRequestType == 0x80 // bRequest, standard; for bmRequestType == 0x80
#define GET_STATUS 0x00 #define GET_STATUS 0x00
#define GET_DESCRIPTOR 0x06 #define GET_DESCRIPTOR 0x06
@ -46,21 +51,14 @@
#define GET_INTERFACE 0x0A // unused #define GET_INTERFACE 0x0A // unused
#define SET_INTERFACE 0x0B // unused #define SET_INTERFACE 0x0B // unused
#define SYNC_FRAME 0x0C // unused #define SYNC_FRAME 0x0C // unused
#define VENDOR_REQUEST 0x01 // unused
// vendor requests
#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 // Class-Specific Control Requests
#define SEND_ENCAPSULATED_COMMAND 0x00 #define SEND_ENCAPSULATED_COMMAND 0x00 // unused
#define GET_ENCAPSULATED_RESPONSE 0x01 #define GET_ENCAPSULATED_RESPONSE 0x01 // unused
#define SET_COMM_FEATURE 0x02 #define SET_COMM_FEATURE 0x02 // unused
#define GET_COMM_FEATURE 0x03 #define GET_COMM_FEATURE 0x03 // unused
#define CLEAR_COMM_FEATURE 0x04 #define CLEAR_COMM_FEATURE 0x04 // unused
#define SET_LINE_CODING 0x20 #define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21 #define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22 #define SET_CONTROL_LINE_STATE 0x22
@ -77,7 +75,7 @@
#define STRING_MAN_DESCRIPTOR 0x301 #define STRING_MAN_DESCRIPTOR 0x301
#define STRING_PROD_DESCRIPTOR 0x302 #define STRING_PROD_DESCRIPTOR 0x302
#define STRING_SN_DESCRIPTOR 0x303 #define STRING_SN_DESCRIPTOR 0x303
#define DEVICE_QALIFIER_DESCRIPTOR 0x600 #define DEVICE_QUALIFIER_DESCRIPTOR 0x600
// EPnR bits manipulation // EPnR bits manipulation
#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX)) #define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX))
@ -121,7 +119,7 @@ static const struct name \
uint16_t bString[(sizeof(str) - 2) / 2]; \ uint16_t bString[(sizeof(str) - 2) / 2]; \
\ \
} \ } \
name = {sizeof(name), 0x03, str}; name = {sizeof(name), 0x03, str}
#define _USB_LANG_ID_(name, lng_id) \ #define _USB_LANG_ID_(name, lng_id) \
\ \
@ -132,7 +130,7 @@ static const struct name \
uint16_t bString; \ uint16_t bString; \
\ \
} \ } \
name = {0x04, 0x03, lng_id}; name = {0x04, 0x03, lng_id}
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) #define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
// EP0 configuration packet // EP0 configuration packet