Skip to content

Commit e41002d

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 e41002d

File tree

3 files changed

+89
-43
lines changed

3 files changed

+89
-43
lines changed

system/Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usb.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,20 +269,23 @@ typedef struct
269269

270270
uint8_t doublebuffer; /*!< Double buffer enable
271271
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
272+
273+
uint16_t tx_fifo_num; /*!< This parameter is not required by USB Device FS peripheral, it is used
274274
only by USB OTG FS peripheral
275275
This parameter is added to ensure compatibility across USB peripherals */
276276

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

280280
uint8_t *xfer_buff; /*!< Pointer to transfer buffer */
281-
281+
282+
282283
uint32_t xfer_len; /*!< Current transfer length */
283284

284285
uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */
285286

287+
uint16_t pending; /*!, Fact, that double buffering transfer have pended data */
288+
286289
} USB_EPTypeDef;
287290
#endif /* USB */
288291
/**

system/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.c

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t
116116

117117
#if defined (USB)
118118
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
119+
static HAL_StatusTypeDef HAL_PCD_EP_ReceiveData(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef* ep)
119120
#endif /* USB */
120121
/**
121122
* @}
@@ -190,6 +191,7 @@ HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
190191
hpcd->IN_ep[index].maxpacket = 0U;
191192
hpcd->IN_ep[index].xfer_buff = 0U;
192193
hpcd->IN_ep[index].xfer_len = 0U;
194+
hpcd->IN_ep[index].pending = 0U;
193195
}
194196

195197
for (index = 0U; index < 15U ; index++)
@@ -202,6 +204,7 @@ HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
202204
hpcd->OUT_ep[index].maxpacket = 0U;
203205
hpcd->OUT_ep[index].xfer_buff = 0U;
204206
hpcd->OUT_ep[index].xfer_len = 0U;
207+
hpcd->OUT_ep[index].pending = 0U;
205208
}
206209

207210
/* Init Device */
@@ -907,7 +910,6 @@ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
907910
return HAL_OK;
908911
}
909912

910-
911913
/**
912914
* @brief Receive an amount of data
913915
* @param hpcd: PCD handle
@@ -919,7 +921,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
919921
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
920922
{
921923
PCD_EPTypeDef *ep = NULL;
922-
924+
923925
ep = &hpcd->OUT_ep[ep_addr & 0x7FU];
924926

925927
/*setup and start the Xfer */
@@ -933,7 +935,7 @@ HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, u
933935
}
934936
else
935937
{
936-
USB_EPStartXfer(hpcd->Instance , ep);
938+
HAL_PCD_EP_ReceiveData(hpcd, ep);
937939
}
938940

939941
return HAL_OK;
@@ -1192,7 +1194,7 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
11921194
uint16_t count = 0;
11931195
uint16_t pmaBuffer = 0;
11941196
uint8_t epindex = 0;
1195-
__IO uint16_t wIstr = 0;
1197+
__IO uint16_t wIstr = 0;
11961198
__IO uint16_t wEPVal = 0;
11971199

11981200
/* stay in loop while pending interrupts */
@@ -1220,14 +1222,14 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12201222

12211223
/* TX COMPLETE */
12221224
HAL_PCD_DataInStageCallback(hpcd, 0U);
1223-
1224-
1225+
1226+
12251227
if((hpcd->USB_Address > 0U)&& ( ep->xfer_len == 0U))
12261228
{
12271229
hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
12281230
hpcd->USB_Address = 0U;
12291231
}
1230-
1232+
12311233
}
12321234
else
12331235
{
@@ -1242,14 +1244,14 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12421244
{
12431245
/* Get SETUP Packet*/
12441246
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);
1247+
USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);
12461248
/* SETUP bit kept frozen while CTR_RX = 1*/
12471249
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
12481250

12491251
/* Process SETUP Packet*/
12501252
HAL_PCD_SetupStageCallback(hpcd);
12511253
}
1252-
1254+
12531255
else if ((wEPVal & USB_EP_CTR_RX) != 0U)
12541256
{
12551257
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
@@ -1281,7 +1283,7 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
12811283
/* clear int flag */
12821284
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
12831285
ep = &hpcd->OUT_ep[epindex];
1284-
1286+
12851287
/* OUT double Buffering*/
12861288
if (ep->doublebuffer == 0U)
12871289
{
@@ -1302,24 +1304,38 @@ static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
13021304
count = (uint16_t) PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
13031305
pmaBuffer = ep->pmaaddr1;
13041306
}
1305-
PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);
1307+
if (ep->xfer_len == 0 || ep->xfer_buff == 0)
1308+
{
1309+
/* have no buffer at all, leave data untouched and exit */
1310+
ep->pending = 1U;
1311+
return HAL_OK;
1312+
}
1313+
PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);
13061314
}
1315+
13071316
if (count != 0U)
13081317
{
1318+
/* buffer doesn't contains enough space, stall and error */
1319+
if (count > ep->xfer_len)
1320+
{
1321+
USB_EPSetStall(hpcd->Instance, ep);
1322+
return HAL_ERROR;
1323+
}
13091324
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, pmaBuffer, count);
13101325
}
13111326
/*multi-packet on the NON control OUT endpoint*/
13121327
ep->xfer_count+=count;
13131328
ep->xfer_buff+=count;
1314-
1329+
ep->xfer_len-=count;
1330+
13151331
if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
13161332
{
13171333
/* RX COMPLETE */
13181334
HAL_PCD_DataOutStageCallback(hpcd, ep->num);
13191335
}
1320-
else
1336+
else if (ep->doublebuffer == 0U)
13211337
{
1322-
HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
1338+
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID);
13231339
}
13241340

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

13741441
/**

system/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.c

Lines changed: 2 additions & 26 deletions
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)