A few bug fixes, remove the unstested device notices, note supported boards in READMEs, and implement PMA

access stride (used on MCU's with 512 byte USB buffers).
This commit is contained in:
Nathan Conrad
2019-09-10 01:03:24 -04:00
parent 8f3c0663ad
commit bc2a65b20b
5 changed files with 123 additions and 50 deletions

View File

@@ -29,11 +29,17 @@
*/
/**********************************************
* This driver should work with minimal for the ST Micro "USB A" peripheral. This
* covers:
* This driver has been tested with the following MCUs:
*
*
* STM32F070RB
*
*
* It also should work with minimal changes for any ST MCU with an "USB A" peripheral. This
* covers:
*
* F04x, F072, F078, 070x6/B 1024 byte buffer
* F102, F103 512 byte buffer; no internal D+ pull-up
* F102, F103 512 byte buffer; no internal D+ pull-up (maybe many more changes?)
* F302xB/C, F303xB/C, F373 512 byte buffer; no internal D+ pull-up
* F302x6/8, F302xD/E2, F303xD/E 1024 byte buffer; no internal D+ pull-up
* L0x2, L0x3 1024 byte buffer
@@ -70,6 +76,11 @@
* - Minimal error handling
* - Perhaps error interrupts sholud be reported to the stack, or cause a device reset?
* - Assumes a single USB peripheral; I think that no hardware has multiple so this is fine.
* - Add a callback for enabling/disabling the D+ PU on devices without an internal PU.
* - F3 models use three separate interrupts. I think we could only use the LP interrupt for
* everything? However, the interrupts are configurable so the DisableInt and EnableInt
* below functions could be adjusting the wrong interrupts (if they had been reconfigured)
* - LPM is not used correctly, or at all?
*
* USB documentation and Reference implementations
* - STM32 Reference manuals
@@ -92,7 +103,7 @@
#include "tusb_option.h"
#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_STM32_FSDEV
#if (TUSB_OPT_DEVICE_ENABLED) && ((CFG_TUSB_MCU) == (OPT_MCU_STM32_FSDEV))
// In order to reduce the dependance on HAL, we undefine this.
// Some definitions are copied to our private include file.
@@ -137,6 +148,7 @@
// per STM32F3 reference manual
#error BTABLE must be aligned to 8 bytes
#endif
// Max size of a USB FS packet is 64...
#define MAX_PACKET_SIZE 64
@@ -204,17 +216,21 @@ void dcd_init (uint8_t rhport)
// Initialize the BTABLE for EP0 at this point (though setting up the EP0R is unneeded)
// This is actually not necessary, but helps debugging to start with a blank RAM area
for(uint16_t i=0;i<(PMA_LENGTH>>1); i++)
for(uint16_t i=0;i<(DCD_STM32_BTABLE_LENGTH>>1); i++)
{
((uint16_t*)USB_PMAADDR)[DCD_STM32_BTABLE_BASE + i] = 0u;
pma[PMA_STRIDE*(DCD_STM32_BTABLE_BASE + i)] = 0u;
}
USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_SOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
dcd_handle_bus_reset();
// And finally enable pull-up, which may trigger the RESET IRQ if the host is connected.
// (if this MCU has an internal pullup)
#if defined(USB_BCDR_DPPU)
USB->BCDR |= USB_BCDR_DPPU;
#else
// FIXME: callback to the user to ask them to twiddle a GPIO to disable/enable D+???
#endif
}
// Enable device interrupt
@@ -225,14 +241,12 @@ void dcd_int_enable (uint8_t rhport)
NVIC_SetPriority(USB_IRQn, 0);
NVIC_EnableIRQ(USB_IRQn);
#elif defined(STM32F3)
#warning need to check these since the F3 can have its USB interrupts remapped.
NVIC_SetPriority(USB_HP_CAN_TX_IRQn, 0);
NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 0);
NVIC_SetPriority(USBWakeUp_IRQn, 0);
NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn);
NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
NVIC_EnableIRQ(USBWakeUp_IRQn);
#endif
}
@@ -243,7 +257,6 @@ void dcd_int_disable(uint8_t rhport)
#if defined(STM32F0)
NVIC_DisableIRQ(USB_IRQn);
#elif defined(STM32F3)
#warning need to check these since the F3 can have its USB interrupts remapped.
NVIC_DisableIRQ(USB_HP_CAN_TX_IRQn);
NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn);
NVIC_DisableIRQ(USBWakeUp_IRQn);
@@ -311,7 +324,7 @@ static void dcd_handle_bus_reset(void)
EPREG(0) = 0u;
}
ep_buf_ptr = 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each)
ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8*MAX_EP_COUNT; // 8 bytes per endpoint (two TX and two RX words, each)
dcd_edpt_open (0, &ep0OUT_desc);
dcd_edpt_open (0, &ep0IN_desc);
newDADDR = 0;
@@ -386,7 +399,7 @@ static uint16_t dcd_ep_ctr_handler(void)
/* Get SETUP Packet*/
count = PCD_GET_EP_RX_CNT(USB, EPindex);
//TU_ASSERT_ERR(count == 8);
dcd_read_packet_memory(userMemBuf, *PCD_EP_RX_ADDRESS(USB,EPindex), 8);
dcd_read_packet_memory(userMemBuf, *PCD_EP_RX_ADDRESS_PTR(USB,EPindex), 8);
/* SETUP bit kept frozen while CTR_RX = 1*/
dcd_event_setup_received(0, (uint8_t*)userMemBuf, true);
PCD_CLEAR_RX_EP_CTR(USB, EPindex);
@@ -401,7 +414,7 @@ static uint16_t dcd_ep_ctr_handler(void)
if (count != 0U)
{
dcd_read_packet_memory(xfer->buffer, *PCD_EP_RX_ADDRESS(USB,EPindex), count);
dcd_read_packet_memory(xfer->buffer, *PCD_EP_RX_ADDRESS_PTR(USB,EPindex), count);
xfer->queued_len = (uint16_t)(xfer->queued_len + count);
}
@@ -440,7 +453,7 @@ static uint16_t dcd_ep_ctr_handler(void)
if (count != 0U)
{
dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]),
*PCD_EP_RX_ADDRESS(USB,EPindex), count);
*PCD_EP_RX_ADDRESS_PTR(USB,EPindex), count);
}
/*multi-packet on the NON control OUT endpoint */
@@ -568,14 +581,14 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
if(dir == TUSB_DIR_IN)
{
*PCD_EP_TX_ADDRESS(USB, epnum) = ep_buf_ptr;
*PCD_EP_TX_ADDRESS_PTR(USB, epnum) = ep_buf_ptr;
PCD_SET_EP_RX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size);
PCD_CLEAR_TX_DTOG(USB, epnum);
PCD_SET_EP_TX_STATUS(USB,epnum,USB_EP_TX_NAK);
}
else
{
*PCD_EP_RX_ADDRESS(USB, epnum) = ep_buf_ptr;
*PCD_EP_RX_ADDRESS_PTR(USB, epnum) = ep_buf_ptr;
PCD_SET_EP_RX_CNT(USB, epnum, p_endpoint_desc->wMaxPacketSize.size);
PCD_CLEAR_RX_DTOG(USB, epnum);
PCD_SET_EP_RX_STATUS(USB, epnum, USB_EP_RX_NAK);
@@ -596,11 +609,11 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint16_t ep_ix)
{
len = 64u;
}
dcd_write_packet_memory(*PCD_EP_TX_ADDRESS(USB,ep_ix), &(xfer->buffer[xfer->queued_len]), len);
dcd_write_packet_memory(*PCD_EP_TX_ADDRESS_PTR(USB,ep_ix), &(xfer->buffer[xfer->queued_len]), len);
xfer->queued_len = (uint16_t)(xfer->queued_len + len);
PCD_SET_EP_TX_CNT(USB,ep_ix,len);
PCD_SET_EP_TX_STATUS(USB, ep_ix, USB_EP_TX_VALID)
PCD_SET_EP_TX_STATUS(USB, ep_ix, USB_EP_TX_VALID);
}
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
@@ -687,8 +700,8 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
* @brief Copy a buffer from user memory area to packet memory area (PMA).
* This uses byte-access for user memory (so support non-aligned buffers)
* and 16-bit access for packet memory.
* @param dst, but not necessary in system-memory addressing
* @param pbUsrBuf pointer to user memory area.
* @param dst, byte address in PMA; must be 16-bit aligned
* @param src pointer to user memory area.
* @param wPMABufAddr address into PMA.
* @param wNBytes no. of bytes to be copied.
* @retval None
@@ -699,19 +712,27 @@ static void dcd_write_packet_memory(uint16_t dst, const void *__restrict src, si
uint32_t i;
uint16_t temp1, temp2;
const uint8_t * srcVal;
#ifdef DEBUG
if(((dst%2) != 0) ||
(dst < DCD_STM32_BTABLE_BASE) ||
dst >= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH))
while(1) TU_BREAKPOINT();
#endif
// The GCC optimizer will combine access to 32-bit sizes if we let it. Force
// it volatile so that it won't do that.
__IO uint16_t *pdwVal;
srcVal = src;
pdwVal = (__IO uint16_t*)( ((uint8_t*)USB) + 0x400U + dst );
pdwVal = &pma[PMA_STRIDE*(dst>>1)];
for (i = n; i != 0; i--)
{
temp1 = (uint16_t) *srcVal;
srcVal++;
temp2 = temp1 | ((uint16_t)((uint16_t) ((*srcVal) << 8U))) ;
*pdwVal++ = temp2;
*pdwVal = temp2;
pdwVal += PMA_STRIDE;
srcVal++;
}
}
@@ -731,19 +752,28 @@ static void dcd_read_packet_memory(void *__restrict dst, uint16_t src, size_t wN
__IO const uint16_t *pdwVal;
uint32_t temp;
pdwVal = (__IO uint16_t*)( ((uint8_t*)USB) + 0x400U + src );
#ifdef DEBUG
if((src%2) != 0 ||
(src < DCD_STM32_BTABLE_BASE) ||
src >= (DCD_STM32_BTABLE_BASE + DCD_STM32_BTABLE_LENGTH))
while(1) TU_BREAKPOINT();
#endif
pdwVal = &pma[PMA_STRIDE*(src>>1)];
uint8_t *dstVal = (uint8_t*)dst;
for (i = n; i != 0U; i--)
{
temp = *pdwVal++;
temp = *pdwVal;
pdwVal += PMA_STRIDE;
*dstVal++ = ((temp >> 0) & 0xFF);
*dstVal++ = ((temp >> 8) & 0xFF);
}
if (wNBytes % 2)
{
temp = *pdwVal++;
temp = *pdwVal;
pdwVal += PMA_STRIDE;
*dstVal++ = ((temp >> 0) & 0xFF);
}
}