diff --git a/F0:F030,F042,F072/usbcan_relay/Makefile b/F0:F030,F042,F072/usbcan_relay/Makefile index 86f8a40..882090a 100644 --- a/F0:F030,F042,F072/usbcan_relay/Makefile +++ b/F0:F030,F042,F072/usbcan_relay/Makefile @@ -1,147 +1,10 @@ -BINARY = usbcan -BOOTPORT ?= /dev/ttyUSB0 -BOOTSPEED ?= 57600 -# MCU FAMILY -FAMILY = F0 +BINARY := usbcanrelay # MCU code -MCU = F042x6 -# hardware definitions -#DEFS += -DEBUG +MCU := F072xB # change this linking script depending on particular MCU model, -# for example, if you have STM32F103VBT6, you should write: -LDSCRIPT = stm32f042x6.ld +LDSCRIPT := stm32f0728.ld -INDEPENDENT_HEADERS= +DEFINES := -DUSB2_16 -FP_FLAGS ?= -msoft-float -ASM_FLAGS = -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0 -ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS) - -############################################################################### -# Executables -OPREFIX ?= /opt/bin/arm-none-eabi -#PREFIX ?= /usr/x86_64-pc-linux-gnu/arm-none-eabi/gcc-bin/7.3.0/arm-none-eabi -PREFIX ?= $(OPREFIX) - -RM := rm -f -RMDIR := rmdir -CC := $(PREFIX)-gcc -LD := $(PREFIX)-gcc -AR := $(PREFIX)-ar -AS := $(PREFIX)-as -OBJCOPY := $(OPREFIX)-objcopy -OBJDUMP := $(OPREFIX)-objdump -GDB := $(OPREFIX)-gdb -STFLASH := $(shell which st-flash) -STBOOT := $(shell which stm32flash) -DFUUTIL := $(shell which dfu-util) - -############################################################################### -# Source files -OBJDIR = mk -LDSCRIPT ?= $(BINARY).ld -SRC := $(wildcard *.c) -OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) -STARTUP = $(OBJDIR)/startup.o -OBJS += $(STARTUP) -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 -MD -D__thumb2__=1 -CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration -CFLAGS += -Wredundant-decls $(INCLUDE) -# -Wmissing-prototypes -Wstrict-prototypes -CFLAGS += -fno-common -ffunction-sections -fdata-sections - -############################################################################### -# Linker flags -LDFLAGS += --static -nostartfiles -#--specs=nano.specs -LDFLAGS += -L$(LIB_DIR) -LDFLAGS += -T$(LDSCRIPT) -LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map -LDFLAGS += -Wl,--gc-sections - -############################################################################### -# Used libraries -LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group -LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) - -DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) - -#.SUFFIXES: .elf .bin .hex .srec .list .map .images -#.SECONDEXPANSION: -#.SECONDARY: - -ELF := $(OBJDIR)/$(BINARY).elf -LIST := $(OBJDIR)/$(BINARY).list -BIN := $(BINARY).bin -HEX := $(BINARY).hex - -all: bin list - -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) $(ARCH_FLAGS) -o $@ -c $< - -$(OBJDIR)/%.o: %.c - @echo " CC $<" - $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< - -#$(OBJDIR)/%.d: %.c $(OBJDIR) -# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@ - -$(BIN): $(ELF) - @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) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF) - -clean: - @echo " CLEAN" - $(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map *.d - @rmdir $(OBJDIR) 2>/dev/null || true - -dfuboot: $(BIN) - @echo " LOAD $(BIN) THROUGH DFU" - $(DFUUTIL) -a0 -R -D $(BIN) -s 0x08000000 - -flash: $(BIN) - @echo " FLASH $(BIN)" - $(STFLASH) write $(BIN) 0x8000000 - -boot: $(BIN) - @echo " LOAD $(BIN) through bootloader" - $(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN) - -gentags: - CFLAGS="$(CFLAGS) $(DEFS)" geany -g $(BINARY).c.tags *[hc] 2>/dev/null - -.PHONY: clean flash boot gentags +include ../makefile.f0 +include ../../makefile.stm32 diff --git a/F0:F030,F042,F072/usbcan_relay/can.c b/F0:F030,F042,F072/usbcan_relay/can.c index 24bc8d5..b0f3118 100644 --- a/F0:F030,F042,F072/usbcan_relay/can.c +++ b/F0:F030,F042,F072/usbcan_relay/can.c @@ -20,6 +20,7 @@ #include "canproto.h" #include "hardware.h" #include "proto.h" +#include "usb.h" #include // memcpy @@ -107,6 +108,7 @@ void CAN_setup(uint16_t speed){ else if(speed > 3000) speed = 3000; oldspeed = speed; uint32_t tmout = 16000000; + DBG("Start CAN ini"); // Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx /* (1) Select AF mode (10) on PB8 and PB9 */ /* (2) AF4 for CAN signals */ @@ -129,8 +131,12 @@ void CAN_setup(uint16_t speed){ tmout = 16000000; while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK){ // Wait the init mode leaving IWDG->KR = IWDG_REFRESH; - if(--tmout == 0) break; + if(--tmout == 0){ + DBG("Can't enter CAN INIT mode"); + break; + } } + DBG("CAN initing"); // accept self ID at filter 0, ALL other at filters 1 and 2 CAN->FMR = CAN_FMR_FINIT; CAN->FA1R = CAN_FA1R_FACT0 | CAN_FA1R_FACT1 | CAN_FA1R_FACT2; @@ -147,14 +153,15 @@ void CAN_setup(uint16_t speed){ NVIC_SetPriority(CEC_CAN_IRQn, 0); NVIC_EnableIRQ(CEC_CAN_IRQn); can_status = CAN_READY; + DBG("CAN ready"); } void can_proc(){ #ifdef EBUG if(last_err_code){ - MSG("Error, ESR="); + USB_sendstr("Error, ESR="); printu(last_err_code); - NL(); + newline(); last_err_code = 0; } #endif @@ -167,12 +174,12 @@ void can_proc(){ } IWDG->KR = IWDG_REFRESH; if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS - SEND("\nToo much errors, restarting CAN!\n"); - SEND("Receive error counter: "); + USND("\nToo much errors, restarting CAN!"); + USB_sendstr("Receive error counter: "); printu((CAN->ESR & CAN_ESR_REC)>>24); - SEND("\nTransmit error counter: "); + USB_sendstr("\nTransmit error counter: "); printu((CAN->ESR & CAN_ESR_TEC)>>16); - SEND("\nLast error code: "); + USB_sendstr("\nLast error code: "); int lec = (CAN->ESR & CAN_ESR_LEC) >> 4; const char *errmsg = "No"; switch(lec){ @@ -184,11 +191,10 @@ void can_proc(){ case 6: errmsg = "CRC"; break; case 7: errmsg = "(set by software)"; break; } - SEND(errmsg); SEND(" error\n"); - if(CAN->ESR & CAN_ESR_BOFF) SEND("Bus off"); - if(CAN->ESR & CAN_ESR_EPVF) SEND("Passive error limit"); - if(CAN->ESR & CAN_ESR_EWGF) SEND("Error counter limit"); - NL(); + USB_sendstr(errmsg); USND(" error\n"); + if(CAN->ESR & CAN_ESR_BOFF) USND("Bus off"); + if(CAN->ESR & CAN_ESR_EPVF) USND("Passive error limit"); + if(CAN->ESR & CAN_ESR_EWGF) USND("Error counter limit"); IWDG->KR = IWDG_REFRESH; // request abort for all mailboxes CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2; @@ -214,13 +220,13 @@ CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){ return CAN_BUSY; } #ifdef EBUG - MSG("Send data. Len="); printu(len); - SEND(", tagid="); printuhex(target_id); - SEND(", data="); + USB_sendstr("Send data. Len="); printu(len); + USB_sendstr(", tagid="); printuhex(target_id); + USB_sendstr(", data="); for(int i = 0; i < len; ++i){ - SEND(" "); printuhex(msg[i]); + USB_sendstr(" "); printuhex(msg[i]); } - NL(); + newline(); #endif CAN_TxMailBox_TypeDef *box = &CAN->sTxMailBox[mailbox]; uint32_t lb = 0, hb = 0; diff --git a/F0:F030,F042,F072/usbcan_relay/canproto.c b/F0:F030,F042,F072/usbcan_relay/canproto.c index 46ab9c2..bda0a65 100644 --- a/F0:F030,F042,F072/usbcan_relay/canproto.c +++ b/F0:F030,F042,F072/usbcan_relay/canproto.c @@ -21,6 +21,7 @@ #include "canproto.h" #include "hardware.h" #include "proto.h" +#include "usb.h" /* * Protocol (endian format depends on command!): @@ -130,11 +131,11 @@ TRUE_INLINE uint8_t showTms(uint8_t data[8]){ void parseCANcommand(CAN_message *msg){ uint8_t outpdata[8], len = 0; #ifdef EBUG - SEND("Get data: "); + USB_sendstr("Get data: "); for(int i = 0; i < msg->length; ++i){ - printuhex(msg->data[i]); bufputchar(' '); + printuhex(msg->data[i]); USB_putbyte(' '); } - NL(); + newline(); #endif int N = 1000; uint8_t cmd = msg->data[0] & CANCMDMASK, setter = msg->data[0] & CAN_CMD_SETFLAG; diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.cflags b/F0:F030,F042,F072/usbcan_relay/canrelay.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.config b/F0:F030,F042,F072/usbcan_relay/canrelay.config new file mode 100644 index 0000000..0402e5c --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.config @@ -0,0 +1,5 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG +#define STM32F0 +#define STM32F042x6 diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.creator b/F0:F030,F042,F072/usbcan_relay/canrelay.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.creator @@ -0,0 +1 @@ +[General] diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user new file mode 100644 index 0000000..e683830 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user @@ -0,0 +1,179 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + 0 + false + false + false + 1 + true + true + 0 + 8 + true + false + 2 + true + true + true + *.md, *.MD, Makefile + true + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 4 + false + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /tmp/STM32/usbcan_relay + + + + 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 + + true + true + true + + 2 + + false + -e cpu-cycles --call-graph dwarf,4096 -F 250 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.22 b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.22 new file mode 100644 index 0000000..c38778f --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.22 @@ -0,0 +1,165 @@ + + + + + + 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 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + false + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /Big/Data/00__Electronics/STM32/F0-nolib/usbcdc + + + + all + + false + + + false + true + Сборка + + GenericProjectManager.GenericMakeStep + + 1 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + + clean + + false + + + false + true + Сборка + + GenericProjectManager.GenericMakeStep + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + По умолчанию + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Развёртывание + + ProjectExplorer.BuildSteps.Deploy + + 1 + Конфигурация развёртывания + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + + Особая программа + + ProjectExplorer.CustomExecutableRunConfiguration + + 3768 + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.4.9-pre1 b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.4.9-pre1 new file mode 100644 index 0000000..d1e7562 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.4.9-pre1 @@ -0,0 +1,170 @@ + + + + + + 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 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + false + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /tmp/usbcan + + + + all + + false + + + false + true + Сборка + + GenericProjectManager.GenericMakeStep + + 1 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + + clean + + false + + + false + true + Сборка + + GenericProjectManager.GenericMakeStep + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + По умолчанию + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Установка + + ProjectExplorer.BuildSteps.Deploy + + 1 + Конфигурация установки + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + 2 + + + Особая программа + + ProjectExplorer.CustomExecutableRunConfiguration + + 3768 + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.7bd84e3 b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.7bd84e3 new file mode 100644 index 0000000..196ab73 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.creator.user.7bd84e3 @@ -0,0 +1,160 @@ + + + + + + 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 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + false + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} + 0 + 0 + 0 + + /Big/Data/00__Electronics/STM32/F0-nolib/usbcdc + + + + all + + false + + + false + true + GenericProjectManager.GenericMakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + clean + + false + + + false + true + GenericProjectManager.GenericMakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + + ProjectExplorer.CustomExecutableRunConfiguration + + + false + + false + true + false + false + true + + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.cxxflags b/F0:F030,F042,F072/usbcan_relay/canrelay.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.files b/F0:F030,F042,F072/usbcan_relay/canrelay.files new file mode 100644 index 0000000..45287ee --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.files @@ -0,0 +1,20 @@ +adc.c +adc.h +buttons.c +buttons.h +can.c +can.h +canproto.c +canproto.h +custom_buttons.c +custom_buttons.h +hardware.c +hardware.h +main.c +proto.c +proto.h +usb.c +usb.h +usb_defs.h +usb_lib.c +usb_lib.h diff --git a/F0:F030,F042,F072/usbcan_relay/canrelay.includes b/F0:F030,F042,F072/usbcan_relay/canrelay.includes new file mode 100644 index 0000000..641fd56 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/canrelay.includes @@ -0,0 +1,4 @@ +. +../inc +../inc/Fx +../inc/cm diff --git a/F0:F030,F042,F072/usbcan_relay/hardware.c b/F0:F030,F042,F072/usbcan_relay/hardware.c index fd2c7ae..e9c730d 100644 --- a/F0:F030,F042,F072/usbcan_relay/hardware.c +++ b/F0:F030,F042,F072/usbcan_relay/hardware.c @@ -94,55 +94,33 @@ void pause_ms(uint32_t pause){ while(Tms < Tnxt) nop(); } +#ifndef STM32F072xB +#warning "Only F072 can jump to bootloader" +#endif -#ifdef EBUG -void Jump2Boot(){ - __disable_irq(); - IWDG->KR = IWDG_REFRESH; +void Jump2Boot(){ // for STM32F072 void (*SysMemBootJump)(void); - volatile uint32_t addr = SystemMem; + volatile uint32_t addr = 0x1FFFC800; // reset systick SysTick->CTRL = 0; // reset clocks RCC->APB1RSTR = RCC_APB1RSTR_CECRST | RCC_APB1RSTR_DACRST | RCC_APB1RSTR_PWRRST | RCC_APB1RSTR_CRSRST | RCC_APB1RSTR_CANRST | RCC_APB1RSTR_USBRST | RCC_APB1RSTR_I2C2RST | RCC_APB1RSTR_I2C1RST | RCC_APB1RSTR_USART4RST | RCC_APB1RSTR_USART3RST | RCC_APB1RSTR_USART2RST | RCC_APB1RSTR_SPI2RST | - RCC_APB1RSTR_WWDGRST | RCC_APB1RSTR_TIM14RST | -#ifdef STM32F072xB - RCC_APB1RSTR_TIM7RST | RCC_APB1RSTR_TIM6RST | -#endif + RCC_APB1RSTR_WWDGRST | RCC_APB1RSTR_TIM14RST | RCC_APB1RSTR_TIM7RST | RCC_APB1RSTR_TIM6RST | RCC_APB1RSTR_TIM3RST | RCC_APB1RSTR_TIM2RST; - RCC->APB2RSTR = RCC_APB2RSTR_DBGMCURST | RCC_APB2RSTR_TIM17RST | RCC_APB2RSTR_TIM16RST | -#ifdef STM32F072xB - RCC_APB2RSTR_TIM15RST | -#endif + RCC->APB2RSTR = RCC_APB2RSTR_DBGMCURST | RCC_APB2RSTR_TIM17RST | RCC_APB2RSTR_TIM16RST | RCC_APB2RSTR_TIM15RST | RCC_APB2RSTR_USART1RST | RCC_APB2RSTR_SPI1RST | RCC_APB2RSTR_TIM1RST | RCC_APB2RSTR_ADCRST | RCC_APB2RSTR_SYSCFGRST; RCC->AHBRSTR = 0; RCC->APB1RSTR = 0; RCC->APB2RSTR = 0; - // enable SYSCFG clocking + // Enable the SYSCFG peripheral. RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; - __DSB(); - // remap system flash memory to 0 (only for STM32F0) + // remap memory to 0 (only for STM32F0) SYSCFG->CFGR1 = 0x01; __DSB(); __ISB(); SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); // set main stack pointer __set_MSP(*((uint32_t *)addr)); - IWDG->KR = IWDG_REFRESH; - // due to "empty check" mechanism, STM32F042 can jump to bootloader only with empty first 4 bytes of user code - while ((FLASH->SR & FLASH_SR_BSY) != 0){} - FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; - if ((FLASH->CR & FLASH_CR_LOCK) != 0){ - FLASH->KEYR = FLASH_KEY1; - FLASH->KEYR = FLASH_KEY2; - } - FLASH->CR |= FLASH_CR_PER; - FLASH->AR = 0x08000000; // erase zero's page - FLASH->CR |= FLASH_CR_STRT; - while(!(FLASH->SR & FLASH_SR_EOP)); - FLASH->SR |= FLASH_SR_EOP; - FLASH->CR &= ~FLASH_CR_PER; - // jump to bootloader (don't work :( ) + // jump to bootloader SysMemBootJump(); } -#endif diff --git a/F0:F030,F042,F072/usbcan_relay/hardware.h b/F0:F030,F042,F072/usbcan_relay/hardware.h index 0fce465..3b94918 100644 --- a/F0:F030,F042,F072/usbcan_relay/hardware.h +++ b/F0:F030,F042,F072/usbcan_relay/hardware.h @@ -32,7 +32,7 @@ #define SYSMEM09x 0x1FFFD800 // define SystemMem to other in MAKEFILE #ifndef SystemMem -#define SystemMem SYSMEM04x +#define SystemMem SYSMEM07x #endif #define CONCAT(a,b) a ## b diff --git a/F0:F030,F042,F072/usbcan_relay/main.c b/F0:F030,F042,F072/usbcan_relay/main.c index 4fbb590..fcf7038 100644 --- a/F0:F030,F042,F072/usbcan_relay/main.c +++ b/F0:F030,F042,F072/usbcan_relay/main.c @@ -25,6 +25,8 @@ #include "usb.h" #include "usb_lib.h" +#define MAXSTRLEN 128 + volatile uint32_t Tms = 0; /* Called when systick fires */ @@ -32,43 +34,10 @@ void sys_tick_handler(void){ ++Tms; } -#define USBBUF 63 -// usb getline -static char *get_USB(){ - static char tmpbuf[USBBUF+1], *curptr = tmpbuf; - static int rest = USBBUF; - uint8_t x = USB_receive((uint8_t*)curptr); - if(!x) return NULL; - curptr[x] = 0; - if(x == 1 && *curptr == 0x7f){ // backspace - if(curptr > tmpbuf){ - --curptr; - USND("\b \b"); - } - return NULL; - } - USB_sendstr(curptr); // echo - if(curptr[x-1] == '\n'){ // || curptr[x-1] == '\r'){ - curptr = tmpbuf; - rest = USBBUF; - // omit empty lines - if(tmpbuf[0] == '\n') return NULL; - // and wrong empty lines - if(tmpbuf[0] == '\r' && tmpbuf[1] == '\n') return NULL; - return tmpbuf; - } - curptr += x; rest -= x; - if(rest <= 0){ // buffer overflow - curptr = tmpbuf; - rest = USBBUF; - } - return NULL; -} - int main(void){ + char inbuff[MAXSTRLEN]; uint8_t ctr, len; CAN_message *can_mesg; - char *txt; sysreset(); SysTick_Config(6000, 1); gpio_setup(); @@ -84,10 +53,8 @@ int main(void){ process_keys(); custom_buttons_process(); can_proc(); - usb_proc(); if(CAN_get_status() == CAN_FIFO_OVERRUN){ - SEND("CAN bus fifo overrun occured!\n"); - sendbuf(); + USND("CAN bus fifo overrun occured!"); } while((can_mesg = CAN_messagebuf_pop())){ if(can_mesg && isgood(can_mesg->ID)){ @@ -95,20 +62,20 @@ int main(void){ IWDG->KR = IWDG_REFRESH; len = can_mesg->length; printu(Tms); - SEND(" #"); + USB_sendstr(" #"); printuhex(can_mesg->ID); for(ctr = 0; ctr < len; ++ctr){ - SEND(" "); + USB_putbyte(' '); printuhex(can_mesg->data[ctr]); } - newline(); sendbuf(); + newline(); } } } - if((txt = get_USB())){ - IWDG->KR = IWDG_REFRESH; - cmd_parser(txt); - } + int l = USB_receivestr(inbuff, MAXSTRLEN); + IWDG->KR = IWDG_REFRESH; + if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); + else if(l) cmd_parser(inbuff); } return 0; } diff --git a/F0:F030,F042,F072/usbcan_relay/proto.c b/F0:F030,F042,F072/usbcan_relay/proto.c index 9e5ee19..86cfd8c 100644 --- a/F0:F030,F042,F072/usbcan_relay/proto.c +++ b/F0:F030,F042,F072/usbcan_relay/proto.c @@ -22,6 +22,7 @@ #include "hardware.h" #include "proto.h" #include "usb.h" +#include "version.inc" #include // strlen @@ -30,30 +31,6 @@ extern volatile uint8_t canerror; uint8_t ShowMsgs = 0; uint16_t Ignore_IDs[IGN_SIZE]; uint8_t IgnSz = 0; -static char buff[BUFSZ+1], *bptr = buff; -static uint8_t blen = 0; - -void sendbuf(){ - IWDG->KR = IWDG_REFRESH; - if(blen == 0) return; - *bptr = 0; - USB_sendstr(buff); - bptr = buff; - blen = 0; -} - -void bufputchar(char ch){ - if(blen > BUFSZ-1){ - sendbuf(); - } - *bptr++ = ch; - ++blen; -} - -void addtobuf(const char *txt){ - IWDG->KR = IWDG_REFRESH; - while(*txt) bufputchar(*txt++); -} char *omit_spaces(const char *buf){ while(*buf){ @@ -148,7 +125,7 @@ static CAN_message *parseCANmsg(char *txt){ txt = n; if(ctr == -1){ if(N > 0x7ff){ - SEND("ID should be 11-bit number!\n"); + USND("ID should be 11-bit number!"); return NULL; } canmsg.ID = (uint16_t)(N&0x7ff); @@ -157,21 +134,20 @@ static CAN_message *parseCANmsg(char *txt){ continue; } if(ctr > 7){ - SEND("ONLY 8 data bytes allowed!\n"); + USND("ONLY 8 data bytes allowed!"); return NULL; } if(N > 0xff){ - SEND("Every data portion is a byte!\n"); + USND("Every data portion is a byte!"); return NULL; } canmsg.data[ctr++] = (uint8_t)(N&0xff); }while(1); if(canmsg.ID == 0xffff){ - SEND("NO ID given, send nothing!\n"); + USND("NO ID given, send nothing!"); return NULL; } - SEND("Message parsed OK\n"); - sendbuf(); + USND("Message parsed OK"); canmsg.length = (uint8_t) ctr; return &canmsg; } @@ -191,55 +167,55 @@ TRUE_INLINE void CANini(char *txt){ uint32_t N; char *n = getnum(txt, &N); if(txt == n){ - SEND("No speed given"); + USND("No speed given"); return; } if(N < 50){ - SEND("Lowest speed is 50kbps"); + USND("Lowest speed is 50kbps"); return; }else if(N > 3000){ - SEND("Highest speed is 3000kbps"); + USND("Highest speed is 3000kbps"); return; } CAN_reinit((uint16_t)N); - SEND("Reinit CAN bus with speed "); - printu(N); SEND("kbps"); + USB_sendstr("Reinit CAN bus with speed "); + printu(N); USND("kbps"); } TRUE_INLINE void addIGN(char *txt){ if(IgnSz == IGN_SIZE){ - MSG("Ignore buffer is full"); + DBG("Ignore buffer is full"); return; } txt = omit_spaces(txt); uint32_t N; char *n = getnum(txt, &N); if(txt == n){ - SEND("No ID given"); + USND("No ID given"); return; } if(N == CANID){ - SEND("You can't ignore self ID!"); + USND("You can't ignore self ID!"); return; } if(N > 0x7ff){ - SEND("ID should be 11-bit number!"); + USND("ID should be 11-bit number!"); return; } Ignore_IDs[IgnSz++] = (uint16_t)(N & 0x7ff); - SEND("Added ID "); printu(N); - SEND("\nIgn buffer size: "); printu(IgnSz); + USB_sendstr("Added ID "); printu(N); + USB_sendstr("\nIgn buffer size: "); printu(IgnSz); newline(); } TRUE_INLINE void print_ign_buf(){ if(IgnSz == 0){ - SEND("Ignore buffer is empty"); + USND("Ignore buffer is empty"); return; } - SEND("Ignored IDs:\n"); + USND("Ignored IDs:"); for(int i = 0; i < IgnSz; ++i){ printu(i); - SEND(": "); + USB_sendstr(": "); printuhex(Ignore_IDs[i]); newline(); } @@ -267,29 +243,29 @@ TRUE_INLINE void list_filters(){ uint32_t fa = CAN->FA1R, ctr = 0, mask = 1; while(fa){ if(fa & 1){ - SEND("Filter "); printu(ctr); SEND(", FIFO"); - if(CAN->FFA1R & mask) SEND("1"); - else SEND("0"); - SEND(" in "); + USB_sendstr("Filter "); printu(ctr); USB_sendstr(", FIFO"); + if(CAN->FFA1R & mask) USB_putbyte('1'); + else USB_putbyte('0'); + USB_sendstr(" in "); if(CAN->FM1R & mask){ // up to 4 filters in LIST mode - SEND("LIST mode, IDs: "); + USB_sendstr("LIST mode, IDs: "); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff); - SEND(" "); + USB_sendstr(" "); printID(CAN->sFilterRegister[ctr].FR1 >> 16); - SEND(" "); + USB_sendstr(" "); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff); - SEND(" "); + USB_sendstr(" "); printID(CAN->sFilterRegister[ctr].FR2 >> 16); }else{ // up to 2 filters in MASK mode - SEND("MASK mode: "); + USB_sendstr("MASK mode: "); if(!(CAN->sFilterRegister[ctr].FR1&0x1f)){ - SEND("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff); - SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16); - SEND(" "); + USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff); + USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16); + USB_sendstr(" "); } if(!(CAN->sFilterRegister[ctr].FR2&0x1f)){ - SEND("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff); - SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16); + USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff); + USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16); } } newline(); @@ -298,7 +274,6 @@ TRUE_INLINE void list_filters(){ ++ctr; mask <<= 1; } - sendbuf(); } /** @@ -315,18 +290,19 @@ static void add_filter(char *str){ str = omit_spaces(str); char *n = getnum(str, &N); if(n == str){ - SEND("No bank# given"); + USND("No bank# given"); return; } if(N == 0 || N > STM32F0FBANKNO-1){ - SEND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!"); + USND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!"); return; } uint8_t bankno = (uint8_t)N; str = omit_spaces(n); if(!*str){ // deactivate filter - SEND("Deactivate filters in bank "); + USB_sendstr("Deactivate filters in bank "); printu(bankno); + newline(); CAN->FMR = CAN_FMR_FINIT; CAN->FA1R &= ~(1<FMR &=~ CAN_FMR_FINIT; @@ -335,7 +311,7 @@ static void add_filter(char *str){ uint8_t fifono = 0; if(*str == '1') fifono = 1; else if(*str != '0'){ - SEND("FIFO# is 0 or 1"); + USND("FIFO# is 0 or 1"); return; } str = omit_spaces(str + 1); @@ -343,7 +319,7 @@ static void add_filter(char *str){ uint8_t mode = 0; // ID if(c == 'M' || c == 'm') mode = 1; else if(c != 'I' && c != 'i'){ - SEND("mode is 'M/m' for MASK and 'I/i' for IDLIST"); + USND("mode is 'M/m' for MASK and 'I/i' for IDLIST"); return; } str = omit_spaces(str + 1); @@ -356,11 +332,11 @@ static void add_filter(char *str){ str = omit_spaces(n); } if(nfilt == 0){ - SEND("You should add at least one filter!"); + USND("You should add at least one filter!"); return; } if(mode && (nfilt&1)){ - SEND("In MASK mode you should point pairs of ID/MASK"); + USND("In MASK mode you should point pairs of ID/MASK"); return; } CAN->FMR = CAN_FMR_FINIT; @@ -389,8 +365,8 @@ static void add_filter(char *str){ CAN->sFilterRegister[bankno].FR1 = (F1 & 0xffff0000) | (filters[0] << 5); } CAN->FMR &=~ CAN_FMR_FINIT; - SEND("Added filter with "); - printu(nfilt); SEND(" parameters"); + USB_sendstr("Added filter with "); + printu(nfilt); USND(" parameters"); } /** @@ -402,13 +378,13 @@ static void ledsOp(const char *str, uint8_t state){ uint32_t N; char *x = getnum(str, &N); if(!x || x == str || N > LEDSNO - 1){ - SEND("Wrong LED number\n"); + USND("Wrong LED number\n"); return; } if(state) LED_on(N); else LED_off(N); - SEND("LED"); printu(N); SEND(" is "); - if(state) SEND("on"); else SEND("off"); + USB_sendstr("LED"); printu(N); USB_sendstr(" is "); + if(state) USND("on"); else USND("off"); } // print current buttons state @@ -418,9 +394,9 @@ TRUE_INLINE void getBtnState(){ uint32_t T; keyevent e = keystate(i, &T); if(e != EVT_NONE){ - SEND("The key "); printu(i); - SEND(" is "); addtobuf(states[e]); SEND(" at "); - printu(T); NL(); + USB_sendstr("The key "); printu(i); + USB_sendstr(" is "); USB_sendstr(states[e]); USB_sendstr(" at "); + printu(T); newline(); } } } @@ -428,13 +404,12 @@ TRUE_INLINE void getBtnState(){ TRUE_INLINE void getPWM(){ volatile uint32_t *reg = &TIM1->CCR1; for(int n = 0; n < 3; ++n){ - SEND("PWM"); - bufputchar('0' + n); - bufputchar('='); + USB_sendstr("PWM"); + USB_putbyte('0' + n); + USB_putbyte('='); printu(*reg++); - bufputchar('\n'); + newline(); } - sendbuf(); } TRUE_INLINE void changePWM(char *str){ @@ -442,34 +417,33 @@ TRUE_INLINE void changePWM(char *str){ uint32_t N, pwm; char *nxt = getnum(str, &N); if(nxt == str || N > 2){ - SEND("Nch = 0..2"); + USND("Nch = 0..2"); return; } str = omit_spaces(nxt); nxt = getnum(str, &pwm); if(nxt == str || pwm > 255){ - SEND("PWM should be from 0 to 255"); + USND("PWM should be from 0 to 255"); return; } volatile uint32_t *reg = &TIM1->CCR1; reg[N] = pwm; - SEND("OK, changed"); + USND("OK, changed"); } TRUE_INLINE void printADC(){ // show all 4 channels ADC for(int i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i){ - SEND("ADC"); bufputchar('0' + i); bufputchar('='); - printu(getADCval(i)); bufputchar('\n'); + USB_sendstr("ADC"); USB_putbyte('0' + i); USB_putbyte('='); + printu(getADCval(i)); newline(); } - sendbuf(); } TRUE_INLINE void printVT(){ // show T and Vdd int32_t t = getMCUtemp(); - SEND("T="); - if(t < 0){ bufputchar('-'); t = -t; } - printu(t); SEND("/10degC\nVDD="); - printu(getVdd()); SEND("/100V"); + USB_sendstr("T="); + if(t < 0){ USB_putbyte('-'); t = -t; } + printu(t); USB_sendstr("/10degC\nVDD="); + printu(getVdd()); USND("/100V"); } // set or check relay(N) state @@ -481,10 +455,36 @@ TRUE_INLINE void relayX(uint8_t N, const char *txt){ if(b && b != txt && sr < 2){ if(sr) Relay_ON(N); else Relay_OFF(N); } - SEND("Relay"); bufputchar('0'+N); bufputchar('='); - bufputchar('0' + Relay_chk(N)); + USB_sendstr("Relay"); USB_putbyte('0'+N); USB_putbyte('='); + USB_putbyte('0' + Relay_chk(N)); newline(); } +static const char *helpmsg = +"https://github.com/eddyem/stm32samples/tree/master/F0-nolib/usbcan_relay build#" BUILD_NUMBER " @ " BUILD_DATE "\n" +"'0' - turn relay0 on(1) or off(0)\n" +"'1' - turn relay1 on(1) or off(0)\n" +"'a' - add ID to ignore list (max 10 IDs)\n" +"'A' - get ADC values @ all 4 channels\n" +"'b' - get buttons' state\n" +"'C' - reinit CAN with given baudrate\n" +"'d' - delete ignore list\n" +"'D' - activate DFU mode\n" +"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n" +"'F' - send/clear flood message: F ID byte0 ... byteN\n" +"'I' - read CAN ID\n" +"'l' - list all active filters\n" +"'m' - get MCU temp & Vdd\n" +"'o' - turn nth LED OFF\n" +"'O' - turn nth LED ON\n" +"'p' - print ignore buffer\n" +"'P' - pause/resume in packets displaying\n" +"'R' - software reset\n" +"'s/S' - send data over CAN: s ID byte0 .. byteN\n" +"'T' - get time from start (ms)\n" +"'w' - get PWM settings\n" +"'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n" +; + /** * @brief cmd_parser - command parsing * @param txt - buffer with commands & data @@ -550,15 +550,13 @@ void cmd_parser(char *txt){ case 'd': IgnSz = 0; break; -#ifdef EBUG case 'D': - SEND("Go into DFU mode\n"); - sendbuf(); + USND("Go into DFU mode\n"); + USB_sendall(); Jump2Boot(); break; -#endif case 'I': - SEND("CAN ID: "); printuhex(CANID); + USB_sendstr("CAN ID: "); printuhex(CANID); break; case 'l': list_filters(); @@ -571,17 +569,17 @@ void cmd_parser(char *txt){ break; case 'P': ShowMsgs = !ShowMsgs; - if(ShowMsgs) SEND("Resume\n"); - else SEND("Pause\n"); + if(ShowMsgs) USND("Resume"); + else USND("Pause"); break; case 'R': - SEND("Soft reset\n"); - sendbuf(); + USND("Soft reset"); + USB_sendall(); pause_ms(5); // a little pause to transmit data NVIC_SystemReset(); break; case 'T': - SEND("Time (ms): "); + USB_sendstr("Time (ms): "); printu(Tms); break; case 'w': @@ -589,37 +587,11 @@ void cmd_parser(char *txt){ return; break; default: // help - SEND( - "'0' - turn relay0 on(1) or off(0)\n" - "'1' - turn relay1 on(1) or off(0)\n" - "'a' - add ID to ignore list (max 10 IDs)\n" - "'A' - get ADC values @ all 4 channels\n" - "'b' - get buttons' state\n" - "'C' - reinit CAN with given baudrate\n" - "'d' - delete ignore list\n" - #ifdef EBUG - "'D' - activate DFU mode\n" - #endif - "'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n" - "'F' - send/clear flood message: F ID byte0 ... byteN\n" - "'I' - read CAN ID\n" - "'l' - list all active filters\n" - "'m' - get MCU temp & Vdd\n" - "'o' - turn nth LED OFF\n" - "'O' - turn nth LED ON\n" - "'p' - print ignore buffer\n" - "'P' - pause/resume in packets displaying\n" - "'R' - software reset\n" - "'s/S' - send data over CAN: s ID byte0 .. byteN\n" - "'T' - get time from start (ms)\n" - "'w' - get PWM settings\n" - "'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n" - ); + USND(helpmsg); break; } eof: newline(); - sendbuf(); } // print 32bit unsigned int @@ -634,12 +606,12 @@ void printu(uint32_t val){ val /= 10; } } - addtobuf(bufptr); + USB_sendstr(bufptr); } // print 32bit unsigned int as hex void printuhex(uint32_t val){ - addtobuf("0x"); + USB_sendstr("0x"); uint8_t *ptr = (uint8_t*)&val + 3; int8_t i, j, z=1; for(i = 0; i < 4; ++i, --ptr){ @@ -650,8 +622,8 @@ void printuhex(uint32_t val){ else z = 0; for(j = 1; j > -1; --j){ uint8_t half = (*ptr >> (4*j)) & 0x0f; - if(half < 10) bufputchar(half + '0'); - else bufputchar(half - 10 + 'a'); + if(half < 10) USB_putbyte(half + '0'); + else USB_putbyte(half - 10 + 'a'); } } } diff --git a/F0:F030,F042,F072/usbcan_relay/proto.h b/F0:F030,F042,F072/usbcan_relay/proto.h index 57d99b0..724b691 100644 --- a/F0:F030,F042,F072/usbcan_relay/proto.h +++ b/F0:F030,F042,F072/usbcan_relay/proto.h @@ -24,30 +24,14 @@ #define BUFSZ (64) -// macro for static strings -#define SEND(str) do{addtobuf(str);}while(0) - -#ifdef EBUG -#define MSG(str) do{addtobuf(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) -#else -#define MSG(str) -#endif - -#define newline() do{bufputchar('\n');}while(0) -// newline with buffer sending over USART -#define NL() do{bufputchar('\n'); sendbuf();}while(0) - #define IGN_SIZE 10 extern uint16_t Ignore_IDs[IGN_SIZE]; extern uint8_t IgnSz; extern uint8_t ShowMsgs; void cmd_parser(char *buf); -void addtobuf(const char *txt); -void bufputchar(char ch); void printu(uint32_t val); void printuhex(uint32_t val); -void sendbuf(); char *omit_spaces(const char *buf); char *getnum(const char *buf, uint32_t *N); diff --git a/F0:F030,F042,F072/usbcan_relay/ringbuffer.c b/F0:F030,F042,F072/usbcan_relay/ringbuffer.c new file mode 100644 index 0000000..d70a9a7 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/ringbuffer.c @@ -0,0 +1,124 @@ +/* + * This file is part of the pl2303 project. + * Copyright 2022 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/F0:F030,F042,F072/usbcan_relay/ringbuffer.h b/F0:F030,F042,F072/usbcan_relay/ringbuffer.h new file mode 100644 index 0000000..2c04863 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/ringbuffer.h @@ -0,0 +1,39 @@ +/* + * This file is part of the pl2303 project. + * Copyright 2022 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 +#ifndef RINGBUFFER_H__ +#define RINGBUFFER_H__ + +#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); + +#endif // RINGBUFFER_H__ diff --git a/F0:F030,F042,F072/usbcan_relay/usb.c b/F0:F030,F042,F072/usbcan_relay/usb.c index 68c909c..9a83e16 100644 --- a/F0:F030,F042,F072/usbcan_relay/usb.c +++ b/F0:F030,F042,F072/usbcan_relay/usb.c @@ -1,6 +1,6 @@ /* - * This file is part of the canrelay project. - * Copyright 2021 Edward V. Emelianov . + * This file is part of the usbcanrb 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,160 +16,111 @@ * along with this program. If not, see . */ +#include + +#include "hardware.h" #include "usb.h" #include "usb_lib.h" -static 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; -// 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_setup(){ - RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB - RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB - RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 - uint32_t tmout = 16000000; - while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;} - FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; - CRS->CFGR &= ~CRS_CFGR_SYNCSRC; - CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source - CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim - CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only - RCC->CFGR |= RCC_CFGR_SW; - // allow RESET and CTRM interrupts - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; - // clear flags - USB->ISTR = 0; - // and activate pullup - USB->BCDR |= USB_BCDR_DPPU; - NVIC_EnableIRQ(USB_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; } -// send zero-terminated string -void USB_sendstr(const char *str){ - uint16_t l = 0; - const char *ptr = str; - while(*ptr++) ++l; - USB_send((uint8_t*)str, l); -} - -// 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; - uint8_t sz = EP_Read(2, 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/F0:F030,F042,F072/usbcan_relay/usb.h b/F0:F030,F042,F072/usbcan_relay/usb.h index 29641f8..14512f2 100644 --- a/F0:F030,F042,F072/usbcan_relay/usb.h +++ b/F0:F030,F042,F072/usbcan_relay/usb.h @@ -1,6 +1,6 @@ /* - * This file is part of the canrelay project. - * Copyright 2021 Edward V. Emelianov . + * This file is part of the usbcanrb 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,21 +17,33 @@ */ #pragma once -#ifndef __USB_H__ -#define __USB_H__ -#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) -// send string with constant length -#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0) +#define 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_sendstr(const char *str); -void USB_send_blk(const uint8_t *buf, uint16_t len); -uint8_t USB_receive(uint8_t *buf); +#define STR_HELPER(s) #s +#define STR(s) STR_HELPER(s) -#endif // __USB_H__ +#ifdef EBUG +#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0) +#else +#define DBG(str) +#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/F0:F030,F042,F072/usbcan_relay/usb_lib.c b/F0:F030,F042,F072/usbcan_relay/usb_lib.c index 8209288..afa09af 100644 --- a/F0:F030,F042,F072/usbcan_relay/usb_lib.c +++ b/F0:F030,F042,F072/usbcan_relay/usb_lib.c @@ -1,6 +1,6 @@ /* - * This file is part of the canrelay project. - * Copyright 2021 Edward V. Emelianov . + * This file is part of the usbcanrb 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,21 @@ */ #include +#include "usb.h" #include "usb_lib.h" +#include "usbhw.h" ep_t endpoints[STM32ENDPOINTS]; -usb_dev_t USB_Dev; -uint8_t usbON = 0; +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]; +config_pack_t *setup_packet = (config_pack_t*) setupdatabuf; usb_LineCoding getLineCoding(){return lineCoding;} +volatile uint8_t usbON = 0; // device disconnected from terminal + // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor #define bcdUSB_L 0x10 #define bcdUSB_H 0x01 @@ -53,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 }; @@ -95,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 */ @@ -125,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-CAN relay module"); +_USB_STRING_(ID, u"canusb_relay"); +static void const *StringDescriptor[iDESCR_AMOUNT] = { + [iLANGUAGE_DESCR] = &LD, + [iMANUFACTURER_DESCR] = &MD, + [iPRODUCT_DESCR] = &PD, + [iSERIAL_DESCR] = &SD, + [iINTERFACE_DESCR] = &ID +}; + /* * default handlers @@ -148,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; @@ -163,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; @@ -198,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]); @@ -225,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; @@ -236,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; @@ -268,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){ @@ -284,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; @@ -300,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; @@ -309,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]); @@ -335,93 +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 - * !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! - * @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)()){ - 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); - 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); - lastaddr += rxsz; - // buffer size: Table127 of RM - USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; - endpoints[number].func = func; - return 0; -} - -// standard IRQ handler -void usb_isr(){ - if (USB->ISTR & USB_ISTR_RESET){ - // 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; // roll back to beginning of buffer - EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler); - // clear address, leave only enable bit - USB->DADDR = USB_DADDR_EF; - // state is default - wait for enumeration - USB_Dev.USB_Status = USB_STATE_DEFAULT; - } - 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, (uint8_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, (uint8_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_LPMODE; - USB->ISTR = ~USB_ISTR_SUSP; - } - if(USB->ISTR & USB_ISTR_WKUP){ // wakeup - USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE); // clear suspend flags - USB->ISTR = ~USB_ISTR_WKUP; - } -} - /** * Write data to EP buffer (called from IRQ handler) * @param number - EP number @@ -429,14 +377,24 @@ void usb_isr(){ * @param size - its size */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ - uint8_t i; - if(size > USB_TXBUFSZ) size = USB_TXBUFSZ; + 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; - for (i = 0; i < N2; i++){ +#if defined USB1_16 + // very bad: what if `size` is odd? + uint32_t *out = (uint32_t *)endpoints[number].tx_buf; + 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; } @@ -459,10 +417,22 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ * @return amount of data read */ int EP_Read(uint8_t number, uint8_t *buf){ - int n = endpoints[number].rx_cnt; - if(n){ - for(int i = 0; i < n; ++i) - buf[i] = endpoints[number].rx_buf[i]; - } - return n; + 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; + 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/F0:F030,F042,F072/usbcan_relay/usb_lib.h b/F0:F030,F042,F072/usbcan_relay/usb_lib.h index d6fc0cc..8bfe48a 100644 --- a/F0:F030,F042,F072/usbcan_relay/usb_lib.h +++ b/F0:F030,F042,F072/usbcan_relay/usb_lib.h @@ -1,6 +1,6 @@ /* - * This file is part of the canrelay project. - * Copyright 2021 Edward V. Emelianov . + * This file is part of the usbcanrb 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,11 +17,9 @@ */ #pragma once -#ifndef __USB_LIB_H__ -#define __USB_LIB_H__ #include -#include "usb_defs.h" +#include "usbhw.h" #define EP0DATABUF_SIZE (64) #define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) @@ -62,14 +60,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 +84,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, client connected -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 +112,6 @@ static const struct name \ \ } \ name = {0x04, 0x03, lng_id} -#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) // EP0 configuration packet typedef struct { @@ -127,20 +123,14 @@ typedef struct { } config_pack_t; // endpoints state -typedef struct __ep_t{ +typedef struct{ uint16_t *tx_buf; // transmission buffer address uint16_t txbufsz; // transmission buffer size uint8_t *rx_buf; // reception buffer address void (*func)(); // endpoint action function - uint16_t rx_cnt; // received data counter + 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,12 +155,12 @@ 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 config_pack_t *setup_packet; +extern uint8_t ep0databuf[], setupdatabuf[]; + +void EP0_Handler(); -void USB_Init(); -uint8_t USB_GetState(); -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, uint8_t *buf); @@ -180,5 +170,3 @@ 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/F0:F030,F042,F072/usbcan_relay/usbcan.bin b/F0:F030,F042,F072/usbcan_relay/usbcan.bin deleted file mode 100644 index 299e9c7..0000000 Binary files a/F0:F030,F042,F072/usbcan_relay/usbcan.bin and /dev/null differ diff --git a/F0:F030,F042,F072/usbcan_relay/usbcanrelay.bin b/F0:F030,F042,F072/usbcan_relay/usbcanrelay.bin new file mode 100755 index 0000000..abb8c3e Binary files /dev/null and b/F0:F030,F042,F072/usbcan_relay/usbcanrelay.bin differ diff --git a/F0:F030,F042,F072/usbcan_relay/usbhw.c b/F0:F030,F042,F072/usbcan_relay/usbhw.c new file mode 100644 index 0000000..345138c --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/usbhw.c @@ -0,0 +1,127 @@ +/* + * This file is part of the usbcanrb 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 "usb_lib.h" + +// here we suppose that all PIN settings done in hw_setup earlier +void USB_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB + RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB + RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 + uint32_t tmout = 16000000; + while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;} + FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; + CRS->CFGR &= ~CRS_CFGR_SYNCSRC; + CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source + CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim + CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only + RCC->CFGR |= RCC_CFGR_SW; + // allow RESET and WKUPM interrupts + USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; + // clear flags + USB->ISTR = 0; + // and activate pullup + USB->BCDR |= USB_BCDR_DPPU; + NVIC_EnableIRQ(USB_IRQn); +} + +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 (just rename it due to MCU model) +void usb_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_LPMODE; + USB->ISTR = ~USB_ISTR_SUSP; + } + if(USB->ISTR & USB_ISTR_WKUP){ // wakeup + USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE); // clear suspend flags + USB->ISTR = ~USB_ISTR_WKUP; + } +} + diff --git a/F0:F030,F042,F072/usbcan_relay/usb_defs.h b/F0:F030,F042,F072/usbcan_relay/usbhw.h similarity index 80% rename from F0:F030,F042,F072/usbcan_relay/usb_defs.h rename to F0:F030,F042,F072/usbcan_relay/usbhw.h index ba4e3c5..14d40d1 100644 --- a/F0:F030,F042,F072/usbcan_relay/usb_defs.h +++ b/F0:F030,F042,F072/usbcan_relay/usbhw.h @@ -1,6 +1,6 @@ /* - * This file is part of the canrelay project. - * Copyright 2021 Edward V. Emelianov . + * This file is part of the usbcanrb 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,8 +17,6 @@ */ #pragma once -#ifndef __USB_DEFS_H__ -#define __USB_DEFS_H__ #include @@ -27,8 +25,9 @@ /** * Buffers size definition **/ -// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! #define USB_BTABLE_SIZE 768 +// 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) @@ -39,6 +38,7 @@ #define USB_EP1BUFSZ 8 #define USB_BTABLE_BASE 0x40006000 +#define USB ((USB_TypeDef *) USB_BASE) #ifdef USB_BTABLE #undef USB_BTABLE @@ -73,7 +73,7 @@ #define USB_TypeDef USB_TypeDef_custom -typedef struct{ +typedef struct { __IO uint32_t EPnR[STM32ENDPOINTS]; __IO uint32_t RESERVED[STM32ENDPOINTS]; __IO uint32_t CNTR; @@ -85,15 +85,31 @@ typedef struct{ __IO uint32_t BCDR; } USB_TypeDef; +// F303 D/E have 2x16 access scheme 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; -#endif // __USB_DEFS_H__ +void USB_setup(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); diff --git a/F0:F030,F042,F072/usbcan_relay/version.inc b/F0:F030,F042,F072/usbcan_relay/version.inc new file mode 100644 index 0000000..79cbf24 --- /dev/null +++ b/F0:F030,F042,F072/usbcan_relay/version.inc @@ -0,0 +1,2 @@ +#define BUILD_NUMBER "9" +#define BUILD_DATE "2024-08-02" diff --git a/F3:F303/CANbus4BTA/kicad/stm32.kicad_pro b/F3:F303/CANbus4BTA/kicad/stm32.kicad_pro index 2f95bf7..295edf1 100644 --- a/F3:F303/CANbus4BTA/kicad/stm32.kicad_pro +++ b/F3:F303/CANbus4BTA/kicad/stm32.kicad_pro @@ -81,6 +81,7 @@ "footprint_type_mismatch": "error", "hole_clearance": "error", "hole_near_hole": "error", + "holes_co_located": "warning", "invalid_outline": "error", "isolated_copper": "warning", "item_on_disabled_layer": "error", @@ -541,7 +542,7 @@ "plot": "gerbers", "pos_files": "", "specctra_dsn": "", - "step": "", + "step": "../../../../../../tmp/kompas-3d/Datchik_tolschiny_plenki_ki.stp", "svg": "", "vrml": "" },