- USB driver: TX FIFO overpushing fixed

- USB driver: TX FIFO allocated address must be in WORDs (fixed)
This commit is contained in:
Wiesner András 2024-04-20 10:51:43 +02:00
parent 8ef6249e01
commit db4e59cfd9
3 changed files with 16 additions and 14 deletions

View File

@ -8,6 +8,8 @@
#include <blocking_io/blocking_fifo.h> #include <blocking_io/blocking_fifo.h>
#include <cmsis_gcc.h>
// state // state
static USB_CdcState cdcs = { 0 }; static USB_CdcState cdcs = { 0 };
static uint8_t tx_buffer[USB_CDC_PCKT_BUFSIZE]; static uint8_t tx_buffer[USB_CDC_PCKT_BUFSIZE];

View File

@ -62,7 +62,7 @@ typedef struct {
// ---------------- // ----------------
#define USB_CDC_PCKT_BUFSIZE (64) #define USB_CDC_PCKT_BUFSIZE (72)
// ---------------- // ----------------

View File

@ -265,7 +265,7 @@ void usbdrv_build_fifo() {
for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) { for (uint8_t i = 0; i < USB_NUM_OF_ENDPOINTS; i++) {
USBDRV_EpConfig *cfg = &gs.ep_IN[i]; USBDRV_EpConfig *cfg = &gs.ep_IN[i];
if (cfg->is_configured) { if (cfg->is_configured) {
cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, cfg->max_packet_size)); // correct FIFO size if necessary cfg->fifo_size = CEIL4(MAX(USB_MIN_GROSS_TX_FIFO_SIZE, 2 * cfg->max_packet_size + USB_FIFO_MARGIN)); // correct FIFO size if necessary
cfg->fifo_address = next_fifo_addr; // store FIFO address cfg->fifo_address = next_fifo_addr; // store FIFO address
cfg->zlp_next = false; // clear ZLP next cfg->zlp_next = false; // clear ZLP next
next_fifo_addr += cfg->fifo_size; // advance next address next_fifo_addr += cfg->fifo_size; // advance next address
@ -346,7 +346,7 @@ void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *c
WRITE_FIELD(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_TXFNUM, ep); WRITE_FIELD(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_TXFNUM, ep);
// store Tx FIFO size // store Tx FIFO size
uint32_t tx_fifo_config = ((cfg->fifo_size >> 2) << USB_OTG_DIEPTXF_INEPTXFD_Pos) | cfg->fifo_address; // combine size in DWORDs and address uint32_t tx_fifo_config = ((cfg->fifo_size >> 2) << USB_OTG_DIEPTXF_INEPTXFD_Pos) | (cfg->fifo_address >> 2); // combine size in DWORDs and address
*(USB_pDIEPTXF[ep]) = tx_fifo_config; // save *(USB_pDIEPTXF[ep]) = tx_fifo_config; // save
// enable interrupt // enable interrupt
@ -477,9 +477,9 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
// determine final write size // determine final write size
uint32_t freeSize = 0; uint32_t freeSize = 0;
if (len > 0) { // only poll DTXFSTS if (len > 0) (see datasheet) // if (len > 0) { // only poll DTXFSTS if (len > 0) (see datasheet)
freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size freeSize = USBINEP[ep].DTXFSTS * sizeof(uint32_t); // get free transmit buffer size
} //}
uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size uint16_t writeSize = MIN(freeSize, len); // limit transmit size to free size
// calculate packet count based on max packet size // calculate packet count based on max packet size
@ -493,7 +493,7 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
gs.ep_IN[ep].zlp_next = (writeSize > 0) && ((writeSize % mps) == 0); gs.ep_IN[ep].zlp_next = (writeSize > 0) && ((writeSize % mps) == 0);
// program DIEPTSIZ with transfer length // program DIEPTSIZ with transfer length
USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize; USBINEP[ep].DIEPTSIZ = (packet_count << USB_OTG_DIEPTSIZ_MULCNT_Pos) | (packet_count << USB_OTG_DIEPTSIZ_PKTCNT_Pos) | writeSize;
// enable endpoint and cancel responding NAK // enable endpoint and cancel responding NAK
SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK); SET_BIT(USBINEP[ep].DIEPCTL, USB_OTG_DIEPCTL_EPENA | USB_OTG_DIEPCTL_CNAK);
@ -511,11 +511,11 @@ uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len) {
} }
// push the remaining partial dword // push the remaining partial dword
uint8_t rem_bytes = len & 0b11; uint8_t rem_bytes = writeSize & 0b11;
if (rem_bytes > 0) { if (rem_bytes > 0) {
uint32_t rem_dword = 0; uint32_t rem_dword = 0;
uint16_t rem_start = len - rem_bytes; uint16_t rem_start = writeSize - rem_bytes;
for (int16_t i = len - 1; i >= rem_start; i--) { for (int16_t i = writeSize - 1; i >= rem_start; i--) {
rem_dword = (rem_dword << 8) | data[i]; rem_dword = (rem_dword << 8) | data[i];
} }
*p = rem_dword; *p = rem_dword;