aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/STM32/LLD/OTGv1
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-12-28 11:16:40 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-12-28 11:16:40 +0000
commitde202dd376ea3109e21f535554647689dda23c7b (patch)
treee7247994911999dc69ab1755346057df768309bb /os/hal/ports/STM32/LLD/OTGv1
parentd93fdcd424c049078009119940d0042bb229ed38 (diff)
downloadChibiOS-de202dd376ea3109e21f535554647689dda23c7b.tar.gz
ChibiOS-de202dd376ea3109e21f535554647689dda23c7b.tar.bz2
ChibiOS-de202dd376ea3109e21f535554647689dda23c7b.zip
New USB API finalized, updated OTGv1, USBv1 not yet updated.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8653 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/STM32/LLD/OTGv1')
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.c80
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.h2
2 files changed, 34 insertions, 48 deletions
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
index a4a784d2a..e0d817d05 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
@@ -369,7 +369,6 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
cover the remaining.*/
isp->txsize = isp->totsize - isp->txsize;
isp->txcnt = 0;
- usb_lld_prepare_transmit(usbp, ep);
osalSysLockFromISR();
usb_lld_start_in(usbp, ep);
osalSysUnlockFromISR();
@@ -415,13 +414,14 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
/* Receive transfer complete.*/
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
- if (osp->rxsize < osp->totsize) {
+ /* A short packet always terminates a transaction.*/
+ if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) &&
+ (osp->rxsize < osp->totsize)) {
/* In case the transaction covered only part of the total transfer
then another transaction is immediately started in order to
cover the remaining.*/
osp->rxsize = osp->totsize - osp->rxsize;
osp->rxcnt = 0;
- usb_lld_prepare_receive(usbp, ep);
osalSysLockFromISR();
usb_lld_start_out(usbp, ep);
osalSysUnlockFromISR();
@@ -476,7 +476,6 @@ static void otg_isoc_in_failed_handler(USBDriver *usbp) {
*
* @notapi
*/
-
static void otg_isoc_out_failed_handler(USBDriver *usbp) {
usbep_t ep;
stm32_otg_t *otgp = usbp->otg;
@@ -1135,38 +1134,57 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
}
/**
- * @brief Prepares for a receive operation.
+ * @brief Starts a receive operation on an OUT endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
-void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
- uint32_t pcnt;
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+ uint32_t pcnt, rxsize;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
/* Transfer initialization.*/
osp->totsize = osp->rxsize;
- if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
+ if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
osp->rxsize = EP0_MAX_OUTSIZE;
- pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
- usbp->epc[ep]->out_maxsize;
+ /* Transaction size is rounded to a multiple of packet size because the
+ following requirement in the RM:
+ "For OUT transfers, the transfer size field in the endpoint's transfer
+ size register must be a multiple of the maximum packet size of the
+ endpoint, adjusted to the Word boundary".*/
+ pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
+ usbp->epc[ep]->out_maxsize;
+ rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU;
+
+ /*Setting up transaction parameters in DOEPTSIZ.*/
usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
- DOEPTSIZ_XFRSIZ(osp->rxsize);
+ DOEPTSIZ_XFRSIZ(rxsize);
+
+ /* Special case of isochronous endpoint.*/
+ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
+ /* Odd/even bit toggling for isochronous endpoint.*/
+ if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
+ else
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
+ }
+ /* Starting operation.*/
+ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
}
/**
- * @brief Prepares for a transmit operation.
+ * @brief Starts a transmit operation on an IN endpoint.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
*
* @notapi
*/
-void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
/* Transfer initialization.*/
@@ -1176,7 +1194,7 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
}
else {
- if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
+ if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
isp->txsize = EP0_MAX_INSIZE;
/* Normal case.*/
@@ -1186,39 +1204,8 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
DIEPTSIZ_XFRSIZ(isp->txsize);
}
-}
-
-/**
- * @brief Starts a receive operation on an OUT endpoint.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- *
- * @notapi
- */
-void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
-
- if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
- /* Odd/even bit toggling for isochronous endpoint.*/
- if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SEVNFRM;
- else
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
- }
-
- usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
-}
-
-/**
- * @brief Starts a transmit operation on an IN endpoint.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- *
- * @notapi
- */
-void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+ /* Special case of isochronous endpoint.*/
if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
/* Odd/even bit toggling.*/
if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
@@ -1227,6 +1214,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM;
}
+ /* Starting operation.*/
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
}
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
index c90424c36..85038a9e2 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
@@ -540,8 +540,6 @@ extern "C" {
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
- void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
- void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);