git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8659 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
Giovanni Di Sirio 2015-12-31 08:01:48 +00:00
parent 5f4e2e2389
commit ac528c28c7
3 changed files with 124 additions and 4 deletions

View File

@ -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
*

View File

@ -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 */
/** @} */

View File

@ -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