diff --git a/F1-nolib/CDC_ACM/sync.c b/F1-nolib/CDC_ACM/sync.c deleted file mode 100644 index ae02c3b..0000000 --- a/F1-nolib/CDC_ACM/sync.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2012 Fergus Noble - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see . - */ - -/* - * TODO: - * implement mutexes for other type of MCU (which doesn't have strex & ldrex) - */ - -#include "sync.h" - -/* DMB is supported on CM0 */ -void __dmb() -{ - __asm__ volatile ("dmb"); -} - -/* Those are defined only on CM3 or CM4 */ -#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) - -uint32_t __ldrex(volatile uint32_t *addr) -{ - uint32_t res; - __asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr)); - return res; -} - -uint32_t __strex(uint32_t val, volatile uint32_t *addr) -{ - uint32_t res; - __asm__ volatile ("strex %0, %2, [%1]" - : "=&r" (res) : "r" (addr), "r" (val)); - return res; -} - -void mutex_lock(mutex_t *m) -{ - uint32_t status = 0; - - do { - /* Wait until the mutex is unlocked. */ - while (__ldrex(m) != MUTEX_UNLOCKED); - - /* Try to acquire it. */ - status = __strex(MUTEX_LOCKED, m); - - /* Did we get it? If not then try again. */ - } while (status != 0); - - /* Execute the mysterious Data Memory Barrier instruction! */ - __dmb(); -} - -void mutex_unlock(mutex_t *m) -{ - /* Ensure accesses to protected resource are finished */ - __dmb(); - - /* Free the lock. */ - *m = MUTEX_UNLOCKED; -} - -/* - * Try to lock mutex - * if it's already locked or there was error in STREX, return MUTEX_LOCKED - * else return MUTEX_UNLOCKED - */ -mutex_t mutex_trylock(mutex_t *m){ - uint32_t status = 0; - mutex_t old_lock = __ldrex(m); // get mutex value - // set mutex - status = __strex(MUTEX_LOCKED, m); - if(status == 0) __dmb(); - else old_lock = MUTEX_LOCKED; - return old_lock; -} - -#endif diff --git a/F1-nolib/CDC_ACM/sync.h b/F1-nolib/CDC_ACM/sync.h deleted file mode 100644 index 8f060a5..0000000 --- a/F1-nolib/CDC_ACM/sync.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of the libopencm3 project. - * - * Copyright (C) 2012 Fergus Noble - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library. If not, see . - */ -#pragma once -#ifndef SYNC_H__ -#define SYNC_H__ - -#include "stm32f1.h" -void __dmb(void); - -/* Implements synchronisation primitives as discussed in the ARM document - * DHT0008A (ID081709) "ARM Synchronization Primitives" and the ARM v7-M - * Architecture Reference Manual. -*/ - -/* --- Exclusive load and store instructions ------------------------------- */ - -/* Those are defined only on CM3 or CM4 */ -#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) - -uint32_t __ldrex(volatile uint32_t *addr); -uint32_t __strex(uint32_t val, volatile uint32_t *addr); - -/* --- Convenience functions ----------------------------------------------- */ - -/* Here we implement some simple synchronisation primitives. */ - -typedef uint32_t mutex_t; - -#define MUTEX_UNLOCKED 0 -#define MUTEX_LOCKED 1 - -void mutex_lock(mutex_t *m); -void mutex_unlock(mutex_t *m); -mutex_t mutex_trylock(mutex_t *m); - -#else -#error "This arch have NO ldrex/strex!" - -#endif - -#endif // SYNC_H__ diff --git a/F1-nolib/F1_testbrd/Makefile b/F1-nolib/F1_testbrd/Makefile index ec0a80c..c243bd9 100644 --- a/F1-nolib/F1_testbrd/Makefile +++ b/F1-nolib/F1_testbrd/Makefile @@ -10,7 +10,7 @@ DENSITY ?= MD # change this linking script depending on particular MCU model, LDSCRIPT ?= stm32f103x8.ld # debug -DEFS = -DEBUG +#DEFS = -DEBUG INDEPENDENT_HEADERS= diff --git a/F1-nolib/F1_testbrd/main.c b/F1-nolib/F1_testbrd/main.c index 8615a2a..08896db 100644 --- a/F1-nolib/F1_testbrd/main.c +++ b/F1-nolib/F1_testbrd/main.c @@ -55,6 +55,7 @@ void iwdg_setup(){ IWDG->KR = IWDG_REFRESH; /* (6) */ } +#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0) char *parse_cmd(char *buf){ static char btns[] = "BTN0=0, BTN1=0\n"; if(buf[1] != '\n') return buf; @@ -81,17 +82,17 @@ char *parse_cmd(char *buf){ return u2str(getADCval(0)); break; case 'L': - USB_send("Very long test string for USB (it's length is more than 64 bytes).\n" + USND("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 "Long test sent\n"; break; case 'R': - USB_send("Soft reset\n"); + USND("Soft reset\n"); SEND("Soft reset\n"); NVIC_SystemReset(); break; case 'S': - USB_send("Test string for USB\n"); + USND("Test string for USB\n"); return "Short test sent\n"; break; case 'T': @@ -101,13 +102,13 @@ char *parse_cmd(char *buf){ return u2str(getVdd()); break; case 'W': - USB_send("Wait for reboot\n"); + USND("Wait for reboot\n"); SEND("Wait for reboot\n"); while(1){nop();}; break; default: // help return - "0/1 - turn on/off LED1" + "0/1 - turn on/off LED1\n" "'b' - get buttons's state\n" "'p' - toggle USB pullup\n" "'A' - get ADC8 value\n" @@ -127,7 +128,7 @@ char *parse_cmd(char *buf){ char *get_USB(){ static char tmpbuf[512], *curptr = tmpbuf; static int rest = 511; - int x = USB_receive(curptr, rest); + int x = USB_receive((uint8_t*)curptr); curptr[x] = 0; if(!x) return NULL; if(curptr[x-1] == '\n'){ @@ -171,25 +172,6 @@ int main(void){ while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog - /*if(dump){ - SEND("\nin buffer:\n"); - uint16_t buf[32]; - uint32_t *in = (uint32_t *)endpoints[0].rx_buf; - for(int i = 0; i < 32; ++i, ++in) - buf[i] = *(uint16_t*)in; - hexdump((uint8_t*)buf, 64); - SEND("\nout buffer:\n"); - in = (uint32_t *)endpoints[0].tx_buf; - for(int i = 0; i < 32; ++i, ++in) - buf[i] = *(uint16_t*)in; - hexdump((uint8_t*)buf, 64); - SEND("Config:\n"); - hexdump((uint8_t*)&setup_packet, sizeof(setup_packet)); - newline(); - hexdump16((uint16_t*)USB_BTABLE, 64); - newline(); - dump = 0; - }*/ if(lastT > Tms || Tms - lastT > LEDperiod){ LED_blink(LED0); lastT = Tms; @@ -203,7 +185,11 @@ int main(void){ SEND("Received data over USB:\n"); SEND(txt); newline(); - if(ans) USB_send(ans); + if(ans){ + uint16_t l = 0; char *p = ans; + while(*p++) l++; + USB_send((uint8_t*)ans, l); + } } if(usartrx()){ // usart1 received data, store in in buffer r = usart_getline(&txt); diff --git a/F1-nolib/F1_testbrd/pl2303.bin b/F1-nolib/F1_testbrd/pl2303.bin index f9821fa..1b434f4 100755 Binary files a/F1-nolib/F1_testbrd/pl2303.bin and b/F1-nolib/F1_testbrd/pl2303.bin differ diff --git a/F1-nolib/F1_testbrd/usart.h b/F1-nolib/F1_testbrd/usart.h index a48b92c..2e7dad3 100644 --- a/F1-nolib/F1_testbrd/usart.h +++ b/F1-nolib/F1_testbrd/usart.h @@ -22,6 +22,8 @@ #ifndef __USART_H__ #define __USART_H__ +#include + // input and output buffers size #define UARTBUFSZI (32) #define UARTBUFSZO (512) diff --git a/F1-nolib/F1_testbrd/usb.c b/F1-nolib/F1_testbrd/usb.c index cb3a88e..2a9a7be 100644 --- a/F1-nolib/F1_testbrd/usb.c +++ b/F1-nolib/F1_testbrd/usb.c @@ -20,58 +20,36 @@ * MA 02110-1301, USA. * */ +#include "usart.h" #include "usb.h" #include "usb_lib.h" -#include "usart.h" -// incoming buffer size -#define IDATASZ (256) -static uint8_t incoming_data[IDATASZ]; -static uint8_t ovfl = 0; -static uint16_t idatalen = 0; -static volatile uint8_t tx_succesfull = 0; -static int8_t usbON = 0; // ==1 when USB fully configured +static volatile uint8_t tx_succesfull = 1; +static volatile uint8_t rxNE = 0; // interrupt IN handler (never used?) -static uint16_t EP1_Handler(ep_t ep){ - if (ep.rx_flag){ -#ifdef EBUG -SEND("EP1OUT: "); printu(ep.rx_cnt); usart_putchar('\n'); -#endif - ep.status = SET_VALID_TX(ep.status); - ep.status = KEEP_STAT_RX(ep.status); - }else if (ep.tx_flag){ -DBG("EP1IN"); - ep.status = SET_VALID_RX(ep.status); - ep.status = SET_STALL_TX(ep.status); - } - return ep.status; +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 handler -static uint16_t EP23_Handler(ep_t ep){ - if(ep.rx_flag){ - int rd = ep.rx_cnt, rest = IDATASZ - idatalen; - if(rd){ - if(rd <= rest){ - idatalen += EP_Read(2, (uint16_t*)&incoming_data[idatalen]); - ovfl = 0; - }else{ - ep.status = SET_NAK_RX(ep.status); - ovfl = 1; - return ep.status; - } - } - // end of transaction: clear DTOGs - ep.status = CLEAR_DTOG_RX(ep.status); - ep.status = CLEAR_DTOG_TX(ep.status); - ep.status = SET_STALL_TX(ep.status); - }else if (ep.tx_flag){ - ep.status = KEEP_STAT_TX(ep.status); - tx_succesfull = 1; - } - ep.status = SET_VALID_RX(ep.status); - return ep.status; +// data IN/OUT handlers +static void transmit_Handler(){ // EP3IN + tx_succesfull = 1; + uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]); + // clear CTR keep DTOGs & STATs + USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr +} + +static void receive_Handler(){ // EP2OUT + rxNE = 1; + uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[2]); + USB->EPnR[2] = (epstatus & ~(USB_EPnR_CTR_RX)); // clear RX ctr + DBG("RXh"); } void USB_setup(){ @@ -86,75 +64,104 @@ void USB_setup(){ USB->DADDR = 0; USB->ISTR = 0; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts - /*USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_PMAOVRM | - USB_CNTR_ERRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_SOFM | - USB_CNTR_ESOFM;*/ NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); - NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn ); } -void usb_proc(){ - if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints - if(!usbON){ // endpoints not activated - // 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, 10, 0, EP1_Handler); // IN1 - transmit - EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, EP23_Handler); // OUT2 - receive data - EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, EP23_Handler); // IN3 - transmit data - usbON = 1; - } - }else{ - usbON = 0; +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); + return; + } + while(len--) usbbuff[buflen++] = *buf++; +} + +// 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; + } + int needzlp = 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); } } -void USB_send(char *buf){ - uint16_t l = 0, ctr = 0; - char *p = buf; - while(*p++) ++l; - while(l){ - uint16_t s = (l > USB_TXBUFSZ) ? USB_TXBUFSZ : l; - tx_succesfull = 0; - EP_Write(3, (uint8_t*)&buf[ctr], s); - uint32_t ctra = 1000000; - while(--ctra && tx_succesfull == 0); - l -= s; - ctr += s; +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; + send_next(); } } /** * @brief USB_receive - * @param buf (i) - buffer for received data - * @param bufsize - its size + * @param buf (i) - buffer[64] for received data * @return amount of received bytes */ -int USB_receive(char *buf, int bufsize){ - if(!bufsize || !idatalen) return 0; - USB->CNTR = 0; - int sz = (idatalen > bufsize) ? bufsize : idatalen, rest = idatalen - sz; - for(int i = 0; i < sz; ++i) buf[i] = incoming_data[i]; - if(rest > 0){ - uint8_t *ptr = &incoming_data[sz]; - for(int i = 0; i < rest; ++i) incoming_data[i] = *ptr++; - //memmove(incoming_data, &incoming_data[sz], rest); - hardfault on memcpy&memmove - idatalen = rest; - }else idatalen = 0; - if(ovfl){ - EP23_Handler(endpoints[2]); - uint16_t epstatus = USB->EPnR[2]; - epstatus = CLEAR_DTOG_RX(epstatus); - epstatus = SET_VALID_RX(epstatus); - USB->EPnR[2] = epstatus; - } - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; +uint8_t USB_receive(uint8_t *buf){ + if(!usbON || !rxNE) return 0; + DBG("Get data"); + SEND((char*)buf); newline(); + uint8_t sz = EP_Read(2, (uint16_t*)buf); + uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]); + // keep stat_tx & set ACK rx + USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX; + rxNE = 0; return sz; } - -/** - * @brief USB_configured - * @return 1 if USB is in configured state - */ -int USB_configured(){ - return usbON; -} diff --git a/F1-nolib/F1_testbrd/usb.h b/F1-nolib/F1_testbrd/usb.h index 0d5831a..894cec7 100644 --- a/F1-nolib/F1_testbrd/usb.h +++ b/F1-nolib/F1_testbrd/usb.h @@ -30,8 +30,8 @@ void USB_setup(); void usb_proc(); -void USB_send(char *buf); -int USB_receive(char *buf, int bufsize); -int USB_configured(); +void USB_send(const uint8_t *buf, uint16_t len); +void USB_send_blk(const uint8_t *buf, uint16_t len); +uint8_t USB_receive(uint8_t *buf); #endif // __USB_H__ diff --git a/F1-nolib/F1_testbrd/usb_defs.h b/F1-nolib/F1_testbrd/usb_defs.h index d6bc03f..1ac3dd0 100644 --- a/F1-nolib/F1_testbrd/usb_defs.h +++ b/F1-nolib/F1_testbrd/usb_defs.h @@ -41,6 +41,8 @@ #define USB_TXBUFSZ 64 // USB receive buffer size (64 for PL2303) #define USB_RXBUFSZ 64 +// EP1 - interrupt - buffer size +#define USB_EP1BUFSZ 8 #define USB_BTABLE_BASE 0x40006000 #define USB_BASE ((uint32_t)0x40005C00) @@ -91,18 +93,6 @@ typedef struct { __IO uint32_t BTABLE; } USB_TypeDef; -/* -typedef struct{ - __IO uint16_t USB_ADDR_TX; - __IO uint16_t res1; - __IO uint16_t USB_COUNT_TX; - __IO uint16_t res2; - __IO uint16_t USB_ADDR_RX; - __IO uint16_t res3; - __IO uint16_t USB_COUNT_RX; - __IO uint16_t res4; -} USB_EPDATA_TypeDef;*/ - typedef struct{ __IO uint32_t USB_ADDR_TX; __IO uint32_t USB_COUNT_TX; diff --git a/F1-nolib/F1_testbrd/usb_lib.c b/F1-nolib/F1_testbrd/usb_lib.c index c45f3f2..ee5b7ad 100644 --- a/F1-nolib/F1_testbrd/usb_lib.c +++ b/F1-nolib/F1_testbrd/usb_lib.c @@ -23,18 +23,19 @@ #include #include "usb_lib.h" -#include "usart.h" ep_t endpoints[STM32ENDPOINTS]; -static usb_dev_t USB_Dev; +usb_dev_t USB_Dev; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; -config_pack_t setup_packet; +static config_pack_t setup_packet; static uint8_t ep0databuf[EP0DATABUF_SIZE]; static uint8_t ep0dbuflen = 0; usb_LineCoding getLineCoding(){return lineCoding;} +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 @@ -175,8 +176,31 @@ void WEAK vendor_handler(config_pack_t *packet){ } static void wr0(const uint8_t *buf, uint16_t size){ - if(setup_packet.wLength < size) size = setup_packet.wLength; - EP_WriteIRQ(0, buf, size); + if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request + if(size < endpoints[0].txbufsz){ + EP_WriteIRQ(0, buf, size); + return; + } + while(size){ + uint16_t l = size; + if(l > endpoints[0].txbufsz) l = endpoints[0].txbufsz; + EP_WriteIRQ(0, buf, l); + buf += l; + size -= l; + uint8_t needzlp = (l == endpoints[0].txbufsz) ? 1 : 0; + if(size || needzlp){ // send last data buffer + uint16_t status = KEEP_DTOG(USB->EPnR[0]); + // keep DTOGs, clear CTR_RX,TX, set TX VALID, leave stat_Rx + USB->EPnR[0] = (status & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX|USB_EPnR_STAT_RX)) + ^ USB_EPnR_STAT_TX; + uint32_t ctr = 1000000; + while(--ctr && (USB->ISTR & USB_ISTR_CTR) == 0){IWDG->KR = IWDG_REFRESH;}; + if((USB->ISTR & USB_ISTR_CTR) == 0){ + return; + } + if(needzlp) EP_WriteIRQ(0, (uint8_t*)0, 0); + } + } } static inline void get_descriptor(){ @@ -233,7 +257,7 @@ static inline void std_h2d_req(){ break; case SET_CONFIGURATION: // Now device configured - USB_Dev.USB_Status = USB_CONFIGURE_STATE; + USB_Dev.USB_Status = USB_STATE_CONFIGURED; configuration = setup_packet.wValue; break; default: @@ -249,14 +273,13 @@ bmRequestType: 76543210 */ /** * Endpoint0 (control) handler - * @param ep - endpoint state - * @return data written to EP0R */ -static uint16_t EP0_Handler(ep_t ep){ - uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications +static 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; - if ((ep.rx_flag) && (ep.setup_flag)){ + int rxflag = RX_FLAG(epstatus); + if(rxflag && SETUP_FLAG(epstatus)){ switch(reqtype){ case STANDARD_DEVICE_REQUEST_TYPE: // standard device request if(dev2host){ @@ -265,20 +288,14 @@ static uint16_t EP0_Handler(ep_t ep){ std_h2d_req(); EP_WriteIRQ(0, (uint8_t *)0, 0); } - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); break; case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request if(setup_packet.bRequest == CLEAR_FEATURE){ EP_WriteIRQ(0, (uint8_t *)0, 0); - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); } break; case VENDOR_REQUEST_TYPE: vendor_handler(&setup_packet); - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); break; case CONTROL_REQUEST_TYPE: switch(setup_packet.bRequest){ @@ -288,47 +305,40 @@ static uint16_t EP0_Handler(ep_t ep){ case SET_LINE_CODING: // omit this for next stage, when data will come break; case SET_CONTROL_LINE_STATE: + usbON = 1; clstate_handler(setup_packet.wValue); break; case SEND_BREAK: + usbON = 0; break_handler(); break; default: break; } - if(!dev2host) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement - epstatus = SET_VALID_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); + 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); - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); } - }else if (ep.rx_flag){ // got data over EP0 or host acknowlegement - if(ep.rx_cnt){ - //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){ linecoding_handler((usb_LineCoding*)ep0databuf); } } - // wait for new data from host - epstatus = SET_VALID_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); - } else if (ep.tx_flag){ // package transmitted + } 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_ADRESSED_STATE; + USB_Dev.USB_Status = USB_STATE_ADDRESSED; } - // end of transaction - epstatus = CLEAR_DTOG_RX(epstatus); - epstatus = CLEAR_DTOG_TX(epstatus); - epstatus = SET_VALID_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); } - return epstatus; + epstatus = KEEP_DTOG(USB->EPnR[0]); + if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP/data transmission + else epstatus &= ~USB_EPnR_STAT_TX; // or leave unchanged + // keep DTOGs, clear CTR_RX,TX, set RX VALID + USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX; } static uint16_t lastaddr = LASTADDR_DEFAULT; @@ -341,7 +351,7 @@ static uint16_t lastaddr = LASTADDR_DEFAULT; * @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, uint16_t (*func)(ep_t ep)){ +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 @@ -356,6 +366,7 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t } USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr; endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); + endpoints[number].txbufsz = txsz; lastaddr += txsz; USB_BTABLE->EP[number].USB_COUNT_TX = 0; USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; @@ -368,32 +379,28 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t //extern int8_t dump; // standard IRQ handler -void usb_isr(){ - if (USB->ISTR & USB_ISTR_RESET){ +void usb_lp_can_rx0_isr(){ + if(USB->ISTR & USB_ISTR_RESET){ + usbON = 0; // Reinit registers - USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; + USB->CNTR = 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; - if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ - DBG("Err init EP0"); - } // clear address, leave only enable bit USB->DADDR = USB_DADDR_EF; - // state is default - wait for enumeration - USB_Dev.USB_Status = USB_DEFAULT_STATE; + USB_Dev.USB_Status = USB_STATE_DEFAULT; + USB->ISTR = ~USB_ISTR_RESET; + if(EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler)){ + return; + } } if(USB->ISTR & USB_ISTR_CTR){ // EP number uint8_t n = USB->ISTR & USB_ISTR_EPID; // copy status register uint16_t epstatus = USB->EPnR[n]; - // dump = 1; - // Calculate flags - endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0; - endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; - endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0; // copy received bytes amount endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter // check direction @@ -408,61 +415,19 @@ void usb_isr(){ EP_Read(0, (uint16_t*)&ep0databuf); } } - }else{ // IN interrupt - transmit data, only CTR_TX == 1 - // enumeration end could be here (if EP0) } - // prepare status field for EP handler - endpoints[n].status = epstatus; - // call EP handler (even if it will change EPnR, it should return new status) - epstatus = endpoints[n].func(endpoints[n]); - // keep DTOG state - epstatus = KEEP_DTOG_TX(epstatus); - epstatus = KEEP_DTOG_RX(epstatus); - // clear all RX/TX flags - epstatus = CLEAR_CTR_RX(epstatus); - epstatus = CLEAR_CTR_TX(epstatus); - // refresh EPnR - USB->EPnR[n] = epstatus; + // call EP handler + if(endpoints[n].func) endpoints[n].func(endpoints[n]); } -} - -/* - if (USB->ISTR & USB_ISTR_PMAOVR) { - MSG("PMAOVR\n"); - // Handle PMAOVR status + if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep + usbON = 0; + USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE; + USB->ISTR = ~USB_ISTR_SUSP; } - if (USB->ISTR & USB_ISTR_SUSP) { - MSG("SUSP\n"); - if (USB->DADDR & 0x7f) { - USB->DADDR = 0; - USB->CNTR &= ~ 0x800; - } + if(USB->ISTR & USB_ISTR_WKUP){ // wakeup + USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags + USB->ISTR = ~USB_ISTR_WKUP; } - if (USB->ISTR & USB_ISTR_ERR) { - MSG("ERR\n"); - // Handle Error - } - if (USB->ISTR & USB_ISTR_WKUP) { - MSG("WKUP\n"); - // Handle Wakeup - } - if (USB->ISTR & USB_ISTR_SOF) { - MSG("SOF\n"); - // Handle SOF - } - if (USB->ISTR & USB_ISTR_ESOF) { - MSG("ESOF\n"); - // Handle ESOF - } - USB->ISTR = 0; -*/ - -void usb_lp_can_rx0_isr(){ - usb_isr(); -} - -void usb_hp_can_tx_isr(){ - usb_isr(); } /** @@ -473,7 +438,7 @@ void usb_hp_can_tx_isr(){ */ 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; @@ -491,13 +456,10 @@ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ * @param size - its size */ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ - uint16_t status = USB->EPnR[number]; EP_WriteIRQ(number, buf, size); - status = SET_NAK_RX(status); - status = SET_VALID_TX(status); - status = KEEP_DTOG_TX(status); - status = KEEP_DTOG_RX(status); - USB->EPnR[number] = status; + uint16_t status = KEEP_DTOG(USB->EPnR[number]); + // keep DTOGs, clear CTR_TX & set TX VALID to start transmission + USB->EPnR[number] = (status & ~(USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_TX; } /* @@ -506,16 +468,15 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){ * @return amount of data read */ int EP_Read(uint8_t number, uint16_t *buf){ - int n = (endpoints[number].rx_cnt + 1) >> 1; + int sz = endpoints[number].rx_cnt; + if(!sz) return 0; + endpoints[number].rx_cnt = 0; + int n = (sz + 1) >> 1; uint32_t *in = (uint32_t *)endpoints[number].rx_buf; if(n){ for(int i = 0; i < n; ++i, ++in) buf[i] = *(uint16_t*)in; } - return endpoints[number].rx_cnt; + return sz; } -// USB status -uint8_t USB_GetState(){ - return USB_Dev.USB_Status; -} diff --git a/F1-nolib/F1_testbrd/usb_lib.h b/F1-nolib/F1_testbrd/usb_lib.h index 25398c5..b10c10f 100644 --- a/F1-nolib/F1_testbrd/usb_lib.h +++ b/F1-nolib/F1_testbrd/usb_lib.h @@ -31,8 +31,6 @@ #define EP0DATABUF_SIZE (64) #define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) -// Max EP amount (EP0 + other used) -//#define ENDPOINTS_NUM 4 // bmRequestType & 0x7f #define STANDARD_DEVICE_REQUEST_TYPE 0 #define STANDARD_ENDPOINT_REQUEST_TYPE 2 @@ -78,31 +76,21 @@ #define STRING_SN_DESCRIPTOR 0x303 #define DEVICE_QUALIFIER_DESCRIPTOR 0x600 +#define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX) +#define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX) +#define SETUP_FLAG(epstat) (epstat & USB_EPnR_SETUP) + // EPnR bits manipulation -#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX)) -#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R -#define TOGGLE_DTOG_RX(R) (R | USB_EPnR_DTOG_RX) -#define KEEP_DTOG_RX(R) (R & (~USB_EPnR_DTOG_RX)) -#define CLEAR_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? R : (R & (~USB_EPnR_DTOG_TX)) -#define SET_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? (R & (~USB_EPnR_DTOG_TX)) : R -#define TOGGLE_DTOG_TX(R) (R | USB_EPnR_DTOG_TX) -#define KEEP_DTOG_TX(R) (R & (~USB_EPnR_DTOG_TX)) -#define SET_VALID_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX) | (R & (~USB_EPnR_STAT_RX)) -#define SET_NAK_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_1) | (R & (~USB_EPnR_STAT_RX)) -#define SET_STALL_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_0) | (R & (~USB_EPnR_STAT_RX)) -#define KEEP_STAT_RX(R) (R & (~USB_EPnR_STAT_RX)) -#define SET_VALID_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX) | (R & (~USB_EPnR_STAT_TX)) -#define SET_NAK_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_1) | (R & (~USB_EPnR_STAT_TX)) -#define SET_STALL_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_0) | (R & (~USB_EPnR_STAT_TX)) -#define KEEP_STAT_TX(R) (R & (~USB_EPnR_STAT_TX)) -#define CLEAR_CTR_RX(R) (R & (~USB_EPnR_CTR_RX)) -#define CLEAR_CTR_TX(R) (R & (~USB_EPnR_CTR_TX)) -#define CLEAR_CTR_RX_TX(R) (R & (~(USB_EPnR_CTR_TX | USB_EPnR_CTR_RX))) +#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 -#define USB_DEFAULT_STATE 0 -#define USB_ADRESSED_STATE 1 -#define USB_CONFIGURE_STATE 2 +typedef enum{ + USB_STATE_DEFAULT, + USB_STATE_ADDRESSED, + USB_STATE_CONFIGURED, + USB_STATE_CONNECTED +} USB_state; // EP types #define EP_TYPE_BULK 0x00 @@ -144,15 +132,12 @@ 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 uint16_t *rx_buf; // reception buffer address - uint16_t (*func)(); // endpoint action function - uint16_t status; // status flags + void (*func)(); // endpoint action function unsigned rx_cnt : 10; // received data counter - unsigned tx_flag : 1; // transmission flag - unsigned rx_flag : 1; // reception flag - unsigned setup_flag : 1; // this is setup packet (only for EP0) } ep_t; // USB status & its address @@ -185,18 +170,20 @@ typedef struct { } __attribute__ ((packed)) usb_cdc_notification; extern ep_t endpoints[]; +extern usb_dev_t USB_Dev; +extern uint8_t usbON; void USB_Init(); -uint8_t USB_GetState(); -int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)); +void USB_ResetState(); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); int EP_Read(uint8_t number, uint16_t *buf); usb_LineCoding getLineCoding(); -void WEAK linecoding_handler(usb_LineCoding *lc); -void WEAK clstate_handler(uint16_t val); -void WEAK break_handler(); -void WEAK vendor_handler(config_pack_t *packet); +void linecoding_handler(usb_LineCoding *lc); +void clstate_handler(uint16_t val); +void break_handler(); +void vendor_handler(config_pack_t *packet); #endif // __USB_LIB_H__ diff --git a/F1-nolib/PL2303/pl2303.bin b/F1-nolib/PL2303/pl2303.bin index 81a55a6..53d6b03 100755 Binary files a/F1-nolib/PL2303/pl2303.bin and b/F1-nolib/PL2303/pl2303.bin differ diff --git a/F1-nolib/PL2303/usb_lib.c b/F1-nolib/PL2303/usb_lib.c index db9635b..687a9a4 100644 --- a/F1-nolib/PL2303/usb_lib.c +++ b/F1-nolib/PL2303/usb_lib.c @@ -377,7 +377,6 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f return 0; } -//extern int8_t dump; // standard IRQ handler void usb_lp_can_rx0_isr(){ if(USB->ISTR & USB_ISTR_RESET){ @@ -480,7 +479,3 @@ int EP_Read(uint8_t number, uint16_t *buf){ return sz; } -// USB status -uint8_t USB_GetState(){ - return USB_Dev.USB_Status; -} diff --git a/F1-nolib/USB_HID/usb_lib.c b/F1-nolib/USB_HID/usb_lib.c index 3ce80c5..c5ec591 100644 --- a/F1-nolib/USB_HID/usb_lib.c +++ b/F1-nolib/USB_HID/usb_lib.c @@ -350,10 +350,10 @@ static uint16_t lastaddr = LASTADDR_DEFAULT; * @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 + * @param void (*func)() - 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)){ +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 @@ -415,7 +415,7 @@ void usb_lp_can_rx0_isr(){ }else{ // IN interrupt - transmit data, only CTR_TX == 1 // enumeration end could be here (if EP0) } - if(endpoints[n].func) endpoints[n].func(endpoints[n]); + if(endpoints[n].func) endpoints[n].func(); } if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep usbON = 0; diff --git a/F1-nolib/USB_HID/usb_lib.h b/F1-nolib/USB_HID/usb_lib.h index 06b0972..f3aac90 100644 --- a/F1-nolib/USB_HID/usb_lib.h +++ b/F1-nolib/USB_HID/usb_lib.h @@ -93,8 +93,7 @@ typedef enum{ USB_STATE_DEFAULT, USB_STATE_ADDRESSED, - USB_STATE_CONFIGURED, - USB_STATE_CONNECTED + USB_STATE_CONFIGURED } USB_state; // EP types @@ -157,7 +156,7 @@ extern uint8_t usbON; void USB_Init(); void USB_ResetState(); -int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)(ep_t ep)); +int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()); void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); int EP_Read(uint8_t number, uint16_t *buf); diff --git a/F1-nolib/USB_HID/usbhid103.bin b/F1-nolib/USB_HID/usbhid103.bin index eebdad4..3e1027d 100755 Binary files a/F1-nolib/USB_HID/usbhid103.bin and b/F1-nolib/USB_HID/usbhid103.bin differ diff --git a/F1-nolib/inc/Fx/common_macros.h b/F1-nolib/inc/Fx/common_macros.h index 9e01f3b..516257e 100644 --- a/F1-nolib/inc/Fx/common_macros.h +++ b/F1-nolib/inc/Fx/common_macros.h @@ -22,6 +22,8 @@ #ifndef __COMMON_MACROS_H__ #define __COMMON_MACROS_H__ +#include + #ifndef TRUE_INLINE #define TRUE_INLINE __attribute__((always_inline)) static inline #endif diff --git a/F1-nolib/inc/Fx/stm32f0.h b/F1-nolib/inc/Fx/stm32f0.h index 360e24a..a9fb7f2 100644 --- a/F1-nolib/inc/Fx/stm32f0.h +++ b/F1-nolib/inc/Fx/stm32f0.h @@ -110,7 +110,7 @@ TRUE_INLINE void StartHSE(){ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){} } -#if !defined (STM32F030x4) && !defined (STM32F030x6) && !defined (STM32F030x8) && !defined (STM32F031x6) && !defined (STM32F038xx) && !defined (STM32F030xC) +#if defined (STM32F042x6) || defined (STM32F072xb) TRUE_INLINE void StartHSI48(){ // disable PLL RCC->CR &= ~RCC_CR_PLLON;