little fixes in pl2303

This commit is contained in:
eddyem 2019-04-25 09:05:19 +03:00
parent 3dd520bed2
commit f11e5e5b4d
15 changed files with 2054 additions and 1511 deletions

2
.gitignore vendored
View File

@ -7,6 +7,8 @@
*.pho *.pho
*.drl *.drl
*.pdf *.pdf
*.svg
*.xml
*/mk/* */mk/*
.hg* .hg*
.dropbox.attr .dropbox.attr

View File

@ -0,0 +1,107 @@
"Source:","/tmp/kicad/Servo_control.sch"
"Date:","óÒ 13 ÍÁÒ 2019 17:09:04"
"Tool:","Eeschema (6.0.0-rc1-dev-1613-ga55d9819b)"
"Generator:","/usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py"
"Component Count:","59"
"Individual Components:"
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet"
"","","BZ1","Buzzer","Device:Buzzer","Buzzer_Beeper:Buzzer_12x9.5RM7.6","~"
"","","C1","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C2","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C3","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C4","47u","Servo_control-rescue:CP-Chiller_control-rescue","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.53x1.40mm_HandSolder",""
"","","C5","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C6","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C7","22p","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C8","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C9","22p","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C10","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C11","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C12","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"","","C13","1u","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","C14","10u","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_1206_3216Metric_Pad1.24x1.80mm_HandSolder",""
"","","D1","USB6B1","elements:USB6B1","Package_SOIC:SOIC-8_3.9x4.9mm_P1.27mm",""
"","","D2","SP0504BAHT","Power_Protection:SP0504BAHT","Package_TO_SOT_SMD:SOT-23-5","http://www.littelfuse.com/~/media/files/littelfuse/technical%20resources/documents/data%20sheets/sp05xxba.pdf"
"","","D3","SMAJ5.0","Device:D","Diode_SMD:D_SMA_Handsoldering",""
"","","D4","SMAJ5.0","Device:D","Diode_SMD:D_SMA_Handsoldering",""
"","","D5","SS14","Device:D_Schottky","Diode_SMD:D_SMA_Handsoldering",""
"","","J1","USB_B_Micro","Servo_control-rescue:USB_B_Micro-Connector_Specialized","Connector_USB:USB_Micro-B_Wuerth-629105150521","~"
"","","J2","ADC_in","Connector_Generic:Conn_01x06","Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical","~"
"","","J3","Jumper0","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"","","J4","Jumper1","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"","","J5","Dig_In","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"","","J6","Ext_LED","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"","","J7","Servo1","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"","","J8","Servo2","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"","","J9","Servo3","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"","","J10","5V","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"","","L1","BMBA 0.1mH","Servo_control-rescue:L-Chiller_control-rescue","Inductor_SMD:L_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","Q1","2N7002","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"","","Q2","SI2300","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"","","Q3","2N7002","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"","","Q4","2N7002","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"","","Q5","2N7002","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"","","R1","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R2","220","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R3","220","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R4","220","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R5","220","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R6","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R7","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R8","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R9","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R10","1k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R11","1k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R12","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R13","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R14","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R15","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R16","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","R17","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"","","SW1","Reset","Servo_control-rescue:SW_Push-Chiller_control-rescue","Button_Switch_SMD:SW_SPST_FSMSM",""
"","","SW2","Boot","Servo_control-rescue:SW_Push-Chiller_control-rescue","Button_Switch_SMD:SW_SPST_FSMSM",""
"","","U1","LM1117-3.3","Servo_control-rescue:LM1117-3.3-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-223-3_TabPin2",""
"","","U2","CH340G","ch34x:CH340G","Package_SOIC:SOIC-16_3.9x9.9mm_P1.27mm",""
"","","U3","STM32F030F4Px","Servo_control-rescue:STM32F030F4Px-Chiller_control-rescue","Package_SSOP:TSSOP-20_4.4x6.5mm_P0.65mm",""
"","","Y1","12MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical",""
"Collated Components:"
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet"
"1","1","BZ1","Buzzer","Device:Buzzer","Buzzer_Beeper:Buzzer_12x9.5RM7.6","~"
"2","9","C1, C2, C3, C5, C6, C8, C10, C11, C12","0.1","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"3","1","C4","47u","Servo_control-rescue:CP-Chiller_control-rescue","Capacitor_Tantalum_SMD:CP_EIA-3216-18_Kemet-A_Pad1.53x1.40mm_HandSolder",""
"4","2","C7, C9","22p","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad0.84x1.00mm_HandSolder",""
"5","1","C13","1u","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"6","1","C14","10u","Servo_control-rescue:C-Chiller_control-rescue","Capacitor_SMD:C_1206_3216Metric_Pad1.24x1.80mm_HandSolder",""
"7","1","D1","USB6B1","elements:USB6B1","Package_SOIC:SOIC-8_3.9x4.9mm_P1.27mm",""
"8","1","D2","SP0504BAHT","Power_Protection:SP0504BAHT","Package_TO_SOT_SMD:SOT-23-5","http://www.littelfuse.com/~/media/files/littelfuse/technical%20resources/documents/data%20sheets/sp05xxba.pdf"
"9","2","D3, D4","SMAJ5.0","Device:D","Diode_SMD:D_SMA_Handsoldering",""
"10","1","D5","SS14","Device:D_Schottky","Diode_SMD:D_SMA_Handsoldering",""
"11","1","J1","USB_B_Micro","Servo_control-rescue:USB_B_Micro-Connector_Specialized","Connector_USB:USB_Micro-B_Wuerth-629105150521","~"
"12","1","J2","ADC_in","Connector_Generic:Conn_01x06","Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical","~"
"13","1","J3","Jumper0","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"14","1","J4","Jumper1","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"15","1","J5","Dig_In","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"16","1","J6","Ext_LED","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"17","1","J7","Servo1","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"18","1","J8","Servo2","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"19","1","J9","Servo3","Connector_Generic:Conn_01x03","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","~"
"20","1","J10","5V","Connector_Generic:Conn_01x02","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","~"
"21","1","L1","BMBA 0.1mH","Servo_control-rescue:L-Chiller_control-rescue","Inductor_SMD:L_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"22","4","Q1, Q3, Q4, Q5","2N7002","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"23","1","Q2","SI2300","Servo_control-rescue:Q_NMOS_GSD-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-23",""
"24","6","R1, R7, R9, R15, R16, R17","10k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"25","4","R2, R3, R4, R5","220","Device:R","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"26","5","R6, R8, R12, R13, R14","510","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"27","2","R10, R11","1k","Servo_control-rescue:R-Chiller_control-rescue","Resistor_SMD:R_0805_2012Metric_Pad1.15x1.50mm_HandSolder",""
"28","1","SW1","Reset","Servo_control-rescue:SW_Push-Chiller_control-rescue","Button_Switch_SMD:SW_SPST_FSMSM",""
"29","1","SW2","Boot","Servo_control-rescue:SW_Push-Chiller_control-rescue","Button_Switch_SMD:SW_SPST_FSMSM",""
"30","1","U1","LM1117-3.3","Servo_control-rescue:LM1117-3.3-Chiller_control-rescue","Package_TO_SOT_SMD:SOT-223-3_TabPin2",""
"31","1","U2","CH340G","ch34x:CH340G","Package_SOIC:SOIC-16_3.9x9.9mm_P1.27mm",""
"32","1","U3","STM32F030F4Px","Servo_control-rescue:STM32F030F4Px-Chiller_control-rescue","Package_SSOP:TSSOP-20_4.4x6.5mm_P0.65mm",""
"33","1","Y1","12MHz","Device:Crystal","Crystal:Crystal_HC49-U_Vertical",""

View File

@ -442,4 +442,39 @@ X 2 2 200 0 100 L 50 50 0 1 P
ENDDRAW ENDDRAW
ENDDEF ENDDEF
# #
# USB_B_Micro-Connector_Specialized
#
DEF USB_B_Micro-Connector_Specialized J 0 40 Y Y 1 F N
F0 "J" -200 450 50 H V L CNN
F1 "USB_B_Micro-Connector_Specialized" -200 350 50 H V L CNN
F2 "" 150 -50 50 H I C CNN
F3 "" 150 -50 50 H I C CNN
$FPLIST
USB*
$ENDFPLIST
DRAW
C -150 85 25 0 1 10 F
C -25 135 15 0 1 10 F
S -200 -300 200 300 0 1 10 f
S -5 -300 5 -270 0 1 0 N
S 10 50 -20 20 0 1 10 F
S 200 -205 170 -195 0 1 0 N
S 200 -105 170 -95 0 1 0 N
S 200 -5 170 5 0 1 0 N
S 200 195 170 205 0 1 0 N
P 2 0 1 10 -75 85 25 85 N
P 4 0 1 10 -125 85 -100 85 -50 135 -25 135 N
P 4 0 1 10 -100 85 -75 85 -50 35 0 35 N
P 4 0 1 10 25 110 25 60 75 85 25 110 F
P 5 0 1 0 -170 220 -70 220 -80 190 -160 190 -170 220 F
P 9 0 1 0 -185 230 -185 220 -175 190 -175 180 -65 180 -65 190 -55 220 -55 230 -185 230 N
X VBUS 1 300 200 100 L 50 50 1 1 w
X D- 2 300 -100 100 L 50 50 1 1 P
X D+ 3 300 0 100 L 50 50 1 1 P
X ID 4 300 -200 100 L 50 50 1 1 P
X GND 5 0 -400 100 U 50 50 1 1 w
X Shield 6 -100 -400 100 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
#End Library #End Library

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
EESchema Schematic File Version 4 EESchema Schematic File Version 4
LIBS:Servo_control-cache LIBS:Servo_control-cache
EELAYER 26 0 EELAYER 29 0
EELAYER END EELAYER END
$Descr A4 11693 8268 $Descr A4 11693 8268
encoding utf-8 encoding utf-8
@ -1429,7 +1429,7 @@ Wire Wire Line
Connection ~ 4900 2525 Connection ~ 4900 2525
Connection ~ 4400 2275 Connection ~ 4400 2275
$Comp $Comp
L Connector_Specialized:USB_B_Micro J1 L Servo_control-rescue:USB_B_Micro-Connector_Specialized J1
U 1 1 5C8BC41C U 1 1 5C8BC41C
P 850 4650 P 850 4650
F 0 "J1" H 905 5117 50 0000 C CNN F 0 "J1" H 905 5117 50 0000 C CNN

Binary file not shown.

View File

@ -30,6 +30,7 @@ CC := $(PREFIX)-gcc
LD := $(PREFIX)-gcc LD := $(PREFIX)-gcc
AR := $(PREFIX)-ar AR := $(PREFIX)-ar
AS := $(PREFIX)-as AS := $(PREFIX)-as
SIZE := $(PREFIX)-size
OBJCOPY := $(OPREFIX)-objcopy OBJCOPY := $(OPREFIX)-objcopy
OBJDUMP := $(OPREFIX)-objdump OBJDUMP := $(OPREFIX)-objdump
GDB := $(OPREFIX)-gdb GDB := $(OPREFIX)-gdb
@ -85,7 +86,7 @@ LIST := $(OBJDIR)/$(BINARY).list
BIN := $(BINARY).bin BIN := $(BINARY).bin
HEX := $(BINARY).hex HEX := $(BINARY).hex
all: bin list all: bin list size
elf: $(ELF) elf: $(ELF)
bin: $(BIN) bin: $(BIN)
@ -106,9 +107,6 @@ $(OBJDIR)/%.o: %.c
@echo " CC $<" @echo " CC $<"
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
#$(OBJDIR)/%.d: %.c $(OBJDIR)
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
$(BIN): $(ELF) $(BIN): $(ELF)
@echo " OBJCOPY $(BIN)" @echo " OBJCOPY $(BIN)"
$(OBJCOPY) -Obinary $(ELF) $(BIN) $(OBJCOPY) -Obinary $(ELF) $(BIN)
@ -125,9 +123,12 @@ $(ELF): $(OBJDIR) $(OBJS)
@echo " LD $(ELF)" @echo " LD $(ELF)"
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF) $(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
size: $(ELF)
$(SIZE) $(ELF)
clean: clean:
@echo " CLEAN" @echo " CLEAN"
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map $(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map *.d
@rmdir $(OBJDIR) 2>/dev/null || true @rmdir $(OBJDIR) 2>/dev/null || true
dfuboot: $(BIN) dfuboot: $(BIN)

View File

@ -32,6 +32,17 @@
#define FORMUSART(X) CONCAT(USART, X) #define FORMUSART(X) CONCAT(USART, X)
#define USARTX FORMUSART(USARTNUM) #define USARTX FORMUSART(USARTNUM)
#if USARTNUM == 2
#define USARTDMA DMA1_Channel4
#define DMAIRQn DMA1_Channel4_5_IRQn
#define USARTIRQn USART2_IRQn
#elif USARTNUM == 1
#define USARTDMA DMA1_Channel2
#define DMAIRQn DMA1_Channel2_3_IRQn
#define USARTIRQn USART1_IRQn
#else
#error "Wrong USARTNUM"
#endif
// LEDS: 0 - PC13, 1 - PC14 // LEDS: 0 - PC13, 1 - PC14
// LED0 // LED0

View File

@ -70,14 +70,14 @@ void clstate_handler(uint16_t val){
int main(void){ int main(void){
uint32_t lastT = 0; uint32_t lastT = 0;
int L; int L = 0;
char *txt; char *txt;
char tmpbuf[129]; char tmpbuf[129];
sysreset(); sysreset();
SysTick_Config(6000, 1); SysTick_Config(6000, 1);
gpio_setup(); gpio_setup();
usart_setup(); usart_setup();
SEND("Hello!\n"); SEND("Hello!\n");
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
@ -89,7 +89,7 @@ int main(void){
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
USB_setup(); USB_setup();
//iwdg_setup(); iwdg_setup();
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog IWDG->KR = IWDG_REFRESH; // refresh watchdog
@ -97,13 +97,6 @@ int main(void){
LED_blink(LED0); LED_blink(LED0);
lastT = Tms; lastT = Tms;
transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s
/*uint8_t r = 0;
if((r = USB_receive(tmpbuf, 128))){
tmpbuf[r] = 0;
SEND("Received data over USB:\n");
SEND(tmpbuf);
newline();
}*/
} }
usb_proc(); usb_proc();
uint8_t r = 0; uint8_t r = 0;
@ -124,11 +117,15 @@ int main(void){
if(!USB_configured()) SEND("dis"); if(!USB_configured()) SEND("dis");
SEND("connected\n"); SEND("connected\n");
break; break;
case 'L':
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");
break;
case 'R': case 'R':
SEND("Soft reset\n"); SEND("Soft reset\n");
NVIC_SystemReset(); NVIC_SystemReset();
break; break;
case 'U': case 'S':
USB_send("Test string for USB\n"); USB_send("Test string for USB\n");
break; break;
case 'W': case 'W':
@ -137,9 +134,10 @@ int main(void){
break; break;
default: // help default: // help
SEND( SEND(
"'C' - test is USB configured\n" "'C' - test if USB is configured\n"
"'L' - send long string over USB\n"
"'R' - software reset\n" "'R' - software reset\n"
"'U' - send test string over USB\n" "'S' - send short string over USB\n"
"'W' - test watchdog\n" "'W' - test watchdog\n"
); );
break; break;

Binary file not shown.

View File

@ -60,19 +60,10 @@ void transmit_tbuf(){
if(!l) return; if(!l) return;
txrdy = 0; txrdy = 0;
odatalen[tbufno] = 0; odatalen[tbufno] = 0;
#if USARTNUM == 2 USARTDMA->CCR &= ~DMA_CCR_EN;
DMA1_Channel4->CCR &= ~DMA_CCR_EN; USARTDMA->CMAR = (uint32_t) tbuf[tbufno]; // mem
DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem USARTDMA->CNDTR = l;
DMA1_Channel4->CNDTR = l; USARTDMA->CCR |= DMA_CCR_EN;
DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission
#elif USARTNUM == 1
DMA1_Channel2->CCR &= ~DMA_CCR_EN;
DMA1_Channel2->CMAR = (uint32_t) tbuf[tbufno]; // mem
DMA1_Channel2->CNDTR = l;
DMA1_Channel2->CCR |= DMA_CCR_EN;
#else
#error "Not implemented"
#endif
tbufno = !tbufno; tbufno = !tbufno;
} }
@ -103,8 +94,8 @@ void newline(){
void usart_setup(){ void usart_setup(){
// Nucleo's USART2 connected to VCP proxy of st-link
uint32_t tmout = 16000000; uint32_t tmout = 16000000;
// Nucleo's USART2 connected to VCP proxy of st-link
#if USARTNUM == 2 #if USARTNUM == 2
// setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1) // setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1)
// AF mode (AF1) // AF mode (AF1)
@ -112,24 +103,7 @@ void usart_setup(){
| (GPIO_MODER_MODER2_AF | GPIO_MODER_MODER15_AF); | (GPIO_MODER_MODER2_AF | GPIO_MODER_MODER15_AF);
GPIOA->AFR[0] = (GPIOA->AFR[0] &~GPIO_AFRH_AFRH2) | 1 << (2 * 4); // PA2 GPIOA->AFR[0] = (GPIOA->AFR[0] &~GPIO_AFRH_AFRH2) | 1 << (2 * 4); // PA2
GPIOA->AFR[1] = (GPIOA->AFR[1] &~GPIO_AFRH_AFRH7) | 1 << (7 * 4); // PA15 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->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);
NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
NVIC_SetPriority(USART2_IRQn, 0);
// setup usart2
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // clock RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // clock
// oversampling by16, 115200bps (fck=48mHz)
//USART2_BRR = 0x1a1; // 48000000 / 115200
USART2->BRR = 480000 / 1152;
USART2->CR3 = USART_CR3_DMAT; // enable DMA Tx
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
while(!(USART2->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
USART2->ICR |= USART_ICR_TCCF; // clear TC flag
USART2->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(USART2_IRQn);
// USART1 of main board // USART1 of main board
#elif USARTNUM == 1 #elif USARTNUM == 1
// PA9 - Tx, PA10 - Rx (AF1) // PA9 - Tx, PA10 - Rx (AF1)
@ -137,26 +111,26 @@ void usart_setup(){
| (GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF); | (GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF);
GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) |
1 << (1 * 4) | 1 << (2 * 4); // PA9, PA10 1 << (1 * 4) | 1 << (2 * 4); // PA9, PA10
// USART1 Tx DMA - Channel2 (default value in SYSCFG_CFGR1)
DMA1_Channel2->CPAR = (uint32_t) &USART1->TDR; // periph
DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem
DMA1_Channel2->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_Channel2_3_IRQn, 3);
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
NVIC_SetPriority(USART1_IRQn, 0);
// setup usart1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
USART1->BRR = 480000 / 1152;
USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
while(!(USART1->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
USART1->ICR |= USART_ICR_TCCF; // clear TC flag
USART1->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(USART1_IRQn);
#else #else
#error "Not implemented" #error "Wrong USARTNUM"
#endif #endif
// USARTX Tx DMA
USARTDMA->CPAR = (uint32_t) &USARTX->TDR; // periph
USARTDMA->CMAR = (uint32_t) tbuf; // mem
USARTDMA->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(DMAIRQn, 3);
NVIC_EnableIRQ(DMAIRQn);
NVIC_SetPriority(USARTIRQn, 0);
// setup usart1
USARTX->BRR = 480000 / 1152;
USARTX->CR3 = USART_CR3_DMAT; // enable DMA Tx
USARTX->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
while(!(USARTX->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
USARTX->ICR |= USART_ICR_TCCF; // clear TC flag
USARTX->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(USARTIRQn);
} }
#if USARTNUM == 2 #if USARTNUM == 2
@ -165,7 +139,7 @@ void usart2_isr(){
#elif USARTNUM == 1 #elif USARTNUM == 1
void usart1_isr(){ void usart1_isr(){
#else #else
#error "Not implemented" #error "Wrong USARTNUM"
#endif #endif
#ifdef CHECK_TMOUT #ifdef CHECK_TMOUT
static uint32_t tmout = 0; static uint32_t tmout = 0;
@ -276,5 +250,5 @@ void dma1_channel2_3_isr(){
} }
} }
#else #else
#error "Not implemented" #error "Wrong USARTNUM"
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
* geany_encoding=koi8-r * geany_encoding=koi8-r
* usb.c * usb.c - base functions for different USB types
* *
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com> * Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
* *
@ -48,7 +48,7 @@ static uint16_t EP1_Handler(ep_t ep){
} }
// data IN/OUT handler // data IN/OUT handler
static uint16_t EP2_Handler(ep_t ep){ static uint16_t EP23_Handler(ep_t ep){
MSG("EP2\n"); MSG("EP2\n");
if(ep.rx_flag){ if(ep.rx_flag){
int rd = ep.rx_cnt, rest = IDATASZ - idatalen; int rd = ep.rx_cnt, rest = IDATASZ - idatalen;
@ -98,11 +98,11 @@ void USB_setup(){
CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only
RCC->CFGR |= RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW;
// allow RESET and CTRM interrupts // allow RESET and CTRM interrupts
USB -> CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
// clear flags // clear flags
USB -> ISTR = 0; USB->ISTR = 0;
// and activate pullup // and activate pullup
USB -> BCDR |= USB_BCDR_DPPU; USB->BCDR |= USB_BCDR_DPPU;
NVIC_EnableIRQ(USB_IRQn); NVIC_EnableIRQ(USB_IRQn);
} }
@ -111,13 +111,10 @@ void usb_proc(){
if(!usbON){ // endpoints not activated if(!usbON){ // endpoints not activated
MSG("Configured; activate other endpoints\n"); MSG("Configured; activate other endpoints\n");
// make new BULK endpoint // make new BULK endpoint
// Buffer have 1024 bytes, but last 256 we use for CAN bus // Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features)
// first free is 64; 768 - CAN data EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit
// free: 64 128 192 256 320 384 448 512 576 640 704 EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, EP23_Handler); // OUT2 - receive data
// (first 64 are control registers, up to 192 - buffer for EP0) EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, EP23_Handler); // IN3 - transmit data
EP_Init(1, EP_TYPE_INTERRUPT, 192, 192, EP1_Handler);
EP_Init(2, EP_TYPE_BULK, 256, 256, EP2_Handler); // OUT - receive data
EP_Init(3, EP_TYPE_BULK, 320, 320, EP2_Handler); // IN - transmit data
usbON = 1; usbON = 1;
} }
}else{ }else{
@ -126,10 +123,15 @@ void usb_proc(){
} }
void USB_send(char *buf){ void USB_send(char *buf){
uint16_t l = 0; uint16_t l = 0, ctr = 0;
char *p = buf; char *p = buf;
while(*p++) ++l; while(*p++) ++l;
EP_Write(3, (uint8_t*)buf, l); while(l){
uint16_t s = (l > USB_TXBUFSZ) ? USB_TXBUFSZ : l;
EP_Write(3, (uint8_t*)&buf[ctr], s);
l -= s;
ctr += s;
}
} }
/** /**
@ -148,7 +150,7 @@ int USB_receive(char *buf, int bufsize){
idatalen = rest; idatalen = rest;
}else idatalen = 0; }else idatalen = 0;
if(ovfl){ if(ovfl){
EP2_Handler(endpoints[2]); EP23_Handler(endpoints[2]);
uint16_t epstatus = USB->EPnR[2]; uint16_t epstatus = USB->EPnR[2];
epstatus = CLEAR_DTOG_RX(epstatus); epstatus = CLEAR_DTOG_RX(epstatus);
epstatus = SET_VALID_RX(epstatus); epstatus = SET_VALID_RX(epstatus);

View File

@ -1,92 +1,103 @@
/* /*
* geany_encoding=koi8-r * geany_encoding=koi8-r
* usb_defs.h * usb_defs.h
* *
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com> * Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. * MA 02110-1301, USA.
* *
*/ */
#pragma once #pragma once
#ifndef __USB_DEFS_H__ #ifndef __USB_DEFS_H__
#define __USB_DEFS_H__ #define __USB_DEFS_H__
#include <stm32f0xx.h> #include <stm32f0xx.h>
#define USB_BTABLE_BASE 0x40006000 #define USB_BTABLE_BASE 0x40006000
#undef USB_BTABLE // !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) #define USB_BTABLE_SIZE 1024
#define USB_ISTR_EPID 0x0000000F // first 64 bytes of USB_BTABLE are registers!
#define USB_FNR_LSOF_0 0x00000800 #define USB_EP0_BASEADDR 64
#define USB_FNR_lSOF_1 0x00001000 // for USB FS EP0 buffers are from 8 to 64 bytes long
#define USB_LPMCSR_BESL_0 0x00000010 #define USB_EP0_BUFSZ 8
#define USB_LPMCSR_BESL_1 0x00000020 // USB transmit buffer size
#define USB_LPMCSR_BESL_2 0x00000040 #define USB_TXBUFSZ 64
#define USB_LPMCSR_BESL_3 0x00000080 // USB receive buffer size
#define USB_EPnR_CTR_RX 0x00008000 #define USB_RXBUFSZ 64
#define USB_EPnR_DTOG_RX 0x00004000
#define USB_EPnR_STAT_RX 0x00003000 #undef USB_BTABLE
#define USB_EPnR_STAT_RX_0 0x00001000 #define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
#define USB_EPnR_STAT_RX_1 0x00002000 #define USB_ISTR_EPID 0x0000000F
#define USB_EPnR_SETUP 0x00000800 #define USB_FNR_LSOF_0 0x00000800
#define USB_EPnR_EP_TYPE 0x00000600 #define USB_FNR_lSOF_1 0x00001000
#define USB_EPnR_EP_TYPE_0 0x00000200 #define USB_LPMCSR_BESL_0 0x00000010
#define USB_EPnR_EP_TYPE_1 0x00000400 #define USB_LPMCSR_BESL_1 0x00000020
#define USB_EPnR_EP_KIND 0x00000100 #define USB_LPMCSR_BESL_2 0x00000040
#define USB_EPnR_CTR_TX 0x00000080 #define USB_LPMCSR_BESL_3 0x00000080
#define USB_EPnR_DTOG_TX 0x00000040 #define USB_EPnR_CTR_RX 0x00008000
#define USB_EPnR_STAT_TX 0x00000030 #define USB_EPnR_DTOG_RX 0x00004000
#define USB_EPnR_STAT_TX_0 0x00000010 #define USB_EPnR_STAT_RX 0x00003000
#define USB_EPnR_STAT_TX_1 0x00000020 #define USB_EPnR_STAT_RX_0 0x00001000
#define USB_EPnR_EA 0x0000000F #define USB_EPnR_STAT_RX_1 0x00002000
#define USB_COUNTn_RX_BLSIZE 0x00008000 #define USB_EPnR_SETUP 0x00000800
#define USB_COUNTn_NUM_BLOCK 0x00007C00 #define USB_EPnR_EP_TYPE 0x00000600
#define USB_COUNTn_RX 0x0000003F #define USB_EPnR_EP_TYPE_0 0x00000200
#define USB_EPnR_EP_TYPE_1 0x00000400
#define USB_TypeDef USB_TypeDef_custom #define USB_EPnR_EP_KIND 0x00000100
#define USB_EPnR_CTR_TX 0x00000080
typedef struct{ #define USB_EPnR_DTOG_TX 0x00000040
__IO uint32_t EPnR[8]; #define USB_EPnR_STAT_TX 0x00000030
__IO uint32_t RESERVED1; #define USB_EPnR_STAT_TX_0 0x00000010
__IO uint32_t RESERVED2; #define USB_EPnR_STAT_TX_1 0x00000020
__IO uint32_t RESERVED3; #define USB_EPnR_EA 0x0000000F
__IO uint32_t RESERVED4; #define USB_COUNTn_RX_BLSIZE 0x00008000
__IO uint32_t RESERVED5; #define USB_COUNTn_NUM_BLOCK 0x00007C00
__IO uint32_t RESERVED6; #define USB_COUNTn_RX 0x0000003F
__IO uint32_t RESERVED7;
__IO uint32_t RESERVED8; #define USB_TypeDef USB_TypeDef_custom
__IO uint32_t CNTR;
__IO uint32_t ISTR; typedef struct{
__IO uint32_t FNR; __IO uint32_t EPnR[8];
__IO uint32_t DADDR; __IO uint32_t RESERVED1;
__IO uint32_t BTABLE; __IO uint32_t RESERVED2;
__IO uint32_t LPMCSR; __IO uint32_t RESERVED3;
__IO uint32_t BCDR; __IO uint32_t RESERVED4;
} USB_TypeDef; __IO uint32_t RESERVED5;
__IO uint32_t RESERVED6;
typedef struct{ __IO uint32_t RESERVED7;
__IO uint16_t USB_ADDR_TX; __IO uint32_t RESERVED8;
__IO uint16_t USB_COUNT_TX; __IO uint32_t CNTR;
__IO uint16_t USB_ADDR_RX; __IO uint32_t ISTR;
__IO uint16_t USB_COUNT_RX; __IO uint32_t FNR;
} USB_EPDATA_TypeDef; __IO uint32_t DADDR;
__IO uint32_t BTABLE;
typedef struct{ __IO uint32_t LPMCSR;
__IO USB_EPDATA_TypeDef EP[8]; __IO uint32_t BCDR;
} USB_BtableDef; } USB_TypeDef;
#endif // __USB_DEFS_H__ typedef struct{
__IO uint16_t USB_ADDR_TX;
__IO uint16_t USB_COUNT_TX;
__IO uint16_t USB_ADDR_RX;
__IO uint16_t USB_COUNT_RX;
} USB_EPDATA_TypeDef;
typedef struct{
__IO USB_EPDATA_TypeDef EP[8];
} USB_BtableDef;
#endif // __USB_DEFS_H__

View File

@ -1,489 +1,496 @@
/* /*
* geany_encoding=koi8-r * geany_encoding=koi8-r
* usb_lib.c * usb_lib.c
* *
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com> * Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA. * MA 02110-1301, USA.
* *
*/ */
#include <stdint.h> #include <stdint.h>
#include "usb_lib.h" #include "usb_lib.h"
#include <string.h> // memcpy #include <string.h> // memcpy
#include "usart.h" #include "usart.h"
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
#define EP0DATABUF_SIZE (64) static config_pack_t setup_packet;
#define DEVICE_DESCRIPTOR_SIZE_BYTE (18) static uint8_t ep0databuf[EP0DATABUF_SIZE];
#define DEVICE_QALIFIER_SIZE_BYTE (10) static uint8_t ep0dbuflen = 0;
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
usb_LineCoding getLineCoding(){return lineCoding;}
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
static config_pack_t setup_packet; const uint8_t USB_DeviceDescriptor[] = {
static uint8_t ep0databuf[EP0DATABUF_SIZE]; 18, // bLength
static uint8_t ep0dbuflen = 0; 0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE
0x10, // bcdUSB_L - 1.10
usb_LineCoding getLineCoding(){return lineCoding;} 0x01, // bcdUSB_H
0x00, // bDeviceClass - USB_COMM
const uint8_t USB_DeviceDescriptor[] = { 0x00, // bDeviceSubClass
DEVICE_DESCRIPTOR_SIZE_BYTE, // bLength 0x00, // bDeviceProtocol
0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE 0x40, // bMaxPacketSize
0x10, // bcdUSB_L - 1.10 0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303
0x01, // bcdUSB_H 0x06, // idVendor_H
0x00, // bDeviceClass - USB_COMM 0x03, // idProduct_L
0x00, // bDeviceSubClass 0x23, // idProduct_H
0x00, // bDeviceProtocol 0x00, // bcdDevice_Ver_L
0x40, // bMaxPacketSize 0x03, // bcdDevice_Ver_H
0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303 0x01, // iManufacturer
0x06, // idVendor_H 0x02, // iProduct
0x03, // idProduct_L 0x00, // iSerialNumber
0x23, // idProduct_H 0x01 // bNumConfigurations
0x00, // bcdDevice_Ver_L };
0x03, // bcdDevice_Ver_H
0x01, // iManufacturer const uint8_t USB_DeviceQualifierDescriptor[] = {
0x02, // iProduct 10, //bLength
0x00, // iSerialNumber 0x06, // bDescriptorType
0x01 // bNumConfigurations 0x10, // bcdUSB_L
}; 0x01, // bcdUSB_H
0x00, // bDeviceClass
const uint8_t USB_DeviceQualifierDescriptor[] = { 0x00, // bDeviceSubClass
DEVICE_QALIFIER_SIZE_BYTE, //bLength 0x00, // bDeviceProtocol
0x06, // bDescriptorType 0x40, // bMaxPacketSize0
0x10, // bcdUSB_L 0x01, // bNumConfigurations
0x01, // bcdUSB_H 0x00 // Reserved
0x00, // bDeviceClass };
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol const uint8_t USB_ConfigDescriptor[] = {
0x40, // bMaxPacketSize0 /*Configuration Descriptor*/
0x01, // bNumConfigurations 0x09, /* bLength: Configuration Descriptor size */
0x00 // Reserved 0x02, /* bDescriptorType: Configuration */
}; 39, /* wTotalLength:no of returned bytes */
0x00,
const uint8_t USB_ConfigDescriptor[] = { 0x01, /* bNumInterfaces: 1 interface */
/*Configuration Descriptor*/ 0x01, /* bConfigurationValue: Configuration value */
0x09, /* bLength: Configuration Descriptor size */ 0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0x02, /* bDescriptorType: Configuration */ 0xa0, /* bmAttributes - Bus powered, Remote wakeup */
39, /* wTotalLength:no of returned bytes */ 0x32, /* MaxPower 100 mA */
0x00,
0x01, /* bNumInterfaces: 1 interface */ /*---------------------------------------------------------------------------*/
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */ /*Interface Descriptor */
0xa0, /* bmAttributes - Bus powered, Remote wakeup */ 0x09, /* bLength: Interface Descriptor size */
0x32, /* MaxPower 100 mA */ 0x04, /* bDescriptorType: Interface */
0x00, /* bInterfaceNumber: Number of Interface */
/*---------------------------------------------------------------------------*/ 0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
/*Interface Descriptor */ 0xff, /* bInterfaceClass */
0x09, /* bLength: Interface Descriptor size */ 0x00, /* bInterfaceSubClass */
0x04, /* bDescriptorType: Interface */ 0x00, /* bInterfaceProtocol */
0x00, /* bInterfaceNumber: Number of Interface */ 0x00, /* iInterface: */
0x00, /* bAlternateSetting: Alternate setting */ ///////////////////////////////////////////////////
0x03, /* bNumEndpoints: 3 endpoints used */ /*Endpoint 1 Descriptor*/
0xff, /* bInterfaceClass */ 0x07, /* bLength: Endpoint Descriptor size */
0x00, /* bInterfaceSubClass */ 0x05, /* bDescriptorType: Endpoint */
0x00, /* bInterfaceProtocol */ 0x81, /* bEndpointAddress IN1 */
0x00, /* iInterface: */ 0x03, /* bmAttributes: Interrupt */
/////////////////////////////////////////////////// 0x0a, /* wMaxPacketSize LO: */
/*Endpoint 1 Descriptor*/ 0x00, /* wMaxPacketSize HI: */
0x07, /* bLength: Endpoint Descriptor size */ 0x01, /* bInterval: */
0x05, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress IN1 */ /*Endpoint OUT2 Descriptor*/
0x03, /* bmAttributes: Interrupt */ 0x07, /* bLength: Endpoint Descriptor size */
0x0a, /* wMaxPacketSize LO: */ 0x05, /* bDescriptorType: Endpoint */
0x00, /* wMaxPacketSize HI: */ 0x02, /* bEndpointAddress: OUT2 */
0x01, /* bInterval: */ 0x02, /* bmAttributes: Bulk */
(USB_RXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
/*Endpoint OUT2 Descriptor*/ (USB_RXBUFSZ >> 8),
0x07, /* bLength: Endpoint Descriptor size */ 0x00, /* bInterval: ignore for Bulk transfer */
0x05, /* bDescriptorType: Endpoint */
0x02, /* bEndpointAddress: OUT2 */ /*Endpoint IN3 Descriptor*/
0x02, /* bmAttributes: Bulk */ 0x07, /* bLength: Endpoint Descriptor size */
0x40, /* wMaxPacketSize: */ 0x05, /* bDescriptorType: Endpoint */
0x00, 0x83, /* bEndpointAddress IN3 */
0x00, /* bInterval: ignore for Bulk transfer */ 0x02, /* bmAttributes: Bulk */
(USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
/*Endpoint IN3 Descriptor*/ (USB_TXBUFSZ >> 8),
0x07, /* bLength: Endpoint Descriptor size */ 0x00, /* bInterval: ignore for Bulk transfer */
0x05, /* bDescriptorType: Endpoint */ };
0x83, /* bEndpointAddress IN3 */
0x02, /* bmAttributes: Bulk */ _USB_LANG_ID_(USB_StringLangDescriptor, LANG_US);
0x40, /* wMaxPacketSize: 64 */ // these descriptors are not used in PL2303 emulator!
0x00, _USB_STRING_(USB_StringSerialDescriptor, u"0")
0x00, /* bInterval: ignore for Bulk transfer */ _USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.")
}; _USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller")
_USB_LANG_ID_(LANG_US); static usb_dev_t USB_Dev;
// these descriptors are not used in PL2303 emulator! ep_t endpoints[ENDPOINTS_NUM];
_USB_STRING_(USB_StringSerialDescriptor, u"0")
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.") /*
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller") * default handlers
*/
static usb_dev_t USB_Dev; // SET_LINE_CODING
ep_t endpoints[MAX_ENDPOINTS]; void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){
MSG("linecoding_handler\n");
/* }
* default handlers
*/ // SET_CONTROL_LINE_STATE
// SET_LINE_CODING void WEAK clstate_handler(uint16_t __attribute__((unused)) val){
void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ MSG("clstate_handler\n");
MSG("linecoding"); }
}
// SEND_BREAK
// SET_CONTROL_LINE_STATE void WEAK break_handler(){
void WEAK clstate_handler(uint16_t __attribute__((unused)) val){ MSG("break_handler\n");
#ifdef EBUG }
SEND("change state to ");
printu(val); // handler of vendor requests
usart_putchar('\n'); void WEAK vendor_handler(config_pack_t *packet){
#endif /*SEND("Vendor, reqt=");
} printuhex(packet->bmRequestType);
SEND(", wval=");
// SEND_BREAK printuhex(packet->wValue);
void WEAK break_handler(){ usart_putchar('\n');*/
MSG("Break\n"); if(packet->bmRequestType & 0x80){ // read
} uint8_t c;
switch(packet->wValue){
// handler of vendor requests case 0x8484:
void WEAK vendor_handler(config_pack_t *packet){ c = 2;
/*SEND("Vendor, reqt="); break;
printuhex(packet->bmRequestType); case 0x0080:
SEND(", wval="); c = 1;
printuhex(packet->wValue); break;
usart_putchar('\n');*/ case 0x8686:
if(packet->bmRequestType & 0x80){ // read c = 0xaa;
uint8_t c; break;
switch(packet->wValue){ default:
case 0x8484: c = 0;
c = 2; }
break; EP_WriteIRQ(0, &c, 1);
case 0x0080: }else{ // write ZLP
c = 1; EP_WriteIRQ(0, (uint8_t *)0, 0);
break; }
case 0x8686: }
c = 0xaa;
break; /*
default: bmRequestType: 76543210
c = 0; 7 direction: 0 - host->device, 1 - device->host
} 65 type: 0 - standard, 1 - class, 2 - vendor
EP_WriteIRQ(0, &c, 1); 4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other
}else{ // write ZLP */
EP_WriteIRQ(0, (uint8_t *)0, 0); /**
} * Endpoint0 (control) handler
} * @param ep - endpoint state
* @return data written to EP0R
/* */
bmRequestType: 76543210 uint16_t EP0_Handler(ep_t ep){
7 direction: 0 - host->device, 1 - device->host uint16_t status = 0; // bus powered
65 type: 0 - standard, 1 - class, 2 - vendor uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications
4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured)
*/ void wr0(const uint8_t *buf, uint16_t size){
/** if(setup_packet.wLength < size) size = setup_packet.wLength;
* Endpoint0 (control) handler EP_WriteIRQ(0, buf, size);
* @param ep - endpoint state }
* @return data written to EP0R #ifdef EBUG
*/ uint8_t _2wr = 0;
uint16_t EP0_Handler(ep_t ep){ #define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0)
uint16_t status = 0; // bus powered #else
uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications #define WRITEDUMP(str)
static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) #endif
void wr0(const uint8_t *buf, uint16_t size){ if ((ep.rx_flag) && (ep.setup_flag)){
if(setup_packet.wLength < size) size = setup_packet.wLength; if (setup_packet.bmRequestType == 0x80){ // standard device request (device to host)
EP_WriteIRQ(0, buf, size); switch(setup_packet.bRequest){
} case GET_DESCRIPTOR:
#ifdef EBUG switch(setup_packet.wValue){
uint8_t _2wr = 0; case DEVICE_DESCRIPTOR:
#define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0) wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
#else break;
#define WRITEDUMP(str) case CONFIGURATION_DESCRIPTOR:
#endif wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
if ((ep.rx_flag) && (ep.setup_flag)){ break;
if (setup_packet.bmRequestType == 0x80){ // standard device request (device to host) case STRING_LANG_DESCRIPTOR:
switch(setup_packet.bRequest){ wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE);
case GET_DESCRIPTOR: break;
switch(setup_packet.wValue){ case STRING_MAN_DESCRIPTOR:
case DEVICE_DESCRIPTOR: wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); break;
break; case STRING_PROD_DESCRIPTOR:
case CONFIGURATION_DESCRIPTOR: wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); break;
break; case STRING_SN_DESCRIPTOR:
case STRING_LANG_DESCRIPTOR: wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); break;
break; case DEVICE_QALIFIER_DESCRIPTOR:
case STRING_MAN_DESCRIPTOR: wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]);
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); break;
break; default:
case STRING_PROD_DESCRIPTOR: WRITEDUMP("UNK_DES");
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); break;
break; }
case STRING_SN_DESCRIPTOR: break;
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); case GET_STATUS:
break; EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered
case DEVICE_QALIFIER_DESCRIPTOR: break;
wr0(USB_DeviceQualifierDescriptor, DEVICE_QALIFIER_SIZE_BYTE); case GET_CONFIGURATION:
break; WRITEDUMP("GET_CONFIGURATION");
default: EP_WriteIRQ(0, &configuration, 1);
WRITEDUMP("UNK_DES"); break;
break; default:
} WRITEDUMP("80:WR_REQ");
break; break;
case GET_STATUS: }
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered epstatus = SET_NAK_RX(epstatus);
break; epstatus = SET_VALID_TX(epstatus);
case GET_CONFIGURATION: }else if(setup_packet.bmRequestType == 0x00){ // standard device request (host to device)
WRITEDUMP("GET_CONFIGURATION"); switch(setup_packet.bRequest){
EP_WriteIRQ(0, &configuration, 1); case SET_ADDRESS:
break; // new address will be assigned later - after acknowlegement or request to host
default: USB_Dev.USB_Addr = setup_packet.wValue;
WRITEDUMP("80:WR_REQ"); break;
break; case SET_CONFIGURATION:
} // Now device configured
epstatus = SET_NAK_RX(epstatus); USB_Dev.USB_Status = USB_CONFIGURE_STATE;
epstatus = SET_VALID_TX(epstatus); configuration = setup_packet.wValue;
}else if(setup_packet.bmRequestType == 0x00){ // standard device request (host to device) break;
switch(setup_packet.bRequest){ default:
case SET_ADDRESS: WRITEDUMP("0:WR_REQ");
// new address will be assigned later - after acknowlegement or request to host break;
USB_Dev.USB_Addr = setup_packet.wValue; }
break; // send ZLP
case SET_CONFIGURATION: EP_WriteIRQ(0, (uint8_t *)0, 0);
// Now device configured epstatus = SET_NAK_RX(epstatus);
USB_Dev.USB_Status = USB_CONFIGURE_STATE; epstatus = SET_VALID_TX(epstatus);
configuration = setup_packet.wValue; }else if(setup_packet.bmRequestType == 0x02){ // standard endpoint request (host to device)
break; if (setup_packet.bRequest == CLEAR_FEATURE){
default: // send ZLP
WRITEDUMP("0:WR_REQ"); EP_WriteIRQ(0, (uint8_t *)0, 0);
break; epstatus = SET_NAK_RX(epstatus);
} epstatus = SET_VALID_TX(epstatus);
// send ZLP }else{
EP_WriteIRQ(0, (uint8_t *)0, 0); WRITEDUMP("02:WR_REQ");
epstatus = SET_NAK_RX(epstatus); }
epstatus = SET_VALID_TX(epstatus); }else if((setup_packet.bmRequestType & VENDOR_MASK_REQUEST) == VENDOR_MASK_REQUEST){ // vendor request
}else if(setup_packet.bmRequestType == 0x02){ // standard endpoint request (host to device) vendor_handler(&setup_packet);
if (setup_packet.bRequest == CLEAR_FEATURE){ epstatus = SET_NAK_RX(epstatus);
// send ZLP epstatus = SET_VALID_TX(epstatus);
EP_WriteIRQ(0, (uint8_t *)0, 0); }else if((setup_packet.bmRequestType & 0x7f) == CONTROL_REQUEST_TYPE){ // control request
epstatus = SET_NAK_RX(epstatus); switch(setup_packet.bRequest){
epstatus = SET_VALID_TX(epstatus); case GET_LINE_CODING:
}else{ EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
WRITEDUMP("02:WR_REQ"); break;
} case SET_LINE_CODING:
}else if((setup_packet.bmRequestType & VENDOR_MASK_REQUEST) == VENDOR_MASK_REQUEST){ // vendor request break;
vendor_handler(&setup_packet); case SET_CONTROL_LINE_STATE:
epstatus = SET_NAK_RX(epstatus); clstate_handler(setup_packet.wValue);
epstatus = SET_VALID_TX(epstatus); break;
}else if((setup_packet.bmRequestType & 0x7f) == CONTROL_REQUEST_TYPE){ // control request case SEND_BREAK:
switch(setup_packet.bRequest){ break_handler();
case GET_LINE_CODING: break;
EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); default:
break; WRITEDUMP("undef control req");
case SET_LINE_CODING: }
break; if((setup_packet.bmRequestType & 0x80) == 0) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
case SET_CONTROL_LINE_STATE: epstatus = SET_VALID_RX(epstatus);
clstate_handler(setup_packet.wValue); epstatus = SET_VALID_TX(epstatus);
break; }
case SEND_BREAK: }else if (ep.rx_flag){ // got data over EP0 or host acknowlegement
break_handler(); if(ep.rx_cnt){
break; if(setup_packet.bRequest == SET_LINE_CODING){
default: //WRITEDUMP("SET_LINE_CODING");
WRITEDUMP("undef control req"); linecoding_handler((usb_LineCoding*)ep0databuf);
} }
if((setup_packet.bmRequestType & 0x80) == 0) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement EP_WriteIRQ(0, (uint8_t *)0, 0);
epstatus = SET_VALID_RX(epstatus); }
epstatus = SET_VALID_TX(epstatus); // Close transaction
} epstatus = CLEAR_DTOG_RX(epstatus);
}else if (ep.rx_flag){ // got data over EP0 or host acknowlegement epstatus = CLEAR_DTOG_TX(epstatus);
if(ep.rx_cnt){ // wait for new data from host
if(setup_packet.bRequest == SET_LINE_CODING){ epstatus = SET_VALID_RX(epstatus);
//WRITEDUMP("SET_LINE_CODING"); epstatus = SET_STALL_TX(epstatus);
linecoding_handler((usb_LineCoding*)ep0databuf); } else if (ep.tx_flag){ // package transmitted
} // now we can change address after enumeration
EP_WriteIRQ(0, (uint8_t *)0, 0); if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
} USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr;
// Close transaction // change state to ADRESSED
epstatus = CLEAR_DTOG_RX(epstatus); USB_Dev.USB_Status = USB_ADRESSED_STATE;
epstatus = CLEAR_DTOG_TX(epstatus); }
// wait for new data from host // end of transaction
epstatus = SET_VALID_RX(epstatus); epstatus = CLEAR_DTOG_RX(epstatus);
epstatus = SET_STALL_TX(epstatus); epstatus = CLEAR_DTOG_TX(epstatus);
} else if (ep.tx_flag){ // package transmitted epstatus = SET_VALID_RX(epstatus);
// now we can change address after enumeration epstatus = SET_VALID_TX(epstatus);
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ }
USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; #ifdef EBUG
// change state to ADRESSED if(_2wr){
USB_Dev.USB_Status = USB_ADRESSED_STATE; usart_putchar(' ');
} if (ep.rx_flag) usart_putchar('r');
// end of transaction else usart_putchar('t');
epstatus = CLEAR_DTOG_RX(epstatus); printu(setup_packet.wLength);
epstatus = CLEAR_DTOG_TX(epstatus); if(ep.setup_flag) usart_putchar('s');
epstatus = SET_VALID_RX(epstatus); usart_putchar(' ');
epstatus = SET_VALID_TX(epstatus); usart_putchar('I');
} printu(setup_packet.wIndex);
#ifdef EBUG usart_putchar('V');
if(_2wr){ printu(setup_packet.wValue);
usart_putchar(' '); usart_putchar('R');
if (ep.rx_flag) usart_putchar('r'); printu(setup_packet.bRequest);
else usart_putchar('t'); usart_putchar('T');
printu(setup_packet.wLength); printu(setup_packet.bmRequestType);
if(ep.setup_flag) usart_putchar('s'); usart_putchar(' ');
usart_putchar(' '); usart_putchar('0' + ep0dbuflen);
usart_putchar('I'); usart_putchar(' ');
printu(setup_packet.wIndex); hexdump(ep0databuf, ep0dbuflen);
usart_putchar('V'); usart_putchar('\n');
printu(setup_packet.wValue); }
usart_putchar('R'); #endif
printu(setup_packet.bRequest); return epstatus;
usart_putchar('T'); }
printu(setup_packet.bmRequestType);
usart_putchar(' '); static uint16_t lastaddr = USB_EP0_BASEADDR;
usart_putchar('0' + ep0dbuflen); /**
usart_putchar(' '); * Endpoint initialisation
hexdump(ep0databuf, ep0dbuflen); * !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
usart_putchar('\n'); * @param number - EP num (0...7)
} * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT)
#endif * @param txsz - transmission buffer size @ USB/CAN buffer
return epstatus; * @param rxsz - reception buffer size @ USB/CAN buffer
} * @param uint16_t (*func)(ep_t *ep) - EP handler function
* @return 0 if all OK
// TODO: change initialisation with different buffer size! (EP0 have 8 bytes per buffer, EP1 - 10 bytes!) */
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){
/** if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
* Endpoint initialisation, size of input buffer fixed to 64 bytes if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable
* @param number - EP num (0...7) USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
* @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
* @param addr_tx - transmission buffer address @ USB/CAN buffer if(rxsz & 1 || rxsz > 992) return 3; // wrong rx buffer size
* @param addr_rx - reception buffer address @ USB/CAN buffer uint16_t countrx = 0;
* @param uint16_t (*func)(ep_t *ep) - EP handler function if(rxsz < 64) countrx = rxsz / 2;
*/ else{
void EP_Init(uint8_t number, uint8_t type, uint16_t addr_tx, uint16_t addr_rx, uint16_t (*func)(ep_t ep)){ if(rxsz & 0x1f) return 3; // should be multiple of 32
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); countrx = 31 + rxsz / 32;
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; }
USB_BTABLE->EP[number].USB_ADDR_TX = addr_tx; USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr;
USB_BTABLE->EP[number].USB_COUNT_TX = 0; endpoints[number].tx_sz = txsz;
USB_BTABLE->EP[number].USB_ADDR_RX = addr_rx; endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr);
USB_BTABLE->EP[number].USB_COUNT_RX = 0x8400; // buffer size (64 bytes): Table127 of RM: BL_SIZE=1, NUM_BLOCK=1 lastaddr += txsz;
endpoints[number].func = func; USB_BTABLE->EP[number].USB_COUNT_TX = 0;
endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + addr_tx); USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr;
endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + addr_rx); endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr);
} lastaddr += rxsz;
// buffer size: Table127 of RM: BL_SIZE=1, NUM_BLOCK=1
// standard IRQ handler USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10;
void usb_isr(){ endpoints[number].func = func;
uint8_t n; return 0;
if (USB->ISTR & USB_ISTR_RESET){ }
// Reinit registers
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; // standard IRQ handler
USB->ISTR = 0; void usb_isr(){
// Endpoint 0 - CONTROL uint8_t n;
EP_Init(0, EP_TYPE_CONTROL, 64, 128, EP0_Handler); if (USB->ISTR & USB_ISTR_RESET){
// clear address, leave only enable bit // Reinit registers
USB->DADDR = USB_DADDR_EF; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
// state is default - wait for enumeration USB->ISTR = 0;
USB_Dev.USB_Status = USB_DEFAULT_STATE; // Endpoint 0 - CONTROL
} // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes!
if(USB->ISTR & USB_ISTR_CTR){ lastaddr = USB_EP0_BASEADDR; // roll back to beginning of buffer
// EP number EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler);
n = USB->ISTR & USB_ISTR_EPID; // clear address, leave only enable bit
// copy status register USB->DADDR = USB_DADDR_EF;
uint16_t epstatus = USB->EPnR[n]; // state is default - wait for enumeration
// Calculate flags USB_Dev.USB_Status = USB_DEFAULT_STATE;
endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0; }
endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; if(USB->ISTR & USB_ISTR_CTR){
endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0; // EP number
// copy received bytes amount n = USB->ISTR & USB_ISTR_EPID;
endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX; // copy status register
// check direction uint16_t epstatus = USB->EPnR[n];
if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) // Calculate flags
if(n == 0){ // control endpoint endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0;
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0;
memcpy(&setup_packet, endpoints[0].rx_buf, sizeof(setup_packet)); endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0;
ep0dbuflen = 0; // copy received bytes amount
// interrupt handler will be called later endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX;
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf // check direction
ep0dbuflen = endpoints[0].rx_cnt; if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit)
memcpy(ep0databuf, endpoints[0].rx_buf, ep0dbuflen); if(n == 0){ // control endpoint
} if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack
} memcpy(&setup_packet, endpoints[0].rx_buf, sizeof(setup_packet));
}else{ // IN interrupt - transmit data, only CTR_TX == 1 ep0dbuflen = 0;
// enumeration end could be here (if EP0) // interrupt handler will be called later
} }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
// prepare status field for EP handler ep0dbuflen = endpoints[0].rx_cnt;
endpoints[n].status = epstatus; memcpy(ep0databuf, endpoints[0].rx_buf, ep0dbuflen);
// call EP handler (even if it will change EPnR, it should return new status) }
epstatus = endpoints[n].func(endpoints[n]); }
// keep DTOG state }else{ // IN interrupt - transmit data, only CTR_TX == 1
epstatus = KEEP_DTOG_TX(epstatus); // enumeration end could be here (if EP0)
epstatus = KEEP_DTOG_RX(epstatus); }
// clear all RX/TX flags // prepare status field for EP handler
epstatus = CLEAR_CTR_RX(epstatus); endpoints[n].status = epstatus;
epstatus = CLEAR_CTR_TX(epstatus); // call EP handler (even if it will change EPnR, it should return new status)
// refresh EPnR epstatus = endpoints[n].func(endpoints[n]);
USB->EPnR[n] = epstatus; // keep DTOG state
} epstatus = KEEP_DTOG_TX(epstatus);
} epstatus = KEEP_DTOG_RX(epstatus);
// clear all RX/TX flags
/** epstatus = CLEAR_CTR_RX(epstatus);
* Write data to EP buffer (called from IRQ handler) epstatus = CLEAR_CTR_TX(epstatus);
* @param number - EP number // refresh EPnR
* @param *buf - array with data USB->EPnR[n] = epstatus;
* @param size - its size }
*/ }
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
uint8_t i; /**
uint16_t N2 = (size + 1) >> 1; * Write data to EP buffer (called from IRQ handler)
// the buffer is 16-bit, so we should copy data as it would be uint16_t * @param number - EP number
uint16_t *buf16 = (uint16_t *)buf; * @param *buf - array with data
for (i = 0; i < N2; i++){ * @param size - its size
endpoints[number].tx_buf[i] = buf16[i]; */
} void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
USB_BTABLE->EP[number].USB_COUNT_TX = size; uint8_t i;
} 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;
* Write data to EP buffer (called outside IRQ handler) for (i = 0; i < N2; i++){
* @param number - EP number endpoints[number].tx_buf[i] = buf16[i];
* @param *buf - array with data }
* @param size - its size USB_BTABLE->EP[number].USB_COUNT_TX = size;
*/ }
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
uint16_t status = USB->EPnR[number]; /**
EP_WriteIRQ(number, buf, size); * Write data to EP buffer (called outside IRQ handler)
status = SET_NAK_RX(status); * @param number - EP number
status = SET_VALID_TX(status); * @param *buf - array with data
status = KEEP_DTOG_TX(status); * @param size - its size
status = KEEP_DTOG_RX(status); */
USB->EPnR[number] = status; void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
} uint16_t status = USB->EPnR[number];
EP_WriteIRQ(number, buf, size);
/* status = SET_NAK_RX(status);
* Copy data from EP buffer into user buffer area status = SET_VALID_TX(status);
* @param *buf - user array for data status = KEEP_DTOG_TX(status);
* @return amount of data read status = KEEP_DTOG_RX(status);
*/ USB->EPnR[number] = status;
int EP_Read(uint8_t number, uint8_t *buf){ }
int n = endpoints[number].rx_cnt;
if(n){ /*
for(int i = 0; i < n; ++i) * Copy data from EP buffer into user buffer area
buf[i] = endpoints[number].rx_buf[i]; * @param *buf - user array for data
} * @return amount of data read
return n; */
} int EP_Read(uint8_t number, uint8_t *buf){
int n = endpoints[number].rx_cnt;
// USB status if(n){
uint8_t USB_GetState(){ for(int i = 0; i < n; ++i)
return USB_Dev.USB_Status; buf[i] = endpoints[number].rx_buf[i];
} }
return n;
}
// USB status
uint8_t USB_GetState(){
return USB_Dev.USB_Status;
}

View File

@ -28,8 +28,10 @@
#include <wchar.h> #include <wchar.h>
#include "usb_defs.h" #include "usb_defs.h"
#define EP0DATABUF_SIZE (64)
// Max EP amount (EP0 + other used) // Max EP amount (EP0 + other used)
#define MAX_ENDPOINTS 4 #define ENDPOINTS_NUM 4
// 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
@ -121,16 +123,17 @@ static const struct name \
} \ } \
name = {sizeof(name), 0x03, str}; name = {sizeof(name), 0x03, str};
#define _USB_LANG_ID_(lng_id) \ #define _USB_LANG_ID_(name, lng_id) \
\ \
static const struct USB_StringLangDescriptor \ static const struct name \
{ \ { \
uint8_t bLength; \ uint8_t bLength; \
uint8_t bDescriptorType; \ uint8_t bDescriptorType; \
uint16_t bString; \ uint16_t bString; \
\ \
} \ } \
USB_StringLangDescriptor = {0x04, 0x03, lng_id}; name = {0x04, 0x03, lng_id};
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
// EP0 configuration packet // EP0 configuration packet
typedef struct { typedef struct {
@ -143,19 +146,20 @@ typedef struct {
// endpoints state // endpoints state
typedef struct __ep_t{ typedef struct __ep_t{
uint16_t *tx_buf; uint16_t *tx_buf; // transmission buffer address
uint8_t *rx_buf; uint8_t *rx_buf; // reception buffer address
uint16_t (*func)(); uint16_t (*func)(); // endpoint action function
uint16_t status; uint16_t status; // status flags
unsigned rx_cnt : 10; unsigned tx_sz : 10; // Tx buffer size
unsigned tx_flag : 1; unsigned rx_cnt : 10; // received data counter
unsigned rx_flag : 1; unsigned tx_flag : 1; // transmission flag
unsigned setup_flag : 1; unsigned rx_flag : 1; // reception flag
unsigned setup_flag : 1; // this is setup packet (only for EP0)
} ep_t; } ep_t;
// USB status & its address // USB status & its address
typedef struct { typedef struct {
uint8_t USB_Status; uint8_t USB_Status;
uint16_t USB_Addr; uint16_t USB_Addr;
}usb_dev_t; }usb_dev_t;
@ -186,7 +190,7 @@ extern ep_t endpoints[];
void USB_Init(); void USB_Init();
uint8_t USB_GetState(); uint8_t USB_GetState();
void EP_Init(uint8_t number, uint8_t type, uint16_t addr_tx, uint16_t addr_rx, 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));
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);
void EP_Write(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); int EP_Read(uint8_t number, uint8_t *buf);