aboutsummaryrefslogtreecommitdiffstats
path: root/os
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-12-31 08:01:48 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-12-31 08:01:48 +0000
commitac528c28c72ed412c8c9d33dcf0967a723d6aede (patch)
tree02de4f8d2b1138d50a43c63604f1d7ad993b5d1a /os
parent5f4e2e23899cf213b69be82a1f47b8f6fc18ecb4 (diff)
downloadChibiOS-ac528c28c72ed412c8c9d33dcf0967a723d6aede.tar.gz
ChibiOS-ac528c28c72ed412c8c9d33dcf0967a723d6aede.tar.bz2
ChibiOS-ac528c28c72ed412c8c9d33dcf0967a723d6aede.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8659 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.c2
-rw-r--r--os/hal/ports/STM32/LLD/USBv1/usb_lld.c78
-rw-r--r--os/hal/ports/STM32/LLD/USBv1/usb_lld.h48
3 files changed, 124 insertions, 4 deletions
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
index e0d817d05..6224cbb5c 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
@@ -1276,7 +1276,7 @@ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
* @details This function must be executed by a system thread in order to
* make the USB driver work.
* @note The data copy part of the driver is implemented in this thread
- * in order to not perform heavy tasks withing interrupt handlers.
+ * in order to not perform heavy tasks within interrupt handlers.
*
* @param[in] p pointer to the @p USBDriver object
*
diff --git a/os/hal/ports/STM32/LLD/USBv1/usb_lld.c b/os/hal/ports/STM32/LLD/USBv1/usb_lld.c
index d5a1c62d1..a4a8e4519 100644
--- a/os/hal/ports/STM32/LLD/USBv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/USBv1/usb_lld.c
@@ -126,6 +126,7 @@ static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) {
*
* @notapi
*/
+__attribute__((noinline))
static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
size_t i, n;
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
@@ -139,9 +140,10 @@ static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
in which the next received packet will be stored, so we need to
read the counter of the OTHER buffer, which is where the last
received packet was stored.*/
- n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
if (EPR_EP_TYPE_IS_ISO(epr) && !(epr & EPR_DTOG_RX))
n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK;
+ else
+ n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
i = n;
while (i > 1) {
@@ -183,9 +185,10 @@ static void usb_packet_write_from_buffer(usbep_t ep,
that is currently in use by the USB peripheral, that is, the buffer
from which the next packet will be sent, so we need to write the
counter of that buffer.*/
- udp->TXCOUNT0 = (stm32_usb_pma_t)n;
if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX))
udp->TXCOUNT1 = (stm32_usb_pma_t)n;
+ else
+ udp->TXCOUNT0 = (stm32_usb_pma_t)n;
while (i > 0) {
w = *buf++;
@@ -413,7 +416,17 @@ void usb_lld_start(USBDriver *usbp) {
/* Reset procedure enforced on driver start.*/
_usb_reset(usbp);
}
- /* Configuration.*/
+
+#if STM32_USB_USE_PUMP_THREAD && defined(_CHIBIOS_RT_)
+ /* Creates the data pump thread. Note, it is created only once.*/
+ if (usbp->tr == NULL) {
+ usbp->tr = chThdCreateI(usbp->wa_pump, sizeof usbp->wa_pump,
+ STM32_USB_PUMP_THREAD_PRIO,
+ usb_lld_pump, usbp);
+ chThdStartI(usbp->tr);
+ chSchRescheduleS();
+ }
+#endif
}
/**
@@ -765,6 +778,65 @@ void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) {
EPR_SET_STAT_TX(ep, EPR_STAT_TX_NAK);
}
+#if STM32_USB_USE_PUMP_THREAD || defined(__DOXYGEN__)
+/**
+ * @brief USB data transfer loop.
+ * @details This function must be executed by a system thread in order to
+ * make the USB driver work.
+ * @note The data copy part of the driver is implemented in this thread
+ * in order to not perform heavy tasks within interrupt handlers.
+ *
+ * @param[in] p pointer to the @p USBDriver object
+ *
+ * @special
+ */
+void usb_lld_pump(void *p) {
+ USBDriver *usbp = (USBDriver *)p;
+
+#if defined(_CHIBIOS_RT_)
+ chRegSetThreadName("usb_lld_pump");
+#endif
+ while (true) {
+ usbep_t ep;
+
+ /* Checking if to go to sleep.*/
+ osalSysLock();
+ if ((usbp->state == USB_STOP) && (usbp->pending == 0U)) {
+ osalThreadSuspendS(&usbp->wait);
+ }
+ osalSysUnlock();
+
+ /* Scanning endpoints.*/
+ for (ep = 0; ep <= USB_ENDOPOINTS_NUMBER; ep++) {
+ uint32_t epmask;
+
+ /* Checking of active endpoints.*/
+ const USBEndpointConfig *epcp = usbp->epc[ep];
+ if (epcp != NULL) {
+ if (epcp->in_state != NULL) {
+ epmask = (1U << 16U) << ep;
+ if ((usbp->pending & epmask) != 0U) {
+ /* Handling transfer of this IN endpoint.*/
+
+ osalSysLock();
+ usbp->pending &= ~epmask;
+ osalSysUnlock();
+ }
+ epmask = 1U << ep;
+ if ((usbp->pending & epmask) != 0U) {
+ /* Handling transfer of this OUT endpoint.*/
+
+ osalSysLock();
+ usbp->pending &= ~epmask;
+ osalSysUnlock();
+ }
+ }
+ }
+ }
+ }
+}
+#endif /* STM32_USB_USE_PUMP_THREAD */
+
#endif /* HAL_USE_USB */
/** @} */
diff --git a/os/hal/ports/STM32/LLD/USBv1/usb_lld.h b/os/hal/ports/STM32/LLD/USBv1/usb_lld.h
index 3f4abc052..11cd924d0 100644
--- a/os/hal/ports/STM32/LLD/USBv1/usb_lld.h
+++ b/os/hal/ports/STM32/LLD/USBv1/usb_lld.h
@@ -88,6 +88,30 @@
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
#endif
+/**
+ * @brief Enables the use of a thread for data moving.
+ * @details This option improves IRQ handling by performing data moving
+ * from a dedicated internal thread at the cost of increased
+ * footprint.
+ */
+#if !defined(STM32_USB_USE_PUMP_THREAD) || defined(__DOXYGEN__)
+#define STM32_USB_USE_PUMP_THREAD FALSE
+#endif
+
+/**
+ * @brief Dedicated data pump threads priority.
+ */
+#if !defined(STM32_USB_PUMP_THREAD_PRIO) || defined(__DOXYGEN__)
+#define STM32_USB_PUMP_THREAD_PRIO LOWPRIO
+#endif
+
+/**
+ * @brief Dedicated data pump threads stack size.
+ */
+#if !defined(STM32_USB_PUMP_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
+#define STM32_USB_PUMP_THREAD_STACK_SIZE 128
+#endif
+
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
@@ -360,6 +384,27 @@ struct USBDriver {
* @brief Pointer to the next address in the packet memory.
*/
uint32_t pmnext;
+#if STM32_USB_USE_PUMP_THREAD || defined(__DOXYGEN__)
+ /**
+ * @brief Mask of endpoints to be served by the pump thread.
+ * @note 0..15 for OUT endpoints, 16..31 for IN endpoints.
+ */
+ uint32_t pending;
+ /**
+ * @brief Pointer to the thread when it is sleeping or @p NULL.
+ */
+ thread_reference_t wait;
+#if defined(_CHIBIOS_RT_) || defined(__DOXYGEN__)
+ /**
+ * @brief Pointer to the thread once created.
+ */
+ thread_reference_t tr;
+ /**
+ * @brief Working area for the dedicated data pump thread;
+ */
+ THD_WORKING_AREA(wa_pump, STM32_USB_PUMP_THREAD_STACK_SIZE);
+#endif /* _CHIBIOS_RT_ */
+#endif /* STM32_USB_USE_PUMP_THREAD */
};
/*===========================================================================*/
@@ -450,6 +495,9 @@ extern "C" {
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
+#if STM32_USB_USE_PUMP_THREAD
+ void usb_lld_pump(void *p);
+#endif
#ifdef __cplusplus
}
#endif