Why does the CubeMX-generated USB HID device send the wrong data when both endpoint and PMA address are changed?
This is a cross-post from https://stackoverflow.com/questions/59856541/stm32f3-cubemx-generated-usb-hid-device-sends-wrong-data-when-both-endpoint-and
I'm debugging a problem with a composite device that I'm creating, and have recreated the issue in freshly-CubeMX-generated HID-only code, to make it easier to resolve.
I've added small amount of code to `main()` to let me send ISB HID mouse-clicks, and flash an LED, when the blue-button is pressed.
...
uint8_t click_report[CLICK_REPORT_SIZE] = {0};
extern USBD_HandleTypeDef hUsbDeviceFS;
...
int main(void)
{
...
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_SET){
HAL_GPIO_WritePin(LD4_GPIO_Port, LD4_Pin, GPIO_PIN_SET);
click_report[0] = 1; // send button press
USBD_HID_SendReport(&hUsbDeviceFS, click_report, CLICK_REPORT_SIZE);
HAL_Delay(50);
click_report[0] = 0; // send button release
USBD_HID_SendReport(&hUsbDeviceFS, click_report, CLICK_REPORT_SIZE);
HAL_Delay(200);
HAL_GPIO_WritePin(LD4_GPIO_Port, LD4_Pin, GPIO_PIN_RESET);
}
}
I am using Wireshark and usbmon (on Ubuntu 16.04) to look at the packets which my STM32F3DISCOVERY board sends.
With this freshly-generated code, I can see `URB_INTERRUPT` packets being sent from 3.23.1. (Only the last part of that address, the endpoint, is relevant.)
The packet contents are:
01 00 00 00
00
00 00 00 00
00
as expected.
(The 5-byte messages are fragmented into 4-byte and 1-byte messages, as there is a 4-byte maximum packet size for HID.)
I then changed `HID_EPIN_ADDR` in `usdb_hid.h` from `0x81` to `0x83`, to make the device use endpoint 3 for HID messages, instead of endpoint 1.
//#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_ADDR 0x83U
With this change, everything continued to work, with the expected change that packets are being sent from x.x.3. The packets still contain:
01 00 00 00
00
00 00 00 00
00
As far as I can see, this should *not* work, as I haven't yet allocated an address for endpoint 3 (`0x83`) in the PMA (packet memory area).
I do this, by editing usb_conf.c:
/* USER CODE BEGIN EndPoint_Configuration */
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
/* USER CODE END EndPoint_Configuration */
/* USER CODE BEGIN EndPoint_Configuration_HID */
//HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0x100);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x83 , PCD_SNG_BUF, 0x180);
/* USER CODE END EndPoint_Configuration_HID */
return USBD_OK;
}
Now, when I send the same `01 00 00 00 00` and `00 00 00 00 00` `click_reports` I see packet contents of:
58 00 2c 00
58
58 00 2c 00
58
I have traced the contents of the non-PMA buffer right down to `USB_WritePMA` in `stm32f3xx_ll_usb`.
The sending code (in `stm32f3xx_ll_usb`) is:
/* IN endpoint */
if (ep->is_in == 1U)
{
/*Multi packet transfer*/
if (ep->xfer_len > ep->maxpacket)
{
len = ep->maxpacket;
ep->xfer_len -= len;
}
else
{
len = ep->xfer_len;
ep->xfer_len = 0U;
}
/* configure and validate Tx endpoint */
if (ep->doublebuffer == 0U)
{
USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
PCD_SET_EP_TX_CNT(USBx, ep->num, len);
}
else
{
Why is the data on the wire not the data that I give `USB_WritePMA`, once I've added `HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x83 , PCD_SNG_BUF, 0x180);`?
