From 00913a7e801544ad2602261979a3278af6630c9b Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 13 Jun 2023 19:49:35 +0300 Subject: [PATCH] change USB for common files --- F1:F103/F1_testbrd/F1_testbrd.files | 6 + F1:F103/F1_testbrd/Makefile | 142 +------ F1:F103/F1_testbrd/hardware.h | 6 - F1:F103/F1_testbrd/main.c | 27 +- F1:F103/F1_testbrd/pl2303.bin | Bin 13280 -> 10824 bytes F1:F103/F1_testbrd/proto.c | 371 ++++-------------- F1:F103/F1_testbrd/proto.h | 14 +- F1:F103/F1_testbrd/ringbuffer.c | 124 ++++++ F1:F103/F1_testbrd/ringbuffer.h | 35 ++ F1:F103/F1_testbrd/strfunc.c | 267 +++++++++++++ F1:F103/F1_testbrd/strfunc.h | 30 ++ F1:F103/F1_testbrd/usart.c | 7 +- F1:F103/F1_testbrd/usart.h | 4 +- F1:F103/F1_testbrd/usb.c | 218 +++++----- F1:F103/F1_testbrd/usb.h | 37 +- F1:F103/F1_testbrd/usb_lib.c | 257 +++++------- F1:F103/F1_testbrd/usb_lib.h | 55 ++- F1:F103/F1_testbrd/usbhw.c | 123 ++++++ F1:F103/F1_testbrd/{usb_defs.h => usbhw.h} | 28 +- F1:F103/F1_testbrd/version.inc | 2 + F1:F103/PL2303_ringbuffer/Makefile | 6 +- F1:F103/PL2303_ringbuffer/Makefile.old | 151 ------- F1:F103/PL2303_ringbuffer/PL2303.bin | Bin 6660 -> 6672 bytes F1:F103/PL2303_ringbuffer/hardware.c | 8 +- F1:F103/PL2303_ringbuffer/hardware.h | 8 +- F1:F103/PL2303_ringbuffer/main.c | 38 +- F1:F103/PL2303_ringbuffer/openocd.cfg | 4 + F1:F103/PL2303_ringbuffer/pl2303.cflags | 1 + F1:F103/PL2303_ringbuffer/pl2303.config | 6 + F1:F103/PL2303_ringbuffer/pl2303.creator | 1 + F1:F103/PL2303_ringbuffer/pl2303.creator.user | 171 ++++++++ F1:F103/PL2303_ringbuffer/pl2303.cxxflags | 1 + F1:F103/PL2303_ringbuffer/pl2303.files | 15 + F1:F103/PL2303_ringbuffer/pl2303.includes | 6 + F1:F103/PL2303_ringbuffer/proto.c | 6 +- F1:F103/PL2303_ringbuffer/ringbuffer.c | 119 ++++-- F1:F103/PL2303_ringbuffer/ringbuffer.h | 26 +- F1:F103/PL2303_ringbuffer/usart.c | 2 +- F1:F103/PL2303_ringbuffer/usb.c | 156 ++++---- F1:F103/PL2303_ringbuffer/usb.h | 39 +- F1:F103/PL2303_ringbuffer/usb_lib.c | 169 +++++--- F1:F103/PL2303_ringbuffer/usb_lib.h | 58 +-- F1:F103/PL2303_ringbuffer/usbhw.c | 17 +- F1:F103/PL2303_ringbuffer/usbhw.h | 24 +- F1:F103/PL2303_ringbuffer/version.inc | 4 +- .../F0_F1_F3-LQFP48_testboard/stm32.kicad_prl | 4 +- .../F0_F1_F3-LQFP48_testboard/stm32.kicad_pro | 14 +- 47 files changed, 1558 insertions(+), 1249 deletions(-) create mode 100644 F1:F103/F1_testbrd/ringbuffer.c create mode 100644 F1:F103/F1_testbrd/ringbuffer.h create mode 100644 F1:F103/F1_testbrd/strfunc.c create mode 100644 F1:F103/F1_testbrd/strfunc.h create mode 100644 F1:F103/F1_testbrd/usbhw.c rename F1:F103/F1_testbrd/{usb_defs.h => usbhw.h} (82%) create mode 100644 F1:F103/F1_testbrd/version.inc delete mode 100644 F1:F103/PL2303_ringbuffer/Makefile.old create mode 100644 F1:F103/PL2303_ringbuffer/openocd.cfg create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.cflags create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.config create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.creator create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.creator.user create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.cxxflags create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.files create mode 100644 F1:F103/PL2303_ringbuffer/pl2303.includes diff --git a/F1:F103/F1_testbrd/F1_testbrd.files b/F1:F103/F1_testbrd/F1_testbrd.files index 26b3859..df40d50 100644 --- a/F1:F103/F1_testbrd/F1_testbrd.files +++ b/F1:F103/F1_testbrd/F1_testbrd.files @@ -9,6 +9,10 @@ main.c pl2303.bin proto.c proto.h +ringbuffer.c +ringbuffer.h +strfunc.c +strfunc.h usart.c usart.h usb.c @@ -16,3 +20,5 @@ usb.h usb_defs.h usb_lib.c usb_lib.h +usbhw.c +usbhw.h diff --git a/F1:F103/F1_testbrd/Makefile b/F1:F103/F1_testbrd/Makefile index 1675bb4..f2b1689 100644 --- a/F1:F103/F1_testbrd/Makefile +++ b/F1:F103/F1_testbrd/Makefile @@ -1,139 +1,9 @@ -BINARY = pl2303 -BOOTPORT ?= /dev/ttyUSB0 -BOOTSPEED ?= 115200 -# MCU FAMILY -FAMILY ?= F1 +BINARY := pl2303 # MCU code -MCU ?= F103x6 -# density (stm32f10x.h, lines 70-84) -DENSITY ?= LD +MCU ?= F103x6 # change this linking script depending on particular MCU model, -LDSCRIPT ?= stm32f103x6.ld -# debug -DEFS = -DEBUG +LDSCRIPT ?= stm32f103x6.ld +DEFINES := -DSTM32F10X_LD -DUSB1_16 -INDEPENDENT_HEADERS= - -FP_FLAGS ?= -msoft-float -mfloat-abi=soft -ASM_FLAGS ?= -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd -ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS) - -############################################################################### -# Executables -#PREFIX ?= arm-none-eabi -# gcc from arm web site -PREFIX ?= /opt/bin/arm-none-eabi -TOOLCHLIB ?= /opt/arm-none-eabi/lib -RM := rm -f -RMDIR := rmdir -CC := $(PREFIX)-gcc -# don't replace ld with gcc: the binary size would be much greater!! -LD := $(PREFIX)-ld -AR := $(PREFIX)-ar -AS := $(PREFIX)-as -SIZE := $(PREFIX)-size -OBJCOPY := $(PREFIX)-objcopy -OBJDUMP := $(PREFIX)-objdump -GDB := $(PREFIX)-gdb -STFLASH := $(shell which st-flash) -STBOOT := $(shell which stm32flash) -DFUUTIL := $(shell which dfu-util) - -############################################################################### -# Source files -OBJDIR = mk -SRC := $(wildcard *.c) -OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) -STARTUP = $(OBJDIR)/startup.o -OBJS += $(STARTUP) -# dependencies: we need them to recompile files if their headers-dependencies changed -DEPS := $(OBJS:.o=.d) - -INC_DIR ?= ../inc - -INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm -LIB_DIR := $(INC_DIR)/ld - -############################################################################### -# C flags -CFLAGS += -O2 -g -D__thumb2__=1 -MD -CFLAGS += -Wall -Werror -Wextra -Wshadow -CFLAGS += -fno-common -ffunction-sections -fdata-sections -fno-stack-protector -CFLAGS += $(ARCH_FLAGS) - -############################################################################### -# Linker flags -LDFLAGS += -nostartfiles --static -nostdlibs -LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB) -LDFLAGS += -T$(LDSCRIPT) - -############################################################################### -# Used libraries -LDLIBS += -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) - -DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY) - -ELF := $(OBJDIR)/$(BINARY).elf -LIST := $(OBJDIR)/$(BINARY).list -BIN := $(BINARY).bin -HEX := $(BINARY).hex - -all: bin list size - -elf: $(ELF) -bin: $(BIN) -hex: $(HEX) -list: $(LIST) - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPS) -endif - -$(OBJDIR): - mkdir $(OBJDIR) - -$(STARTUP): $(INC_DIR)/startup/vector.c - $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $< - -$(OBJDIR)/%.o: %.c - @echo " CC $<" - $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $< - -$(BIN): $(ELF) - @echo " OBJCOPY $(BIN)" - $(OBJCOPY) -Obinary $(ELF) $(BIN) - -$(HEX): $(ELF) - @echo " OBJCOPY $(HEX)" - $(OBJCOPY) -Oihex $(ELF) $(HEX) - -$(LIST): $(ELF) - @echo " OBJDUMP $(LIST)" - $(OBJDUMP) -S $(ELF) > $(LIST) - -$(ELF): $(OBJDIR) $(OBJS) - @echo " LD $(ELF)" - $(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF) - -size: $(ELF) - $(SIZE) $(ELF) - -clean: - @echo " CLEAN" - $(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) - @rmdir $(OBJDIR) 2>/dev/null || true - - -flash: $(BIN) - @echo " FLASH $(BIN)" - $(STFLASH) write $(BIN) 0x8000000 - -boot: $(BIN) - @echo " LOAD $(BIN) through bootloader" - $(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN) - -dfuboot: $(BIN) - @echo " LOAD $(BIN) THROUGH DFU" - $(DFUUTIL) -a0 -D $(BIN) -s 0x08000000 - -.PHONY: clean flash boot +include ../makefile.f1 +include ../../makefile.stm32 diff --git a/F1:F103/F1_testbrd/hardware.h b/F1:F103/F1_testbrd/hardware.h index bffefeb..d79d47a 100644 --- a/F1:F103/F1_testbrd/hardware.h +++ b/F1:F103/F1_testbrd/hardware.h @@ -19,11 +19,5 @@ #pragma once #include -// USB pullup (not used in STM32F0x2!) - PA13 -#define USBPU_port GPIOA -#define USBPU_pin (1<<15) -#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin) -#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin) - void hw_setup(); diff --git a/F1:F103/F1_testbrd/main.c b/F1:F103/F1_testbrd/main.c index 77b8521..a46fe7b 100644 --- a/F1:F103/F1_testbrd/main.c +++ b/F1:F103/F1_testbrd/main.c @@ -38,14 +38,16 @@ volatile uint8_t ADCmon = 0; // ==1 to monitor ADC (change PWM of LEDS & show cu uint16_t oldADCval = 0; int main(void){ + char tmpbuf[129]; uint32_t lastT = 0; sysreset(); StartHSE(); + + USBPU_OFF(); hw_setup(); usart_setup(); SysTick_Config(72000); - USBPU_OFF(); USB_setup(); USBPU_ON(); @@ -68,7 +70,8 @@ int main(void){ int32_t d = v - oldADCval; if(d < -ADCthreshold || d > ADCthreshold){ oldADCval = v; - printADCvals(); + printADCvals(USB_sendstr); + printADCvals(usart_send); v >>= 2; // 10 bits TIM3->CCR1 = TIM3->CCR2 = TIM3->CCR3 = 0xff; TIM3->CCR4 = 0; if(v >= 0x300) TIM3->CCR4 = v - 0x300; @@ -90,31 +93,29 @@ int main(void){ USND(") - found device\n"); } } - usb_proc(); int r = 0; char *txt, *ans; - if((txt = get_USB())){ - ans = (char*)parse_cmd(txt); + int l = USB_receivestr(tmpbuf, 128); + if(l){ SEND("Received data over USB:\n"); - SEND(txt); - newline(); + SEND(tmpbuf); + usart_newline(); + ans = (char*)parse_cmd(USB_sendstr, tmpbuf); if(ans){ - uint16_t l = 0; char *p = ans; - while(*p++) l++; - USB_send((uint8_t*)ans, l); - if(ans[l-1] != '\n') USND("\n"); + USB_sendstr(ans); + //if(ans[l-1] != '\n') usb_newline(); } } if(usartrx()){ // usart1 received data, store in in buffer r = usart_getline(&txt); if(r){ txt[r] = 0; - ans = (char*)parse_cmd(txt); + ans = (char*)parse_cmd(usart_send, txt); if(ans){ usart_send(ans); transmit_tbuf(); } - USND("Got string over USART:\n"); + USND("Got string over USART:"); USB_sendstr(txt); } } diff --git a/F1:F103/F1_testbrd/pl2303.bin b/F1:F103/F1_testbrd/pl2303.bin index 289405e3311f88ad706e1eb48718d35f5d2d2e5e..bf997e10e57166eaff2f8db535142308f1adf304 100755 GIT binary patch literal 10824 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 bEhdcrI|1Jih`fivmj-lCNFSlWH^%<~Q`jA! literal 13280 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 M9%0dkxF$yb54|hh_y7O^ diff --git a/F1:F103/F1_testbrd/proto.c b/F1:F103/F1_testbrd/proto.c index 54f0124..6191b0d 100644 --- a/F1:F103/F1_testbrd/proto.c +++ b/F1:F103/F1_testbrd/proto.c @@ -29,15 +29,8 @@ // local buffer for I2C and SPI data to send static uint8_t locBuffer[LOCBUFFSZ]; -void USB_sendstr(const char *str){ - uint16_t l = 0; - const char *b = str; - while(*b++) ++l; - USB_send((const uint8_t*)str, l); -} - -static inline char *chPWM(volatile uint32_t *reg, char *buf){ - char *lbuf = buf; +static inline const char *chPWM(volatile uint32_t *reg, const char *buf){ + const char *lbuf = buf; lbuf = omit_spaces(lbuf); char cmd = *lbuf; lbuf = omit_spaces(lbuf + 1); @@ -51,78 +44,50 @@ static inline char *chPWM(volatile uint32_t *reg, char *buf){ if(oldval + N > 255) return "Already at maximum"; else *reg += N; }else{ - USND("Wrong command: "); - return buf; + return "Wrong command\n"; } return "OK"; } -static inline char *TIM3pwm(char *buf){ +static inline const char *TIM3pwm(const char *buf){ uint8_t channel = *buf - '1'; if(channel > 3) return "Wrong channel number"; volatile uint32_t *reg = (uint32_t*)&(TIM3->CCR1); return chPWM(®[channel], buf+1); } -static inline char *getPWMvals(){ - USND("TIM1CH1: "); USB_sendstr(u2str(TIM1->CCR1)); - USND("\nTIM3CH1: "); USB_sendstr(u2str(TIM3->CCR1)); - USND("\nTIM3CH2: "); USB_sendstr(u2str(TIM3->CCR2)); - USND("\nTIM3CH3: "); USB_sendstr(u2str(TIM3->CCR3)); - USND("\nTIM3CH4: "); USB_sendstr(u2str(TIM3->CCR4)); - USND("\n"); +static inline char *getPWMvals(int (*sendfun)(const char *s)){ + sendfun("TIM1CH1: "); sendfun(u2str(TIM1->CCR1)); + sendfun("\nTIM3CH1: "); sendfun(u2str(TIM3->CCR1)); + sendfun("\nTIM3CH2: "); sendfun(u2str(TIM3->CCR2)); + sendfun("\nTIM3CH3: "); sendfun(u2str(TIM3->CCR3)); + sendfun("\nTIM3CH4: "); sendfun(u2str(TIM3->CCR4)); + sendfun("\n"); return NULL; } -static inline char *USARTsend(char *buf){ -// uint32_t N; -// if(buf == getnum(buf, &N)) return "Point number of USART"; -// if(N < 1 || N > USARTNUM) return "Wrong USART number"; -// buf = omit_spaces(buf + 1); +static inline const char *USARTsend(const char *buf){ usart_send(buf); transmit_tbuf(); return "OK"; } // read N numbers from buf, @return 0 if wrong or none -static uint16_t readNnumbers(char *buf){ +static uint16_t readNnumbers(int (*sendfun)(const char *s), const char *buf){ uint32_t D; - char *nxt; + const char *nxt; uint16_t N = 0; while((nxt = getnum(buf, &D)) && nxt != buf && N < LOCBUFFSZ){ buf = nxt; locBuffer[N++] = (uint8_t) D&0xff; - USND("add byte: "); USB_sendstr(uhex2str(D&0xff)); USND("\n"); + sendfun("add byte: "); sendfun(uhex2str(D&0xff)); sendfun("\n"); } - USND("Send "); USB_sendstr(u2str(N)); USND(" bytes\n"); + sendfun("Send "); sendfun(u2str(N)); sendfun(" bytes\n"); return N; } -// dump memory buffer -static void hexdump(uint8_t *arr, uint16_t len){ - char buf[52], *bptr = buf; - for(uint16_t l = 0; l < len; ++l, ++arr){ - for(int16_t j = 1; j > -1; --j){ - register uint8_t half = (*arr >> (4*j)) & 0x0f; - if(half < 10) *bptr++ = half + '0'; - else *bptr++ = half - 10 + 'a'; - } - if(l % 16 == 15){ - *bptr++ = '\n'; - *bptr = 0; - USB_sendstr(buf); - bptr = buf; - }else *bptr++ = ' '; - } - if(bptr != buf){ - *bptr++ = '\n'; - *bptr = 0; - USB_sendstr(buf); - } -} - static uint8_t i2cinited = 1; -static inline char *setupI2C(char *buf){ +static inline const char *setupI2C(const char *buf){ buf = omit_spaces(buf); if(*buf < '0' || *buf > '2') return "Wrong speed"; i2c_setup(*buf - '0'); @@ -130,79 +95,79 @@ static inline char *setupI2C(char *buf){ return "OK"; } -static inline char *saI2C(char *buf){ +static inline const char *saI2C(int (*sendfun)(const char *s), const char *buf){ uint32_t addr; if(!getnum(buf, &addr) || addr > 0x7f) return "Wrong address"; - USND("I2Caddr="); USB_sendstr(uhex2str(addr)); USND("\n"); + sendfun("I2Caddr="); sendfun(uhex2str(addr)); sendfun("\n"); i2c_set_addr7(addr); return "OK"; } -static inline void rdI2C(char *buf){ +static inline void rdI2C(int (*sendfun)(const char *s), const char *buf){ uint32_t N; - char *nxt = getnum(buf, &N); + const char *nxt = getnum(buf, &N); if(!nxt || buf == nxt || N > 0xff){ - USND("Bad register number\n"); + sendfun("Bad register number\n"); return; } buf = nxt; uint8_t reg = N; nxt = getnum(buf, &N); if(!nxt || buf == nxt || N > LOCBUFFSZ){ - USND("Bad length\n"); + sendfun("Bad length\n"); return; } if(!read_i2c_reg(reg, locBuffer, N)){ - USND("Error reading I2C\n"); + sendfun("Error reading I2C\n"); return; } - if(N == 0){ USND("OK"); return; } - USND("Register "); USB_sendstr(uhex2str(reg)); USND(":\n"); - hexdump(locBuffer, N); + if(N == 0){ sendfun("OK\n"); return; } + sendfun("Register "); sendfun(uhex2str(reg)); sendfun(":\n"); + hexdump(sendfun, locBuffer, N); } -static inline char *wrI2C(char *buf){ - uint16_t N = readNnumbers(buf); +static inline const char *wrI2C(int (*sendfun)(const char *s), const char *buf){ + uint16_t N = readNnumbers(sendfun, buf); if(!write_i2c(locBuffer, N)) return "Error writing I2C"; if(N < 1) return "bad"; return "OK"; } // write locBuffer to SPI -static inline void wrSPI(int SPIidx, char *buf){ +static inline void wrSPI(int (*sendfun)(const char *s), int SPIidx, const char *buf){ if(SPIidx < 0 || SPIidx > 2) return; - uint16_t N = readNnumbers(buf); + uint16_t N = readNnumbers(sendfun, buf); if(N < 1){ *(uint8_t *)&(SPI1->DR) = 0xea; - USND("Enter at least 1 number (max: "); - USB_sendstr(u2str(LOCBUFFSZ)); USND(")\n"); + sendfun("Enter at least 1 number (max: "); + sendfun(u2str(LOCBUFFSZ)); sendfun(")\n"); return; } //if(SPI_transmit(SPIidx, locBuffer, N)) USND("Error: busy?\n"); - else USND("done"); + else sendfun("done"); } -static inline void rdSPI(int SPIidx){ +static inline void rdSPI(int (*sendfun)(const char *s), int SPIidx){ if(SPIidx < 0 || SPIidx > 2) return; - //if(SPI_isoverflow(SPIidx)) USND("SPI buffer overflow\n"); + //if(SPI_isoverflow(SPIidx)) sendfun("SPI buffer overflow\n"); uint8_t len = LOCBUFFSZ; /* if(SPI_getdata(SPIidx, locBuffer, &len)){ - USND("Error getting data: busy?\n"); + sendfun("Error getting data: busy?\n"); return; }*/ if(len == 0){ - USND("Nothing to read\n"); + sendfun("Nothing to read\n"); return; } - if(len > LOCBUFFSZ) USND("Can't get full message: buffer too small\n"); - USND("SPI data:\n"); - hexdump(locBuffer, len); + if(len > LOCBUFFSZ) sendfun("Can't get full message: buffer too small\n"); + sendfun("SPI data:\n"); + hexdump(sendfun, locBuffer, len); } -static inline char *procSPI(char *buf){ +static inline const char *procSPI(int (*sendfun)(const char *s), const char *buf){ int idx = 0; if(*buf == 'p') idx = 1; buf = omit_spaces(buf + 1); - if(*buf == 'w') wrSPI(idx, buf + 1); - else if(*buf == 'r') rdSPI(idx); + if(*buf == 'w') wrSPI(sendfun, idx, buf + 1); + else if(*buf == 'r') rdSPI(sendfun, idx); else return "Enter `w` and data to write, `r` - to read"; return NULL; } @@ -228,24 +193,24 @@ const char *helpstring = "R - software reset\n" "S - send short string over USB\n" "s - setup SPI (and turn off USARTs)\n" - "Ux str - send string to USARTx (1..3)\n" + "U str - send string to USART1\n" "u - setup USARTs (and turn off SPI)\n" "T - MCU temperature\n" "V - Vdd\n" "W - test watchdog\n" ; -void printADCvals(){ - USND("AIN0: "); USB_sendstr(u2str(getADCval(0))); - USND(" ("); USB_sendstr(u2str(getADCvoltage(0))); - USND("/100 V)\nAIN1: "); USB_sendstr(u2str(getADCval(1))); - USND(" ("); USB_sendstr(u2str(getADCvoltage(1))); - USND("/100 V)\nAIN5: "); USB_sendstr(u2str(getADCval(2))); - USND(" ("); USB_sendstr(u2str(getADCvoltage(2))); - USND("/100 V)\n"); +void printADCvals(int (*sendfun)(const char *s)){ + sendfun("AIN0: "); sendfun(u2str(getADCval(0))); + sendfun(" ("); sendfun(u2str(getADCvoltage(0))); + sendfun("/100 V)\nAIN1: "); sendfun(u2str(getADCval(1))); + sendfun(" ("); sendfun(u2str(getADCvoltage(1))); + sendfun("/100 V)\nAIN5: "); sendfun(u2str(getADCval(2))); + sendfun(" ("); sendfun(u2str(getADCvoltage(2))); + sendfun("/100 V)\n"); } -const char *parse_cmd(char *buf){ +const char *parse_cmd(int (*sendfun)(const char *s), const char *buf){ // "long" commands switch(*buf){ case '+': @@ -266,15 +231,15 @@ const char *parse_cmd(char *buf){ case 'I': if(!i2cinited) return "Init I2C first"; buf = omit_spaces(buf + 1); - if(*buf == 'a') return saI2C(buf + 1); - else if(*buf == 'r'){ rdI2C(buf + 1); return NULL; } - else if(*buf == 'w') return wrI2C(buf + 1); + if(*buf == 'a') return saI2C(sendfun, buf + 1); + else if(*buf == 'r'){ rdI2C(sendfun, buf + 1); return NULL; } + else if(*buf == 'w') return wrI2C(sendfun, buf + 1); else if(*buf == 's'){ i2c_init_scan_mode(); return "Start scan\n";} else return "Command should be 'Ia', 'Iw', 'Ir' or 'Is'\n"; break; case 'p': case 'P': - //return procSPI(buf); + //return procSPI(sendfun, buf); return "TODO"; break; case 'U': @@ -282,7 +247,7 @@ const char *parse_cmd(char *buf){ break; } // "short" commands - if(buf[1] != '\n') return buf; + if(buf[1] && buf[1] != '\n') return buf; switch(*buf){ case '0': pin_toggle(USBPU_port, USBPU_pin); @@ -290,10 +255,10 @@ const char *parse_cmd(char *buf){ else return "Pullup set"; break; case 'g': - return getPWMvals(); + return getPWMvals(sendfun); break; case 'A': - printADCvals(); + printADCvals(sendfun); break; case 'L': USND("Very long test string for USB (it's length is more than 64 bytes).\n" @@ -302,21 +267,21 @@ const char *parse_cmd(char *buf){ break; case 'm': ADCmon = !ADCmon; - USND("Monitoring is "); - if(ADCmon) USND("on\n"); - else USND("off\n"); + sendfun("Monitoring is "); + if(ADCmon) sendfun("on\n"); + else sendfun("off\n"); break; case 'R': - USND("Soft reset\n"); + USND("Soft reset"); SEND("Soft reset\n"); NVIC_SystemReset(); break; case 'S': - USND("Test string for USB\n"); + USND("Test string for USB"); return "Short test sent"; break; case 's': - USND("SPI are ON, USART are OFF\n"); + sendfun("SPI are ON, USART are OFF\n"); //usart_stop(); //spi_setup(); break; @@ -342,205 +307,3 @@ const char *parse_cmd(char *buf){ } return NULL; } - -// usb getline -char *get_USB(){ - static char tmpbuf[129], *curptr = tmpbuf; - static int rest = 128; - int x = USB_receive((uint8_t*)curptr); - curptr[x] = 0; - if(!x) return NULL; - if(curptr[x-1] == '\n'){ - curptr = tmpbuf; - rest = 128; - return tmpbuf; - } - curptr += x; rest -= x; - if(rest <= 0){ // buffer overflow - curptr = tmpbuf; - rest = 128; - } - return NULL; -} - - -static char *_2str(uint32_t val, uint8_t minus){ - static char strbuf[12]; - char *bufptr = &strbuf[11]; - *bufptr = 0; - if(!val){ - *(--bufptr) = '0'; - }else{ - while(val){ - *(--bufptr) = val % 10 + '0'; - val /= 10; - } - } - if(minus) *(--bufptr) = '-'; - return bufptr; -} - -// return string with number `val` -char *u2str(uint32_t val){ - return _2str(val, 0); -} -char *i2str(int32_t i){ - uint8_t minus = 0; - uint32_t val; - if(i < 0){ - minus = 1; - val = -i; - }else val = i; - return _2str(val, minus); -} -// print 32bit unsigned int as hex -char *uhex2str(uint32_t val){ - static char buf[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) buf[npos++] = half + '0'; - else buf[npos++] = half - 10 + 'a'; - } - } - buf[npos] = 0; - return buf; -} - -char *omit_spaces(const char *buf){ - while(*buf){ - if(*buf > ' ') break; - ++buf; - } - return (char*)buf; -} - -// In case of overflow return `buf` and N==0xffffffff -// read decimal number & return pointer to next non-number symbol -static char *getdec(const char *buf, uint32_t *N){ - char *start = (char*)buf; - uint32_t num = 0; - while(*buf){ - char c = *buf; - if(c < '0' || c > '9'){ - break; - } - if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow - *N = 0xffffff; - return start; - } - num *= 10; - num += c - '0'; - ++buf; - } - *N = num; - return (char*)buf; -} -// read hexadecimal number (without 0x prefix!) -static char *gethex(const char *buf, uint32_t *N){ - char *start = (char*)buf; - uint32_t num = 0; - while(*buf){ - char c = *buf; - uint8_t M = 0; - if(c >= '0' && c <= '9'){ - M = '0'; - }else if(c >= 'A' && c <= 'F'){ - M = 'A' - 10; - }else if(c >= 'a' && c <= 'f'){ - M = 'a' - 10; - } - if(M){ - if(num & 0xf0000000){ // overflow - *N = 0xffffff; - return start; - } - num <<= 4; - num += c - M; - }else{ - break; - } - ++buf; - } - *N = num; - return (char*)buf; -} -// read octal number (without 0 prefix!) -static char *getoct(const char *buf, uint32_t *N){ - char *start = (char*)buf; - uint32_t num = 0; - while(*buf){ - char c = *buf; - if(c < '0' || c > '7'){ - break; - } - if(num & 0xe0000000){ // overflow - *N = 0xffffff; - return start; - } - num <<= 3; - num += c - '0'; - ++buf; - } - *N = num; - return (char*)buf; -} -// read binary number (without b prefix!) -static char *getbin(const char *buf, uint32_t *N){ - char *start = (char*)buf; - uint32_t num = 0; - while(*buf){ - char c = *buf; - if(c < '0' || c > '1'){ - break; - } - if(num & 0x80000000){ // overflow - *N = 0xffffff; - return start; - } - num <<= 1; - if(c == '1') num |= 1; - ++buf; - } - *N = num; - return (char*)buf; -} - -/** - * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) - * @param buf - buffer with number and so on - * @param N - the number read - * @return pointer to first non-number symbol in buf - * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) - */ -char *getnum(const char *txt, uint32_t *N){ - char *nxt = NULL; - char *s = omit_spaces(txt); - if(*s == '0'){ // hex, oct or 0 - if(s[1] == 'x' || s[1] == 'X'){ // hex - nxt = gethex(s+2, N); - if(nxt == s+2) nxt = (char*)txt; - }else if(s[1] > '0'-1 && s[1] < '8'){ // oct - nxt = getoct(s+1, N); - if(nxt == s+1) nxt = (char*)txt; - }else{ // 0 - nxt = s+1; - *N = 0; - } - }else if(*s == 'b' || *s == 'B'){ - nxt = getbin(s+1, N); - if(nxt == s+1) nxt = (char*)txt; - }else{ - nxt = getdec(s, N); - if(nxt == s) nxt = (char*)txt; - } - return nxt; -} diff --git a/F1:F103/F1_testbrd/proto.h b/F1:F103/F1_testbrd/proto.h index 28969c6..262f075 100644 --- a/F1:F103/F1_testbrd/proto.h +++ b/F1:F103/F1_testbrd/proto.h @@ -19,17 +19,11 @@ #pragma once #include +#include "strfunc.h" + extern volatile uint8_t ADCmon; -void USB_sendstr(const char *str); -char *get_USB(); -const char *parse_cmd(char *buf); +const char *parse_cmd(int (*sendfun)(const char *s), const char *buf); +void printADCvals(int (*sendfun)(const char *s)); -void printADCvals(); - -char *u2str(uint32_t val); -char *i2str(int32_t i); -char *uhex2str(uint32_t val); -char *getnum(const char *txt, uint32_t *N); -char *omit_spaces(const char *buf); diff --git a/F1:F103/F1_testbrd/ringbuffer.c b/F1:F103/F1_testbrd/ringbuffer.c new file mode 100644 index 0000000..1974fc3 --- /dev/null +++ b/F1:F103/F1_testbrd/ringbuffer.c @@ -0,0 +1,124 @@ +/* + * This file is part of the F1_testbrd project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 3 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, see . + */ + +#include "ringbuffer.h" + +// stored data length +int RB_datalen(ringbuffer *b){ + if(b->tail >= b->head) return (b->tail - b->head); + else return (b->length - b->head + b->tail); +} + +/** + * @brief RB_hasbyte - check if buffer has given byte stored + * @param b - buffer + * @param byte - byte to find + * @return index if found, -1 if none + */ +int RB_hasbyte(ringbuffer *b, uint8_t byte){ + if(b->head == b->tail) return -1; // no data in buffer + int startidx = b->head; + if(b->head > b->tail){ // + for(int found = b->head; found < b->length; ++found) + if(b->data[found] == byte) return found; + startidx = 0; + } + for(int found = startidx; found < b->tail; ++found) + if(b->data[found] == byte) return found; + return -1; +} + +// poor memcpy +static void mcpy(uint8_t *targ, const uint8_t *src, int l){ + while(l--) *targ++ = *src++; +} + +// increment head or tail +TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ + *what += n; + if(*what >= b->length) *what -= b->length; +} + +/** + * @brief RB_read - read data from ringbuffer + * @param b - buffer + * @param s - array to write data + * @param len - max len of `s` + * @return bytes read + */ +int RB_read(ringbuffer *b, uint8_t *s, int len){ + int l = RB_datalen(b); + if(!l) return 0; + if(l > len) l = len; + int _1st = b->length - b->head; + if(_1st > l) _1st = l; + if(_1st > len) _1st = len; + mcpy(s, b->data + b->head, _1st); + if(_1st < len && l > _1st){ + mcpy(s+_1st, b->data, l - _1st); + incr(b, &b->head, l); + return l; + } + incr(b, &b->head, _1st); + return _1st; +} + +/** + * @brief RB_readto fill array `s` with data until byte `byte` (with it) + * @param b - ringbuffer + * @param byte - check byte + * @param s - buffer to write data + * @param len - length of `s` + * @return amount of bytes written (negative, if lenhead; + // now calculate length of new data portion + if(idx < b->head) partlen += b->length; + if(partlen > len) return -RB_read(b, s, len); + return RB_read(b, s, partlen); +} + +/** + * @brief RB_write - write some data to ringbuffer + * @param b - buffer + * @param str - data + * @param l - length + * @return amount of bytes written + */ +int RB_write(ringbuffer *b, const uint8_t *str, int l){ + int r = b->length - 1 - RB_datalen(b); // rest length + if(l > r) l = r; + if(!l) return 0; + int _1st = b->length - b->tail; + if(_1st > l) _1st = l; + mcpy(b->data + b->tail, str, _1st); + if(_1st < l){ // add another piece from start + mcpy(b->data, str+_1st, l-_1st); + } + incr(b, &b->tail, l); + return l; +} + +// just delete all information in buffer `b` +void RB_clearbuf(ringbuffer *b){ + b->head = 0; + b->tail = 0; +} diff --git a/F1:F103/F1_testbrd/ringbuffer.h b/F1:F103/F1_testbrd/ringbuffer.h new file mode 100644 index 0000000..3ab5ae1 --- /dev/null +++ b/F1:F103/F1_testbrd/ringbuffer.h @@ -0,0 +1,35 @@ +/* + * This file is part of the F1_testbrd project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 3 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, see . + */ + +#pragma once +#include + +typedef struct{ + uint8_t *data; // data buffer + const int length; // its length + int head; // head index + int tail; // tail index +} ringbuffer; + +int RB_read(ringbuffer *b, uint8_t *s, int len); +int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); +int RB_hasbyte(ringbuffer *b, uint8_t byte); +int RB_write(ringbuffer *b, const uint8_t *str, int l); +int RB_datalen(ringbuffer *b); +void RB_clearbuf(ringbuffer *b); + diff --git a/F1:F103/F1_testbrd/strfunc.c b/F1:F103/F1_testbrd/strfunc.c new file mode 100644 index 0000000..25d1d54 --- /dev/null +++ b/F1:F103/F1_testbrd/strfunc.c @@ -0,0 +1,267 @@ +/* + * This file is part of the F1_testbrd project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 3 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, see . + */ + +#include +#include +/** + * @brief hexdump - dump hex array by 16 bytes in string + * @param sendfun - function to send data + * @param arr - array to dump + * @param len - length of `arr` + */ +void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){ + char buf[52], *bptr = buf; + for(uint16_t l = 0; l < len; ++l, ++arr){ + for(int16_t j = 1; j > -1; --j){ + register uint8_t half = (*arr >> (4*j)) & 0x0f; + if(half < 10) *bptr++ = half + '0'; + else *bptr++ = half - 10 + 'a'; + } + if(l % 16 == 15){ + *bptr++ = '\n'; + *bptr = 0; + sendfun(buf); + bptr = buf; + }else *bptr++ = ' '; + } + if(bptr != buf){ + *bptr++ = '\n'; + *bptr = 0; + sendfun(buf); + } +} + +/** + * @brief _2str - convert value into string buffer + * @param val - |value| + * @param minus - ==0 if value > 0 + * @return buffer with number + */ +static char *_2str(uint32_t val, uint8_t minus){ + static char strbuf[12]; + char *bufptr = &strbuf[11]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + uint32_t x = val / 10; + *(--bufptr) = (val - 10*x) + '0'; + val = x; + //*(--bufptr) = val % 10 + '0'; + //val /= 10; + } + } + if(minus) *(--bufptr) = '-'; + return bufptr; +} + +// return string with number `val` +char *u2str(uint32_t val){ + return _2str(val, 0); +} +char *i2str(int32_t i){ + uint8_t minus = 0; + uint32_t val; + if(i < 0){ + minus = 1; + val = -i; + }else val = i; + return _2str(val, minus); +} + +/** + * @brief uhex2str - print 32bit unsigned int as hex + * @param val - value + * @return string with number + */ +char *uhex2str(uint32_t val){ + static char buf[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) buf[npos++] = half + '0'; + else buf[npos++] = half - 10 + 'a'; + } + } + buf[npos] = 0; + return buf; +} + +/** + * @brief omit_spaces - eliminate leading spaces and other trash in string + * @param buf - string + * @return - pointer to first character in `buf` > ' ' + */ +const char *omit_spaces(const char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return buf; +} + +/** + * @brief getdec - read decimal number & return pointer to next non-number symbol + * @param buf - string + * @param N - number read + * @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff + */ +static const char *getdec(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow + *N = 0xffffff; + return start; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read hexadecimal number (without 0x prefix!) +static const char *gethex(const char *buf, uint32_t *N){ + const char *start = buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + uint8_t M = 0; + if(c >= '0' && c <= '9'){ + M = '0'; + }else if(c >= 'A' && c <= 'F'){ + M = 'A' - 10; + }else if(c >= 'a' && c <= 'f'){ + M = 'a' - 10; + } + if(M){ + if(num & 0xf0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return buf; +} +// read octal number (without 0 prefix!) +static const char *getoct(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '7'){ + break; + } + if(num & 0xe0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 3; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read binary number (without b prefix!) +static const char *getbin(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + if(num & 0x80000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 1; + if(c == '1') num |= 1; + ++buf; + } + *N = num; + return buf; +} + +/** + * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) + * @param buf - buffer with number and so on + * @param N - the number read + * @return pointer to first non-number symbol in buf + * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) + */ +const char *getnum(const char *txt, uint32_t *N){ + const char *nxt = NULL; + const char *s = omit_spaces(txt); + if(*s == '0'){ // hex, oct or 0 + if(s[1] == 'x' || s[1] == 'X'){ // hex + nxt = gethex(s+2, N); + if(nxt == s+2) nxt = (char*)txt; + }else if(s[1] > '0'-1 && s[1] < '8'){ // oct + nxt = getoct(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ // 0 + nxt = s+1; + *N = 0; + } + }else if(*s == 'b' || *s == 'B'){ + nxt = getbin(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ + nxt = getdec(s, N); + if(nxt == s) nxt = (char*)txt; + } + return nxt; +} + +// get signed integer +const char *getint(const char *txt, int32_t *I){ + const char *s = omit_spaces(txt); + int32_t sign = 1; + uint32_t U; + if(*s == '-'){ + sign = -1; + ++s; + } + const char *nxt = getnum(s, &U); + if(nxt == s) return txt; + if(U & 0x80000000) return txt; // overfull + *I = sign * (int32_t)U; + return nxt; +} diff --git a/F1:F103/F1_testbrd/strfunc.h b/F1:F103/F1_testbrd/strfunc.h new file mode 100644 index 0000000..4375e23 --- /dev/null +++ b/F1:F103/F1_testbrd/strfunc.h @@ -0,0 +1,30 @@ +/* + * This file is part of the F1_testbrd project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 3 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, see . + */ + +#pragma once + +#include +#include + +void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len); +const char *u2str(uint32_t val); +const char *i2str(int32_t i); +const char *uhex2str(uint32_t val); +const char *getnum(const char *txt, uint32_t *N); +const char *omit_spaces(const char *buf); +const char *getint(const char *txt, int32_t *I); diff --git a/F1:F103/F1_testbrd/usart.c b/F1:F103/F1_testbrd/usart.c index 679ae7e..b06fb51 100644 --- a/F1:F103/F1_testbrd/usart.c +++ b/F1:F103/F1_testbrd/usart.c @@ -72,17 +72,20 @@ void usart_putchar(const char ch){ tbuf[tbufno][odatalen[tbufno]++] = ch; } -void usart_send(const char *str){ +int usart_send(const char *str){ + int l = 0; while(*str){ if(odatalen[tbufno] == UARTBUFSZO){ transmit_tbuf(); continue; } tbuf[tbufno][odatalen[tbufno]++] = *str++; + ++l; } + return l; } -void newline(){ +void usart_newline(){ usart_putchar('\n'); transmit_tbuf(); } diff --git a/F1:F103/F1_testbrd/usart.h b/F1:F103/F1_testbrd/usart.h index 13d1042..692a7db 100644 --- a/F1:F103/F1_testbrd/usart.h +++ b/F1:F103/F1_testbrd/usart.h @@ -49,7 +49,7 @@ extern volatile int linerdy, bufovr, txrdy; void transmit_tbuf(); void usart_setup(); int usart_getline(char **line); -void usart_send(const char *str); -void newline(); +int usart_send(const char *str); +void usart_newline(); void usart_putchar(const char ch); diff --git a/F1:F103/F1_testbrd/usb.c b/F1:F103/F1_testbrd/usb.c index 7380bde..1ee69d7 100644 --- a/F1:F103/F1_testbrd/usb.c +++ b/F1:F103/F1_testbrd/usb.c @@ -1,6 +1,6 @@ /* * This file is part of the F1_testbrd project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -16,153 +16,111 @@ * along with this program. If not, see . */ -#include "usart.h" +#include + +#include "hardware.h" #include "usb.h" #include "usb_lib.h" -#ifdef DBG -#undef DBG -#define DBG(x) -#endif +static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data +// ring buffers for incoming and outgoing data +static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ]; +volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; +volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; +// transmission is succesfull +volatile uint8_t bufisempty = 1; +volatile uint8_t bufovrfl = 0; -static volatile uint8_t tx_succesfull = 1; -static volatile uint8_t rxNE = 0; - -// interrupt IN handler (never used?) -static void EP1_Handler(){ - uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); - 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 - epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)); - USB->EPnR[1] = epstatus; -} - -// data IN/OUT handlers -static void transmit_Handler(){ // EP3IN - tx_succesfull = 1; - uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); - // clear CTR keep DTOGs & STATs - USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr -} - -static void receive_Handler(){ // EP2OUT - rxNE = 1; - uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[2]); - USB->EPnR[2] = (epstatus & ~(USB_EPnR_CTR_RX)); // clear RX ctr - DBG("RXh"); -} - -void USB_setup(){ - NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); - NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); - RCC->APB1ENR |= RCC_APB1ENR_USBEN; - USB->CNTR = USB_CNTR_FRES; // Force USB Reset - for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms - //uint32_t ctr = 0; - USB->CNTR = 0; - USB->BTABLE = 0; - USB->DADDR = 0; - USB->ISTR = 0; - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts - NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); -} - -static int usbwr(const uint8_t *buf, uint16_t l){ - uint32_t ctra = 1000000; - while(--ctra && tx_succesfull == 0){ - IWDG->KR = IWDG_REFRESH; - } - tx_succesfull = 0; - EP_Write(3, buf, l); - ctra = 1000000; - while(--ctra && tx_succesfull == 0){ - IWDG->KR = IWDG_REFRESH; - } - if(tx_succesfull == 0){usbON = 0; return 1;} // usb is OFF? - return 0; -} - -static uint8_t usbbuff[USB_TXBUFSZ-1]; // temporary buffer (63 - to prevent need of ZLP) -static uint8_t buflen = 0; // amount of symbols in usbbuff - -// send next up to 63 bytes of data in usbbuff -static void send_next(){ - if(!buflen || !tx_succesfull) return; - tx_succesfull = 0; - EP_Write(3, usbbuff, buflen); - buflen = 0; -} - -// unblocking sending - just fill a buffer -void USB_send(const uint8_t *buf, uint16_t len){ - if(!usbON || !len) return; - if(len > USB_TXBUFSZ-1 - buflen){ - usbwr(usbbuff, buflen); - buflen = 0; - } - if(len > USB_TXBUFSZ-1){ - USB_send_blk(buf, len); +void send_next(){ + if(bufisempty) return; + static int lastdsz = 0; + int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); + if(!buflen){ + if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send + lastdsz = 0; + bufisempty = 1; return; } - while(len--) usbbuff[buflen++] = *buf++; + EP_Write(3, (uint8_t*)usbbuff, buflen); + lastdsz = buflen; } -// blocking sending -void USB_send_blk(const uint8_t *buf, uint16_t len){ - if(!usbON || !len) return; // USB disconnected - if(buflen){ - usbwr(usbbuff, buflen); - buflen = 0; +// blocking send full content of ring buffer +int USB_sendall(){ + while(!bufisempty){ + if(!usbON) return 0; } - int needzlp = 0; + return 1; +} + +// put `buf` into queue to send +int USB_send(const uint8_t *buf, int len){ + if(!buf || !usbON || !len) return 0; while(len){ - if(len == USB_TXBUFSZ) needzlp = 1; - uint16_t s = (len > USB_TXBUFSZ) ? USB_TXBUFSZ : len; - if(usbwr(buf, s)) return; - len -= s; - buf += s; - } - if(needzlp){ - usbwr(NULL, 0); + int a = RB_write((ringbuffer*)&rbout, buf, len); + len -= a; + buf += a; + if(bufisempty){ + bufisempty = 0; + send_next(); + } } + return 1; } -void usb_proc(){ - switch(USB_Dev.USB_Status){ - case USB_STATE_CONFIGURED: - // make new BULK endpoint - // 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, 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 - USB_Dev.USB_Status = USB_STATE_CONNECTED; - break; - case USB_STATE_DEFAULT: - case USB_STATE_ADDRESSED: - if(usbON){ - usbON = 0; - } - break; - default: // USB_STATE_CONNECTED - send next data portion - if(!usbON) return; +int USB_putbyte(uint8_t byte){ + if(!usbON) return 0; + while(0 == RB_write((ringbuffer*)&rbout, &byte, 1)){ + if(bufisempty){ + bufisempty = 0; send_next(); + } } + return 1; +} + +int USB_sendstr(const char *string){ + if(!string || !usbON) return 0; + int len = 0; + const char *b = string; + while(*b++) ++len; + if(!len) return 0; + return USB_send((const uint8_t*)string, len); } /** - * @brief USB_receive - * @param buf (i) - buffer[64] for received data - * @return amount of received bytes + * @brief USB_receive - get binary data from receiving ring-buffer + * @param buf (i) - buffer for received data + * @param len - length of `buf` + * @return amount of received bytes (negative, if overfull happened) */ -uint8_t USB_receive(uint8_t *buf){ - if(!usbON || !rxNE) return 0; - DBG("Get data"); - SEND((char*)buf); newline(); - uint8_t sz = EP_Read(2, (uint16_t*)buf); - uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); - // keep stat_tx & set ACK rx - USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; - rxNE = 0; +int USB_receive(uint8_t *buf, int len){ + int sz = RB_read((ringbuffer*)&rbin, buf, len); + if(bufovrfl){ + RB_clearbuf((ringbuffer*)&rbin); + if(!sz) sz = -1; + else sz = -sz; + bufovrfl = 0; + } return sz; } + +/** + * @brief USB_receivestr - get string up to '\n' and replace '\n' with 0 + * @param buf - receiving buffer + * @param len - its length + * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) + */ +int USB_receivestr(char *buf, int len){ + int l = RB_readto((ringbuffer*)&rbin, '\n', (uint8_t*)buf, len); + if(l == 0) return 0; + if(--l < 0 || bufovrfl) RB_clearbuf((ringbuffer*)&rbin); + else buf[l] = 0; // replace '\n' with strend + if(bufovrfl){ + if(l > 0) l = -l; + else l = -1; + bufovrfl = 0; + } + return l; +} + diff --git a/F1:F103/F1_testbrd/usb.h b/F1:F103/F1_testbrd/usb.h index 27070c6..c23dbce 100644 --- a/F1:F103/F1_testbrd/usb.h +++ b/F1:F103/F1_testbrd/usb.h @@ -1,6 +1,6 @@ /* * This file is part of the F1_testbrd project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,14 +17,33 @@ */ #pragma once -#include "hardware.h" +#include "ringbuffer.h" +#include "usbhw.h" -#define BUFFSIZE (64) +// sizes of ringbuffers for outgoing and incoming data +#define RBOUTSZ (512) +#define RBINSZ (512) -#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0) +#define usb_newline() USB_putbyte('\n') +#define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) -void USB_setup(); -void usb_proc(); -void USB_send(const uint8_t *buf, uint16_t len); -void USB_send_blk(const uint8_t *buf, uint16_t len); -uint8_t USB_receive(uint8_t *buf); +#if 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 +#endif + +extern volatile ringbuffer rbout, rbin; +extern volatile uint8_t bufisempty, bufovrfl; + +void send_next(); +int USB_sendall(); +int USB_send(const uint8_t *buf, int len); +int USB_putbyte(uint8_t byte); +int USB_sendstr(const char *string); +int USB_receive(uint8_t *buf, int len); +int USB_receivestr(char *buf, int len); diff --git a/F1:F103/F1_testbrd/usb_lib.c b/F1:F103/F1_testbrd/usb_lib.c index 20d5633..f96d67a 100644 --- a/F1:F103/F1_testbrd/usb_lib.c +++ b/F1:F103/F1_testbrd/usb_lib.c @@ -1,6 +1,6 @@ /* * This file is part of the F1_testbrd project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,19 +17,20 @@ */ #include +#include "usb.h" #include "usb_lib.h" +#include "usbhw.h" ep_t endpoints[STM32ENDPOINTS]; -usb_dev_t USB_Dev; +static uint16_t USB_Addr = 0; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; -static config_pack_t setup_packet; -static uint8_t ep0databuf[EP0DATABUF_SIZE]; -static uint8_t ep0dbuflen = 0; +uint8_t ep0databuf[EP0DATABUF_SIZE], setupdatabuf[EP0DATABUF_SIZE]; +static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; usb_LineCoding getLineCoding(){return lineCoding;} -uint8_t usbON = 0; // device disconnected from terminal +volatile uint8_t usbON = 0; // device disconnected from terminal // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor #define bcdUSB_L 0x10 @@ -54,9 +55,9 @@ static const uint8_t USB_DeviceDescriptor[] = { 0x23, // idProduct_H 0x00, // bcdDevice_Ver_L 0x03, // bcdDevice_Ver_H - 0x01, // iManufacturer - 0x02, // iProduct - 0x00, // iSerialNumber + iMANUFACTURER_DESCR, // iManufacturer + iPRODUCT_DESCR, // iProduct + iSERIAL_DESCR, // iSerialNumber bNumConfigurations // bNumConfigurations }; @@ -96,7 +97,7 @@ static const uint8_t USB_ConfigDescriptor[] = { 0xff, /* bInterfaceClass */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface: */ + iINTERFACE_DESCR, /* iInterface: */ /////////////////////////////////////////////////// /*Endpoint 1 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ @@ -126,11 +127,19 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x00, /* bInterval: ignore for Bulk transfer */ }; -_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); -// these descriptors are not used in PL2303 emulator! -_USB_STRING_(USB_StringSerialDescriptor, u"0"); -_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); -_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); +_USB_LANG_ID_(LD, LANG_US); +_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(MD, u"Prolific Technology Inc."); +_USB_STRING_(PD, u"USB-Serial Controller"); +_USB_STRING_(ID, u"pl2303_emulator"); +static void const *StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, + [iINTERFACE_DESCR] = &ID +}; + /* * default handlers @@ -149,8 +158,8 @@ void WEAK break_handler(){ // handler of vendor requests void WEAK vendor_handler(config_pack_t *packet){ + uint16_t c; if(packet->bmRequestType & 0x80){ // read - uint8_t c; switch(packet->wValue){ case 0x8484: c = 2; @@ -164,14 +173,15 @@ void WEAK vendor_handler(config_pack_t *packet){ default: c = 0; } - EP_WriteIRQ(0, &c, 1); + EP_WriteIRQ(0, (uint8_t*)&c, 1); }else{ // write ZLP - EP_WriteIRQ(0, (uint8_t *)0, 0); + c = 0; + EP_WriteIRQ(0, (uint8_t *)&c, 0); } } static void wr0(const uint8_t *buf, uint16_t size){ - if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request + if(setup_packet->wLength < size) size = setup_packet->wLength; // shortened request if(size < endpoints[0].txbufsz){ EP_WriteIRQ(0, buf, size); return; @@ -199,24 +209,18 @@ static void wr0(const uint8_t *buf, uint16_t size){ } static inline void get_descriptor(){ - switch(setup_packet.wValue){ + uint8_t descrtype = setup_packet->wValue >> 8, + descridx = setup_packet->wValue & 0xff; + switch(descrtype){ 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); + case STRING_DESCRIPTOR: + if(descridx < iDESCR_AMOUNT) wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx])); + else EP_WriteIRQ(0, (uint8_t*)0, 0); break; case DEVICE_QUALIFIER_DESCRIPTOR: wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); @@ -226,10 +230,10 @@ static inline void get_descriptor(){ } } -static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static uint16_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){ + switch(setup_packet->bRequest){ case GET_DESCRIPTOR: get_descriptor(); break; @@ -237,23 +241,54 @@ static inline void std_d2h_req(){ EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered break; case GET_CONFIGURATION: - EP_WriteIRQ(0, &configuration, 1); + EP_WriteIRQ(0, (uint8_t*)&configuration, 1); break; default: break; } } +// interrupt IN handler (never used?) +static void EP1_Handler(){ + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + 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 + epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)); + USB->EPnR[1] = epstatus; +} + +// data IN/OUT handlers +static void transmit_Handler(){ // EP3IN + uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); + // clear CTR keep DTOGs & STATs + USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr + send_next(); +} + +static void receive_Handler(){ // EP2OUT + uint8_t buf[USB_RXBUFSZ]; + uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); + uint8_t sz = EP_Read(2, (uint8_t*)buf); + if(sz){ + if(RB_write((ringbuffer*)&rbin, buf, sz) != sz) bufovrfl = 1; + } + // keep stat_tx & set ACK rx, clear RX ctr + USB->EPnR[2] = (epstatus & ~USB_EPnR_CTR_RX) ^ USB_EPnR_STAT_RX; +} + static inline void std_h2d_req(){ - switch(setup_packet.bRequest){ + 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; + USB_Addr = setup_packet->wValue; break; case SET_CONFIGURATION: // Now device configured - USB_Dev.USB_Status = USB_STATE_CONFIGURED; - configuration = setup_packet.wValue; + configuration = setup_packet->wValue; + 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 break; default: break; @@ -269,10 +304,10 @@ bmRequestType: 76543210 /** * Endpoint0 (control) handler */ -static void EP0_Handler(){ +void EP0_Handler(){ uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications - uint8_t reqtype = setup_packet.bmRequestType & 0x7f; - uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; + uint8_t reqtype = setup_packet->bmRequestType & 0x7f; + uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; int rxflag = RX_FLAG(epstatus); if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ @@ -285,15 +320,15 @@ static void EP0_Handler(){ } break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request - if(setup_packet.bRequest == CLEAR_FEATURE){ + if(setup_packet->bRequest == CLEAR_FEATURE){ EP_WriteIRQ(0, (uint8_t *)0, 0); } break; case VENDOR_REQUEST_TYPE: - vendor_handler(&setup_packet); + vendor_handler(setup_packet); break; case CONTROL_REQUEST_TYPE: - switch(setup_packet.bRequest){ + switch(setup_packet->bRequest){ case GET_LINE_CODING: EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); break; @@ -301,7 +336,7 @@ static void EP0_Handler(){ break; case SET_CONTROL_LINE_STATE: usbON = 1; - clstate_handler(setup_packet.wValue); + clstate_handler(setup_packet->wValue); break; case SEND_BREAK: usbON = 0; @@ -310,23 +345,22 @@ static void EP0_Handler(){ default: break; } - if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + if(setup_packet->bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement break; default: EP_WriteIRQ(0, (uint8_t *)0, 0); } }else if(rxflag){ // got data over EP0 or host acknowlegement if(endpoints[0].rx_cnt){ - if(setup_packet.bRequest == SET_LINE_CODING){ + if(setup_packet->bRequest == SET_LINE_CODING){ linecoding_handler((usb_LineCoding*)ep0databuf); } } } else if(TX_FLAG(epstatus)){ // package transmitted // now we can change address after enumeration - if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ - USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; - // change state to ADRESSED - USB_Dev.USB_Status = USB_STATE_ADDRESSED; + if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Addr; + usbON = 0; } } epstatus = KEEP_DTOG(USB->EPnR[0]); @@ -336,95 +370,6 @@ static void EP0_Handler(){ USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; } -static uint16_t lastaddr = LASTADDR_DEFAULT; -/** - * Endpoint initialisation - * @param number - EP num (0...7) - * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) - * @param txsz - transmission buffer size @ USB/CAN buffer - * @param rxsz - reception buffer size @ USB/CAN buffer - * @param uint16_t (*func)(ep_t *ep) - EP handler function - * @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)){ - 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) 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; - if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size - uint16_t countrx = 0; - if(rxsz < 64) countrx = rxsz / 2; - else{ - if(rxsz & 0x1f) return 3; // should be multiple of 32 - countrx = 31 + rxsz / 32; - } - USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; - endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); - endpoints[number].txbufsz = txsz; - lastaddr += txsz; - USB_BTABLE->EP[number].USB_COUNT_TX = 0; - USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; - endpoints[number].rx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); - lastaddr += rxsz; - USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; - endpoints[number].func = func; - return 0; -} - -//extern int8_t dump; -// standard IRQ handler -void usb_lp_can_rx0_isr(){ - if(USB->ISTR & USB_ISTR_RESET){ - usbON = 0; - // Reinit registers - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - USB->ISTR = 0; - // 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; - USB_Dev.USB_Status = USB_STATE_DEFAULT; - USB->ISTR = ~USB_ISTR_RESET; - if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ - return; - } - } - if(USB->ISTR & 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, (uint16_t*)&setup_packet); - ep0dbuflen = 0; - // interrupt handler will be called later - }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf - ep0dbuflen = endpoints[0].rx_cnt; - EP_Read(0, (uint16_t*)&ep0databuf); - } - } - } - // call EP handler - if(endpoints[n].func) endpoints[n].func(endpoints[n]); - } - if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep - usbON = 0; - USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE; - USB->ISTR = ~USB_ISTR_SUSP; - } - if(USB->ISTR & USB_ISTR_WKUP){ // wakeup - USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags - USB->ISTR = ~USB_ISTR_WKUP; - } -} - /** * Write data to EP buffer (called from IRQ handler) * @param number - EP number @@ -432,15 +377,24 @@ void usb_lp_can_rx0_isr(){ * @param size - its size */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ - uint8_t i; if(size > endpoints[number].txbufsz) size = endpoints[number].txbufsz; 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; +#if defined USB1_16 + // very bad: what if `size` is odd? uint32_t *out = (uint32_t *)endpoints[number].tx_buf; - for(i = 0; i < N2; ++i, ++out){ + for(int i = 0; i < N2; ++i, ++out){ *out = buf16[i]; } +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < N2; i++){ + endpoints[number].tx_buf[i] = buf16[i]; + } +#else +#error "Define USB1_16 or USB2_16" +#endif USB_BTABLE->EP[number].USB_COUNT_TX = size; } @@ -462,16 +416,23 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ * @param *buf - user array for data * @return amount of data read */ -int EP_Read(uint8_t number, uint16_t *buf){ +int EP_Read(uint8_t number, uint8_t *buf){ int sz = endpoints[number].rx_cnt; if(!sz) return 0; endpoints[number].rx_cnt = 0; +#if defined USB1_16 int n = (sz + 1) >> 1; - uint32_t *in = (uint32_t *)endpoints[number].rx_buf; - if(n){ - for(int i = 0; i < n; ++i, ++in) - buf[i] = *(uint16_t*)in; - } + uint32_t *in = (uint32_t*)endpoints[number].rx_buf; + uint16_t *out = (uint16_t*)buf; + for(int i = 0; i < n; ++i, ++in) + out[i] = *(uint16_t*)in; +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < sz; ++i) + buf[i] = endpoints[number].rx_buf[i]; +#else +#error "Define USB1_16 or USB2_16" +#endif return sz; } diff --git a/F1:F103/F1_testbrd/usb_lib.h b/F1:F103/F1_testbrd/usb_lib.h index f938b85..9d68798 100644 --- a/F1:F103/F1_testbrd/usb_lib.h +++ b/F1:F103/F1_testbrd/usb_lib.h @@ -1,6 +1,6 @@ /* * This file is part of the F1_testbrd project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -18,7 +18,7 @@ #pragma once #include -#include "usb_defs.h" +#include "usbhw.h" #define EP0DATABUF_SIZE (64) #define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) @@ -59,14 +59,21 @@ #define CONTROL_DTR 0x01 #define CONTROL_RTS 0x02 -// wValue -#define DEVICE_DESCRIPTOR 0x100 -#define CONFIGURATION_DESCRIPTOR 0x200 -#define STRING_LANG_DESCRIPTOR 0x300 -#define STRING_MAN_DESCRIPTOR 0x301 -#define STRING_PROD_DESCRIPTOR 0x302 -#define STRING_SN_DESCRIPTOR 0x303 -#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 +// string descriptors +enum{ + iLANGUAGE_DESCR, + iMANUFACTURER_DESCR, + iPRODUCT_DESCR, + iSERIAL_DESCR, + iINTERFACE_DESCR, + iDESCR_AMOUNT +}; + +// Types of descriptors +#define DEVICE_DESCRIPTOR 0x01 +#define CONFIGURATION_DESCRIPTOR 0x02 +#define STRING_DESCRIPTOR 0x03 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x06 #define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) #define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) @@ -76,14 +83,6 @@ #define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) #define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) -// USB state: uninitialized, addressed, ready for use -typedef enum{ - USB_STATE_DEFAULT, - USB_STATE_ADDRESSED, - USB_STATE_CONFIGURED, - USB_STATE_CONNECTED -} USB_state; - // EP types #define EP_TYPE_BULK 0x00 #define EP_TYPE_CONTROL 0x01 @@ -112,7 +111,6 @@ static const struct name \ \ } \ name = {0x04, 0x03, lng_id} -#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) // EP0 configuration packet typedef struct { @@ -127,17 +125,11 @@ typedef struct { typedef struct{ uint16_t *tx_buf; // transmission buffer address uint16_t txbufsz; // transmission buffer size - uint16_t *rx_buf; // reception buffer address + uint8_t *rx_buf; // reception buffer address void (*func)(); // endpoint action function unsigned rx_cnt : 10; // received data counter } ep_t; -// USB status & its address -typedef struct { - uint8_t USB_Status; - uint16_t USB_Addr; -}usb_dev_t; - typedef struct { uint32_t dwDTERate; uint8_t bCharFormat; @@ -162,15 +154,14 @@ typedef struct { } __attribute__ ((packed)) usb_cdc_notification; extern ep_t endpoints[]; -extern usb_dev_t USB_Dev; -extern uint8_t usbON; +extern volatile uint8_t usbON; +extern uint8_t ep0databuf[], setupdatabuf[]; + +void EP0_Handler(); -void USB_Init(); -void USB_ResetState(); -int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); -int EP_Read(uint8_t number, uint16_t *buf); +int EP_Read(uint8_t number, uint8_t *buf); usb_LineCoding getLineCoding(); void linecoding_handler(usb_LineCoding *lc); diff --git a/F1:F103/F1_testbrd/usbhw.c b/F1:F103/F1_testbrd/usbhw.c new file mode 100644 index 0000000..42668e5 --- /dev/null +++ b/F1:F103/F1_testbrd/usbhw.c @@ -0,0 +1,123 @@ +/* + * This file is part of the F1_testbrd project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 3 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, see . + */ + +#include "usb.h" +#include "usbhw.h" +#include "usb_lib.h" + +void USB_setup(){ + NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); + USBPU_OFF(); + RCC->APB1ENR |= RCC_APB1ENR_USBEN; + RCC->APB2ENR |= USB_RCC; + USB->CNTR = USB_CNTR_FRES; // Force USB Reset + for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms + //uint32_t ctr = 0; + USB->CNTR = 0; + USB->BTABLE = 0; + USB->DADDR = 0; + USB->ISTR = 0; + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts + NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); + USBPU_ON(); +} + +static uint16_t lastaddr = LASTADDR_DEFAULT; +/** + * Endpoint initialisation + * @param number - EP num (0...7) + * @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT) + * @param txsz - transmission buffer size @ USB/CAN buffer + * @param rxsz - reception buffer size @ USB/CAN buffer + * @param uint16_t (*func)(ep_t *ep) - EP handler function + * @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)){ + 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) 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; + if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size + uint16_t countrx = 0; + if(rxsz < 64) countrx = rxsz / 2; + else{ + if(rxsz & 0x1f) return 3; // should be multiple of 32 + countrx = 31 + rxsz / 32; + } + USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; + endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); + endpoints[number].txbufsz = txsz; + 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); + lastaddr += rxsz; + USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; + endpoints[number].func = func; + return 0; +} + +// standard IRQ handler +void usb_lp_can_rx0_isr(){ + if(USB->ISTR & USB_ISTR_RESET){ + usbON = 0; + // Reinit registers + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + // 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_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ + return; + } + USB->ISTR = ~USB_ISTR_RESET; + } + if(USB->ISTR & 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 + EP_Read(0, ep0databuf); + } + } + } + // call EP handler + if(endpoints[n].func) endpoints[n].func(endpoints[n]); + } + if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + usbON = 0; + USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE; + USB->ISTR = ~USB_ISTR_SUSP; + } + if(USB->ISTR & USB_ISTR_WKUP){ // wakeup + USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags + USB->ISTR = ~USB_ISTR_WKUP; + } +} diff --git a/F1:F103/F1_testbrd/usb_defs.h b/F1:F103/F1_testbrd/usbhw.h similarity index 82% rename from F1:F103/F1_testbrd/usb_defs.h rename to F1:F103/F1_testbrd/usbhw.h index 0b98f02..4c2fd04 100644 --- a/F1:F103/F1_testbrd/usb_defs.h +++ b/F1:F103/F1_testbrd/usbhw.h @@ -1,6 +1,6 @@ /* * This file is part of the F1_testbrd project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -19,14 +19,18 @@ #pragma once #include +#define USB_RCC RCC_APB2ENR_IOPAEN +#define USBPU_port GPIOA +#define USBPU_pin (1<<15) +#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin) +#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin) + // max endpoints number #define STM32ENDPOINTS 8 /** * Buffers size definition **/ #define USB_BTABLE_SIZE 512 -// first 64 bytes of USB_BTABLE are registers! -//#define USB_EP0_BASEADDR 64 // for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) #define USB_EP0_BUFSZ 64 // USB transmit buffer size (64 for PL2303) @@ -71,9 +75,7 @@ #define USB_COUNTn_NUM_BLOCK 0x00007C00 #define USB_COUNTn_RX 0x0000003F -#ifdef USB_TypeDef #define USB_TypeDef USB_TypeDef_custom -#endif typedef struct { __IO uint32_t EPnR[STM32ENDPOINTS]; @@ -86,12 +88,28 @@ typedef struct { } USB_TypeDef; typedef struct{ +#if defined USB2_16 + __IO uint16_t USB_ADDR_TX; + __IO uint16_t USB_COUNT_TX; + __IO uint16_t USB_ADDR_RX; + __IO uint16_t USB_COUNT_RX; +#define ACCESSZ (1) +#define BUFTYPE uint8_t +#elif defined USB1_16 __IO uint32_t USB_ADDR_TX; __IO uint32_t USB_COUNT_TX; __IO uint32_t USB_ADDR_RX; __IO uint32_t USB_COUNT_RX; +#define ACCESSZ (2) +#define BUFTYPE uint16_t +#else +#error "Define USB1_16 or USB2_16" +#endif } USB_EPDATA_TypeDef; typedef struct{ __IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS]; } USB_BtableDef; + +void USB_setup(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); diff --git a/F1:F103/F1_testbrd/version.inc b/F1:F103/F1_testbrd/version.inc new file mode 100644 index 0000000..3680a40 --- /dev/null +++ b/F1:F103/F1_testbrd/version.inc @@ -0,0 +1,2 @@ +#define BUILD_NUMBER "22" +#define BUILD_DATE "2023-06-11" diff --git a/F1:F103/PL2303_ringbuffer/Makefile b/F1:F103/PL2303_ringbuffer/Makefile index d24a3a8..b3cf7a9 100644 --- a/F1:F103/PL2303_ringbuffer/Makefile +++ b/F1:F103/PL2303_ringbuffer/Makefile @@ -1,9 +1,9 @@ BINARY := PL2303 # MCU code -MCU ?= F103x8 +MCU ?= F103x6 # change this linking script depending on particular MCU model, -LDSCRIPT ?= stm32f103x8.ld -DEFINES := -DSTM32F10X_MD +LDSCRIPT ?= stm32f103x6.ld +DEFINES := -DUSB1_16 -DSTM32F10X_LD include ../makefile.f1 include ../../makefile.stm32 diff --git a/F1:F103/PL2303_ringbuffer/Makefile.old b/F1:F103/PL2303_ringbuffer/Makefile.old deleted file mode 100644 index 1d3be00..0000000 --- a/F1:F103/PL2303_ringbuffer/Makefile.old +++ /dev/null @@ -1,151 +0,0 @@ -BINARY = PL2303 -BOOTPORT ?= /dev/ttyUSB0 -BOOTSPEED ?= 115200 -# MCU FAMILY -FAMILY ?= F1 -# MCU code -MCU ?= F103x8 -# density (stm32f10x.h, lines 70-84) -DENSITY ?= MD -# change this linking script depending on particular MCU model, -LDSCRIPT ?= stm32f103x8.ld -# debug -#DEFS = -DEBUG - -# autoincremental version & build date -VERSION_FILE = version.inc -NEXTVER := $(shell expr $$(awk '/#define BUILD_NUMBER/' $(VERSION_FILE) | tr -cd "[0-9]") + 1) -BUILDDATE := $(shell date +%Y-%m-%d) - -INDEPENDENT_HEADERS= - -FP_FLAGS ?= -msoft-float -mfloat-abi=soft -ASM_FLAGS ?= -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd -ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS) - -############################################################################### -# Executables -#PREFIX ?= arm-none-eabi -# gcc from arm web site -PREFIX ?= /opt/bin/arm-none-eabi -TOOLCHLIB ?= /opt/arm-none-eabi/lib -RM := rm -f -RMDIR := rmdir -CC := $(PREFIX)-gcc -# don't replace ld with gcc: the binary size would be much greater!! -LD := $(PREFIX)-ld -AR := $(PREFIX)-ar -AS := $(PREFIX)-as -SIZE := $(PREFIX)-size -OBJCOPY := $(PREFIX)-objcopy -OBJDUMP := $(PREFIX)-objdump -GDB := $(PREFIX)-gdb -STFLASH := $(shell which st-flash) -STBOOT := $(shell which stm32flash) -DFUUTIL := $(shell which dfu-util) - -############################################################################### -# Source files -OBJDIR := mk -SRC := $(wildcard *.c) -OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) -STARTUP = $(OBJDIR)/startup.o -OBJS += $(STARTUP) -# dependencies: we need them to recompile files if their headers-dependencies changed -DEPS := $(OBJS:.o=.d) - -INC_DIR ?= ../inc - -INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm -LIB_DIR := $(INC_DIR)/ld - -############################################################################### -# C flags -CFLAGS += -O2 -g -D__thumb2__=1 -MD -g -gdwarf-2 -CFLAGS += -Wall -Werror -Wextra -Wshadow -CFLAGS += -fno-common -ffunction-sections -fdata-sections -fno-stack-protector -fshort-enums -CFLAGS += $(ARCH_FLAGS) - -############################################################################### -# Linker flags -LDFLAGS += -nostartfiles --static --gc-sections --print-memory-usage -specs=nano.specs -LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB) -LDFLAGS += -T$(LDSCRIPT) - -############################################################################### -# Used libraries -LDLIBS += -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) - -DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY) - -ELF := $(OBJDIR)/$(BINARY).elf -LIST := $(OBJDIR)/$(BINARY).list -BIN := $(BINARY).bin -HEX := $(BINARY).hex - -all: bin list size - -elf: $(ELF) -bin: $(BIN) -hex: $(HEX) -list: $(LIST) - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPS) -endif - -$(OBJDIR): - mkdir $(OBJDIR) - -$(STARTUP): $(INC_DIR)/startup/vector.c - $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $< - -$(VERSION_FILE): *.[ch] - @echo " Generate version: $(NEXTVER) for date $(BUILDDATE)" - @sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE) - @sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE) - -$(OBJDIR)/proto.o: proto.c $(VERSION_FILE) - -$(OBJDIR)/%.o: %.c - @echo " CC $<" - $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) -o $@ -c $< - -$(BIN): $(ELF) - @echo " OBJCOPY $(BIN)" - $(OBJCOPY) -Obinary $(ELF) $(BIN) - -$(HEX): $(ELF) - @echo " OBJCOPY $(HEX)" - $(OBJCOPY) -Oihex $(ELF) $(HEX) - -$(LIST): $(ELF) - @echo " OBJDUMP $(LIST)" - $(OBJDUMP) -S $(ELF) > $(LIST) - -$(ELF): $(OBJDIR) $(OBJS) - @echo " LD $(ELF)" - $(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF) - -size: $(ELF) - $(SIZE) $(ELF) - -clean: - @echo " CLEAN" - $(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) - @rmdir $(OBJDIR) 2>/dev/null || true - - -flash: $(BIN) - @echo " FLASH $(BIN)" - $(STFLASH) write $(BIN) 0x8000000 - -boot: $(BIN) - @echo " LOAD $(BIN) through bootloader" - $(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN) - -dfuboot: $(BIN) - @echo " LOAD $(BIN) THROUGH DFU" - $(DFUUTIL) -a0 -D $(BIN) -s 0x08000000 - -.PHONY: clean flash boot diff --git a/F1:F103/PL2303_ringbuffer/PL2303.bin b/F1:F103/PL2303_ringbuffer/PL2303.bin index ece1e8adc76bf8fcc070e7586d470d8938e13b5c..615b166171898b92ba7b11f3f638986062c844b6 100755 GIT binary patch literal 6672 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 literal 6660 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 wDE3Z<)a`0;k&Pral{>d?t*W~xc!-A!APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; + // Enable clocks to the GPIO subsystems, turn on AFIO clocking to disable SWD/JTAG + RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; // turn off SWJ/JTAG // AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE; AFIO->MAPR = AFIO_MAPR_SWJ_CFG_JTAGDISABLE; // for PA15 // Set led as opendrain output - GPIOC->CRH |= CRH(13, CNF_ODOUTPUT | MODE_SLOW); + //GPIOC->CRH |= CRH(13, CNF_ODOUTPUT | MODE_SLOW); + // USB pullup (PA15) - pushpull output + GPIOA->CRH = CRH(8, CNF_PPOUTPUT | MODE_SLOW) | CRH(15, CNF_PPOUTPUT | MODE_SLOW); } void hw_setup(){ diff --git a/F1:F103/PL2303_ringbuffer/hardware.h b/F1:F103/PL2303_ringbuffer/hardware.h index d0955cf..2763e34 100644 --- a/F1:F103/PL2303_ringbuffer/hardware.h +++ b/F1:F103/PL2303_ringbuffer/hardware.h @@ -17,14 +17,13 @@ */ #pragma once -#ifndef __HARDWARE_H__ -#define __HARDWARE_H__ #include // LED0 - PC13 (bluepill), blinking each second -#define LED0_port GPIOC -#define LED0_pin (1<<13) +// PA8 - my board +#define LED0_port GPIOA +#define LED0_pin (1<<8) #define LED_blink(x) pin_toggle(x ## _port, x ## _pin) #define LED_on(x) pin_clear(x ## _port, x ## _pin) @@ -34,4 +33,3 @@ extern volatile uint32_t Tms; void hw_setup(); -#endif // __HARDWARE_H__ diff --git a/F1:F103/PL2303_ringbuffer/main.c b/F1:F103/PL2303_ringbuffer/main.c index 2ab42e5..846aeb0 100644 --- a/F1:F103/PL2303_ringbuffer/main.c +++ b/F1:F103/PL2303_ringbuffer/main.c @@ -21,7 +21,7 @@ #include "usart.h" #include "usb.h" -#define USBBUFSZ 127 +#define MAXSTRLEN RBINSZ volatile uint32_t Tms = 0; @@ -29,34 +29,16 @@ void sys_tick_handler(void){ ++Tms; } -// usb getline -char *get_USB(){ - static char tmpbuf[USBBUFSZ+1], *curptr = tmpbuf; - static int rest = USBBUFSZ; - uint8_t x = USB_receive(curptr); - if(!x) return NULL; - curptr[x] = 0; - if(curptr[x-1] == '\n'){ - curptr = tmpbuf; - rest = USBBUFSZ; - return tmpbuf; - } - curptr += x; rest -= x; - if(rest <= 0){ // buffer overflow - curptr = tmpbuf; - rest = USBBUFSZ; - USEND("USB buffer overflow\n"); - } - return NULL; -} - int main(void){ + char inbuff[MAXSTRLEN+1]; StartHSE(); hw_setup(); SysTick_Config(72000); + USBPU_OFF(); hw_setup(); usart_setup(); USB_setup(); + USBPU_ON(); uint32_t ctr = Tms; while(1){ @@ -66,12 +48,16 @@ int main(void){ LED_blink(LED0); usart_transmit(); } + if(usartovr()){ + usart_send("USART buffer overfull\n"); + } char *txt = NULL; - usb_proc(); - if((txt = get_USB())){ + int l = USB_receivestr(inbuff, MAXSTRLEN); + if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); + else if(l){ USEND("Got USB data\n"); - const char *ans = parse_cmd(txt); - if(ans) USB_send(ans); + const char *ans = parse_cmd(inbuff); + if(ans) USB_sendstr(ans); } if(usartrx()){ if(usart_getline(&txt)){ diff --git a/F1:F103/PL2303_ringbuffer/openocd.cfg b/F1:F103/PL2303_ringbuffer/openocd.cfg new file mode 100644 index 0000000..18ecde1 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/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/PL2303_ringbuffer/pl2303.cflags b/F1:F103/PL2303_ringbuffer/pl2303.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/F1:F103/PL2303_ringbuffer/pl2303.config b/F1:F103/PL2303_ringbuffer/pl2303.config new file mode 100644 index 0000000..c41f0d7 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.config @@ -0,0 +1,6 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG +#define STM32F1 +#define STM32F103x8 +#define STM32F10X_MD diff --git a/F1:F103/PL2303_ringbuffer/pl2303.creator b/F1:F103/PL2303_ringbuffer/pl2303.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.creator @@ -0,0 +1 @@ +[General] diff --git a/F1:F103/PL2303_ringbuffer/pl2303.creator.user b/F1:F103/PL2303_ringbuffer/pl2303.creator.user new file mode 100644 index 0000000..0e70a42 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.creator.user @@ -0,0 +1,171 @@ + + + + + + EnvironmentId + {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + false + true + *.md, *.MD, Makefile + false + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 8 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /Big/Data/00__Electronics/STM32/F303-nolib/blink + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Default + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F1:F103/PL2303_ringbuffer/pl2303.cxxflags b/F1:F103/PL2303_ringbuffer/pl2303.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/F1:F103/PL2303_ringbuffer/pl2303.files b/F1:F103/PL2303_ringbuffer/pl2303.files new file mode 100644 index 0000000..68d42e7 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.files @@ -0,0 +1,15 @@ +hardware.c +hardware.h +main.c +proto.c +proto.h +ringbuffer.c +ringbuffer.h +usart.c +usart.h +usb.c +usb.h +usb_lib.c +usb_lib.h +usbhw.c +usbhw.h diff --git a/F1:F103/PL2303_ringbuffer/pl2303.includes b/F1:F103/PL2303_ringbuffer/pl2303.includes new file mode 100644 index 0000000..06d1130 --- /dev/null +++ b/F1:F103/PL2303_ringbuffer/pl2303.includes @@ -0,0 +1,6 @@ +. +../inc +../inc/Fx +../inc/cm +../inc/ld +../inc/startup diff --git a/F1:F103/PL2303_ringbuffer/proto.c b/F1:F103/PL2303_ringbuffer/proto.c index 273335b..b56ac7a 100644 --- a/F1:F103/PL2303_ringbuffer/proto.c +++ b/F1:F103/PL2303_ringbuffer/proto.c @@ -194,12 +194,12 @@ const char *parse_cmd(const char *buf){ else add2buf("on\n"); break; case 'R': - USB_send("Soft reset\n"); + USB_sendstr("Soft reset\n"); NVIC_SystemReset(); break; case 'T': u3 = Tms; - for(int i = 0; i < 1000; ++i) USB_send(test); + for(int i = 0; i < 1000; ++i) USB_sendstr(test); add2buf("\n\nspd="); add2buf(u2str(2000000000/(Tms - u3))); add2buf("\n"); // strlen == 2Mbit, speed in bits per second break; @@ -210,7 +210,7 @@ const char *parse_cmd(const char *buf){ add2buf("\n"); break; case 'W': - USB_send("Wait for reboot\n"); + USB_sendstr("Wait for reboot\n"); while(1){nop();}; break; default: diff --git a/F1:F103/PL2303_ringbuffer/ringbuffer.c b/F1:F103/PL2303_ringbuffer/ringbuffer.c index f2b5f9f..0d10cd7 100644 --- a/F1:F103/PL2303_ringbuffer/ringbuffer.c +++ b/F1:F103/PL2303_ringbuffer/ringbuffer.c @@ -1,6 +1,6 @@ /* * This file is part of the pl2303 project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -16,64 +16,109 @@ * along with this program. If not, see . */ -#include - #include "ringbuffer.h" -#include "usb.h" -#include "usb_lib.h" -// ring buffer -static char ringbuffer[RBSIZE]; -// head - position of first data byte -// tail - position of last data byte + 1 -// head == tail - empty! So, buffer can't store more than RBSIZE-1 bytes of data! -static volatile int head = 0, tail = 0; - -static int datalen(){ - if(tail >= head) return (tail - head); - else return (RBSIZE - head + tail); -} -static int restlen(){ - return (RBSIZE - 1 - datalen()); +// stored data length +int RB_datalen(ringbuffer *b){ + if(b->tail >= b->head) return (b->tail - b->head); + else return (b->length - b->head + b->tail); } -static void mcpy(char *targ, const char *src, int l){ +/** + * @brief RB_hasbyte - check if buffer has given byte stored + * @param b - buffer + * @param byte - byte to find + * @return index if found, -1 if none + */ +int RB_hasbyte(ringbuffer *b, uint8_t byte){ + if(b->head == b->tail) return -1; // no data in buffer + int startidx = b->head; + if(b->head > b->tail){ // + for(int found = b->head; found < b->length; ++found) + if(b->data[found] == byte) return found; + startidx = 0; + } + for(int found = startidx; found < b->tail; ++found) + if(b->data[found] == byte) return found; + return -1; +} + +// poor memcpy +static void mcpy(uint8_t *targ, const uint8_t *src, int l){ while(l--) *targ++ = *src++; } -TRUE_INLINE void incr(volatile int *what, int n){ +// increment head or tail +TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ *what += n; - if(*what >= RBSIZE) *what -= RBSIZE; + if(*what >= b->length) *what -= b->length; } -int RB_read(char s[BLOCKSIZE]){ - int l = datalen(); +/** + * @brief RB_read - read data from ringbuffer + * @param b - buffer + * @param s - array to write data + * @param len - max len of `s` + * @return bytes read + */ +int RB_read(ringbuffer *b, uint8_t *s, int len){ + int l = RB_datalen(b); if(!l) return 0; - if(l > BLOCKSIZE) l = BLOCKSIZE; - int _1st = RBSIZE - head; + if(l > len) l = len; + int _1st = b->length - b->head; if(_1st > l) _1st = l; - if(_1st > BLOCKSIZE) _1st = BLOCKSIZE; - mcpy(s, ringbuffer+head, _1st); - if(_1st < BLOCKSIZE && l > _1st){ - mcpy(s+_1st, ringbuffer, l-_1st); - incr(&head, l); + if(_1st > len) _1st = len; + mcpy(s, b->data + b->head, _1st); + if(_1st < len && l > _1st){ + mcpy(s+_1st, b->data, l - _1st); + incr(b, &b->head, l); return l; } - incr(&head ,_1st); + incr(b, &b->head, _1st); return _1st; } -int RB_write(const char *str, int l){ - int r = restlen(); +/** + * @brief RB_readto fill array `s` with data until byte `byte` (with it) + * @param b - ringbuffer + * @param byte - check byte + * @param s - buffer to write data + * @param len - length of `s` + * @return amount of bytes written (negative, if lenhead; + // now calculate length of new data portion + if(idx < b->head) partlen += b->length; + if(partlen > len) return -RB_read(b, s, len); + return RB_read(b, s, partlen); +} + +/** + * @brief RB_write - write some data to ringbuffer + * @param b - buffer + * @param str - data + * @param l - length + * @return amount of bytes written + */ +int RB_write(ringbuffer *b, const uint8_t *str, int l){ + int r = b->length - 1 - RB_datalen(b); // rest length if(l > r) l = r; if(!l) return 0; - int _1st = RBSIZE - tail; + int _1st = b->length - b->tail; if(_1st > l) _1st = l; - mcpy(ringbuffer+tail, str, _1st); + mcpy(b->data + b->tail, str, _1st); if(_1st < l){ // add another piece from start - mcpy(ringbuffer, str+_1st, l-_1st); + mcpy(b->data, str+_1st, l-_1st); } - incr(&tail, l); + incr(b, &b->tail, l); return l; } +// just delete all information in buffer `b` +void RB_clearbuf(ringbuffer *b){ + b->head = 0; + b->tail = 0; +} diff --git a/F1:F103/PL2303_ringbuffer/ringbuffer.h b/F1:F103/PL2303_ringbuffer/ringbuffer.h index 404fcbb..34daa76 100644 --- a/F1:F103/PL2303_ringbuffer/ringbuffer.h +++ b/F1:F103/PL2303_ringbuffer/ringbuffer.h @@ -1,6 +1,6 @@ /* * This file is part of the pl2303 project. - * Copyright 2022 Edward V. Emelianov . + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,17 +17,19 @@ */ #pragma once -#ifndef RINGBUFFER_H__ -#define RINGBUFFER_H__ +#include -#include "usbhw.h" +typedef struct{ + uint8_t *data; // data buffer + const int length; // its length + int head; // head index + int tail; // tail index +} ringbuffer; -// ring buffer size in bytes -#define RBSIZE (512) -// max reading portion size -#define BLOCKSIZE (USB_TXBUFSZ) +int RB_read(ringbuffer *b, uint8_t *s, int len); +int RB_readto(ringbuffer *b, uint8_t byte, uint8_t *s, int len); +int RB_hasbyte(ringbuffer *b, uint8_t byte); +int RB_write(ringbuffer *b, const uint8_t *str, int l); +int RB_datalen(ringbuffer *b); +void RB_clearbuf(ringbuffer *b); -int RB_read(char s[BLOCKSIZE]); -int RB_write(const char *str, int l); - -#endif // RINGBUFFER_H__ diff --git a/F1:F103/PL2303_ringbuffer/usart.c b/F1:F103/PL2303_ringbuffer/usart.c index 76c2e38..c3b8855 100644 --- a/F1:F103/PL2303_ringbuffer/usart.c +++ b/F1:F103/PL2303_ringbuffer/usart.c @@ -91,7 +91,7 @@ void usart_setup(){ // 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); + 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 diff --git a/F1:F103/PL2303_ringbuffer/usb.c b/F1:F103/PL2303_ringbuffer/usb.c index f39a217..553b6cf 100644 --- a/F1:F103/PL2303_ringbuffer/usb.c +++ b/F1:F103/PL2303_ringbuffer/usb.c @@ -1,6 +1,6 @@ /* - * This file is part of the MLX90640 project. - * Copyright 2022 Edward V. Emelianov . + * This file is part of the pl2303 project. + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -16,101 +16,111 @@ * along with this program. If not, see . */ -#include "ringbuffer.h" +#include + +#include "hardware.h" #include "usb.h" #include "usb_lib.h" -static char usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data -volatile uint8_t tx_succesfull = 1; -static volatile uint8_t rxNE = 0; +static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data +// ring buffers for incoming and outgoing data +static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ]; +volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0}; +volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; +// transmission is succesfull +volatile uint8_t bufisempty = 1; +volatile uint8_t bufovrfl = 0; void send_next(){ - //if(!tx_succesfull) return; + if(bufisempty) return; static int lastdsz = 0; - int buflen = RB_read(usbbuff); + int buflen = RB_read((ringbuffer*)&rbout, (uint8_t*)usbbuff, USB_TXBUFSZ); if(!buflen){ if(lastdsz == 64) EP_Write(3, NULL, 0); // send ZLP after 64 bits packet when nothing more to send lastdsz = 0; + bufisempty = 1; return; } - tx_succesfull = 0; EP_Write(3, (uint8_t*)usbbuff, buflen); lastdsz = buflen; } +// blocking send full content of ring buffer +int USB_sendall(){ + while(!bufisempty){ + if(!usbON) return 0; + } + return 1; +} + // put `buf` into queue to send -void USB_send(const char *buf){ - if(!buf || !usbON) return; - int len = 0; - const char *b = buf; - while(*b++) ++len; - if(!usbON || !len) return; - int l = len; - while(l){ - if(tx_succesfull) send_next(); - int a = RB_write(buf, l); - l -= a; +int USB_send(const uint8_t *buf, int len){ + if(!buf || !usbON || !len) return 0; + while(len){ + int a = RB_write((ringbuffer*)&rbout, buf, len); + len -= a; buf += a; + if(bufisempty){ + bufisempty = 0; + send_next(); + } } + return 1; } -// interrupt IN handler (never used?) -static void EP1_Handler(){ - uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); - 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 - epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)); - USB->EPnR[1] = epstatus; -} - -// data IN/OUT handlers -static void transmit_Handler(){ // EP3IN - tx_succesfull = 1; - uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); - // clear CTR keep DTOGs & STATs - USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr -} - -static void receive_Handler(){ // EP2OUT - rxNE = 1; - uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[2]); - USB->EPnR[2] = (epstatus & ~(USB_EPnR_CTR_RX)); // clear RX ctr -} - -void usb_proc(){ - switch(USB_Dev.USB_Status){ - case USB_STATE_CONFIGURED: - // make new BULK endpoint - // 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, 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 - USB_Dev.USB_Status = USB_STATE_CONNECTED; - break; - case USB_STATE_DEFAULT: - case USB_STATE_ADDRESSED: - if(usbON){ - usbON = 0; - } - break; - default: // USB_STATE_CONNECTED - send next data portion - if(!usbON) return; - if(tx_succesfull) send_next(); +int USB_putbyte(uint8_t byte){ + if(!usbON) return 0; + while(0 == RB_write((ringbuffer*)&rbout, &byte, 1)){ + if(bufisempty){ + bufisempty = 0; + send_next(); + } } + return 1; +} + +int USB_sendstr(const char *string){ + if(!string || !usbON) return 0; + int len = 0; + const char *b = string; + while(*b++) ++len; + if(!len) return 0; + return USB_send((const uint8_t*)string, len); } /** - * @brief USB_receive - * @param buf (i) - buffer[64] for received data - * @return amount of received bytes + * @brief USB_receive - get binary data from receiving ring-buffer + * @param buf (i) - buffer for received data + * @param len - length of `buf` + * @return amount of received bytes (negative, if overfull happened) */ -uint8_t USB_receive(char *buf){ - if(!usbON || !rxNE) return 0; - uint8_t sz = EP_Read(2, (uint16_t*)buf); - uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); - // keep stat_tx & set ACK rx - USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; - rxNE = 0; +int USB_receive(uint8_t *buf, int len){ + int sz = RB_read((ringbuffer*)&rbin, buf, len); + if(bufovrfl){ + RB_clearbuf((ringbuffer*)&rbin); + if(!sz) sz = -1; + else sz = -sz; + bufovrfl = 0; + } return sz; } + +/** + * @brief USB_receivestr - get string up to '\n' and replace '\n' with 0 + * @param buf - receiving buffer + * @param len - its length + * @return strlen or negative value indicating overflow (if so, string won't be ends with 0 and buffer should be cleared) + */ +int USB_receivestr(char *buf, int len){ + int l = RB_readto((ringbuffer*)&rbin, '\n', (uint8_t*)buf, len); + if(l == 0) return 0; + if(--l < 0 || bufovrfl) RB_clearbuf((ringbuffer*)&rbin); + else buf[l] = 0; // replace '\n' with strend + if(bufovrfl){ + if(l > 0) l = -l; + else l = -1; + bufovrfl = 0; + } + return l; +} + diff --git a/F1:F103/PL2303_ringbuffer/usb.h b/F1:F103/PL2303_ringbuffer/usb.h index 6e62b64..2a58624 100644 --- a/F1:F103/PL2303_ringbuffer/usb.h +++ b/F1:F103/PL2303_ringbuffer/usb.h @@ -1,6 +1,6 @@ /* - * This file is part of the MLX90640 project. - * Copyright 2022 Edward V. Emelianov . + * This file is part of the pl2303 project. + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,18 +17,33 @@ */ #pragma once -#ifndef __USB_H__ -#define __USB_H__ - +#include "ringbuffer.h" #include "usbhw.h" -#define BUFFSIZE (64) +// sizes of ringbuffers for outgoing and incoming data +#define RBOUTSZ (512) +#define RBINSZ (512) -extern volatile uint8_t tx_succesfull; +#define newline() USB_putbyte('\n') +#define USND(s) do{USB_sendstr(s); USB_putbyte('\n');}while(0) + +#if 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 +#endif + +extern volatile ringbuffer rbout, rbin; +extern volatile uint8_t bufisempty, bufovrfl; -void usb_proc(); void send_next(); -void USB_send(const char *buf); -uint8_t USB_receive(char *buf); - -#endif // __USB_H__ +int USB_sendall(); +int USB_send(const uint8_t *buf, int len); +int USB_putbyte(uint8_t byte); +int USB_sendstr(const char *string); +int USB_receive(uint8_t *buf, int len); +int USB_receivestr(char *buf, int len); diff --git a/F1:F103/PL2303_ringbuffer/usb_lib.c b/F1:F103/PL2303_ringbuffer/usb_lib.c index e9c4ba5..49eb681 100644 --- a/F1:F103/PL2303_ringbuffer/usb_lib.c +++ b/F1:F103/PL2303_ringbuffer/usb_lib.c @@ -1,6 +1,6 @@ /* - * This file is part of the MLX90640 project. - * Copyright 2022 Edward V. Emelianov . + * This file is part of the pl2303 project. + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,19 +17,20 @@ */ #include +#include "usb.h" #include "usb_lib.h" +#include "usbhw.h" ep_t endpoints[STM32ENDPOINTS]; -usb_dev_t USB_Dev; +static uint16_t USB_Addr = 0; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; -config_pack_t setup_packet; -uint8_t ep0databuf[EP0DATABUF_SIZE]; -uint8_t ep0dbuflen = 0; +uint8_t ep0databuf[EP0DATABUF_SIZE], setupdatabuf[EP0DATABUF_SIZE]; +static config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; usb_LineCoding getLineCoding(){return lineCoding;} -uint8_t usbON = 0; // device disconnected from terminal +volatile uint8_t usbON = 0; // device disconnected from terminal // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor #define bcdUSB_L 0x10 @@ -54,9 +55,9 @@ static const uint8_t USB_DeviceDescriptor[] = { 0x23, // idProduct_H 0x00, // bcdDevice_Ver_L 0x03, // bcdDevice_Ver_H - 0x01, // iManufacturer - 0x02, // iProduct - 0x00, // iSerialNumber + iMANUFACTURER_DESCR, // iManufacturer + iPRODUCT_DESCR, // iProduct + iSERIAL_DESCR, // iSerialNumber bNumConfigurations // bNumConfigurations }; @@ -96,7 +97,7 @@ static const uint8_t USB_ConfigDescriptor[] = { 0xff, /* bInterfaceClass */ 0x00, /* bInterfaceSubClass */ 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface: */ + iINTERFACE_DESCR, /* iInterface: */ /////////////////////////////////////////////////// /*Endpoint 1 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ @@ -126,11 +127,19 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x00, /* bInterval: ignore for Bulk transfer */ }; -_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); -// these descriptors are not used in PL2303 emulator! -_USB_STRING_(USB_StringSerialDescriptor, u"0"); -_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); -_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); +_USB_LANG_ID_(LD, LANG_US); +_USB_STRING_(SD, u"0.0.1"); +_USB_STRING_(MD, u"Prolific Technology Inc."); +_USB_STRING_(PD, u"USB-Serial Controller"); +_USB_STRING_(ID, u"pl2303_emulator"); +static void const *StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, + [iINTERFACE_DESCR] = &ID +}; + /* * default handlers @@ -149,8 +158,8 @@ void WEAK break_handler(){ // handler of vendor requests void WEAK vendor_handler(config_pack_t *packet){ + uint16_t c; if(packet->bmRequestType & 0x80){ // read - uint8_t c; switch(packet->wValue){ case 0x8484: c = 2; @@ -164,14 +173,15 @@ void WEAK vendor_handler(config_pack_t *packet){ default: c = 0; } - EP_WriteIRQ(0, &c, 1); + EP_WriteIRQ(0, (uint8_t*)&c, 1); }else{ // write ZLP - EP_WriteIRQ(0, (uint8_t *)0, 0); + c = 0; + EP_WriteIRQ(0, (uint8_t *)&c, 0); } } static void wr0(const uint8_t *buf, uint16_t size){ - if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request + if(setup_packet->wLength < size) size = setup_packet->wLength; // shortened request if(size < endpoints[0].txbufsz){ EP_WriteIRQ(0, buf, size); return; @@ -199,24 +209,18 @@ static void wr0(const uint8_t *buf, uint16_t size){ } static inline void get_descriptor(){ - switch(setup_packet.wValue){ + uint8_t descrtype = setup_packet->wValue >> 8, + descridx = setup_packet->wValue & 0xff; + switch(descrtype){ 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); + case STRING_DESCRIPTOR: + if(descridx < iDESCR_AMOUNT) wr0((const uint8_t *)StringDescriptor[descridx], *((uint8_t*)StringDescriptor[descridx])); + else EP_WriteIRQ(0, (uint8_t*)0, 0); break; case DEVICE_QUALIFIER_DESCRIPTOR: wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); @@ -226,10 +230,10 @@ static inline void get_descriptor(){ } } -static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static uint16_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){ + switch(setup_packet->bRequest){ case GET_DESCRIPTOR: get_descriptor(); break; @@ -237,23 +241,54 @@ static inline void std_d2h_req(){ EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered break; case GET_CONFIGURATION: - EP_WriteIRQ(0, &configuration, 1); + EP_WriteIRQ(0, (uint8_t*)&configuration, 1); break; default: break; } } +// interrupt IN handler (never used?) +static void EP1_Handler(){ + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + 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 + epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)); + USB->EPnR[1] = epstatus; +} + +// data IN/OUT handlers +static void transmit_Handler(){ // EP3IN + uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); + // clear CTR keep DTOGs & STATs + USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr + send_next(); +} + +static void receive_Handler(){ // EP2OUT + uint8_t buf[USB_RXBUFSZ]; + uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); + uint8_t sz = EP_Read(2, (uint8_t*)buf); + if(sz){ + if(RB_write((ringbuffer*)&rbin, buf, sz) != sz) bufovrfl = 1; + } + // keep stat_tx & set ACK rx, clear RX ctr + USB->EPnR[2] = (epstatus & ~USB_EPnR_CTR_RX) ^ USB_EPnR_STAT_RX; +} + static inline void std_h2d_req(){ - switch(setup_packet.bRequest){ + 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; + USB_Addr = setup_packet->wValue; break; case SET_CONFIGURATION: // Now device configured - USB_Dev.USB_Status = USB_STATE_CONFIGURED; - configuration = setup_packet.wValue; + configuration = setup_packet->wValue; + 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 break; default: break; @@ -271,8 +306,8 @@ bmRequestType: 76543210 */ void EP0_Handler(){ uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications - uint8_t reqtype = setup_packet.bmRequestType & 0x7f; - uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; + uint8_t reqtype = setup_packet->bmRequestType & 0x7f; + uint8_t dev2host = (setup_packet->bmRequestType & 0x80) ? 1 : 0; int rxflag = RX_FLAG(epstatus); if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ @@ -285,15 +320,15 @@ void EP0_Handler(){ } break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request - if(setup_packet.bRequest == CLEAR_FEATURE){ + if(setup_packet->bRequest == CLEAR_FEATURE){ EP_WriteIRQ(0, (uint8_t *)0, 0); } break; case VENDOR_REQUEST_TYPE: - vendor_handler(&setup_packet); + vendor_handler(setup_packet); break; case CONTROL_REQUEST_TYPE: - switch(setup_packet.bRequest){ + switch(setup_packet->bRequest){ case GET_LINE_CODING: EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); break; @@ -301,7 +336,7 @@ void EP0_Handler(){ break; case SET_CONTROL_LINE_STATE: usbON = 1; - clstate_handler(setup_packet.wValue); + clstate_handler(setup_packet->wValue); break; case SEND_BREAK: usbON = 0; @@ -310,23 +345,22 @@ void EP0_Handler(){ default: break; } - if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + if(setup_packet->bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement break; default: EP_WriteIRQ(0, (uint8_t *)0, 0); } }else if(rxflag){ // got data over EP0 or host acknowlegement if(endpoints[0].rx_cnt){ - if(setup_packet.bRequest == SET_LINE_CODING){ + if(setup_packet->bRequest == SET_LINE_CODING){ linecoding_handler((usb_LineCoding*)ep0databuf); } } } else if(TX_FLAG(epstatus)){ // package transmitted // now we can change address after enumeration - if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ - USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; - // change state to ADRESSED - USB_Dev.USB_Status = USB_STATE_ADDRESSED; + if ((USB->DADDR & USB_DADDR_ADD) != USB_Addr){ + USB->DADDR = USB_DADDR_EF | USB_Addr; + usbON = 0; } } epstatus = KEEP_DTOG(USB->EPnR[0]); @@ -343,16 +377,24 @@ void EP0_Handler(){ * @param size - its size */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ - uint8_t i; if(size > endpoints[number].txbufsz) size = endpoints[number].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 uint16_t *buf16 = (uint16_t *)buf; +#if defined USB1_16 + // very bad: what if `size` is odd? uint32_t *out = (uint32_t *)endpoints[number].tx_buf; - for(i = 0; i < N2; ++i, ++out){ + for(int i = 0; i < N2; ++i, ++out){ *out = buf16[i]; } +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < N2; i++){ + endpoints[number].tx_buf[i] = buf16[i]; + } +#else +#error "Define USB1_16 or USB2_16" +#endif USB_BTABLE->EP[number].USB_COUNT_TX = size; } @@ -374,16 +416,23 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ * @param *buf - user array for data * @return amount of data read */ -int EP_Read(uint8_t number, uint16_t *buf){ +int EP_Read(uint8_t number, uint8_t *buf){ int sz = endpoints[number].rx_cnt; if(!sz) return 0; endpoints[number].rx_cnt = 0; +#if defined USB1_16 int n = (sz + 1) >> 1; - uint32_t *in = (uint32_t *)endpoints[number].rx_buf; - if(n){ - for(int i = 0; i < n; ++i, ++in) - buf[i] = *(uint16_t*)in; - } + uint32_t *in = (uint32_t*)endpoints[number].rx_buf; + uint16_t *out = (uint16_t*)buf; + for(int i = 0; i < n; ++i, ++in) + out[i] = *(uint16_t*)in; +#elif defined USB2_16 + // use memcpy instead? + for(int i = 0; i < sz; ++i) + buf[i] = endpoints[number].rx_buf[i]; +#else +#error "Define USB1_16 or USB2_16" +#endif return sz; } diff --git a/F1:F103/PL2303_ringbuffer/usb_lib.h b/F1:F103/PL2303_ringbuffer/usb_lib.h index 739fe2d..d509e4f 100644 --- a/F1:F103/PL2303_ringbuffer/usb_lib.h +++ b/F1:F103/PL2303_ringbuffer/usb_lib.h @@ -1,6 +1,6 @@ /* - * This file is part of the MLX90640 project. - * Copyright 2022 Edward V. Emelianov . + * This file is part of the pl2303 project. + * Copyright 2023 Edward V. Emelianov . * * 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 @@ -17,9 +17,6 @@ */ #pragma once -#ifndef __USB_LIB_H__ -#define __USB_LIB_H__ - #include #include "usbhw.h" @@ -62,14 +59,21 @@ #define CONTROL_DTR 0x01 #define CONTROL_RTS 0x02 -// wValue -#define DEVICE_DESCRIPTOR 0x100 -#define CONFIGURATION_DESCRIPTOR 0x200 -#define STRING_LANG_DESCRIPTOR 0x300 -#define STRING_MAN_DESCRIPTOR 0x301 -#define STRING_PROD_DESCRIPTOR 0x302 -#define STRING_SN_DESCRIPTOR 0x303 -#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 +// string descriptors +enum{ + iLANGUAGE_DESCR, + iMANUFACTURER_DESCR, + iPRODUCT_DESCR, + iSERIAL_DESCR, + iINTERFACE_DESCR, + iDESCR_AMOUNT +}; + +// Types of descriptors +#define DEVICE_DESCRIPTOR 0x01 +#define CONFIGURATION_DESCRIPTOR 0x02 +#define STRING_DESCRIPTOR 0x03 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x06 #define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) #define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) @@ -79,14 +83,6 @@ #define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) #define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX)) -// USB state: uninitialized, addressed, ready for use -typedef enum{ - USB_STATE_DEFAULT, - USB_STATE_ADDRESSED, - USB_STATE_CONFIGURED, - USB_STATE_CONNECTED -} USB_state; - // EP types #define EP_TYPE_BULK 0x00 #define EP_TYPE_CONTROL 0x01 @@ -115,7 +111,6 @@ static const struct name \ \ } \ name = {0x04, 0x03, lng_id} -#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) // EP0 configuration packet typedef struct { @@ -130,17 +125,11 @@ typedef struct { typedef struct{ uint16_t *tx_buf; // transmission buffer address uint16_t txbufsz; // transmission buffer size - uint16_t *rx_buf; // reception buffer address + uint8_t *rx_buf; // reception buffer address void (*func)(); // endpoint action function unsigned rx_cnt : 10; // received data counter } ep_t; -// USB status & its address -typedef struct { - uint8_t USB_Status; - uint16_t USB_Addr; -}usb_dev_t; - typedef struct { uint32_t dwDTERate; uint8_t bCharFormat; @@ -165,22 +154,17 @@ typedef struct { } __attribute__ ((packed)) usb_cdc_notification; extern ep_t endpoints[]; -extern usb_dev_t USB_Dev; -extern uint8_t usbON; -extern config_pack_t setup_packet; -extern uint8_t ep0databuf[]; -extern uint8_t ep0dbuflen; +extern volatile uint8_t usbON; +extern uint8_t ep0databuf[], setupdatabuf[]; void EP0_Handler(); void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); -int EP_Read(uint8_t number, uint16_t *buf); +int EP_Read(uint8_t number, uint8_t *buf); usb_LineCoding getLineCoding(); void linecoding_handler(usb_LineCoding *lc); void clstate_handler(uint16_t val); void break_handler(); void vendor_handler(config_pack_t *packet); - -#endif // __USB_LIB_H__ diff --git a/F1:F103/PL2303_ringbuffer/usbhw.c b/F1:F103/PL2303_ringbuffer/usbhw.c index d93c927..ac73fcf 100644 --- a/F1:F103/PL2303_ringbuffer/usbhw.c +++ b/F1:F103/PL2303_ringbuffer/usbhw.c @@ -26,8 +26,6 @@ void USB_setup(){ USBPU_OFF(); RCC->APB1ENR |= RCC_APB1ENR_USBEN; RCC->APB2ENR |= USB_RCC; - // USB pullup (PA15) - pushpull output - GPIOA->CRH |= CRH(15, CNF_PPOUTPUT | MODE_SLOW); USB->CNTR = USB_CNTR_FRES; // Force USB Reset for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms //uint32_t ctr = 0; @@ -64,12 +62,12 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f countrx = 31 + rxsz / 32; } USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; - endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); + endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); endpoints[number].txbufsz = txsz; lastaddr += txsz; USB_BTABLE->EP[number].USB_COUNT_TX = 0; USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; - endpoints[number].rx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); + endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr * ACCESSZ); lastaddr += rxsz; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; endpoints[number].func = func; @@ -82,17 +80,15 @@ void usb_lp_can_rx0_isr(){ usbON = 0; // Reinit registers USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - USB->ISTR = 0; // 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; - USB_Dev.USB_Status = USB_STATE_DEFAULT; - USB->ISTR = ~USB_ISTR_RESET; if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ return; } + USB->ISTR = ~USB_ISTR_RESET; } if(USB->ISTR & USB_ISTR_CTR){ // EP number @@ -105,12 +101,10 @@ void usb_lp_can_rx0_isr(){ 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, (uint16_t*)&setup_packet); - ep0dbuflen = 0; + 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 = endpoints[0].rx_cnt; - EP_Read(0, (uint16_t*)&ep0databuf); + EP_Read(0, ep0databuf); } } } @@ -127,4 +121,3 @@ void usb_lp_can_rx0_isr(){ USB->ISTR = ~USB_ISTR_WKUP; } } - diff --git a/F1:F103/PL2303_ringbuffer/usbhw.h b/F1:F103/PL2303_ringbuffer/usbhw.h index ac41455..fadac61 100644 --- a/F1:F103/PL2303_ringbuffer/usbhw.h +++ b/F1:F103/PL2303_ringbuffer/usbhw.h @@ -17,16 +17,13 @@ */ #pragma once -#ifndef USBHW_H__ -#define USBHW_H__ - #include #define USB_RCC RCC_APB2ENR_IOPAEN #define USBPU_port GPIOA #define USBPU_pin (1<<15) -#define USBPU_ON() pin_set(USBPU_port, USBPU_pin) -#define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin) +#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin) +#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin) // max endpoints number #define STM32ENDPOINTS 8 @@ -34,8 +31,6 @@ * Buffers size definition **/ #define USB_BTABLE_SIZE 512 -// first 64 bytes of USB_BTABLE are registers! -//#define USB_EP0_BASEADDR 64 // for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) #define USB_EP0_BUFSZ 64 // USB transmit buffer size (64 for PL2303) @@ -93,10 +88,23 @@ typedef struct { } USB_TypeDef; typedef struct{ +#if defined USB2_16 + __IO uint16_t USB_ADDR_TX; + __IO uint16_t USB_COUNT_TX; + __IO uint16_t USB_ADDR_RX; + __IO uint16_t USB_COUNT_RX; +#define ACCESSZ (1) +#define BUFTYPE uint8_t +#elif defined USB1_16 __IO uint32_t USB_ADDR_TX; __IO uint32_t USB_COUNT_TX; __IO uint32_t USB_ADDR_RX; __IO uint32_t USB_COUNT_RX; +#define ACCESSZ (2) +#define BUFTYPE uint16_t +#else +#error "Define USB1_16 or USB2_16" +#endif } USB_EPDATA_TypeDef; typedef struct{ @@ -105,5 +113,3 @@ typedef struct{ void USB_setup(); int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); - -#endif // USBHW_H__ diff --git a/F1:F103/PL2303_ringbuffer/version.inc b/F1:F103/PL2303_ringbuffer/version.inc index 6ca1649..1f9f21d 100644 --- a/F1:F103/PL2303_ringbuffer/version.inc +++ b/F1:F103/PL2303_ringbuffer/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "72" -#define BUILD_DATE "2023-01-11" +#define BUILD_NUMBER "80" +#define BUILD_DATE "2023-06-11" diff --git a/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_prl b/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_prl index eb0e5ac..a6fa347 100644 --- a/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_prl +++ b/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_prl @@ -3,10 +3,12 @@ "active_layer": 0, "active_layer_preset": "All Copper Layers", "auto_track_width": true, + "hidden_netclasses": [], "hidden_nets": [], "high_contrast_mode": 0, "net_color_mode": 1, "opacity": { + "images": 0.6, "pads": 1.0, "tracks": 1.0, "vias": 1.0, @@ -62,7 +64,7 @@ 35, 36 ], - "visible_layers": "fffffff_ffffffff", + "visible_layers": "0001000_ffffffff", "zone_display_mode": 1 }, "meta": { diff --git a/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_pro b/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_pro index cb6eea1..887ef34 100644 --- a/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_pro +++ b/testboard/F0_F1_F3-LQFP48_testboard/stm32.kicad_pro @@ -1,5 +1,6 @@ { "board": { + "3dviewports": [], "design_settings": { "defaults": { "board_outline_line_width": 0.09999999999999999, @@ -137,7 +138,8 @@ "zones_allow_external_fillets": false, "zones_use_no_outline": true }, - "layer_presets": [] + "layer_presets": [], + "viewports": [] }, "boards": [], "cvpcb": { @@ -359,7 +361,7 @@ "net_settings": { "classes": [ { - "bus_width": 12.0, + "bus_width": 12, "clearance": 0.2, "diff_pair_gap": 0.25, "diff_pair_via_gap": 0.25, @@ -373,13 +375,15 @@ "track_width": 0.25, "via_diameter": 2.0, "via_drill": 0.6, - "wire_width": 6.0 + "wire_width": 6 } ], "meta": { - "version": 2 + "version": 3 }, - "net_colors": null + "net_colors": null, + "netclass_assignments": null, + "netclass_patterns": [] }, "pcbnew": { "last_paths": {