Compiles but not tested and there are known errors. ISOC part not yet enabled.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15075 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-11-14 10:30:33 +00:00
parent 2a27797871
commit 8ba8bd3f72
2 changed files with 97 additions and 79 deletions

View File

@ -32,10 +32,6 @@
/* Driver local definitions. */
/*===========================================================================*/
#define BTABLE_ADDR 0x0000
#define EPR_EP_TYPE_IS_ISO(bits) ((bits & EPR_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS)
/**
* @brief Returns an endpoint descriptor pointer.
*/
@ -221,19 +217,22 @@ static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) {
/**
* @brief Reads from a dedicated packet buffer.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[out] buf buffer where to copy the packet data
* @return The size of the receivee packet.
*
* @notapi
*/
static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
static size_t usb_packet_read_to_buffer(USBDriver *usbp,
usbep_t ep,
uint8_t *buf) {
size_t i, n;
uint32_t w;
USB_DRD_PMABuffDescTypeDef *udp = USB_GET_DESCRIPTOR(ep);
uint32_t *pmap = USB_GET_RX_BUFFER(udp);
#if STM32_USB_USE_ISOCHRONOUS
uint32_t epr = STM32_USB->CHEPR[ep];
uint32_t epr = usbp->usb->CHEPR[ep];
/* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
@ -249,6 +248,8 @@ static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
n = USB_GET_RX_COUNT0(udp);
}
#else
(void)usbp;
n = USB_GET_RX_COUNT0(udp);
#endif
@ -311,6 +312,7 @@ static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
/**
* @brief Writes to a dedicated packet buffer.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] buf buffer where to fetch the packet data
* @param[in] n maximum number of bytes to copy. This value must
@ -318,7 +320,8 @@ static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
*
* @notapi
*/
static void usb_packet_write_from_buffer(usbep_t ep,
static void usb_packet_write_from_buffer(USBDriver *usbp,
usbep_t ep,
const uint8_t *buf,
size_t n) {
USB_DRD_PMABuffDescTypeDef *udp = USB_GET_DESCRIPTOR(ep);
@ -326,7 +329,7 @@ static void usb_packet_write_from_buffer(usbep_t ep,
int i = (int)n;
#if STM32_USB_USE_ISOCHRONOUS
uint32_t epr = STM32_USB->CHEPR[ep];
uint32_t epr = usbp->usb->CHEPR[ep];
/* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
@ -341,6 +344,8 @@ static void usb_packet_write_from_buffer(usbep_t ep,
USB_SET_TX_COUNT0(udp, n);
}
#else
(void)usbp;
USB_SET_TX_COUNT0(udp, n);
#endif
@ -395,16 +400,17 @@ static void usb_packet_write_from_buffer(usbep_t ep,
* @brief Common ISR code, serves the EP-related interrupts.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
* @param[in] istr ISTR register value to consider
*
* @notapi
*/
static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
static void usb_serve_endpoints(USBDriver *usbp, uint32_t istr) {
size_t n;
uint32_t ep = istr & USB_ISTR_IDN_Msk;
uint32_t chepr = usbp->usb->CHEPR[ep];
const USBEndpointConfig *epcp = usbp->epc[ep];
if (chepr & USB_EP_VTTX) {
if ((istr & USB_ISTR_DIR) == 0U) {
/* IN endpoint, transmission.*/
USBInEndpointState *isp = epcp->in_state;
@ -420,7 +426,7 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
/* Writes the packet from the defined buffer.*/
isp->txbuf += isp->txlast;
isp->txlast = n;
usb_packet_write_from_buffer(ep, isp->txbuf, n);
usb_packet_write_from_buffer(usbp, ep, isp->txbuf, n);
/* Starting IN operation.*/
CHEPR_SET_STATTX(usbp, ep, USB_EP_TX_VALID);
@ -430,7 +436,7 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
_usb_isr_invoke_in_cb(usbp, ep);
}
}
if (chepr & USB_EP_VTRX) {
else {
/* OUT endpoint, receive.*/
CHEPR_CLEAR_VTRX(usbp, ep);
@ -444,7 +450,7 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
USBOutEndpointState *osp = epcp->out_state;
/* Reads the packet into the defined buffer.*/
n = usb_packet_read_to_buffer(ep, osp->rxbuf);
n = usb_packet_read_to_buffer(usbp, ep, osp->rxbuf);
osp->rxbuf += n;
/* Transaction data updated.*/
@ -485,10 +491,10 @@ OSAL_IRQ_HANDLER(STM32_USB1_HP_HANDLER) {
OSAL_IRQ_PROLOGUE();
/* Endpoint events handling.*/
istr = STM32_USB->ISTR;
while (istr & USB_ISTR_SOF) {
usb_serve_endpoints(usbp, istr & USB_ISTR_IDN_Msk);
istr = STM32_USB->ISTR;
istr = usbp->usb->ISTR;
while ((istr & USB_ISTR_SOF) != 0U) {
usb_serve_endpoints(usbp, istr);
istr = usbp->usb->ISTR;
}
OSAL_IRQ_EPILOGUE();
@ -507,54 +513,53 @@ OSAL_IRQ_HANDLER(STM32_USB1_LP_HANDLER) {
OSAL_IRQ_PROLOGUE();
istr = STM32_USB->ISTR;
/* Reading interrupt sources and atomically clearing them.*/
istr = usbp->usb->ISTR;
usbp->usb->ISTR = ~istr;
/* USB bus reset condition handling.*/
if (istr & USB_ISTR_RESET) {
STM32_USB->ISTR = ~USB_ISTR_RESET;
_usb_reset(usbp);
}
/* USB bus SUSPEND condition handling.*/
if (istr & USB_ISTR_SUSP) {
STM32_USB->CNTR |= USB_CNTR_SUSPEN;
if ((istr & USB_ISTR_SUSP) != 0U) {
usbp->usb->CNTR |= USB_CNTR_SUSPEN;
#if STM32_USB_LOW_POWER_ON_SUSPEND
STM32_USB->CNTR |= USB_CNTR_LP_MODE;
usbp->usb->CNTR |= USB_CNTR_LP_MODE;
#endif
STM32_USB->ISTR = ~USB_ISTR_SUSP;
_usb_suspend(usbp);
}
/* USB bus WAKEUP condition handling.*/
if (istr & USB_ISTR_WKUP) {
uint32_t fnr = STM32_USB->FNR;
if (!(fnr & USB_FNR_RXDP)) {
STM32_USB->CNTR &= ~USB_CNTR_SUSPEN;
if ((istr & USB_ISTR_WKUP) != 0U) {
uint32_t fnr = usbp->usb->FNR;
if ((fnr & USB_FNR_RXDP) == 0U) {
_usb_wakeup(usbp);
}
#if STM32_USB_LOW_POWER_ON_SUSPEND
else {
/* Just noise, going back in SUSPEND mode, reference manual 22.4.5,
table 169.*/
STM32_USB->CNTR |= USB_CNTR_LP_MODE;
usbp->usb->CNTR |= USB_CNTR_LP_MODE;
}
#endif
STM32_USB->ISTR = ~USB_ISTR_WKUP;
}
/* SOF handling.*/
if (istr & USB_ISTR_SOF) {
if ((istr & USB_ISTR_SOF) != 0U) {
_usb_isr_invoke_sof_cb(usbp);
STM32_USB->ISTR = ~USB_ISTR_SOF;
}
/* ERR handling.*/
if ((istr & USB_ISTR_ERR) != 0U) {
/* CHTODO */
}
/* Endpoint events handling.*/
while (istr & USB_ISTR_SOF) {
usb_serve_endpoints(usbp, istr & USB_ISTR_IDN_Msk);
istr = STM32_USB->ISTR;
while ((istr & USB_ISTR_SOF) != 0U) {
usb_serve_endpoints(usbp, istr);
istr = usbp->usb->ISTR;
}
OSAL_IRQ_EPILOGUE();
@ -596,14 +601,18 @@ void usb_lld_start(USBDriver *usbp) {
/* USB clock enabled.*/
rccEnableUSB(true);
rccResetUSB();
/* Powers up the transceiver while holding the USB in reset state.*/
STM32_USB->CNTR = USB_CNTR_L2RES;
usbp->usb->CNTR = USB_CNTR_USBRST;
/* Enabling the USB IRQ vectors, this also gives enough time to allow
the transceiver power up (1uS).*/
#if STM32_USB1_HP_NUMBER != STM32_USB1_LP_NUMBER
nvicEnableVector(STM32_USB1_HP_NUMBER, STM32_USB_USB1_HP_IRQ_PRIORITY);
#endif
nvicEnableVector(STM32_USB1_LP_NUMBER, STM32_USB_USB1_LP_IRQ_PRIORITY);
/* Releases the USB reset.*/
STM32_USB->CNTR = 0;
}
@ -648,7 +657,6 @@ void usb_lld_reset(USBDriver *usbp) {
uint32_t cntr;
/* Post reset initialization.*/
STM32_USB->BTABLE = BTABLE_ADDR;
STM32_USB->ISTR = 0;
STM32_USB->DADDR = USB_DADDR_EF;
cntr = /* USB_CNTR_ESOFM | */ USB_CNTR_RESETM | USB_CNTR_SUSPM |
@ -688,7 +696,7 @@ void usb_lld_set_address(USBDriver *usbp) {
* @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
uint16_t epr;
uint32_t chepr;
USB_DRD_PMABuffDescTypeDef *dp;
const USBEndpointConfig *epcp = usbp->epc[ep];
@ -700,28 +708,27 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
#if STM32_USB_USE_ISOCHRONOUS
osalDbgAssert((epcp->in_state == NULL) || (epcp->out_state == NULL),
"isochronous EP cannot be IN and OUT");
epr = USB_EP_ISOCHRONOUS;
chepr = USB_EP_ISOCHRONOUS;
break;
#else
osalDbgAssert(false, "isochronous support disabled");
#endif
/* Falls through.*/
case USB_EP_MODE_TYPE_BULK:
epr = USB_EP_BULK;
chepr = USB_EP_BULK;
break;
case USB_EP_MODE_TYPE_INTR:
epr = USB_EP_INTERRUPT;
chepr = USB_EP_INTERRUPT;
break;
default:
epr = USB_EP_CONTROL;
chepr = USB_EP_CONTROL;
}
dp = USB_GET_DESCRIPTOR(ep);
/* IN endpoint handling.*/
if (epcp->in_state != NULL) {
dp->TXCOUNT0 = 0;
dp->TXADDR0 = usb_pm_alloc(usbp, epcp->in_maxsize);
dp->TXBD = usb_pm_alloc(usbp, epcp->in_maxsize);
#if STM32_USB_USE_ISOCHRONOUS
if (epr == USB_EP_ISOCHRONOUS) {
@ -733,22 +740,23 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
epr |= USB_EP_TX_NAK;
}
#else
epr |= USB_EP_TX_NAK;
chepr |= USB_EP_TX_NAK;
#endif
}
/* OUT endpoint handling.*/
if (epcp->out_state != NULL) {
uint16_t nblocks;
uint32_t nblocks;
/* Endpoint size and address initialization.*/
if (epcp->out_maxsize > 62)
nblocks = (((((epcp->out_maxsize - 1) | 0x1f) + 1) / 32) << 10) |
0x8000;
else
nblocks = ((((epcp->out_maxsize - 1) | 1) + 1) / 2) << 10;
dp->RXCOUNT0 = nblocks;
dp->RXADDR0 = usb_pm_alloc(usbp, epcp->out_maxsize);
if (epcp->out_maxsize > 62U) {
nblocks = ((((((uint32_t)epcp->out_maxsize - 1U) | 0x1FU) + 1U) / 32U) << 26) |
0x80000000U;
}
else {
nblocks = (((((uint32_t)epcp->out_maxsize - 1U) | 1U) + 1U) / 2U) << 26;
}
dp->RXBD = nblocks | usb_pm_alloc(usbp, epcp->out_maxsize);
#if STM32_USB_USE_ISOCHRONOUS
if (epr == USB_EP_ISOCHRONOUS) {
@ -760,22 +768,22 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
epr |= USB_EP_RX_NAK;
}
#else
epr |= USB_EP_RX_NAK;
chepr |= USB_EP_RX_NAK;
#endif
}
/* Resetting the data toggling bits for this endpoint.*/
if (STM32_USB->CHEPR[ep] & USB_EP_DTOG_RX) {
epr |= USB_EP_DTOG_RX;
if (usbp->usb->CHEPR[ep] & USB_EP_DTOG_RX) {
chepr |= USB_EP_DTOG_RX;
}
if (STM32_USB->CHEPR[ep] & USB_EP_DTOG_TX) {
epr |= USB_EP_DTOG_TX;
if (usbp->usb->CHEPR[ep] & USB_EP_DTOG_TX) {
chepr |= USB_EP_DTOG_TX;
}
/* EPxR register setup.*/
EPR_SET(ep, epr | ep);
EPR_TOGGLE(ep, epr);
/* CHEPxR register cleared and initialized.*/
usbp->usb->CHEPR[ep] = usbp->usb->CHEPR[ep];
usbp->usb->CHEPR[ep] = chepr;
}
/**
@ -792,9 +800,11 @@ void usb_lld_disable_endpoints(USBDriver *usbp) {
usb_pm_reset(usbp);
/* Disabling all endpoints.*/
for (i = 1; i <= USB_ENDPOINTS_NUMBER; i++) {
EPR_TOGGLE(i, 0);
EPR_SET(i, 0);
for (i = 1U; i <= (unsigned)USB_ENDPOINTS_NUMBER; i++) {
/* Clearing all toggle bits then zeroing the rest.*/
usbp->usb->CHEPR[i] = usbp->usb->CHEPR[i];
usbp->usb->CHEPR[i] = 0U;
}
}
@ -863,13 +873,13 @@ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) {
* @notapi
*/
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
stm32_usb_pma_t *pmap;
uint32_t *pmap;
USB_DRD_PMABuffDescTypeDef *udp;
uint32_t n;
(void)usbp;
udp = USB_GET_DESCRIPTOR(ep);
pmap = USB_ADDR2PTR(udp->RXADDR0);
pmap = USB_GET_RX_BUFFER(udp);
for (n = 0; n < 4; n++) {
*(uint16_t *)(void *)buf = (uint16_t)*pmap++;
buf += 2;
@ -894,7 +904,7 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize);
CHEPR_SET_STATRX(ep, USB_EP_RX_VALID);
CHEPR_SET_STATRX(usbp, ep, USB_EP_RX_VALID);
}
/**
@ -915,9 +925,9 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
n = (size_t)usbp->epc[ep]->in_maxsize;
isp->txlast = n;
usb_packet_write_from_buffer(ep, isp->txbuf, n);
usb_packet_write_from_buffer(usbp, ep, isp->txbuf, n);
CHEPR_SET_STATTX(ep, USB_EP_TX_VALID);
CHEPR_SET_STATTX(usbp, ep, USB_EP_TX_VALID);
}
/**
@ -932,7 +942,7 @@ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
(void)usbp;
EPR_SET_STAT_RX(ep, USB_EP_RX_STALL);
CHEPR_SET_STATRX(usbp, ep, USB_EP_RX_STALL);
}
/**
@ -947,7 +957,7 @@ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
(void)usbp;
EPR_SET_STAT_TX(ep, USB_EP_TX_STALL);
CHEPR_SET_STATTX(usbp, ep, USB_EP_TX_STALL);
}
/**
@ -964,8 +974,9 @@ void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) {
/* Makes sure to not put to NAK an endpoint that is already
transferring.*/
if ((STM32_USB->CHEPR[ep] & USB_CHEP_RX_STRX_Msk) != USB_EP_RX_VALID )
EPR_SET_STAT_RX(ep, USB_EP_RX_NAK);
if ((STM32_USB->CHEPR[ep] & USB_CHEP_RX_STRX_Msk) != USB_EP_RX_VALID) {
CHEPR_SET_STATRX(usbp, ep, USB_EP_RX_NAK);
}
}
/**
@ -982,8 +993,9 @@ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
/* Makes sure to not put to NAK an endpoint that is already
transferring.*/
if ((STM32_USB->CHEPR[ep] & USB_CHEP_TX_STTX_Msk ) != USB_EP_TX_VALID)
EPR_SET_STAT_TX(ep, USB_EP_TX_NAK );
if ((STM32_USB->CHEPR[ep] & USB_CHEP_TX_STTX_Msk ) != USB_EP_TX_VALID) {
CHEPR_SET_STATTX(usbp, ep, USB_EP_TX_NAK );
}
}
#endif /* HAL_USE_USB */

View File

@ -31,10 +31,16 @@
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of the available endpoints.
* @details This value does not include the endpoint 0 which is always present.
*/
#define USB_ENDPOINTS_NUMBER 7
/**
* @brief Maximum endpoint address.
*/
#define USB_MAX_ENDPOINTS 8
#define USB_MAX_ENDPOINTS USB_ENDPOINTS_NUMBER
/**
* @brief Status stage handling method.