stmhal: Make USB CDC driver use SOF instead of TIM3 for outgoing data.

Previous to this patch the USB CDC driver used TIM3 to trigger the
sending of outgoing data over USB serial.  This patch changes the
behaviour so that the USB SOF interrupt is used to trigger the processing
of the sending.  This reduces latency and increases bandwidth of outgoing
data.

Thanks to Martin Fischer, aka @hoihu, for the idea and initial prototype.

See PR #1713.
This commit is contained in:
Damien George 2016-01-09 21:59:15 +00:00
parent 7417ccfb0d
commit d363133917
5 changed files with 11 additions and 16 deletions

View File

@ -480,8 +480,6 @@ void EXTI15_10_IRQHandler(void) {
void PVD_IRQHandler(void) {
IRQ_ENTER(PVD_IRQn);
#if defined(MICROPY_HW_USE_ALT_IRQ_FOR_CDC)
extern void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void);
USBD_CDC_HAL_TIM_PeriodElapsedCallback();
#endif
Handle_EXTI_Irq(EXTI_PVD_OUTPUT);
IRQ_EXIT(PVD_IRQn);

View File

@ -252,7 +252,6 @@ TIM_HandleTypeDef *timer_tim6_init(uint freq) {
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
#if !defined(MICROPY_HW_USE_ALT_IRQ_FOR_CDC)
if (htim == &TIM3_Handle) {
USBD_CDC_HAL_TIM_PeriodElapsedCallback();
} else
#endif
if (htim == &TIM5_Handle) {

View File

@ -257,12 +257,10 @@ static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
return USBD_OK;
}
/**
* @brief TIM period elapsed callback
* @param htim: TIM handle
* @retval None
*/
void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
// This function is called to process outgoing data. We hook directly into the
// SOF (start of frame) callback so that it is called exactly at the time it is
// needed (reducing latency), and often enough (increasing bandwidth).
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
if (!dev_is_connected) {
// CDC device is not connected to a host, so we are unable to send any data
return;
@ -276,9 +274,8 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
if (UserTxBufPtrOut != UserTxBufPtrOutShadow) {
// We have sent data and are waiting for the low-level USB driver to
// finish sending it over the USB in-endpoint.
// We have a 15 * 10ms = 150ms timeout
if (UserTxBufPtrWaitCount < 15) {
PCD_HandleTypeDef *hpcd = hUSBDDevice.pData;
// SOF occurs every 1ms, so we have a 150 * 1ms = 150ms timeout
if (UserTxBufPtrWaitCount < 150) {
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
// USB in-endpoint is still reading the data
@ -457,7 +454,7 @@ void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) {
}
// Some unused code that makes sure the low-level USB buffer is drained.
// Waiting for low-level is handled in USBD_CDC_HAL_TIM_PeriodElapsedCallback.
// Waiting for low-level is handled in HAL_PCD_SOFCallback.
/*
start = HAL_GetTick();
PCD_HandleTypeDef *hpcd = hUSBDDevice.pData;

View File

@ -31,8 +31,6 @@
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops;
void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void);
int USBD_CDC_IsConnected(void);
void USBD_CDC_SetInterrupt(int chr, void *data);

View File

@ -276,10 +276,13 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
* @param hpcd: PCD handle
* @retval None
*/
/*
This is now handled by the USB CDC interface.
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{
USBD_LL_SOF(hpcd->pData);
}
*/
/**
* @brief Reset callback.
@ -394,7 +397,7 @@ if (pdev->id == USB_PHY_FS_ID)
pcd_fs_handle.Init.dma_enable = 0;
pcd_fs_handle.Init.low_power_enable = 0;
pcd_fs_handle.Init.phy_itface = PCD_PHY_EMBEDDED;
pcd_fs_handle.Init.Sof_enable = 0;
pcd_fs_handle.Init.Sof_enable = 1;
pcd_fs_handle.Init.speed = PCD_SPEED_FULL;
#if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0