Skip to content

Commit f246905

Browse files
committed
Double buffering fix for reception.
In the case of double buffering, it is impossible to determine exactly how large the allocated buffer should be. To achieve double-buffering acceleration, the PCD_FreeUserBuffer call must occur before the HAL_PCD_DataOutStageCallback call. But the real data buffer can be allocated only in this callback. It turns out that the approach itself needs to be changed - always allocate maximum allowable endpoint buffer size (it's already happends in USB_ActivateEndpoint). At the same time we need to check the size of the data received. This check be done at the time of data receipt. During reception confirmation, it may be that there is no allocated buffer at all. In this case, we will have to leave the filled PMA intact and not complete its release. In this case, this operation will be repeated in HAL_PCD_EP_ReceiveData.
1 parent 81ac026 commit f246905

File tree

3 files changed

+99
-43
lines changed

3 files changed

+99
-43
lines changed

Diff for: system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usb.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ typedef struct
160160
uint32_t xfer_len; /*!< Current transfer length */
161161

162162
uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */
163+
164+
uint16_t pending; /*!, Fact, that double buffering transfer have pended data */
163165
}USB_OTG_EPTypeDef;
164166

165167
typedef struct
@@ -269,20 +271,23 @@ typedef struct
269271

270272
uint8_t doublebuffer; /*!< Double buffer enable
271273
This parameter can be 0 or 1 */
272-
273-
uint16_t tx_fifo_num; /*!< This parameter is not required by USB Device FS peripheral, it is used
274+
275+
uint16_t tx_fifo_num; /*!< This parameter is not required by USB Device FS peripheral, it is used
274276
only by USB OTG FS peripheral
275277
This parameter is added to ensure compatibility across USB peripherals */
276278

277279
uint32_t maxpacket; /*!< Endpoint Max packet size
278280
This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */
279281

280282
uint8_t *xfer_buff; /*!< Pointer to transfer buffer */
281-
283+
284+
282285
uint32_t xfer_len; /*!< Current transfer length */
283286

284287
uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */
285288

289+
uint16_t pending; /*!, Fact, that double buffering transfer have pended data */
290+
286291
} USB_EPTypeDef;
287292
#endif /* USB */
288293
/**

Diff for: system/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.c

+89-14
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t
117117
#if defined (USB)
118118
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
119119
#endif /* USB */
120+
121+
static HAL_StatusTypeDef HAL_PCD_EP_ReceiveData(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef* ep);
122+
120123
/**
121124
* @}
122125
*/
@@ -190,6 +193,7 @@ HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
190193
hpcd->IN_ep[index].maxpacket = 0U;
191194
hpcd->IN_ep[index].xfer_buff = 0U;
192195
hpcd->IN_ep[index].xfer_len = 0U;
196+
hpcd->IN_ep[index].pending = 0U;
193197
}
194198

195199
for (index = 0U; index < 15U ; index++)
@@ -202,6 +206,7 @@ HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
202206
hpcd->OUT_ep[index].maxpacket = 0U;
203207
hpcd->OUT_ep[index].xfer_buff = 0U;
204208
hpcd->OUT_ep[index].xfer_len = 0U;
209+
hpcd->OUT_ep[index].pending = 0U;
205210
}
206211

207212
/* Init Device */
@@ -907,7 +912,6 @@ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
907912
return HAL_OK;
908913
}
909914

910-
911915
/**
912916
* @brief Receive an amount of data
913917
* @param hpcd: PCD handle
@@ -919,7 +923,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
919923
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
920924
{
921925
PCD_EPTypeDef *ep = NULL;
922-
926+
923927
ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
924928

925929
/*setup and start the Xfer */
@@ -933,7 +937,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, u
933937
}
934938
else
935939
{
936-
USB_EPStartXfer(hpcd->Instance , ep);
940+
HAL_PCD_EP_ReceiveData(hpcd, ep);
937941
}
938942

939943
return HAL_OK;
@@ -1178,6 +1182,12 @@ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t
11781182

11791183
return HAL_OK;
11801184
}
1185+
1186+
HAL_StatusTypeDef HAL_PCD_EP_ReceiveData(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef* ep)
1187+
{
1188+
USB_EPStartXfer(hpcd->Instance, ep);
1189+
}
1190+
11811191
#endif /* USB_OTG_FS */
11821192

11831193
#if defined (USB)
@@ -1192,7 +1202,7 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
11921202
uint16_t count = 0;
11931203
uint16_t pmaBuffer = 0;
11941204
uint8_t epindex = 0;
1195-
__IO uint16_t wIstr = 0;
1205+
__IO uint16_t wIstr = 0;
11961206
__IO uint16_t wEPVal = 0;
11971207

11981208
/* stay in loop while pending interrupts */
@@ -1220,14 +1230,14 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12201230

12211231
/* TX COMPLETE */
12221232
HAL_PCD_DataInStageCallback(hpcd, 0U);
1223-
1224-
1233+
1234+
12251235
if((hpcd->USB_Address > 0U)&& ( ep->xfer_len == 0U))
12261236
{
12271237
hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
12281238
hpcd->USB_Address = 0U;
12291239
}
1230-
1240+
12311241
}
12321242
else
12331243
{
@@ -1242,14 +1252,14 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12421252
{
12431253
/* Get SETUP Packet*/
12441254
ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1245-
USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);
1255+
USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);
12461256
/* SETUP bit kept frozen while CTR_RX = 1*/
12471257
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
12481258

12491259
/* Process SETUP Packet*/
12501260
HAL_PCD_SetupStageCallback(hpcd);
12511261
}
1252-
1262+
12531263
else if ((wEPVal & USB_EP_CTR_RX) != 0U)
12541264
{
12551265
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
@@ -1281,7 +1291,7 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12811291
/* clear int flag */
12821292
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
12831293
ep = &hpcd->OUT_ep[epindex];
1284-
1294+
12851295
/* OUT double Buffering*/
12861296
if (ep->doublebuffer == 0U)
12871297
{
@@ -1302,24 +1312,38 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
13021312
count = (uint16_t) PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
13031313
pmaBuffer = ep->pmaaddr1;
13041314
}
1305-
PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);
1315+
if (ep->xfer_len == 0 || ep->xfer_buff == 0)
1316+
{
1317+
/* have no buffer at all, leave data untouched and exit */
1318+
ep->pending = 1U;
1319+
return HAL_OK;
1320+
}
1321+
PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);
13061322
}
1323+
13071324
if (count != 0U)
13081325
{
1326+
/* buffer doesn't contains enough space, stall and error */
1327+
if (count > ep->xfer_len)
1328+
{
1329+
USB_EPSetStall(hpcd->Instance, ep);
1330+
return HAL_ERROR;
1331+
}
13091332
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, pmaBuffer, count);
13101333
}
13111334
/*multi-packet on the NON control OUT endpoint*/
13121335
ep->xfer_count+=count;
13131336
ep->xfer_buff+=count;
1314-
1337+
ep->xfer_len-=count;
1338+
13151339
if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
13161340
{
13171341
/* RX COMPLETE */
13181342
HAL_PCD_DataOutStageCallback(hpcd, ep->num);
13191343
}
1320-
else
1344+
else if (ep->doublebuffer == 0U)
13211345
{
1322-
HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1346+
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID);
13231347
}
13241348

13251349
} /* if((wEPVal & EP_CTR_RX) */
@@ -1369,6 +1393,57 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
13691393
}
13701394
return HAL_OK;
13711395
}
1396+
1397+
HAL_StatusTypeDef HAL_PCD_EP_ReceiveData(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef* ep)
1398+
{
1399+
uint16_t count;
1400+
uint16_t pmaBuffer;
1401+
1402+
if (ep->pending)
1403+
{
1404+
ep->pending = 0U;
1405+
PCD_FreeUserBuffer(hpcd->Instance, ep->num, ep->is_in);
1406+
if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX)
1407+
{
1408+
/*read from endpoint BUF0Addr buffer*/
1409+
count = (uint16_t) PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1410+
pmaBuffer = ep->pmaaddr0;
1411+
}
1412+
else
1413+
{
1414+
/*read from endpoint BUF1Addr buffer*/
1415+
count = (uint16_t) PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1416+
pmaBuffer = ep->pmaaddr1;
1417+
}
1418+
1419+
/* buffer doesn't contains enough space, stall and error */
1420+
if (count > ep->xfer_len)
1421+
{
1422+
USB_EPSetStall(hpcd->Instance, ep);
1423+
return HAL_ERROR;
1424+
}
1425+
1426+
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, pmaBuffer, count);
1427+
1428+
/*multi-packet on the NON control OUT endpoint*/
1429+
ep->xfer_count += count;
1430+
ep->xfer_buff += count;
1431+
ep->xfer_len -= count;
1432+
1433+
if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
1434+
{
1435+
/* RX COMPLETE */
1436+
HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1437+
return HAL_OK;
1438+
}
1439+
}
1440+
if (ep->doublebuffer == 0U)
1441+
{
1442+
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID);
1443+
}
1444+
return HAL_OK;
1445+
}
1446+
13721447
#endif /* USB */
13731448

13741449
/**

Diff for: system/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.c

+2-26
Original file line numberDiff line numberDiff line change
@@ -1887,35 +1887,11 @@ HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep)
18871887
PCD_FreeUserBuffer(USBx, ep->num, ep->is_in);
18881888
}
18891889
}
1890-
else /* OUT endpoint */
1890+
else
18911891
{
1892-
/* Multi packet transfer*/
1893-
if (ep->xfer_len > ep->maxpacket)
1894-
{
1895-
len=ep->maxpacket;
1896-
ep->xfer_len-=len;
1897-
}
1898-
else
1899-
{
1900-
len=ep->xfer_len;
1901-
ep->xfer_len =0;
1902-
}
1903-
1904-
/* configure and validate Rx endpoint */
1905-
if (ep->doublebuffer == 0)
1906-
{
1907-
/*Set RX buffer count*/
1908-
PCD_SET_EP_RX_CNT(USBx, ep->num, len);
1909-
}
1910-
else
1911-
{
1912-
/*Set the Double buffer counter*/
1913-
PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
1914-
}
1915-
19161892
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
19171893
}
1918-
1894+
19191895
return HAL_OK;
19201896
}
19211897

0 commit comments

Comments
 (0)