2016-01-23 10:05 AM
* @file stm32f3xx_hal_pcd_ex.c
* @author MCD Application Team * @version V1.2.0 * @date 13-November-2015/**
* @brief Copy a buffer from user memory area to packet memory area (PMA)
* @param USBx: USB peripheral instance register address.
* @param pbUsrBuf: pointer to user memory area.
* @param wPMABufAddr: address into PMA.
* @param wNBytes: no. of bytes to be copied.
* @retval None
*/
void
PCD_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
uint32_t n = (wNBytes + 1) >> 1;
/* n = (wNBytes + 1) / 2 */
uint32_t i, temp1, temp2;
uint16_t *pdwVal;
pdwVal = (uint16_t *)(wPMABufAddr * 2 + (uint32_t)USBx + 0x400);
for
(i = n; i != 0; i--)
{
temp1 = (uint16_t) * pbUsrBuf;
pbUsrBuf++;
temp2 = temp1 | (uint16_t) * pbUsrBuf << 8;
*pdwVal++ = temp2;
pdwVal++;
pbUsrBuf++;
}
}
Probably this is most critical part for USB performance - data is moved from memory to PMA. Why bit arithmetic is here? What for so many useless variables are here?
my version(works fine)
void
PCD_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
{
int
n = (wNBytes + 1) >> 1;
// n = (wNBytes + 1) / 2
__IO uint32_t *pdwVal = (uint32_t *)(wPMABufAddr * 2 + (uint32_t)USBx + 0x400);
uint16_t * pwUsrBuf = (uint16_t *) pbUsrBuf;
for
(; n != 0; n--)
{
*pdwVal = *pwUsrBuf;
pwUsrBuf++;
pdwVal++;
}
}
2016-01-24 04:56 AM
very good!
2016-01-25 01:17 AM
Thanks.
One observation, if you don't mind: signed bitwise operations aren't well-defined in the C standard, I would suggest defining n as an unsigned value (uint32_t n), as was in the original code.2016-01-25 02:29 AM
Agree, but in this particular case incoming value is unsigned 16 bit, and n is positive in any case and then I see no problems at all. In fact, I used int to let compiler optimize real variable type. Probably it should be unsigned int.
2016-02-01 08:34 AM
Hi,
With your code, the user buffer (pbUsrBuf) should be 16bit aligned to works properly. If pbUsrBuf point an odd address, I'm not sure that the copy is correct. By the way, if you want to improve this transfert, you can use DMA. I've already done Regards2016-02-15 03:21 PM
You are not right. My code works for
STM32F303VCT6. Yes, the source is 16-bit aligned, PMA is 32-bit aligned. In fact USB FS packets are relatively small, 64bytes only, that means 32 half words to be copied at maximum, and this is comparable to DMA start procedure. I'm not sure if DMA really improves performance here. Looks like PMA double buffering is going to be more effective but it's not supported in HAL.