Modified F0: testbrd, CDC, pl2303 and HID

This commit is contained in:
eddyem 2020-04-08 14:53:18 +03:00
parent 10ad505bda
commit 100885c113
18 changed files with 235 additions and 456 deletions

View File

@ -1,93 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* 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

View File

@ -1,57 +0,0 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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__

View File

@ -10,7 +10,7 @@ DENSITY ?= MD
# change this linking script depending on particular MCU model, # change this linking script depending on particular MCU model,
LDSCRIPT ?= stm32f103x8.ld LDSCRIPT ?= stm32f103x8.ld
# debug # debug
DEFS = -DEBUG #DEFS = -DEBUG
INDEPENDENT_HEADERS= INDEPENDENT_HEADERS=

View File

@ -55,6 +55,7 @@ void iwdg_setup(){
IWDG->KR = IWDG_REFRESH; /* (6) */ IWDG->KR = IWDG_REFRESH; /* (6) */
} }
#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0)
char *parse_cmd(char *buf){ char *parse_cmd(char *buf){
static char btns[] = "BTN0=0, BTN1=0\n"; static char btns[] = "BTN0=0, BTN1=0\n";
if(buf[1] != '\n') return buf; if(buf[1] != '\n') return buf;
@ -81,17 +82,17 @@ char *parse_cmd(char *buf){
return u2str(getADCval(0)); return u2str(getADCval(0));
break; break;
case 'L': 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"); "This is another part of the string! Can you see all of this?\n");
return "Long test sent\n"; return "Long test sent\n";
break; break;
case 'R': case 'R':
USB_send("Soft reset\n"); USND("Soft reset\n");
SEND("Soft reset\n"); SEND("Soft reset\n");
NVIC_SystemReset(); NVIC_SystemReset();
break; break;
case 'S': case 'S':
USB_send("Test string for USB\n"); USND("Test string for USB\n");
return "Short test sent\n"; return "Short test sent\n";
break; break;
case 'T': case 'T':
@ -101,13 +102,13 @@ char *parse_cmd(char *buf){
return u2str(getVdd()); return u2str(getVdd());
break; break;
case 'W': case 'W':
USB_send("Wait for reboot\n"); USND("Wait for reboot\n");
SEND("Wait for reboot\n"); SEND("Wait for reboot\n");
while(1){nop();}; while(1){nop();};
break; break;
default: // help default: // help
return return
"0/1 - turn on/off LED1" "0/1 - turn on/off LED1\n"
"'b' - get buttons's state\n" "'b' - get buttons's state\n"
"'p' - toggle USB pullup\n" "'p' - toggle USB pullup\n"
"'A' - get ADC8 value\n" "'A' - get ADC8 value\n"
@ -127,7 +128,7 @@ char *parse_cmd(char *buf){
char *get_USB(){ char *get_USB(){
static char tmpbuf[512], *curptr = tmpbuf; static char tmpbuf[512], *curptr = tmpbuf;
static int rest = 511; static int rest = 511;
int x = USB_receive(curptr, rest); int x = USB_receive((uint8_t*)curptr);
curptr[x] = 0; curptr[x] = 0;
if(!x) return NULL; if(!x) return NULL;
if(curptr[x-1] == '\n'){ if(curptr[x-1] == '\n'){
@ -171,25 +172,6 @@ int main(void){
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog 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){ if(lastT > Tms || Tms - lastT > LEDperiod){
LED_blink(LED0); LED_blink(LED0);
lastT = Tms; lastT = Tms;
@ -203,7 +185,11 @@ int main(void){
SEND("Received data over USB:\n"); SEND("Received data over USB:\n");
SEND(txt); SEND(txt);
newline(); 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 if(usartrx()){ // usart1 received data, store in in buffer
r = usart_getline(&txt); r = usart_getline(&txt);

Binary file not shown.

View File

@ -22,6 +22,8 @@
#ifndef __USART_H__ #ifndef __USART_H__
#define __USART_H__ #define __USART_H__
#include <stdint.h>
// input and output buffers size // input and output buffers size
#define UARTBUFSZI (32) #define UARTBUFSZI (32)
#define UARTBUFSZO (512) #define UARTBUFSZO (512)

View File

@ -20,58 +20,36 @@
* MA 02110-1301, USA. * MA 02110-1301, USA.
* *
*/ */
#include "usart.h"
#include "usb.h" #include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#include "usart.h"
// incoming buffer size static volatile uint8_t tx_succesfull = 1;
#define IDATASZ (256) static volatile uint8_t rxNE = 0;
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
// interrupt IN handler (never used?) // interrupt IN handler (never used?)
static uint16_t EP1_Handler(ep_t ep){ static void EP1_Handler(){
if (ep.rx_flag){ uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]);
#ifdef EBUG if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX
SEND("EP1OUT: "); printu(ep.rx_cnt); usart_putchar('\n'); else epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX);
#endif // clear CTR
ep.status = SET_VALID_TX(ep.status); epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX));
ep.status = KEEP_STAT_RX(ep.status); USB->EPnR[1] = epstatus;
}else if (ep.tx_flag){
DBG("EP1IN");
ep.status = SET_VALID_RX(ep.status);
ep.status = SET_STALL_TX(ep.status);
}
return ep.status;
} }
// data IN/OUT handler // data IN/OUT handlers
static uint16_t EP23_Handler(ep_t ep){ static void transmit_Handler(){ // EP3IN
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; 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
} }
ep.status = SET_VALID_RX(ep.status);
return ep.status; 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(){ void USB_setup(){
@ -86,75 +64,104 @@ void USB_setup(){
USB->DADDR = 0; USB->DADDR = 0;
USB->ISTR = 0; USB->ISTR = 0;
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts 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_LP_CAN1_RX0_IRQn);
NVIC_EnableIRQ(USB_HP_CAN1_TX_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);
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_proc(){ void usb_proc(){
if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints switch(USB_Dev.USB_Status){
if(!usbON){ // endpoints not activated case USB_STATE_CONFIGURED:
// make new BULK endpoint // make new BULK endpoint
// Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features) // 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(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit
EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, EP23_Handler); // OUT2 - receive data EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data
EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, EP23_Handler); // IN3 - transmit data EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data
usbON = 1; USB_Dev.USB_Status = USB_STATE_CONNECTED;
} break;
}else{ case USB_STATE_DEFAULT:
case USB_STATE_ADDRESSED:
if(usbON){
usbON = 0; usbON = 0;
} }
} break;
default: // USB_STATE_CONNECTED - send next data portion
void USB_send(char *buf){ if(!usbON) return;
uint16_t l = 0, ctr = 0; send_next();
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;
} }
} }
/** /**
* @brief USB_receive * @brief USB_receive
* @param buf (i) - buffer for received data * @param buf (i) - buffer[64] for received data
* @param bufsize - its size
* @return amount of received bytes * @return amount of received bytes
*/ */
int USB_receive(char *buf, int bufsize){ uint8_t USB_receive(uint8_t *buf){
if(!bufsize || !idatalen) return 0; if(!usbON || !rxNE) return 0;
USB->CNTR = 0; DBG("Get data");
int sz = (idatalen > bufsize) ? bufsize : idatalen, rest = idatalen - sz; SEND((char*)buf); newline();
for(int i = 0; i < sz; ++i) buf[i] = incoming_data[i]; uint8_t sz = EP_Read(2, (uint16_t*)buf);
if(rest > 0){ uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]);
uint8_t *ptr = &incoming_data[sz]; // keep stat_tx & set ACK rx
for(int i = 0; i < rest; ++i) incoming_data[i] = *ptr++; USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX;
//memmove(incoming_data, &incoming_data[sz], rest); - hardfault on memcpy&memmove rxNE = 0;
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;
return sz; return sz;
} }
/**
* @brief USB_configured
* @return 1 if USB is in configured state
*/
int USB_configured(){
return usbON;
}

View File

@ -30,8 +30,8 @@
void USB_setup(); void USB_setup();
void usb_proc(); void usb_proc();
void USB_send(char *buf); void USB_send(const uint8_t *buf, uint16_t len);
int USB_receive(char *buf, int bufsize); void USB_send_blk(const uint8_t *buf, uint16_t len);
int USB_configured(); uint8_t USB_receive(uint8_t *buf);
#endif // __USB_H__ #endif // __USB_H__

View File

@ -41,6 +41,8 @@
#define USB_TXBUFSZ 64 #define USB_TXBUFSZ 64
// USB receive buffer size (64 for PL2303) // USB receive buffer size (64 for PL2303)
#define USB_RXBUFSZ 64 #define USB_RXBUFSZ 64
// EP1 - interrupt - buffer size
#define USB_EP1BUFSZ 8
#define USB_BTABLE_BASE 0x40006000 #define USB_BTABLE_BASE 0x40006000
#define USB_BASE ((uint32_t)0x40005C00) #define USB_BASE ((uint32_t)0x40005C00)
@ -91,18 +93,6 @@ typedef struct {
__IO uint32_t BTABLE; __IO uint32_t BTABLE;
} USB_TypeDef; } 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{ typedef struct{
__IO uint32_t USB_ADDR_TX; __IO uint32_t USB_ADDR_TX;
__IO uint32_t USB_COUNT_TX; __IO uint32_t USB_COUNT_TX;

View File

@ -23,18 +23,19 @@
#include <stdint.h> #include <stdint.h>
#include "usb_lib.h" #include "usb_lib.h"
#include "usart.h"
ep_t endpoints[STM32ENDPOINTS]; ep_t endpoints[STM32ENDPOINTS];
static usb_dev_t USB_Dev; usb_dev_t USB_Dev;
static usb_LineCoding lineCoding = {115200, 0, 0, 8}; 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 ep0databuf[EP0DATABUF_SIZE];
static uint8_t ep0dbuflen = 0; static uint8_t ep0dbuflen = 0;
usb_LineCoding getLineCoding(){return lineCoding;} usb_LineCoding getLineCoding(){return lineCoding;}
uint8_t usbON = 0; // device disconnected from terminal
// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor // definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor
#define bcdUSB_L 0x10 #define bcdUSB_L 0x10
#define bcdUSB_H 0x01 #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){ static void wr0(const uint8_t *buf, uint16_t size){
if(setup_packet.wLength < size) size = setup_packet.wLength; if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request
if(size < endpoints[0].txbufsz){
EP_WriteIRQ(0, buf, size); 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(){ static inline void get_descriptor(){
@ -233,7 +257,7 @@ static inline void std_h2d_req(){
break; break;
case SET_CONFIGURATION: case SET_CONFIGURATION:
// Now device configured // Now device configured
USB_Dev.USB_Status = USB_CONFIGURE_STATE; USB_Dev.USB_Status = USB_STATE_CONFIGURED;
configuration = setup_packet.wValue; configuration = setup_packet.wValue;
break; break;
default: default:
@ -249,14 +273,13 @@ bmRequestType: 76543210
*/ */
/** /**
* Endpoint0 (control) handler * Endpoint0 (control) handler
* @param ep - endpoint state
* @return data written to EP0R
*/ */
static uint16_t EP0_Handler(ep_t ep){ static void EP0_Handler(){
uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications
uint8_t reqtype = setup_packet.bmRequestType & 0x7f; uint8_t reqtype = setup_packet.bmRequestType & 0x7f;
uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; 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){ switch(reqtype){
case STANDARD_DEVICE_REQUEST_TYPE: // standard device request case STANDARD_DEVICE_REQUEST_TYPE: // standard device request
if(dev2host){ if(dev2host){
@ -265,20 +288,14 @@ static uint16_t EP0_Handler(ep_t ep){
std_h2d_req(); std_h2d_req();
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
break; break;
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request 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); EP_WriteIRQ(0, (uint8_t *)0, 0);
epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
} }
break; break;
case VENDOR_REQUEST_TYPE: case VENDOR_REQUEST_TYPE:
vendor_handler(&setup_packet); vendor_handler(&setup_packet);
epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
break; break;
case CONTROL_REQUEST_TYPE: case CONTROL_REQUEST_TYPE:
switch(setup_packet.bRequest){ 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 case SET_LINE_CODING: // omit this for next stage, when data will come
break; break;
case SET_CONTROL_LINE_STATE: case SET_CONTROL_LINE_STATE:
usbON = 1;
clstate_handler(setup_packet.wValue); clstate_handler(setup_packet.wValue);
break; break;
case SEND_BREAK: case SEND_BREAK:
usbON = 0;
break_handler(); break_handler();
break; break;
default: default:
break; break;
} }
if(!dev2host) 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
epstatus = SET_VALID_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
break; break;
default: default:
EP_WriteIRQ(0, (uint8_t *)0, 0); 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 }else if(rxflag){ // got data over EP0 or host acknowlegement
if(ep.rx_cnt){ if(endpoints[0].rx_cnt){
//EP_WriteIRQ(0, (uint8_t *)0, 0);
if(setup_packet.bRequest == SET_LINE_CODING){ if(setup_packet.bRequest == SET_LINE_CODING){
linecoding_handler((usb_LineCoding*)ep0databuf); linecoding_handler((usb_LineCoding*)ep0databuf);
} }
} }
// wait for new data from host } else if(TX_FLAG(epstatus)){ // package transmitted
epstatus = SET_VALID_RX(epstatus);
epstatus = SET_VALID_TX(epstatus);
} else if (ep.tx_flag){ // package transmitted
// now we can change address after enumeration // now we can change address after enumeration
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){ if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr; USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr;
// change state to ADRESSED // 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; 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 * @param uint16_t (*func)(ep_t *ep) - EP handler function
* @return 0 if all OK * @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(number >= STM32ENDPOINTS) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large 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 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; USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr;
endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2); endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2);
endpoints[number].txbufsz = txsz;
lastaddr += txsz; lastaddr += txsz;
USB_BTABLE->EP[number].USB_COUNT_TX = 0; USB_BTABLE->EP[number].USB_COUNT_TX = 0;
USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; 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; //extern int8_t dump;
// standard IRQ handler // standard IRQ handler
void usb_isr(){ void usb_lp_can_rx0_isr(){
if(USB->ISTR & USB_ISTR_RESET){ if(USB->ISTR & USB_ISTR_RESET){
usbON = 0;
// Reinit registers // 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; USB->ISTR = 0;
// Endpoint 0 - CONTROL // Endpoint 0 - CONTROL
// ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes! // ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes!
lastaddr = LASTADDR_DEFAULT; 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 // clear address, leave only enable bit
USB->DADDR = USB_DADDR_EF; USB->DADDR = USB_DADDR_EF;
// state is default - wait for enumeration USB_Dev.USB_Status = USB_STATE_DEFAULT;
USB_Dev.USB_Status = USB_DEFAULT_STATE; 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){ if(USB->ISTR & USB_ISTR_CTR){
// EP number // EP number
uint8_t n = USB->ISTR & USB_ISTR_EPID; uint8_t n = USB->ISTR & USB_ISTR_EPID;
// copy status register // copy status register
uint16_t epstatus = USB->EPnR[n]; 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 // copy received bytes amount
endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter
// check direction // check direction
@ -408,61 +415,19 @@ void usb_isr(){
EP_Read(0, (uint16_t*)&ep0databuf); 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 // call EP handler
endpoints[n].status = epstatus; if(endpoints[n].func) endpoints[n].func(endpoints[n]);
// 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;
} }
if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep
usbON = 0;
USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LP_MODE;
USB->ISTR = ~USB_ISTR_SUSP;
} }
if(USB->ISTR & USB_ISTR_WKUP){ // wakeup
/* USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LP_MODE); // clear suspend flags
if (USB->ISTR & USB_ISTR_PMAOVR) { USB->ISTR = ~USB_ISTR_WKUP;
MSG("PMAOVR\n");
// Handle PMAOVR status
} }
if (USB->ISTR & USB_ISTR_SUSP) {
MSG("SUSP\n");
if (USB->DADDR & 0x7f) {
USB->DADDR = 0;
USB->CNTR &= ~ 0x800;
}
}
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){ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
uint8_t i; 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; uint16_t N2 = (size + 1) >> 1;
// the buffer is 16-bit, so we should copy data as it would be uint16_t // the buffer is 16-bit, so we should copy data as it would be uint16_t
uint16_t *buf16 = (uint16_t *)buf; 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 * @param size - its size
*/ */
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t 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); EP_WriteIRQ(number, buf, size);
status = SET_NAK_RX(status); uint16_t status = KEEP_DTOG(USB->EPnR[number]);
status = SET_VALID_TX(status); // keep DTOGs, clear CTR_TX & set TX VALID to start transmission
status = KEEP_DTOG_TX(status); USB->EPnR[number] = (status & ~(USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_TX;
status = KEEP_DTOG_RX(status);
USB->EPnR[number] = status;
} }
/* /*
@ -506,16 +468,15 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
* @return amount of data read * @return amount of data read
*/ */
int EP_Read(uint8_t number, uint16_t *buf){ 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; uint32_t *in = (uint32_t *)endpoints[number].rx_buf;
if(n){ if(n){
for(int i = 0; i < n; ++i, ++in) for(int i = 0; i < n; ++i, ++in)
buf[i] = *(uint16_t*)in; buf[i] = *(uint16_t*)in;
} }
return endpoints[number].rx_cnt; return sz;
} }
// USB status
uint8_t USB_GetState(){
return USB_Dev.USB_Status;
}

View File

@ -31,8 +31,6 @@
#define EP0DATABUF_SIZE (64) #define EP0DATABUF_SIZE (64)
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8) #define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
// Max EP amount (EP0 + other used)
//#define ENDPOINTS_NUM 4
// bmRequestType & 0x7f // bmRequestType & 0x7f
#define STANDARD_DEVICE_REQUEST_TYPE 0 #define STANDARD_DEVICE_REQUEST_TYPE 0
#define STANDARD_ENDPOINT_REQUEST_TYPE 2 #define STANDARD_ENDPOINT_REQUEST_TYPE 2
@ -78,31 +76,21 @@
#define STRING_SN_DESCRIPTOR 0x303 #define STRING_SN_DESCRIPTOR 0x303
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 #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 // EPnR bits manipulation
#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX)) #define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R #define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
#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)))
// USB state: uninitialized, addressed, ready for use // USB state: uninitialized, addressed, ready for use
#define USB_DEFAULT_STATE 0 typedef enum{
#define USB_ADRESSED_STATE 1 USB_STATE_DEFAULT,
#define USB_CONFIGURE_STATE 2 USB_STATE_ADDRESSED,
USB_STATE_CONFIGURED,
USB_STATE_CONNECTED
} USB_state;
// EP types // EP types
#define EP_TYPE_BULK 0x00 #define EP_TYPE_BULK 0x00
@ -144,15 +132,12 @@ typedef struct {
} config_pack_t; } config_pack_t;
// endpoints state // endpoints state
typedef struct __ep_t{ typedef struct{
uint16_t *tx_buf; // transmission buffer address uint16_t *tx_buf; // transmission buffer address
uint16_t txbufsz; // transmission buffer size
uint16_t *rx_buf; // reception buffer address uint16_t *rx_buf; // reception buffer address
uint16_t (*func)(); // endpoint action function void (*func)(); // endpoint action function
uint16_t status; // status flags
unsigned rx_cnt : 10; // received data counter 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; } ep_t;
// USB status & its address // USB status & its address
@ -185,18 +170,20 @@ typedef struct {
} __attribute__ ((packed)) usb_cdc_notification; } __attribute__ ((packed)) usb_cdc_notification;
extern ep_t endpoints[]; extern ep_t endpoints[];
extern usb_dev_t USB_Dev;
extern uint8_t usbON;
void USB_Init(); void USB_Init();
uint8_t USB_GetState(); void USB_ResetState();
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)());
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size); 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); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
int EP_Read(uint8_t number, uint16_t *buf); int EP_Read(uint8_t number, uint16_t *buf);
usb_LineCoding getLineCoding(); usb_LineCoding getLineCoding();
void WEAK linecoding_handler(usb_LineCoding *lc); void linecoding_handler(usb_LineCoding *lc);
void WEAK clstate_handler(uint16_t val); void clstate_handler(uint16_t val);
void WEAK break_handler(); void break_handler();
void WEAK vendor_handler(config_pack_t *packet); void vendor_handler(config_pack_t *packet);
#endif // __USB_LIB_H__ #endif // __USB_LIB_H__

Binary file not shown.

View File

@ -377,7 +377,6 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*f
return 0; return 0;
} }
//extern int8_t dump;
// standard IRQ handler // standard IRQ handler
void usb_lp_can_rx0_isr(){ void usb_lp_can_rx0_isr(){
if(USB->ISTR & USB_ISTR_RESET){ if(USB->ISTR & USB_ISTR_RESET){
@ -480,7 +479,3 @@ int EP_Read(uint8_t number, uint16_t *buf){
return sz; return sz;
} }
// USB status
uint8_t USB_GetState(){
return USB_Dev.USB_Status;
}

View File

@ -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 type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT)
* @param txsz - transmission buffer size @ USB/CAN buffer * @param txsz - transmission buffer size @ USB/CAN buffer
* @param rxsz - reception 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 * @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(number >= STM32ENDPOINTS) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large 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 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 }else{ // IN interrupt - transmit data, only CTR_TX == 1
// enumeration end could be here (if EP0) // 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 if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep
usbON = 0; usbON = 0;

View File

@ -93,8 +93,7 @@
typedef enum{ typedef enum{
USB_STATE_DEFAULT, USB_STATE_DEFAULT,
USB_STATE_ADDRESSED, USB_STATE_ADDRESSED,
USB_STATE_CONFIGURED, USB_STATE_CONFIGURED
USB_STATE_CONNECTED
} USB_state; } USB_state;
// EP types // EP types
@ -157,7 +156,7 @@ extern uint8_t usbON;
void USB_Init(); void USB_Init();
void USB_ResetState(); 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_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size); void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
int EP_Read(uint8_t number, uint16_t *buf); int EP_Read(uint8_t number, uint16_t *buf);

Binary file not shown.

View File

@ -22,6 +22,8 @@
#ifndef __COMMON_MACROS_H__ #ifndef __COMMON_MACROS_H__
#define __COMMON_MACROS_H__ #define __COMMON_MACROS_H__
#include <stdint.h>
#ifndef TRUE_INLINE #ifndef TRUE_INLINE
#define TRUE_INLINE __attribute__((always_inline)) static inline #define TRUE_INLINE __attribute__((always_inline)) static inline
#endif #endif

View File

@ -110,7 +110,7 @@ TRUE_INLINE void StartHSE(){
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){} 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(){ TRUE_INLINE void StartHSI48(){
// disable PLL // disable PLL
RCC->CR &= ~RCC_CR_PLLON; RCC->CR &= ~RCC_CR_PLLON;