Working code for STM32F103 PL2303 emulation

This commit is contained in:
eddyem 2019-05-21 11:41:41 +03:00
parent 0cd287d544
commit d46a604d6f
11 changed files with 200 additions and 90 deletions

View File

@ -42,8 +42,7 @@ DFUUTIL := $(shell which dfu-util)
############################################################################### ###############################################################################
# Source files # Source files
OBJDIR = mk OBJDIR = mk
#SRC := $(wildcard *.c) SRC := $(wildcard *.c)
SRC = adc.c hardware.c main.c usart.c
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o)) OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
STARTUP = $(OBJDIR)/startup.o STARTUP = $(OBJDIR)/startup.o
OBJS += $(STARTUP) OBJS += $(STARTUP)
@ -70,7 +69,7 @@ LDFLAGS += -T$(LDSCRIPT)
############################################################################### ###############################################################################
# Used libraries # Used libraries
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LDLIBS += -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY) DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY)

View File

@ -62,9 +62,11 @@ static inline void adc_setup(){
| DMA_CCR_CIRC | DMA_CCR_PL | DMA_CCR_EN; | DMA_CCR_CIRC | DMA_CCR_PL | DMA_CCR_EN;
// continuous mode & DMA; enable vref & Tsens; wake up ADC // continuous mode & DMA; enable vref & Tsens; wake up ADC
ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_TSVREFE | ADC_CR2_CONT | ADC_CR2_ADON; ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_TSVREFE | ADC_CR2_CONT | ADC_CR2_ADON;
// wait for Tstab - at least 1us
while(++ctr < 0xff) nop();
// calibration // calibration
ADC1->CR2 |= ADC_CR2_RSTCAL; ADC1->CR2 |= ADC_CR2_RSTCAL;
while((ADC1->CR2 & ADC_CR2_RSTCAL) && ++ctr < 0xfffff); ctr = 0; while((ADC1->CR2 & ADC_CR2_RSTCAL) && ++ctr < 0xfffff);
ADC1->CR2 |= ADC_CR2_CAL; ADC1->CR2 |= ADC_CR2_CAL;
ctr = 0; while((ADC1->CR2 & ADC_CR2_CAL) && ++ctr < 0xfffff); ctr = 0; while((ADC1->CR2 & ADC_CR2_CAL) && ++ctr < 0xfffff);
// turn ON ADC // turn ON ADC

View File

@ -41,6 +41,8 @@
// USB pullup (not used in STM32F0x2!) - PA13 // USB pullup (not used in STM32F0x2!) - PA13
#define USBPU_port GPIOA #define USBPU_port GPIOA
#define USBPU_pin (1<<13) #define USBPU_pin (1<<13)
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
#define LED_blink(x) pin_toggle(x ## _port, x ## _pin) #define LED_blink(x) pin_toggle(x ## _port, x ## _pin)
#define LED_on(x) pin_clear(x ## _port, x ## _pin) #define LED_on(x) pin_clear(x ## _port, x ## _pin)

View File

@ -24,13 +24,9 @@
#include "usart.h" #include "usart.h"
#include "usb.h" #include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#include <string.h> // memcpy
volatile uint32_t Tms = 0; volatile uint32_t Tms = 0;
#define USB_send(x) do{}while(0)
/* Called when systick fires */ /* Called when systick fires */
void sys_tick_handler(void){ void sys_tick_handler(void){
++Tms; ++Tms;
@ -127,30 +123,29 @@ char *parse_cmd(char *buf){
return NULL; return NULL;
} }
/*
// usb getline // usb getline
char *get_USB(){ char *get_USB(){
static char tmpbuf[129], *curptr = tmpbuf; static char tmpbuf[512], *curptr = tmpbuf;
static int rest = 128; static int rest = 511;
int x = USB_receive(curptr, rest); int x = USB_receive(curptr, rest);
curptr[x] = 0; curptr[x] = 0;
if(!x) return NULL; if(!x) return NULL;
SEND("got: ");
SEND(curptr);
newline();
if(curptr[x-1] == '\n'){ if(curptr[x-1] == '\n'){
curptr = tmpbuf; curptr = tmpbuf;
rest = 128; rest = 511;
return tmpbuf; return tmpbuf;
} }
curptr += x; rest -= x; curptr += x; rest -= x;
if(rest <= 0){ // buffer overflow if(rest <= 0){ // buffer overflow
SEND("USB buffer overflow!\n");
curptr = tmpbuf; curptr = tmpbuf;
rest = 128; rest = 511;
} }
return NULL; return NULL;
}*/ }
//int8_t dump = 0;
int main(void){ int main(void){
uint32_t lastT = 0, lastB = 0, LEDperiod = 499; uint32_t lastT = 0, lastB = 0, LEDperiod = 499;
sysreset(); sysreset();
@ -169,26 +164,47 @@ int main(void){
} }
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
//USB_setup(); USBPU_OFF();
USB_setup();
iwdg_setup(); iwdg_setup();
USBPU_ON();
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;
transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s transmit_tbuf(); // non-blocking transmission of data from UART buffer every 0.5s
} }
//usb_proc(); usb_proc();
int r = 0; int r = 0;
char *txt, *ans; char *txt, *ans;
/*if((txt = get_USB())){ if((txt = get_USB())){
ans = parse_cmd(txt); ans = parse_cmd(txt);
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) USB_send(ans);
}*/ }
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);
if(r){ if(r){

Binary file not shown.

View File

@ -52,7 +52,7 @@ int usart_getline(char **line){
// transmit current tbuf and swap buffers // transmit current tbuf and swap buffers
void transmit_tbuf(){ void transmit_tbuf(){
uint32_t tmout = 16000000; uint32_t tmout = 72000;
while(!txrdy){if(--tmout == 0) return;}; // wait for previos buffer transmission while(!txrdy){if(--tmout == 0) return;}; // wait for previos buffer transmission
register int l = odatalen[tbufno]; register int l = odatalen[tbufno];
if(!l) return; if(!l) return;
@ -66,14 +66,17 @@ void transmit_tbuf(){
} }
void usart_putchar(const char ch){ void usart_putchar(const char ch){
if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); for(int i = 0; odatalen[tbufno] == UARTBUFSZO && i < 1024; ++i) transmit_tbuf();
tbuf[tbufno][odatalen[tbufno]++] = ch; tbuf[tbufno][odatalen[tbufno]++] = ch;
} }
void usart_send(const char *str){ void usart_send(const char *str){
uint32_t x = 512; uint32_t x = 512;
while(*str && --x){ while(*str && --x){
if(odatalen[tbufno] == UARTBUFSZO) transmit_tbuf(); if(odatalen[tbufno] == UARTBUFSZO){
transmit_tbuf();
continue;
}
tbuf[tbufno][odatalen[tbufno]++] = *str++; tbuf[tbufno][odatalen[tbufno]++] = *str++;
} }
} }
@ -205,6 +208,37 @@ void hexdump(uint8_t *arr, uint16_t len){
else usart_putchar(half - 10 + 'a'); else usart_putchar(half - 10 + 'a');
} }
if(l % 16 == 15) usart_putchar('\n'); if(l % 16 == 15) usart_putchar('\n');
else if((l & 3) == 3) usart_putchar(' ');
}
}
// dump USB memory (uint16_t mapped as uint32_t); len - in uint16_t
void hexdump16(uint16_t *arr, uint16_t len){
for(uint16_t l = 0; l < len; ++l, ++arr){
uint16_t x = arr[l];
for(int8_t i = 0; i < 2; ++i){
for(int16_t j = 1; j > -1; --j){
register uint8_t half = (x >> (4*j+8*i)) & 0x0f;
if(half < 10) usart_putchar(half + '0');
else usart_putchar(half - 10 + 'a');
}
}
if(l % 8 == 7) usart_putchar('\n');
else if(l & 1) usart_putchar(' ');
}
}
void hexdump32(uint32_t *arr, uint16_t len){
for(uint16_t l = 0; l < len; ++l, ++arr){
uint16_t x = (uint16_t)arr[l];
for(int8_t i = 0; i < 2; ++i){
for(int16_t j = 1; j > -1; --j){
register uint8_t half = (x >> (4*j+8*i)) & 0x0f;
if(half < 10) usart_putchar(half + '0');
else usart_putchar(half - 10 + 'a');
}
}
if(l % 8 == 7) usart_putchar('\n');
else if(l & 1) usart_putchar(' '); else if(l & 1) usart_putchar(' ');
} }
} }

View File

@ -38,8 +38,10 @@
#ifdef EBUG #ifdef EBUG
#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) #define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0)
#define DBG(str) do{SEND(str); usart_putchar('\n'); }while(0)
#else #else
#define MSG(str) #define MSG(str)
#define DBG(str)
#endif #endif
#define usartrx() (linerdy) #define usartrx() (linerdy)
@ -57,5 +59,7 @@ char *u2str(uint32_t val);
void printu(uint32_t val); void printu(uint32_t val);
void printuhex(uint32_t val); void printuhex(uint32_t val);
void hexdump(uint8_t *arr, uint16_t len); void hexdump(uint8_t *arr, uint16_t len);
void hexdump16(uint16_t *arr, uint16_t len);
void hexdump32(uint32_t *arr, uint16_t len);
#endif // __USART_H__ #endif // __USART_H__

View File

@ -20,11 +20,9 @@
* MA 02110-1301, USA. * MA 02110-1301, USA.
* *
*/ */
#include "usb.h" #include "usb.h"
#include "usb_lib.h" #include "usb_lib.h"
#include "usart.h" #include "usart.h"
#include <string.h> // memcpy, memmove
// incoming buffer size // incoming buffer size
#define IDATASZ (256) #define IDATASZ (256)
@ -37,9 +35,13 @@ 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 uint16_t EP1_Handler(ep_t ep){
if (ep.rx_flag){ 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 = SET_VALID_TX(ep.status);
ep.status = KEEP_STAT_RX(ep.status); ep.status = KEEP_STAT_RX(ep.status);
}else if (ep.tx_flag){ }else if (ep.tx_flag){
DBG("EP1IN");
ep.status = SET_VALID_RX(ep.status); ep.status = SET_VALID_RX(ep.status);
ep.status = SET_STALL_TX(ep.status); ep.status = SET_STALL_TX(ep.status);
} }
@ -52,7 +54,7 @@ static uint16_t EP23_Handler(ep_t ep){
int rd = ep.rx_cnt, rest = IDATASZ - idatalen; int rd = ep.rx_cnt, rest = IDATASZ - idatalen;
if(rd){ if(rd){
if(rd <= rest){ if(rd <= rest){
idatalen += EP_Read(2, &incoming_data[idatalen]); idatalen += EP_Read(2, (uint16_t*)&incoming_data[idatalen]);
ovfl = 0; ovfl = 0;
}else{ }else{
ep.status = SET_NAK_RX(ep.status); ep.status = SET_NAK_RX(ep.status);
@ -73,24 +75,22 @@ static uint16_t EP23_Handler(ep_t ep){
} }
void USB_setup(){ void USB_setup(){
RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48 RCC->APB1ENR |= RCC_APB1ENR_USBEN;
uint32_t tmout = 16000000; USB->CNTR = USB_CNTR_FRES; // Force USB Reset
while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;} for(uint32_t ctr = 0; ctr < 72000; ++ctr) nop(); // wait >1ms
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; //uint32_t ctr = 0;
CRS->CFGR &= ~CRS_CFGR_SYNCSRC; USB->CNTR = 0;
CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source USB->BTABLE = 0;
CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim USB->DADDR = 0;
CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only USB->ISTR = 0;
RCC->CFGR |= RCC_CFGR_SW; USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM; // allow only wakeup & reset interrupts
// allow RESET and CTRM interrupts /*USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_PMAOVRM |
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; USB_CNTR_ERRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_SOFM |
// clear flags USB_CNTR_ESOFM;*/
USB->ISTR = 0; NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
// and activate pullup NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn );
USB->BCDR |= USB_BCDR_DPPU;
NVIC_EnableIRQ(USB_IRQn);
} }
void usb_proc(){ void usb_proc(){
@ -133,9 +133,11 @@ int USB_receive(char *buf, int bufsize){
if(!bufsize || !idatalen) return 0; if(!bufsize || !idatalen) return 0;
USB->CNTR = 0; USB->CNTR = 0;
int sz = (idatalen > bufsize) ? bufsize : idatalen, rest = idatalen - sz; int sz = (idatalen > bufsize) ? bufsize : idatalen, rest = idatalen - sz;
memcpy(buf, incoming_data, sz); for(int i = 0; i < sz; ++i) buf[i] = incoming_data[i];
if(rest > 0){ if(rest > 0){
memmove(incoming_data, &incoming_data[sz], rest); 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; idatalen = rest;
}else idatalen = 0; }else idatalen = 0;
if(ovfl){ if(ovfl){

View File

@ -27,13 +27,14 @@
#include <stm32f1.h> #include <stm32f1.h>
// max endpoints number
#define STM32ENDPOINTS 8
/** /**
* Buffers size definition * Buffers size definition
**/ **/
// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! #define USB_BTABLE_SIZE 512
#define USB_BTABLE_SIZE 1024
// first 64 bytes of USB_BTABLE are registers! // first 64 bytes of USB_BTABLE are registers!
#define USB_EP0_BASEADDR 64 //#define USB_EP0_BASEADDR 64
// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) // for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303)
#define USB_EP0_BUFSZ 64 #define USB_EP0_BUFSZ 64
// USB transmit buffer size (64 for PL2303) // USB transmit buffer size (64 for PL2303)
@ -42,7 +43,12 @@
#define USB_RXBUFSZ 64 #define USB_RXBUFSZ 64
#define USB_BTABLE_BASE 0x40006000 #define USB_BTABLE_BASE 0x40006000
#define USB_BASE ((uint32_t)0x40005C00)
#define USB ((USB_TypeDef *) USB_BASE)
#ifdef USB_BTABLE
#undef USB_BTABLE #undef USB_BTABLE
#endif
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) #define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
#define USB_ISTR_EPID 0x0000000F #define USB_ISTR_EPID 0x0000000F
#define USB_FNR_LSOF_0 0x00000800 #define USB_FNR_LSOF_0 0x00000800
@ -71,36 +77,41 @@
#define USB_COUNTn_NUM_BLOCK 0x00007C00 #define USB_COUNTn_NUM_BLOCK 0x00007C00
#define USB_COUNTn_RX 0x0000003F #define USB_COUNTn_RX 0x0000003F
#ifdef USB_TypeDef
#define USB_TypeDef USB_TypeDef_custom #define USB_TypeDef USB_TypeDef_custom
#endif
typedef struct{ typedef struct {
__IO uint32_t EPnR[8]; __IO uint32_t EPnR[STM32ENDPOINTS];
__IO uint32_t RESERVED1; __IO uint32_t RESERVED[STM32ENDPOINTS];
__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 CNTR; __IO uint32_t CNTR;
__IO uint32_t ISTR; __IO uint32_t ISTR;
__IO uint32_t FNR; __IO uint32_t FNR;
__IO uint32_t DADDR; __IO uint32_t DADDR;
__IO uint32_t BTABLE; __IO uint32_t BTABLE;
__IO uint32_t LPMCSR;
__IO uint32_t BCDR;
} USB_TypeDef; } USB_TypeDef;
/*
typedef struct{ typedef struct{
__IO uint16_t USB_ADDR_TX; __IO uint16_t USB_ADDR_TX;
__IO uint16_t res1;
__IO uint16_t USB_COUNT_TX; __IO uint16_t USB_COUNT_TX;
__IO uint16_t res2;
__IO uint16_t USB_ADDR_RX; __IO uint16_t USB_ADDR_RX;
__IO uint16_t res3;
__IO uint16_t USB_COUNT_RX; __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;
__IO uint32_t USB_ADDR_RX;
__IO uint32_t USB_COUNT_RX;
} USB_EPDATA_TypeDef; } USB_EPDATA_TypeDef;
typedef struct{ typedef struct{
__IO USB_EPDATA_TypeDef EP[8]; __IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS];
} USB_BtableDef; } USB_BtableDef;
#endif // __USB_DEFS_H__ #endif // __USB_DEFS_H__

View File

@ -23,14 +23,13 @@
#include <stdint.h> #include <stdint.h>
#include "usb_lib.h" #include "usb_lib.h"
#include <string.h> // memcpy
#include "usart.h" #include "usart.h"
ep_t endpoints[ENDPOINTS_NUM]; ep_t endpoints[STM32ENDPOINTS];
static usb_dev_t USB_Dev; static usb_dev_t USB_Dev;
static usb_LineCoding lineCoding = {115200, 0, 0, 8}; static usb_LineCoding lineCoding = {115200, 0, 0, 8};
static config_pack_t setup_packet; 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;
@ -264,7 +263,6 @@ static uint16_t EP0_Handler(ep_t ep){
std_d2h_req(); std_d2h_req();
}else{ }else{
std_h2d_req(); std_h2d_req();
// send ZLP
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
} }
epstatus = SET_NAK_RX(epstatus); epstatus = SET_NAK_RX(epstatus);
@ -272,7 +270,6 @@ static uint16_t EP0_Handler(ep_t ep){
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){
// send ZLP
EP_WriteIRQ(0, (uint8_t *)0, 0); EP_WriteIRQ(0, (uint8_t *)0, 0);
epstatus = SET_NAK_RX(epstatus); epstatus = SET_NAK_RX(epstatus);
epstatus = SET_VALID_TX(epstatus); epstatus = SET_VALID_TX(epstatus);
@ -337,10 +334,9 @@ static uint16_t EP0_Handler(ep_t ep){
return epstatus; return epstatus;
} }
static uint16_t lastaddr = USB_EP0_BASEADDR; static uint16_t lastaddr = LASTADDR_DEFAULT;
/** /**
* Endpoint initialisation * Endpoint initialisation
* !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
* @param number - EP num (0...7) * @param number - EP num (0...7)
* @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
@ -349,12 +345,12 @@ static uint16_t lastaddr = USB_EP0_BASEADDR;
* @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, uint16_t (*func)(ep_t ep)){
if(number >= ENDPOINTS_NUM) 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
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1; USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
if(rxsz & 1 || rxsz > 992) return 3; // wrong rx buffer size if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size
uint16_t countrx = 0; uint16_t countrx = 0;
if(rxsz < 64) countrx = rxsz / 2; if(rxsz < 64) countrx = rxsz / 2;
else{ else{
@ -362,18 +358,18 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t
countrx = 31 + rxsz / 32; countrx = 31 + rxsz / 32;
} }
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); endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2);
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;
endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr); endpoints[number].rx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr*2);
lastaddr += rxsz; lastaddr += rxsz;
// buffer size: Table127 of RM
USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10;
endpoints[number].func = func; endpoints[number].func = func;
return 0; return 0;
} }
//extern int8_t dump;
// standard IRQ handler // standard IRQ handler
void usb_isr(){ void usb_isr(){
if (USB->ISTR & USB_ISTR_RESET){ if (USB->ISTR & USB_ISTR_RESET){
@ -382,8 +378,10 @@ void usb_isr(){
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 = USB_EP0_BASEADDR; // roll back to beginning of buffer lastaddr = LASTADDR_DEFAULT;
EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler); 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 // state is default - wait for enumeration
@ -394,6 +392,7 @@ void usb_isr(){
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 // Calculate flags
endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0; endpoints[n].rx_flag = (epstatus & USB_EPnR_CTR_RX) ? 1 : 0;
endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0;
@ -404,12 +403,12 @@ void usb_isr(){
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(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(n == 0){ // control endpoint
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack 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, (uint16_t*)&setup_packet);
ep0dbuflen = 0; ep0dbuflen = 0;
// interrupt handler will be called later // interrupt handler will be called later
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf }else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
ep0dbuflen = endpoints[0].rx_cnt; ep0dbuflen = endpoints[0].rx_cnt;
memcpy(ep0databuf, endpoints[0].rx_buf, ep0dbuflen); EP_Read(0, (uint16_t*)&ep0databuf);
} }
} }
}else{ // IN interrupt - transmit data, only CTR_TX == 1 }else{ // IN interrupt - transmit data, only CTR_TX == 1
@ -430,6 +429,45 @@ void usb_isr(){
} }
} }
/*
if (USB->ISTR & USB_ISTR_PMAOVR) {
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();
}
/** /**
* Write data to EP buffer (called from IRQ handler) * Write data to EP buffer (called from IRQ handler)
* @param number - EP number * @param number - EP number
@ -442,8 +480,9 @@ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
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;
for (i = 0; i < N2; i++){ uint32_t *out = (uint32_t *)endpoints[number].tx_buf;
endpoints[number].tx_buf[i] = buf16[i]; for(i = 0; i < N2; ++i, ++out){
*out = buf16[i];
} }
USB_BTABLE->EP[number].USB_COUNT_TX = size; USB_BTABLE->EP[number].USB_COUNT_TX = size;
} }
@ -469,13 +508,14 @@ void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
* @param *buf - user array for data * @param *buf - user array for data
* @return amount of data read * @return amount of data read
*/ */
int EP_Read(uint8_t number, uint8_t *buf){ int EP_Read(uint8_t number, uint16_t *buf){
int n = endpoints[number].rx_cnt; int n = (endpoints[number].rx_cnt + 1) >> 1;
uint32_t *in = (uint32_t *)endpoints[number].rx_buf;
if(n){ if(n){
for(int i = 0; i < n; ++i) for(int i = 0; i < n; ++i, ++in)
buf[i] = endpoints[number].rx_buf[i]; buf[i] = *(uint16_t*)in;
} }
return n; return endpoints[number].rx_cnt;
} }
// USB status // USB status

View File

@ -29,9 +29,10 @@
#include "usb_defs.h" #include "usb_defs.h"
#define EP0DATABUF_SIZE (64) #define EP0DATABUF_SIZE (64)
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
// Max EP amount (EP0 + other used) // Max EP amount (EP0 + other used)
#define ENDPOINTS_NUM 4 //#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
@ -145,7 +146,7 @@ typedef struct {
// endpoints state // endpoints state
typedef struct __ep_t{ typedef struct __ep_t{
uint16_t *tx_buf; // transmission buffer address uint16_t *tx_buf; // transmission buffer address
uint8_t *rx_buf; // reception buffer address uint16_t *rx_buf; // reception buffer address
uint16_t (*func)(); // endpoint action function uint16_t (*func)(); // endpoint action function
uint16_t status; // status flags uint16_t status; // status flags
unsigned rx_cnt : 10; // received data counter unsigned rx_cnt : 10; // received data counter
@ -190,10 +191,9 @@ 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, uint16_t (*func)(ep_t ep));
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, uint8_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 WEAK linecoding_handler(usb_LineCoding *lc);
void WEAK clstate_handler(uint16_t val); void WEAK clstate_handler(uint16_t val);
void WEAK break_handler(); void WEAK break_handler();