diff --git a/F0-nolib/Readme.md b/F0-nolib/Readme.md index 8c3bf0b..cc0c969 100644 --- a/F0-nolib/Readme.md +++ b/F0-nolib/Readme.md @@ -14,6 +14,7 @@ This directory contains examples for F0 without any library - QuadEncoder - sample code for working with quadrature encoder (via timer) - Servo - simple servo (like SG-90) controller - Snippets - some small code snippets +- Socket_fans - fan manager - TM1637 - work with 7-segment LED indicators based on TM1637 - tsys01_nucleo - read two TSYS01 sensors using STM32F042 - uart - USART over DMA with hardware end-of-string detection @@ -22,3 +23,4 @@ This directory contains examples for F0 without any library - uart_nucleo - USART over DMA for STM32F042-nucleo - usbcan - USB<>CAN bridge using PL2303 emulation - USBHID - USB HID keyboard + mouse +- USB_pl2303_snippet - full minimal snippet of PL2303 emulation for STM32F072xB diff --git a/F1-nolib/CDC_ACM/Makefile_old b/F1-nolib/CDC_ACM/Makefile_old deleted file mode 100644 index 66de9fb..0000000 --- a/F1-nolib/CDC_ACM/Makefile_old +++ /dev/null @@ -1,139 +0,0 @@ -BINARY = cdcacm -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 - -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) - -PLATFRM ?= -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) $(PLATFRM) $(INCLUDE) -o $@ -c $< - -$(OBJDIR)/%.o: %.c - @echo " CC $<" - $(CC) $(CFLAGS) $(DEFS) $(PLATFRM) $(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-nolib/CDC_ACM/Readme b/F1-nolib/CDC_ACM/Readme new file mode 100644 index 0000000..a96839b --- /dev/null +++ b/F1-nolib/CDC_ACM/Readme @@ -0,0 +1 @@ +Base CDC snippet diff --git a/F1-nolib/CDC_ACM/cdcacm.bin b/F1-nolib/CDC_ACM/cdcacm.bin index 46c7c54..cf38f7d 100755 Binary files a/F1-nolib/CDC_ACM/cdcacm.bin and b/F1-nolib/CDC_ACM/cdcacm.bin differ diff --git a/F1-nolib/CDC_ACM/hardware.c b/F1-nolib/CDC_ACM/hardware.c index 0132ea2..e7b6442 100644 --- a/F1-nolib/CDC_ACM/hardware.c +++ b/F1-nolib/CDC_ACM/hardware.c @@ -23,6 +23,12 @@ #include "hardware.h" +// pause in milliseconds for some purposes +void pause_ms(uint32_t pause){ + uint32_t Tnxt = Tms + pause; + while(Tms < Tnxt) nop(); +} + 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_IOPCEN | RCC_APB2ENR_AFIOEN; diff --git a/F1-nolib/CDC_ACM/hardware.h b/F1-nolib/CDC_ACM/hardware.h index 4115a34..465f8a4 100644 --- a/F1-nolib/CDC_ACM/hardware.h +++ b/F1-nolib/CDC_ACM/hardware.h @@ -40,6 +40,9 @@ #define LED_on(x) pin_clear(x ## _port, x ## _pin) #define LED_off(x) pin_set(x ## _port, x ## _pin) +extern volatile uint32_t Tms; + +void pause_ms(uint32_t pause); void hw_setup(); #endif // __HARDWARE_H__ diff --git a/F1-nolib/CDC_ACM/main.c b/F1-nolib/CDC_ACM/main.c index 4e24697..a74f585 100644 --- a/F1-nolib/CDC_ACM/main.c +++ b/F1-nolib/CDC_ACM/main.c @@ -20,7 +20,7 @@ */ #include "hardware.h" -#include "usart.h" +#include "proto.h" #include "usb.h" #include "usb_lib.h" @@ -53,81 +53,41 @@ void iwdg_setup(){ while(IWDG->SR){if(--tmout == 0) break;} /* (5) */ IWDG->KR = IWDG_REFRESH; /* (6) */ } -/* -char *parse_cmd(char *buf){ - IWDG->KR = IWDG_REFRESH; - if(buf[1] != '\n') return buf; - switch(*buf){ - case 'p': - pin_toggle(USBPU_port, USBPU_pin); - USB_send("USB pullup is "); - if(pin_read(USBPU_port, USBPU_pin)) USB_send("off\n"); - else USB_send("on\n"); - return NULL; - break; - case 'L': - USB_send("Very long test string for USB (it's length is more than 64 bytes).\n" - "This is another part of the string! Can you see all of this?\n"); - return "OK\n"; - break; - case 'R': - USB_send("Soft reset\n"); - NVIC_SystemReset(); - break; - case 'S': - USB_send("Test string for USB\n"); - return "OK\n"; - break; - case 'W': - USB_send("Wait for reboot\n"); - while(1){nop();}; - break; - default: // help - return - "'p' - toggle USB pullup\n" - "'L' - send long string over USB\n" - "'R' - software reset\n" - "'S' - send short string over USB\n" - "'W' - test watchdog\n" - ; - break; - } - return NULL; -}*/ - -/* -char *get_USB(){ - static char tmpbuf[65]; - int x = USB_receive(tmpbuf, 64); - tmpbuf[x] = 0; - if(!x) return NULL; - return tmpbuf; -} +#define USBBUF 63 // usb getline -char *get_USB(){ - static char tmpbuf[128], *curptr = tmpbuf; - static int rest = 127; - int x = USB_receive(curptr, rest); - curptr[x] = 0; +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; - if(curptr[x-1] == '\n'){ - //DBG("Got \\n"); + 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 = 127; + 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 - //DBG("Buffer full"); curptr = tmpbuf; - rest = 127; - return tmpbuf; + rest = USBBUF; } return NULL; -}*/ - +} +/* - these functions need for true USB-TTY static uint32_t newrate = 0; // redefine weak handlers void linecoding_handler(usb_LineCoding *lcd){ @@ -140,21 +100,6 @@ void clstate_handler(uint16_t val){ static int8_t br = 0; void break_handler(){ br = 1; -} -/* -char *u2str(uint32_t val){ - static char strbuf[11]; - char *bufptr = &strbuf[10]; - *bufptr = 0; - if(!val){ - *(--bufptr) = '0'; - }else{ - while(val){ - *(--bufptr) = val % 10 + '0'; - val /= 10; - } - } - return bufptr; }*/ int main(void){ @@ -162,54 +107,39 @@ int main(void){ sysreset(); StartHSE(); SysTick_Config(72000); - hw_setup(); + USBPU_OFF(); - usart_setup(); - DBG("Start"); - if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured +/* if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured SEND("WDGRESET=1"); newline(); } if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured SEND("SOFTRESET=1"); newline(); - } + }*/ RCC->CSR |= RCC_CSR_RMVF; // remove reset flags USB_setup(); iwdg_setup(); USBPU_ON(); - //uint32_t ctr = 0; while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog if(Tms - lastT > 499){ LED_blink(LED0); lastT = Tms; - transmit_tbuf(); } usb_proc(); - if(bufovr){ - bufovr = 0; - USB_send((uint8_t*)"USART overflow!\n", 16); - } - uint8_t tmpbuf[USB_RXBUFSZ], *txt; - uint8_t x = USB_receive(tmpbuf); - if(x){ - //for(int _ = 0; _ < 7000000; ++_)nop(); - //USB_send(tmpbuf, x); - usart_senddata(tmpbuf, x); - //transmit_tbuf(); - /*char *ans = parse_cmd(txt); - if(ans) USB_send(ans);*/ - } - if((x = usart_get(&txt))){ - USB_send(txt, x); + char *txt = get_USB(); + if(txt){ + IWDG->KR = IWDG_REFRESH; + cmd_parser(txt); } + /* int n = 0; if(newrate){SEND("new speed: "); printu(newrate); n = 1; newrate = 0;} if(cl!=0xffff){SEND("controls: "); printuhex(cl); n = 1; cl = 0xffff;} if(br){SEND("break"); n = 1; br = 0;} - if(n){newline(); transmit_tbuf();} + if(n){newline(); transmit_tbuf();}*/ } return 0; } diff --git a/F1-nolib/CDC_ACM/proto.c b/F1-nolib/CDC_ACM/proto.c new file mode 100644 index 0000000..03108dd --- /dev/null +++ b/F1-nolib/CDC_ACM/proto.c @@ -0,0 +1,205 @@ +/* + * geany_encoding=koi8-r + * proto.c + * + * Copyright 2018 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "hardware.h" +#include "proto.h" +#include "usb.h" + +#include // strlen + +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(char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return buf; +} + +// THERE'S NO OVERFLOW PROTECTION IN NUMBER READ PROCEDURES! +// read decimal number +static char *getdec(char *buf, uint32_t *N){ + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read hexadecimal number (without 0x prefix!) +static char *gethex(char *buf, uint32_t *N){ + 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){ + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return buf; +} +// read binary number (without 0b prefix!) +static char *getbin(char *buf, uint32_t *N){ + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + 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) + */ +char *getnum(char *txt, uint32_t *N){ + if(*txt == '0'){ + if(txt[1] == 'x' || txt[1] == 'X') return gethex(txt+2, N); + if(txt[1] == 'b' || txt[1] == 'B') return getbin(txt+2, N); + } + return getdec(txt, N); +} + +/** + * @brief cmd_parser - command parsing + * @param txt - buffer with commands & data + * @param isUSB - == 1 if data got from USB + */ +void cmd_parser(char *txt){ + char _1st = txt[0]; + /* + * parse long commands here + */ + /*switch(_1st){ + case 'a': + addIGN(txt + 1); + goto eof; + break; + }*/ + if(txt[1] != '\n') *txt = '?'; // help for wrong message length + switch(_1st){ + case 'R': + SEND("Soft reset\n"); + sendbuf(); + pause_ms(5); // a little pause to transmit data + NVIC_SystemReset(); + break; + case 'T': + SEND("Time (ms): "); + printu(Tms); + newline(); + break; + default: // help + SEND( + "'R' - software reset\n" + "'T' - get time from start (ms)\n" + ); + break; + } + newline(); + sendbuf(); +} + +// print 32bit unsigned int +void printu(uint32_t val){ + char buf[11], *bufptr = &buf[10]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + *(--bufptr) = val % 10 + '0'; + val /= 10; + } + } + addtobuf(bufptr); +} + +// print 32bit unsigned int as hex +void printuhex(uint32_t val){ + addtobuf("0x"); + 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) bufputchar(half + '0'); + else bufputchar(half - 10 + 'a'); + } + } +} + diff --git a/F1-nolib/CDC_ACM/proto.h b/F1-nolib/CDC_ACM/proto.h new file mode 100644 index 0000000..e979633 --- /dev/null +++ b/F1-nolib/CDC_ACM/proto.h @@ -0,0 +1,55 @@ +/* + * geany_encoding=koi8-r + * proto.h + * + * Copyright 2018 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __PROTO_H__ +#define __PROTO_H__ + +#include "stm32f1.h" +#include "hardware.h" + +#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) + +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(char *buf); +char *getnum(char *buf, uint32_t *N); + +#endif // __PROTO_H__ diff --git a/F1-nolib/CDC_ACM/usart.c b/F1-nolib/CDC_ACM/usart.c deleted file mode 100644 index d631476..0000000 --- a/F1-nolib/CDC_ACM/usart.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * usart.c - * - * Copyright 2018 Edward V. Emelianoff - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#include "stm32f1.h" -#include "usart.h" -#include "usb.h" - -extern volatile uint32_t Tms; -static volatile int idatalen[2] = {0,0}; // received data line length (including '\n') -static volatile int odatalen[2] = {0,0}; - -static int dlen = 0; // length of data (including '\n') in current buffer - -int linerdy = 0, // received data ready - bufovr = 0, // input buffer overfull - txrdy = 1 // transmission done -; - -static int rbufno = 0, tbufno = 0; // current rbuf/tbuf numbers -static uint8_t rbuf[2][UARTBUFSZI], tbuf[2][UARTBUFSZO]; // receive & transmit buffers -static uint8_t *recvdata = NULL; - -/** - * return length of received data (without trailing zero) - */ -uint16_t usart_get(uint8_t **line){ - if(!line) return 0; - *line = NULL; - if(bufovr){ - bufovr = 0; - linerdy = 0; - return 0; - } - if(!linerdy) return 0; - USART1->CR1 &= ~USART_CR1_RXNEIE; // disallow Rx IRQ - dlen = idatalen[rbufno]; - recvdata = rbuf[rbufno]; - // prepare other buffer - rbufno = !rbufno; - idatalen[rbufno] = 0; - recvdata[dlen] = 0; - *line = recvdata; - linerdy = 0; - USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ - return dlen; -} - -// transmit current tbuf and swap buffers -int transmit_tbuf(){ - uint32_t tmout = 7200; - while(!txrdy){ // wait for previos buffer transmission - IWDG->KR = IWDG_REFRESH; - if(--tmout == 0){ - //DMA1_Channel4->CCR &= ~DMA_CCR_EN; - //txrdy = 1; - return 1; - } - } - int l = odatalen[tbufno]; - if(!l){ - return 0; - } - DMA1_Channel4->CCR &= ~DMA_CCR_EN; - DMA1_Channel4->CMAR = (uint32_t) tbuf[tbufno]; // mem - DMA1_Channel4->CNDTR = l; - tbufno = !tbufno; - odatalen[tbufno] = 0; - txrdy = 0; - DMA1_Channel4->CCR |= DMA_CCR_EN; - return 0; -} - -void usart_putchar(const char ch){ - tbuf[tbufno][odatalen[tbufno]++] = ch; - if(odatalen[tbufno] >= UARTBUFSZO){ - while(transmit_tbuf()); - } -} - -void usart_send(const char *str){ - if(!str) return; - while(*str){ - tbuf[tbufno][odatalen[tbufno]++] = *str++; - if(odatalen[tbufno] >= UARTBUFSZO){ - while(transmit_tbuf()); - } - } -} - -/** - * @brief usart_senddata - the same as usart_send, but with given length - */ -void usart_senddata(const uint8_t *str, uint16_t len){ - while(len--){ - tbuf[tbufno][odatalen[tbufno]++] = *str++; - if(odatalen[tbufno] >= UARTBUFSZO){ - while(transmit_tbuf()); - } - } -} - -void newline(){ - usart_putchar('\n'); -} - -/* - * USART speed: baudrate = Fck/(USARTDIV) - * USARTDIV stored in USART->BRR - * - * for 72MHz USARTDIV=72000/f(kboud); so for 115200 USARTDIV=72000/115.2=625 -> BRR=0x271 - * 9600: BRR = 7500 (0x1D4C) - */ - -void usart_setup(){ - uint32_t tmout = 16000000; - // 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); - - // USART1 Tx DMA - Channel4 (Rx - channel 5) - DMA1_Channel4->CPAR = (uint32_t) &USART1->DR; // periph - DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq - // Tx CNDTR set @ each transmission due to data size - NVIC_SetPriority(DMA1_Channel4_IRQn, 3); - NVIC_EnableIRQ(DMA1_Channel4_IRQn); - NVIC_SetPriority(USART1_IRQn, 0); - // setup usart1 - USART1->BRR = 72000000 / 115200; - //USART1->BRR = 24; // 3000000 - USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART - while(!(USART1->SR & USART_SR_TC)){ // polling idle frame Transmission - IWDG->KR = IWDG_REFRESH; - if(--tmout == 0) break; - } - USART1->SR = 0; // clear flags - USART1->CR1 |= USART_CR1_RXNEIE; // allow Rx IRQ - USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx - NVIC_EnableIRQ(USART1_IRQn); -} - - -void usart1_isr(){ - #ifdef CHECK_TMOUT - static uint32_t tmout = 0; - #endif - if(USART1->SR & USART_SR_RXNE){ // RX not emty - receive next char - #ifdef CHECK_TMOUT - if(tmout && Tms >= tmout){ // set overflow flag - bufovr = 1; - idatalen[rbufno] = 0; - } - tmout = Tms + TIMEOUT_MS; - if(!tmout) tmout = 1; // prevent 0 - #endif - uint8_t rb = USART1->DR; - if(idatalen[rbufno] < UARTBUFSZI){ // put next char into buf - rbuf[rbufno][idatalen[rbufno]++] = rb; - linerdy = 1; // ready for reading - #ifdef CHECK_TMOUT - // clear timeout at line end - tmout = 0; - #endif - }else{ // buffer overrun - bufovr = 1; - idatalen[rbufno] = 0; - #ifdef CHECK_TMOUT - tmout = 0; - #endif - } - } -} - - -// print 32bit unsigned int -void printu(uint32_t val){ - char bufa[11], bufb[10]; - int l = 0, bpos = 0; - if(!val){ - bufa[0] = '0'; - l = 1; - }else{ - while(val){ - bufb[l++] = val % 10 + '0'; - val /= 10; - } - int i; - bpos += l; - for(i = 0; i < l; ++i){ - bufa[--bpos] = bufb[i]; - } - } - bufa[l + bpos] = 0; - usart_send(bufa); -} - -// print 32bit unsigned int as hex -void printuhex(uint32_t val){ - usart_send("0x"); - uint8_t *ptr = (uint8_t*)&val + 3; - int i, j; - for(i = 0; i < 4; ++i, --ptr){ - for(j = 1; j > -1; --j){ - register uint8_t half = (*ptr >> (4*j)) & 0x0f; - if(half < 10) usart_putchar(half + '0'); - else usart_putchar(half - 10 + 'a'); - } - } -} -/* -// dump memory buffer -void hexdump(const uint8_t *arr, uint16_t len){ - 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) usart_putchar(half + '0'); - else usart_putchar(half - 10 + 'a'); - } - if(l % 16 == 15) usart_putchar('\n'); - else if(l & 1) usart_putchar(' '); - } -} -*/ -void dma1_channel4_isr(){ - DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag - txrdy = 1; -} - -/* -#if USARTNUM == 2 -void dma1_channel4_5_isr(){ - if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx - DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag - txrdy = 1; - } -} -// USART1 -#elif USARTNUM == 1 -void dma1_channel2_3_isr(){ - if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx - DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag - txrdy = 1; - } -} -#else -#error "Not implemented" -#endif -*/ diff --git a/F1-nolib/CDC_ACM/usart.h b/F1-nolib/CDC_ACM/usart.h deleted file mode 100644 index e64ee73..0000000 --- a/F1-nolib/CDC_ACM/usart.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * usart.h - * - * Copyright 2018 Edward V. Emelianoff - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#pragma once -#ifndef __USART_H__ -#define __USART_H__ - -// input and output buffers size -#define UARTBUFSZI (64) -#define UARTBUFSZO (64) -// timeout between data bytes -#ifndef TIMEOUT_MS -#define TIMEOUT_MS (1500) -#endif - -// macro for static strings -#define SEND(str) usart_send(str) -#define _s(s) #s -#define STR(s) _s(s) - -#ifdef EBUG -#define DBG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0) -#define HERE() do{SEND(STR(__LINE__)); usart_putchar('\n');}while(0) -#define MSG(str) do{SEND(str); usart_putchar('\n');}while(0) -#else -#define MSG(str) -#define HERE() -#define DBG(str) -#endif - -#define usartrx() (linerdy) -#define usartovr() (bufovr) - -extern int linerdy, bufovr, txrdy; - -int transmit_tbuf(); -void usart_setup(); -uint16_t usart_get(uint8_t **line); -void usart_send(const char *str); -void usart_senddata(const uint8_t *str, uint16_t len); -void newline(); -void usart_putchar(const char ch); -void printu(uint32_t val); -void printuhex(uint32_t val); -void hexdump(const uint8_t *arr, uint16_t len); - -#endif // __USART_H__ diff --git a/F1-nolib/CDC_ACM/usb.c b/F1-nolib/CDC_ACM/usb.c index 3af52c9..7d42861 100644 --- a/F1-nolib/CDC_ACM/usb.c +++ b/F1-nolib/CDC_ACM/usb.c @@ -22,34 +22,20 @@ */ #include "usb.h" #include "usb_lib.h" -#include "usart.h" static volatile uint8_t tx_succesfull = 1; - -// interrupt IN handler (never used?) -static void EP1_Handler(){ - DBG("EP1"); - 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 uint8_t rxNE = 0; -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 + +static void rxtx_Handler(){ + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); + if(RX_FLAG(epstatus)){ + rxNE = 1; + epstatus = (epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_CTR_RX)) ^ USB_EPnR_STAT_RX; // keep stat Tx & set valid RX, clear CTR Rx + }else{ + tx_succesfull = 1; + epstatus = (epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; // keep stat Tx & set valid RX, clear CTR Tx + } + USB->EPnR[1] = epstatus; } void USB_setup(){ @@ -64,21 +50,21 @@ void USB_setup(){ USB->ISTR = 0; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); - DBG("USB irq enabled"); } + 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); + EP_Write(1, buf, l); ctra = 1000000; while(--ctra && tx_succesfull == 0){ IWDG->KR = IWDG_REFRESH; } - if(tx_succesfull == 0){usbON = 0; DBG("USB disconnected"); return 1;} // usb is OFF? + if(tx_succesfull == 0){usbON = 0; return 1;} // usb is OFF? return 0; } @@ -89,7 +75,7 @@ static uint8_t buflen = 0; // amount of symbols in usbbuff static void send_next(){ if(!buflen || !tx_succesfull) return; tx_succesfull = 0; - EP_Write(3, usbbuff, buflen); + EP_Write(1, usbbuff, buflen); buflen = 0; } @@ -107,6 +93,14 @@ void USB_send(const uint8_t *buf, uint16_t len){ while(len--) usbbuff[buflen++] = *buf++; } +// 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 @@ -132,16 +126,13 @@ void usb_proc(){ 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 + //EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit + EP_Init(1, EP_TYPE_BULK, USB_TXBUFSZ, USB_RXBUFSZ, rxtx_Handler); // INOUT1 - transmit/receive data USB_Dev.USB_Status = USB_STATE_CONNECTED; - DBG("Connected"); break; case USB_STATE_DEFAULT: case USB_STATE_ADDRESSED: if(usbON){ - DBG("def/adr"); usbON = 0; } break; @@ -158,11 +149,10 @@ void usb_proc(){ */ uint8_t USB_receive(uint8_t *buf){ if(!usbON || !rxNE) return 0; - //DBG("Get data"); - uint8_t sz = EP_Read(2, (uint16_t*)buf); - uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); + uint8_t sz = EP_Read(1, (uint16_t*)buf); + uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]); // keep stat_tx & set ACK rx - USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; + USB->EPnR[1] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; rxNE = 0; return sz; } diff --git a/F1-nolib/CDC_ACM/usb.h b/F1-nolib/CDC_ACM/usb.h index c9d315d..3c191ef 100644 --- a/F1-nolib/CDC_ACM/usb.h +++ b/F1-nolib/CDC_ACM/usb.h @@ -26,9 +26,13 @@ #include "hardware.h" +// send string with constant length +#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}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); diff --git a/F1-nolib/CDC_ACM/usb_lib.c b/F1-nolib/CDC_ACM/usb_lib.c index a25a31d..190ddd2 100644 --- a/F1-nolib/CDC_ACM/usb_lib.c +++ b/F1-nolib/CDC_ACM/usb_lib.c @@ -22,7 +22,6 @@ */ #include -#include "usart.h" #include "usb_lib.h" ep_t endpoints[STM32ENDPOINTS]; @@ -88,9 +87,7 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ 0x80, /* bmAttributes - Bus powered */ 0x32, /* MaxPower 100 mA */ - /*---------------------------------------------------------------------------*/ - /*Interface Descriptor */ 0x09, /* bLength: Interface Descriptor size */ 0x04, /* bDescriptorType: Interface */ @@ -101,44 +98,38 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x02, /* bInterfaceSubClass: Abstract Control Model */ 0x01, /* bInterfaceProtocol: Common AT commands */ 0x00, /* iInterface: */ - /*Header Functional Descriptor*/ 0x05, /* bLength: Endpoint Descriptor size */ 0x24, /* bDescriptorType: CS_INTERFACE */ 0x00, /* bDescriptorSubtype: Header Func Desc */ 0x10, /* bcdCDC: spec release number */ 0x01, - /*Call Management Functional Descriptor*/ 0x05, /* bFunctionLength */ 0x24, /* bDescriptorType: CS_INTERFACE */ 0x01, /* bDescriptorSubtype: Call Management Func Desc */ 0x00, /* bmCapabilities: D0+D1 */ 0x01, /* bDataInterface: 1 */ - /*ACM Functional Descriptor*/ 0x04, /* bFunctionLength */ 0x24, /* bDescriptorType: CS_INTERFACE */ 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ 0x02, /* bmCapabilities */ - /*Union Functional Descriptor*/ 0x05, /* bFunctionLength */ 0x24, /* bDescriptorType: CS_INTERFACE */ 0x06, /* bDescriptorSubtype: Union func desc */ 0x00, /* bMasterInterface: Communication class interface */ 0x01, /* bSlaveInterface0: Data Class Interface */ - /*Endpoint 1 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ 0x05, /* bDescriptorType: Endpoint */ - 0x81, /* bEndpointAddress IN1 */ + 0x8A, /* bEndpointAddress IN10 */ 0x03, /* bmAttributes: Interrupt */ (USB_EP1BUFSZ & 0xff), /* wMaxPacketSize LO: */ (USB_EP1BUFSZ >> 8), /* wMaxPacketSize HI: */ 0x10, /* bInterval: */ /*---------------------------------------------------------------------------*/ - /*Data class interface descriptor*/ 0x09, /* bLength: Endpoint Descriptor size */ 0x04, /* bDescriptorType: */ @@ -149,20 +140,18 @@ static const uint8_t USB_ConfigDescriptor[] = { 0x02, /* bInterfaceSubClass: */ 0x00, /* bInterfaceProtocol: */ 0x00, /* iInterface: */ - /*Endpoint IN3 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ 0x05, /* bDescriptorType: Endpoint */ - 0x83, /* bEndpointAddress IN3 */ + 0x81, /* bEndpointAddress: IN1 */ 0x02, /* bmAttributes: Bulk */ (USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */ (USB_TXBUFSZ >> 8), 0x00, /* bInterval: ignore for Bulk transfer */ - - /*Endpoint OUT2 Descriptor*/ + /*Endpoint OUT1 Descriptor*/ 0x07, /* bLength: Endpoint Descriptor size */ 0x05, /* bDescriptorType: Endpoint */ - 0x02, /* bEndpointAddress */ + 0x01, /* bEndpointAddress: OUT1 */ 0x02, /* bmAttributes: Bulk */ (USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */ (USB_TXBUFSZ >> 8), @@ -181,17 +170,17 @@ USB_STRING(USB_StringProdDescriptor, u"USB-Serial Controller"); */ // SET_LINE_CODING void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lcd){ - MSG("linecoding_handler()"); + //MSG("linecoding_handler()"); } // SET_CONTROL_LINE_STATE void WEAK clstate_handler(uint16_t __attribute__((unused)) val){ - MSG("clstate_handler()"); + //MSG("clstate_handler()"); } // SEND_BREAK void WEAK break_handler(){ - MSG("break_handler()"); + //MSG("break_handler()"); } static void wr0(const uint8_t *buf, uint16_t size){ @@ -225,35 +214,27 @@ static void wr0(const uint8_t *buf, uint16_t size){ static inline void get_descriptor(){ switch(setup_packet.wValue){ case DEVICE_DESCRIPTOR: - //MSG("DEVICE_D"); wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); break; case CONFIGURATION_DESCRIPTOR: - //MSG("CONF_D"); wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); break; case STRING_LANG_DESCRIPTOR: - //MSG("S_L_D"); wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); break; case STRING_MAN_DESCRIPTOR: - //MSG("S_M_D"); wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); break; case STRING_PROD_DESCRIPTOR: - //MSG("S_P_D"); wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); break; case STRING_SN_DESCRIPTOR: - //MSG("S_SN_D"); wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); break; case DEVICE_QUALIFIER_DESCRIPTOR: - //MSG("D_Q_D"); wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); break; default: - DBG("WTF?"); break; } } @@ -266,15 +247,12 @@ static inline void std_d2h_req(){ get_descriptor(); break; case GET_STATUS: - //MSG("GET_STAT"); EP_WriteIRQ(0, (uint8_t *)&state, 2); // send status: Bus Powered break; case GET_CONFIGURATION: - //MSG("GET_CONF"); EP_WriteIRQ(0, &configuration, 1); break; default: - DBG("WTF?"); break; } } @@ -282,18 +260,15 @@ static inline void std_d2h_req(){ static inline void std_h2d_req(){ switch(setup_packet.bRequest){ case SET_ADDRESS: - //MSG("SET_ADDR"); // new address will be assigned later - after acknowlegement or request to host USB_Dev.USB_Addr = setup_packet.wValue; break; case SET_CONFIGURATION: - //MSG("SET_CONF"); // Now device configured USB_Dev.USB_Status = USB_STATE_CONFIGURED; configuration = setup_packet.wValue; break; default: - DBG("WTF?"); break; } } @@ -315,7 +290,6 @@ static void EP0_Handler(){ if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ case STANDARD_DEVICE_REQUEST_TYPE: // standard device request - //DBG("SDRT"); if(dev2host){ std_d2h_req(); }else{ @@ -324,43 +298,33 @@ static void EP0_Handler(){ } break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request - //DBG("SERT"); if(setup_packet.bRequest == CLEAR_FEATURE){ - //MSG("CLEAR_F"); EP_WriteIRQ(0, (uint8_t *)0, 0); }else{ - DBG("WTF?"); } break; case CONTROL_REQUEST_TYPE: - //DBG("CRT"); switch(setup_packet.bRequest){ case GET_LINE_CODING: - //MSG("GET_LINE_C"); EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); break; case SET_LINE_CODING: // omit this for next stage, when data will come - //MSG("SET_LINE_C"); break; case SET_CONTROL_LINE_STATE: - //MSG("SET_CLS"); usbON = 1; clstate_handler(setup_packet.wValue); break; case SEND_BREAK: - //MSG("SEND_BREAK"); usbON = 0; break_handler(); break; default: - DBG("WTF?"); break; } if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); break; default: EP_WriteIRQ(0, (uint8_t *)0, 0); - DBG("WTF?"); } }else if(rxflag){ // got data over EP0 or host acknowlegement if(endpoints[0].rx_cnt){ @@ -374,7 +338,6 @@ static void EP0_Handler(){ USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; // change state to ADRESSED USB_Dev.USB_Status = USB_STATE_ADDRESSED; - //DBG("Addressed"); } } epstatus = KEEP_DTOG(USB->EPnR[0]); @@ -424,7 +387,6 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f // standard IRQ handler void usb_lp_can_rx0_isr(){ if(USB->ISTR & USB_ISTR_RESET){ - //DBG("USB reset"); usbON = 0; // Reinit registers USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; @@ -466,13 +428,11 @@ void usb_lp_can_rx0_isr(){ if(endpoints[n].func) endpoints[n].func(endpoints[n]); } if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep - //DBG("USB suspend"); usbON = 0; USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE; USB->ISTR = ~USB_ISTR_SUSP; } if(USB->ISTR & USB_ISTR_WKUP){ // wakeup - //DBG("USB wakeup"); USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags USB->ISTR = ~USB_ISTR_WKUP; }