当端点和PMA地址都更改时,CubeMX生成的USB HID设备发送错误的数据 [英] CubeMX-generated USB HID device sends wrong data when both endpoint and PMA address are changed

查看:381
本文介绍了当端点和PMA地址都更改时,CubeMX生成的USB HID设备发送错误的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在调试我要创建的复合设备的问题,并用新的CubeMX生成的仅HID代码重新创建了该问题,以使其更易于解决.

我已在main()中添加了少量代码,以便在按下蓝色按钮时发送USB HID鼠标单击并闪烁LED.

...
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);
      }
  }

我正在使用Wireshark和usbmon(在Ubuntu 16.04上)查看STM32F3DISCOVERY板发送的数据包.

使用此新生成的代码,我可以看到URB_INTERRUPT数据包是从3.23.1发送的. (只有该地址的最后一部分,即端点,才是相关的.)

包内容为:

01 00 00 00
00
00 00 00 00
00

符合预期.

(5字节的click_report分为4字节和1字节的消息,因为HID的最大数据包大小为4字节.)

然后我将usdb_hid.h中的HID_EPIN_ADDR0x81更改为0x83,以使设备将端点3用于HID消息,而不是端点1.

//#define HID_EPIN_ADDR                 0x81U
#define HID_EPIN_ADDR                 0x83U

有了此更改,一切都继续进行,并且预期的更改是从x.x.3发送数据包.数据包仍然包含:

01 00 00 00
00
00 00 00 00
00

据我所知,这应该不起作用,因为我尚未为PMA(数据包存储区)中的端点3(0x83)分配地址.

我这样做是通过编辑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;
}

现在,当我发送相同的01 00 00 00 0000 00 00 00 00 click_reports时,我看到的数据包内容是

58 00 2c 00
58
58 00 2c 00
58

我已经将非PMA缓冲区的内容追溯到stm32f3xx_ll_usb中的USB_WritePMA.

(在stm32f3xx_ll_usb中)发送代码是:

  /* 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
    {

在为端点地址0x83添加HAL_PCDEx_PMAConfig(...之后,为什么网上的数据不是我提供的USB_WritePMA数据?


更新:

如果我更改usb_conf.c以便让端点地址0x83使用0x81通常使用的PMA地址:

  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

电线上的数据包仍然损坏:

58 00 2c 00
58
58 00 2c 00
58

如果我将usb_conf.c返回其初始的生成状态(其中0x83没有PMA地址,而0x81使用0x100):

  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

输出按预期工作:

01 00 00 00
00
00 00 00 00
00


更新2:

我在stm32f3xx_ll_usb.cUSB_ActivateEndpoint()中添加了一个断点.

令人惊讶的是,这仅是端点0的调用.

因此,ep->pmaadress(原文如此)绝不会写入硬件",而仅用于更高级别的代码中.

这必须表示端点的pmaadress值已设置为某些默认值,并且我不知道端点0x83的默认值,因此无法进行设置.

当我星期五恢复工作时,我将添加调试以读出默认值.如果它们不存在,我将会非常困惑.


更新3:

我添加了以下调试:

uint16_t *tx_addr_ptr(USB_TypeDef *USBx, uint8_t ep_num) {
  register uint16_t *_wRegValPtr;
  register uint32_t _wRegBase = (uint32_t)USBx;
  _wRegBase += (uint32_t)(USBx)->BTABLE;
  _wRegValPtr = (uint16_t *)(_wRegBase + 0x400U + (((uint32_t)(ep_num) * 8U) * 2U));
  return _wRegValPtr;
}

uint16_t *rx_addr_ptr(USB_TypeDef *USBx, uint8_t ep_num) {
  register uint16_t *_wRegValPtr;
  register uint32_t _wRegBase = (uint32_t)USBx;
  _wRegBase += (uint32_t)(USBx)->BTABLE;
  _wRegValPtr = (uint16_t *)(_wRegBase + 0x400U + ((((uint32_t)(ep_num) * 8U) + 4U) * 2U));
  return _wRegValPtr;
}
...
HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
{
  ...
  int txaddrs[8] = {0};
  int rxaddrs[8] = {0};
  for (int i = 0; i < 8; ++i) {
    txaddrs[i] = *tx_addr_ptr(USBx, i);
    rxaddrs[i] = *rx_addr_ptr(USBx, i);
  }

这向我显示了以下值(在调试器中):

txaddrs:
  0: 0x58
  1: 0xf5c4
  2: 0xc1c2
  3: 0x100

rxaddrs:
  0: 0x18
  1: 0xfa9b
  2: 0xcb56
  3: 0x0

这些,出乎意料的看起来正确.

0x100是端点3的txaddr,即使USB_ActivateEndpoint()只是第一次被调用.

经过大量的探索,我发现PCD_SET_EP_TX_ADDRESS(在stm32f3xx_hal_pcd.h中)不仅直接在USB_ActivateEndpoint()中使用,而且在`stm32f3xx_hal_pcd.h.的PCD_SET_EP_DBUF0_ADDR宏中使用.

PCD_SET_EP_DBUF0_ADDR似乎未使用,所以我不知道usbd_conf.c中的(更改的)值如何:

USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
  ...
  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

进入内存映射的USB寄存器.

我可以从rxaddr[3](端点3)中存在0x00来推断它们是成对发生的(因为没有对HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x3 , PCD_SNG_BUF, 0x0);的调用).


更新4:

将设备更改为再次使用端点1后,txaddrs [3]中的0x100值仍然保留.从上次运行开始就一直在那里,从而消除了一些混乱.


更新5:

这是一个表格问题. BTABLE寄存器的值为0x00,将btable放在PMA的开头.

PMA看起来像这样: 而PMA的起点是btable.

我发现:

PMAAddr + BASEADDR_BTABLE + 0x00000000 : EP0_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000002 : EP0_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000004 : EP0_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000006 : EP0_RX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000008 : EP1_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x0000000A : EP1_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x0000000C : EP1_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x0000000E : EP1_RX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000010 : EP2_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000012 : EP2_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000014 : EP2_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000016 : EP2_RX_COUNT

https://community上进行. st.com/s/question/0D50X00009XkaUASAZ/stm32-usb-endpoint-configuration-clarification-questions

这表明端点0x810x82起作用是因为pma[4]pma[8]都设置为0x100.

端点0x83不起作用,因为pma[12]设置为0x0.

这与具有值58 00 2c 00的损坏数据一致-USB硬件正在读取pma[12],因此由于小端顺序,从pma[0]发送的uint16_t(即0x0058 0x002c)被反向发送. (注意:PMA只有16位宽,因此这里每个地址只有两个字节.)

HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82, PCD_SNG_BUF, 0x100);的调用并没有在pma[12]处设置btable指针,它只是指出要复制到的PMA地址.

现在我只需要查找btable内容的写入位置...

解决方案

EP3的TX地址正被传入的USB数据包覆盖,因为它在PMA中的位置与控件EP0的RX缓冲区的偏移量相同.原始代码可以正常工作,因为它仅使用EP1.

如何精确设置这些偏移量取决于STMCube层中的内容,我的副本似乎有所不同,但这似乎是在OP的代码中设置了EP0中RX和TX缓冲区的偏移量的地方:

HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);

这些常量需要更改为0x40和0x80(例如).

在我的版本中,这些偏移量在头文件中定义,并且还有EP_NUM常量,但是不清楚如何使用它.

其他所有事情似乎都让人分心.

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 USB 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 click_reports 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(... for endpoint address 0x83?


Update:

If I change usb_conf.c to let endpoint address 0x83 use the PMA address that is normally used by 0x81:

  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

the packets on the wire are still corrupted:

58 00 2c 00
58
58 00 2c 00
58

If I return usb_conf.c to its initial, generated, state (where 0x83 has no PMA address, and 0x81 uses 0x100):

  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

the output works as expected:

01 00 00 00
00
00 00 00 00
00


Update 2:

I added a break-point in USB_ActivateEndpoint() in stm32f3xx_ll_usb.c.

Surprisingly this is only ever called for endpoint 0.

Therefore, the ep->pmaadress (sic) is never "written into hardware", and only used in higher-level code.

This must mean that the values of pmaadress for the endpoints are set to some default value, and I do not know the default value for endpoint 0x83 and so can't set it.

When I return to work on Friday, I will add debugging to read-out the default values. If they do not exist, I will be very confused.


Update 3:

I added the following debugging:

uint16_t *tx_addr_ptr(USB_TypeDef *USBx, uint8_t ep_num) {
  register uint16_t *_wRegValPtr;
  register uint32_t _wRegBase = (uint32_t)USBx;
  _wRegBase += (uint32_t)(USBx)->BTABLE;
  _wRegValPtr = (uint16_t *)(_wRegBase + 0x400U + (((uint32_t)(ep_num) * 8U) * 2U));
  return _wRegValPtr;
}

uint16_t *rx_addr_ptr(USB_TypeDef *USBx, uint8_t ep_num) {
  register uint16_t *_wRegValPtr;
  register uint32_t _wRegBase = (uint32_t)USBx;
  _wRegBase += (uint32_t)(USBx)->BTABLE;
  _wRegValPtr = (uint16_t *)(_wRegBase + 0x400U + ((((uint32_t)(ep_num) * 8U) + 4U) * 2U));
  return _wRegValPtr;
}
...
HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
{
  ...
  int txaddrs[8] = {0};
  int rxaddrs[8] = {0};
  for (int i = 0; i < 8; ++i) {
    txaddrs[i] = *tx_addr_ptr(USBx, i);
    rxaddrs[i] = *rx_addr_ptr(USBx, i);
  }

This showed me the following values (in the debugger):

txaddrs:
  0: 0x58
  1: 0xf5c4
  2: 0xc1c2
  3: 0x100

rxaddrs:
  0: 0x18
  1: 0xfa9b
  2: 0xcb56
  3: 0x0

These, unexpectedly, look correct.

0x100 is the txaddr of endpoint 3, even though USB_ActivateEndpoint() has only just been called for the first time.

With a lot of grepping, I found that PCD_SET_EP_TX_ADDRESS (in stm32f3xx_hal_pcd.h) is not only used directly in USB_ActivateEndpoint(), but also in the PCD_SET_EP_DBUF0_ADDR macro from `stm32f3xx_hal_pcd.h.

PCD_SET_EP_DBUF0_ADDR does not appear to be used, so I do not know how the (changed) values from usbd_conf.c:

USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
  ...
  /* 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, 0x100);
  /* USER CODE END EndPoint_Configuration_HID */

get into the memory-mapped USB registers.

I can infer, from the presence of a 0x00 in rxaddr[3] (endpoint 3) that they happen in pairs (as there is no call to HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x3 , PCD_SNG_BUF, 0x0);).


Update 4:

After changing the device to use endpoint 1 again, the value of 0x100 in txaddrs[3] remained. It was simply there from the last run, which removes a little confusion.


Update 5:

It's a BTABLE problem. The BTABLE register has a value of 0x00, putting the btable at the start of the PMA.

The PMA looks like this: and the start of the PMA is the btable.

I found:

PMAAddr + BASEADDR_BTABLE + 0x00000000 : EP0_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000002 : EP0_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000004 : EP0_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000006 : EP0_RX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000008 : EP1_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x0000000A : EP1_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x0000000C : EP1_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x0000000E : EP1_RX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000010 : EP2_TX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000012 : EP2_TX_COUNT
PMAAddr + BASEADDR_BTABLE + 0x00000014 : EP2_RX_ADDR
PMAAddr + BASEADDR_BTABLE + 0x00000016 : EP2_RX_COUNT

on https://community.st.com/s/question/0D50X00009XkaUASAZ/stm32-usb-endpoint-configuration-clarification-questions

This shows that endpoints 0x81 and 0x82 work because both pma[4] and pma[8] are set to 0x100.

Endpoint 0x83 does not work because pma[12] is set to 0x0.

This is consistent with the corrupted data having the value 58 00 2c 00 - the USB hardware was reading pma[12] and therefore sending the uint16_t's from pma[0], which are 0x0058 0x002c, sent reversed because of little-endianness. (Note: the PMA is only 16-bits wide, so there are only two bytes at each address here.)

The call to HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82, PCD_SNG_BUF, 0x100); does not set up the btable pointer at pma[12], it just notes that PMA address to copy-to.

Now I just need to find where the content of the btable is being written...

解决方案

The TX address of EP3 is being overwritten by an incoming USB packet because it is located at the same offset in PMA as the RX buffer for the control EP0. The original code works okay because it only uses EP1.

How exactly these offsets are set depends on what's in the layers of STMCube, and my copy seems to be different, but this appears where the offsets of RX and TX buffers in EP0 are set in the OP's code:

HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);

These constants need to be changed to 0x40 and 0x80 (for example).

In my version, these offsets are defined in a header file and there is also EP_NUM constant, but how it's used is unclear.

Everything else seems to be just distractions.

这篇关于当端点和PMA地址都更改时,CubeMX生成的USB HID设备发送错误的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆