- the way TxFIFO empty interrupts are handled has been redesigned, and the ability to "wake up" the endpoint added
This commit is contained in:
parent
25dc4a9aa8
commit
9a34b5e286
@ -125,6 +125,7 @@ int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
|
||||
void usb_cdc_write(const uint8_t * data, uint32_t size) {
|
||||
if (cdcs.initialized) {
|
||||
bfifo_push_all(&fifo, data, size);
|
||||
usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
|
||||
}
|
||||
}
|
||||
|
||||
|
14
usb.c
14
usb.c
@ -25,7 +25,14 @@
|
||||
|
||||
// ---------------
|
||||
|
||||
static uint8_t tx_assembly_buf[USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS] DWORD_ALIGN; // buffer for assembling packets
|
||||
#ifndef USB_HIGH_SPEED
|
||||
#define USB_RX_BUF_SIZE (USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS)
|
||||
#else
|
||||
#define USB_RX_BUF_SIZE (USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS)
|
||||
#endif
|
||||
|
||||
|
||||
static uint8_t tx_assembly_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // buffer for assembling packets
|
||||
|
||||
// ---------------
|
||||
|
||||
@ -241,7 +248,12 @@ void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) {
|
||||
}
|
||||
}
|
||||
|
||||
void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir) {
|
||||
usbdrv_enable_endpoint_interrupt(ep, dir, true);
|
||||
}
|
||||
|
||||
uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size) {
|
||||
usbdrv_enable_endpoint_interrupt(ep, USB_IN, true);
|
||||
return usbdrv_arm_IN_endpoint(ep, data, size);
|
||||
}
|
||||
|
||||
|
1
usb.h
1
usb.h
@ -6,5 +6,6 @@
|
||||
void usbcore_init(); // initialize USB core
|
||||
uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint, return with number of bytes actually written
|
||||
uint32_t usbcore_schedule_reception(uint8_t ep, uint16_t size); // expect data coming from the endpoint
|
||||
void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir); // wake up endpoint
|
||||
|
||||
#endif /* CORE_USB_USB */
|
||||
|
65
usb_driver.c
65
usb_driver.c
@ -8,6 +8,9 @@
|
||||
|
||||
#include "desc/usb_desc.h"
|
||||
|
||||
#include "embfmt/embformat.h"
|
||||
#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
|
||||
|
||||
// ---------------
|
||||
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
@ -24,7 +27,13 @@
|
||||
|
||||
static USBDRV_GlobalState gs; // global USB state
|
||||
|
||||
static uint8_t rx_buf[USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS] DWORD_ALIGN; // receive buffer
|
||||
#ifndef USB_HIGH_SPEED
|
||||
#define USB_RX_BUF_SIZE (USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS)
|
||||
#else
|
||||
#define USB_RX_BUF_SIZE (USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS)
|
||||
#endif
|
||||
|
||||
static uint8_t rx_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // receive buffer
|
||||
|
||||
#define USB_EVENT_QUEUE_LENGTH (16)
|
||||
|
||||
@ -115,7 +124,7 @@ void usbdrv_gpio_init() {
|
||||
|
||||
// initialize USB subsystem
|
||||
void usbdrv_init() {
|
||||
NVIC_DisableIRQ(USB_IRQn);
|
||||
HAL_NVIC_DisableIRQ(USB_IRQn);
|
||||
|
||||
usbdrv_init_global_state();
|
||||
usbdrv_gpio_init();
|
||||
@ -123,8 +132,8 @@ void usbdrv_init() {
|
||||
usbdrv_initial_ep0_setup();
|
||||
usbdrv_power_and_connect(true);
|
||||
|
||||
NVIC_SetPriority(USB_IRQn, 7);
|
||||
NVIC_EnableIRQ(USB_IRQn);
|
||||
HAL_NVIC_SetPriority(USB_IRQn, 8, 0);
|
||||
HAL_NVIC_EnableIRQ(USB_IRQn);
|
||||
}
|
||||
|
||||
void usbdrv_reset() {
|
||||
@ -258,8 +267,8 @@ void usbdrv_periph_init() {
|
||||
|
||||
#ifdef USB_HIGH_SPEED
|
||||
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED);
|
||||
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_HIGH_SPEED_ULPI);
|
||||
//WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED_ULPI);
|
||||
// WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_HIGH_SPEED_ULPI);
|
||||
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED_ULPI);
|
||||
#else
|
||||
WRITE_FIELD(USBD->DCFG, USB_OTG_DCFG_DSPD, USB_LINESPEED_FULL_SPEED); // there's no other possible option
|
||||
#endif
|
||||
@ -396,6 +405,9 @@ void usbdrv_fetch_endpoint_configuration(uint8_t config_index) {
|
||||
#define USB_MIN_GROSS_RX_FIFO_SIZE (256)
|
||||
#endif
|
||||
|
||||
#define USBDRV_ADDR_TABLE_STR_LEN (255)
|
||||
static char usbdrv_addr_table[USBDRV_ADDR_TABLE_STR_LEN + 1];
|
||||
|
||||
// build FIFO (compute addresses)
|
||||
void usbdrv_build_fifo() {
|
||||
// ---- OUT ----
|
||||
@ -430,19 +442,28 @@ void usbdrv_build_fifo() {
|
||||
next_fifo_addr += fifo_size; // advance next FIFO address
|
||||
usbdrv_set_rx_fifo_size(fifo_size); // set Rx FIFO size in hardware
|
||||
|
||||
uint32_t str_offset = SNPRINTF(usbdrv_addr_table, USBDRV_ADDR_TABLE_STR_LEN, "RX: 000-%03x (%u)\r\n", fifo_size - 1, fifo_size);
|
||||
|
||||
// ---- IN ----
|
||||
for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) {
|
||||
USBDRV_EpConfig *cfg = &gs.ep_IN[i];
|
||||
if (cfg->is_configured) {
|
||||
cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, 2 * cfg->max_packet_size)); // correct FIFO size if necessary
|
||||
cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, cfg->max_packet_size + 64)); // correct FIFO size if necessary
|
||||
cfg->fifo_address = next_fifo_addr; // store FIFO address
|
||||
cfg->zlp_next = false;
|
||||
|
||||
str_offset += SNPRINTF(usbdrv_addr_table + str_offset, USBDRV_ADDR_TABLE_STR_LEN - str_offset, "TX%u: %03x-%03x (%u)\r\n", i, next_fifo_addr, next_fifo_addr + cfg->fifo_size - 1, cfg->fifo_size);
|
||||
|
||||
// cfg->txp = false; // no transfer is in progress
|
||||
next_fifo_addr += cfg->fifo_size; // advance next address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char * usbdrv_get_fifo_addr_table() {
|
||||
return usbdrv_addr_table;
|
||||
}
|
||||
|
||||
// create an initial setup for EP0 in both directions
|
||||
void usbdrv_initial_ep0_setup() {
|
||||
// setup EP0 OUT and IN
|
||||
@ -511,7 +532,6 @@ void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *c
|
||||
SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_USBAEP); // the endpoint is active in the current configuration
|
||||
}
|
||||
|
||||
|
||||
// ---- common for all endpoints ----
|
||||
|
||||
// program FIFO corresponding FIFO number
|
||||
@ -522,7 +542,7 @@ void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *c
|
||||
*(USB_pDIEPTXF[ep]) = tx_fifo_config; // save
|
||||
|
||||
// enable interrupt
|
||||
SET_BIT(USBD->DAINTMSK, 1 << ep);
|
||||
// SET_BIT(USBD->DAINTMSK, 1 << ep);
|
||||
|
||||
// NAK processing
|
||||
if (cfg->responding_NAK) {
|
||||
@ -685,6 +705,9 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
|
||||
|
||||
// enable endpoint and cancel responding NAK
|
||||
SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK);
|
||||
|
||||
// enable endpoint interrupts
|
||||
SET_BIT(USBD->DAINTMSK, 1 << ep);
|
||||
}
|
||||
|
||||
// turn on interrupt generation only, if this is NOT the last FIFO write considering the current transfer
|
||||
@ -753,6 +776,15 @@ void usbdrv_autoarm_OUT_endpoint(uint8_t ep) {
|
||||
gs.ep_OUT[ep].autoarm = true;
|
||||
}
|
||||
|
||||
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en) {
|
||||
uint32_t mask = 1 << (ep + ((dir == USB_OUT) ? USB_OTG_DAINTMSK_OEPM_Pos : 0));
|
||||
if (en) {
|
||||
SET_BIT(USBD->DAINTMSK, mask);
|
||||
} else {
|
||||
CLEAR_BIT(USBD->DAINTMSK, mask);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------
|
||||
|
||||
void usbdrv_set_address(uint8_t addr) {
|
||||
@ -858,7 +890,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
|
||||
// SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
|
||||
} else { // not EP0
|
||||
if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) { // TODO maybe the
|
||||
if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) { // TODO: "maybe the"????
|
||||
USBDRV_CallbackCompound cbcpd;
|
||||
cbcpd.ep = evt_data.rx.ep_num;
|
||||
cbcpd.dir = USB_OUT;
|
||||
@ -903,7 +935,8 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
|
||||
for (uint8_t ep = 0; ep < USB_NUM_OF_ENDPOINTS; ep++) {
|
||||
cbcpd.ep = ep;
|
||||
if (gs.ep_IN[ep].is_configured) { // if the endpoint is running
|
||||
bool ep_on = USBD->DAINTMSK & (1 << ep); // decide if this endpoint is currently enable for transmission based on its endpoint mask
|
||||
if (gs.ep_IN[ep].is_configured && ep_on) { // if the endpoint is running
|
||||
if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC)) { // timeout done
|
||||
SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_TOC);
|
||||
USBMSG("TO\n");
|
||||
@ -931,14 +964,24 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
|
||||
cbcpd.code = USB_CBC_IN_DONE;
|
||||
usbcore_process_nonsetup_event(&cbcpd);
|
||||
}
|
||||
|
||||
} else if (READ_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE)) { // IN endpoint IN token received with Tx FIFO empty interrupt
|
||||
SET_BIT(USBINEP[ep].DIEPINT, USB_OTG_DIEPINT_ITTXFE);
|
||||
|
||||
// MSG("E %u\n", ep);
|
||||
|
||||
// USBMSG("IN FIFOEMPTY [%d]\n", ep);
|
||||
|
||||
// transfer finished
|
||||
// gs.ep_IN[ep].txp = false;
|
||||
|
||||
// if (!gs.ep_IN[ep].) {
|
||||
|
||||
//}
|
||||
|
||||
// disable endpoint interrupt
|
||||
usbdrv_enable_endpoint_interrupt(ep, USB_IN, false);
|
||||
|
||||
cbcpd.code = USB_CBC_IN_FIFOEMPTY;
|
||||
usbcore_process_nonsetup_event(&cbcpd);
|
||||
}
|
||||
|
@ -7,9 +7,13 @@
|
||||
|
||||
// #define USBDBGMSG
|
||||
|
||||
#define USB_NUM_OF_ENDPOINTS (4)
|
||||
#define USB_NUM_OF_ENDPOINTS (4) // FIXME: this is module-dependend
|
||||
|
||||
// non isochronous transfers
|
||||
#define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64)
|
||||
#define USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS (512)
|
||||
|
||||
// isochronous transfers
|
||||
#define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023)
|
||||
|
||||
#define USB_MIN_EP_FIFO_SIZE (64)
|
||||
@ -135,6 +139,7 @@ void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConf
|
||||
void usbdrv_clear_endpoint_config(); // clear endpoint config
|
||||
void usbdrv_apply_endpoint_config(); // apply preloaded endpoint configuration
|
||||
void usbdrv_build_fifo(); // build FIFO (compute addresses)
|
||||
const char *usbdrv_get_fifo_addr_table(); // get FIFO address table
|
||||
|
||||
void usbdrv_fetch_endpoint_configuration(uint8_t config_index); // fetch endpoint configuration from descriptor dump
|
||||
void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint
|
||||
@ -153,7 +158,7 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len);
|
||||
#define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0)
|
||||
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size); // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint)
|
||||
void usbdrv_autoarm_OUT_endpoint(uint8_t ep); // automatically re-arm OUT endpoint at the and of the current OUT transfer
|
||||
|
||||
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en); // enable/disable endpoint interrupt signaling
|
||||
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir); // get endpoint interrupt flag
|
||||
|
||||
void usbdrv_set_address(uint8_t addr); // set device address
|
||||
|
Loading…
x
Reference in New Issue
Block a user