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 289405e..bf997e1 100755 Binary files a/F1:F103/F1_testbrd/pl2303.bin and b/F1:F103/F1_testbrd/pl2303.bin differ 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 ece1e8a..615b166 100755 Binary files a/F1:F103/PL2303_ringbuffer/PL2303.bin and b/F1:F103/PL2303_ringbuffer/PL2303.bin differ diff --git a/F1:F103/PL2303_ringbuffer/hardware.c b/F1:F103/PL2303_ringbuffer/hardware.c index 1df824e..7a78b04 100644 --- a/F1:F103/PL2303_ringbuffer/hardware.c +++ b/F1:F103/PL2303_ringbuffer/hardware.c @@ -19,13 +19,15 @@ #include "hardware.h" static inline void gpio_setup(){ - // Enable clocks to the GPIO subsystems (PB for ADC), turn on AFIO clocking to disable SWD/JTAG - RCC->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": {