Modified F0: testbrd, CDC, pl2303 and HID

This commit is contained in:
eddyem
2020-04-08 14:53:08 +03:00
parent c9b4165645
commit 10ad505bda
68 changed files with 11413 additions and 1233 deletions

View File

@@ -51,7 +51,7 @@ DEPS := $(OBJS:.o=.d)
INC_DIR ?= ../inc
INCLUDE := -I$(INC_DIR)/F0 -I$(INC_DIR)/cm
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
LIB_DIR := $(INC_DIR)/ld
###############################################################################

View File

@@ -24,7 +24,6 @@
#include "usart.h"
#include "usb.h"
#include "usb_lib.h"
#include <string.h> // memcpy
volatile uint32_t Tms = 0;
@@ -56,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;
@@ -87,17 +87,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':
@@ -107,7 +107,7 @@ 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;
@@ -133,12 +133,9 @@ char *parse_cmd(char *buf){
char *get_USB(){
static char tmpbuf[129], *curptr = tmpbuf;
static int rest = 128;
int x = USB_receive(curptr, rest);
int x = USB_receive((uint8_t*)curptr);
curptr[x] = 0;
if(!x) return NULL;
SEND("got: ");
SEND(curptr);
newline();
if(curptr[x-1] == '\n'){
curptr = tmpbuf;
rest = 128;
@@ -187,7 +184,12 @@ 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(ans[l-1] != '\n') USND("\n");
}
}
if(usartrx()){ // usart1 received data, store in in buffer
r = usart_getline(&txt);
@@ -202,18 +204,6 @@ int main(void){
}
// check buttons - each 50ms
if(Tms - lastB > 49){
/*static uint8_t oldbtn0 = 0, oldbtn1 = 0;
uint8_t btn0 = GET_BTN0(), btn1 = GET_BTN1(), pwm = GET_LED_PWM();
// both: set to middle
if(oldbtn0 != btn0 && oldbtn1 != btn1){
SET_LED_PWM(127);
}else if(oldbtn0 != btn0){ // pressed/released
oldbtn0 = btn0;
if(pwm < 255) SET_LED_PWM(pwm+1);
}else if(oldbtn1 != btn1){
oldbtn1 = btn1;
if(pwm > 0) SET_LED_PWM(pwm-1);
}*/
lastB = Tms;
uint8_t btn0 = GET_BTN0(), btn1 = GET_BTN1(), pwm = GET_LED_PWM();
// both: set to middle

Binary file not shown.

View File

@@ -24,52 +24,32 @@
#include "usb.h"
#include "usb_lib.h"
#include "usart.h"
#include <string.h> // memcpy, memmove
// 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){
ep.status = SET_VALID_TX(ep.status);
ep.status = KEEP_STAT_RX(ep.status);
}else if (ep.tx_flag){
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, &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
}
void USB_setup(){
@@ -93,66 +73,100 @@ void USB_setup(){
NVIC_EnableIRQ(USB_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;
memcpy(buf, incoming_data, sz);
if(rest > 0){
memmove(incoming_data, &incoming_data[sz], rest);
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;
SEND((char*)buf); newline();
uint8_t sz = EP_Read(2, buf);
uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]);
// keep stat_tx & set ACK rx
USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX;
rxNE = 0;
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_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__

View File

@@ -25,7 +25,11 @@
#ifndef __USB_DEFS_H__
#define __USB_DEFS_H__
#include <stm32f0xx.h>
#include <stm32f0.h>
// max endpoints number
#define STM32ENDPOINTS 8
#define USB_EP1BUFSZ 8
/**
* Buffers size definition
@@ -74,15 +78,8 @@
#define USB_TypeDef USB_TypeDef_custom
typedef struct{
__IO uint32_t EPnR[8];
__IO uint32_t RESERVED1;
__IO uint32_t RESERVED2;
__IO uint32_t RESERVED3;
__IO uint32_t RESERVED4;
__IO uint32_t RESERVED5;
__IO uint32_t RESERVED6;
__IO uint32_t RESERVED7;
__IO uint32_t RESERVED8;
__IO uint32_t EPnR[STM32ENDPOINTS];
__IO uint32_t RESERVED[STM32ENDPOINTS];
__IO uint32_t CNTR;
__IO uint32_t ISTR;
__IO uint32_t FNR;
@@ -100,7 +97,7 @@ typedef struct{
} USB_EPDATA_TypeDef;
typedef struct{
__IO USB_EPDATA_TypeDef EP[8];
__IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS];
} USB_BtableDef;
#endif // __USB_DEFS_H__

View File

@@ -22,13 +22,15 @@
*/
#include <stdint.h>
#include "usb_lib.h"
#include <string.h> // memcpy
#include "usart.h"
#include "usb_lib.h"
ep_t endpoints[ENDPOINTS_NUM];
static usb_dev_t USB_Dev;
ep_t endpoints[STM32ENDPOINTS];
usb_dev_t USB_Dev;
uint8_t usbON = 0; // device disconnected from terminal
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
static config_pack_t setup_packet;
static uint8_t ep0databuf[EP0DATABUF_SIZE];
@@ -176,8 +178,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(){
@@ -234,7 +259,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:
@@ -250,38 +275,29 @@ 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){
std_d2h_req();
}else{
std_h2d_req();
// send ZLP
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){
// send ZLP
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){
@@ -291,47 +307,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 = USB_EP0_BASEADDR;
@@ -345,8 +354,8 @@ static uint16_t lastaddr = USB_EP0_BASEADDR;
* @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)){
if(number >= ENDPOINTS_NUM) return 4; // out of configured amount
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()){
if(number >= STM32ENDPOINTS) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
@@ -360,6 +369,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);
endpoints[number].txbufsz = txsz;
lastaddr += txsz;
USB_BTABLE->EP[number].USB_COUNT_TX = 0;
USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr;
@@ -374,56 +384,43 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t
// standard IRQ handler
void usb_isr(){
if (USB->ISTR & USB_ISTR_RESET){
usbON = 0;
// Reinit registers
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
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 = USB_EP0_BASEADDR; // roll back to beginning of buffer
lastaddr = LASTADDR_DEFAULT; // roll back to beginning of buffer
EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler);
// clear address, leave only enable bit
USB->DADDR = USB_DADDR_EF;
// state is default - wait for enumeration
USB_Dev.USB_Status = USB_DEFAULT_STATE;
USB_Dev.USB_Status = USB_STATE_DEFAULT;
}
if(USB->ISTR & USB_ISTR_CTR){
// EP number
uint8_t n = USB->ISTR & USB_ISTR_EPID;
// copy status register
uint16_t epstatus = USB->EPnR[n];
// 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
if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit)
if(n == 0){ // control endpoint
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack
memcpy(&setup_packet, endpoints[0].rx_buf, sizeof(setup_packet));
EP_Read(0, (uint8_t*)&setup_packet);
ep0dbuflen = 0;
// interrupt handler will be called later
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
ep0dbuflen = endpoints[0].rx_cnt;
memcpy(ep0databuf, endpoints[0].rx_buf, ep0dbuflen);
EP_Read(0, (uint8_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]);
}
}
@@ -435,7 +432,7 @@ void usb_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;
@@ -452,13 +449,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;
}
/*
@@ -468,14 +462,10 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
*/
int EP_Read(uint8_t number, uint8_t *buf){
int n = endpoints[number].rx_cnt;
endpoints[number].rx_cnt = 0;
if(n){
for(int i = 0; i < n; ++i)
buf[i] = endpoints[number].rx_buf[i];
}
return n;
}
// USB status
uint8_t USB_GetState(){
return USB_Dev.USB_Status;
}

View File

@@ -29,6 +29,7 @@
#include "usb_defs.h"
#define EP0DATABUF_SIZE (64)
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
// Max EP amount (EP0 + other used)
#define ENDPOINTS_NUM 4
@@ -77,31 +78,21 @@
#define STRING_SN_DESCRIPTOR 0x303
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600
// 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 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)
// USB state: uninitialized, addressed, ready for use
#define USB_DEFAULT_STATE 0
#define USB_ADRESSED_STATE 1
#define USB_CONFIGURE_STATE 2
// EPnR bits manipulation
#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, connected
typedef enum{
USB_STATE_DEFAULT,
USB_STATE_ADDRESSED,
USB_STATE_CONFIGURED,
USB_STATE_CONNECTED
} USB_state;
// EP types
#define EP_TYPE_BULK 0x00
@@ -143,15 +134,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
uint8_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
@@ -184,19 +172,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));
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)());
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
int EP_Read(uint8_t number, uint8_t *buf);
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__