cancel
Showing results for 
Search instead for 
Did you mean: 

USB Library - shitty code.

elijah
Associate II
Posted on January 23, 2016 at 19:05

* @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++;
}
}

5 REPLIES 5
wjandsq
Associate III
Posted on January 24, 2016 at 13:56

very good!

qwer.asdf
Senior
Posted on January 25, 2016 at 10:17

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.

elijah
Associate II
Posted on January 25, 2016 at 11:29

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.

thln47
Associate III
Posted on February 01, 2016 at 17:34

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

https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/STM32F302xC%20is%20in%20wrong%20section%20in%20%E2%80%9Cstm32f3xx_hal_pcd_ex.c%E2%80%9D%20file&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000F9A0E...

Regards

elijah
Associate II
Posted on February 16, 2016 at 00:21

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.