Я отлаживаю проблему с созданным композитным устройством и воссоздаю проблему в только что сгенерированном CubeMX HID-только коде, чтобы его было легче решить.
Я добавил небольшое количество кода к main()
, чтобы позволить мне отправлять щелчки мыши USB HID, и индикатор sh, когда синяя кнопка нажата.
...
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
s фрагментированы в 4-байтовые и 1-байтовые сообщения, поскольку максимальный размер пакета для HID составляет 4 байта.)
Затем я изменил HID_EPIN_ADDR
в usdb_hid.h
с 0x81
на 0x83
, чтобы устройство использовало конечную точку 3 для сообщений HID вместо конечной точки 1.
//#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_ADDR 0x83U
С этим изменением все продолжало работать, с ожидаемым изменением, что пакеты отправляются из xx3 , Пакеты по-прежнему содержат:
01 00 00 00
00
00 00 00 00
00
Насколько я вижу, это должно не работать, так как я еще не выделил адрес для конечной точки 3 (0x83
) в PMA (область памяти пакетов).
Я делаю это, редактируя 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 00
и 00 00 00 00 00
click_reports
Я вижу содержимое пакета:
58 00 2c 00
58
58 00 2c 00
58
Я проследил содержимое буфера без PMA вплоть до USB_WritePMA
в stm32f3xx_ll_usb
.
Код отправки (в 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
{
Почему данные на проводе не являются данными, которые я даю USB_WritePMA
, как только я добавил HAL_PCDEx_PMAConfig(...
для адреса конечной точки 0x83
?
Обновление:
Если я изменю usb_conf.c
, чтобы разрешить адресу конечной точки 0x83
использовать адрес PMA, который обычно используется 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 */
пакеты на проводе все еще повреждены:
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 */
вывод работает как expec ted:
01 00 00 00
00
00 00 00 00
00
Обновление 2:
Я добавил точку останова в USB_ActivateEndpoint()
в stm32f3xx_ll_usb.c
.
Удивительно, но это когда-либо вызывалось для конечной точки 0.
Следовательно, ep->pmaadress
(si c) никогда не "записывается в аппаратное обеспечение" и используется только в коде более высокого уровня.
Это должно означать, что значения 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
- это txaddr конечной точки 3, хотя USB_ActivateEndpoint()
только что был вызван только в первый раз.
С большим вниманием я обнаружил, что PCD_SET_EP_TX_ADDRESS
( в stm32f3xx_hal_pcd.h
) используется не только непосредственно в USB_ActivateEndpoint()
, но и в макросе PCD_SET_EP_DBUF0_ADDR
из `stm32f3xx_hal_pcd.h.
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-регистры с отображением в памяти.
Я могу вывести из наличия 0x00
в rxaddr[3]
(конечная точка 3), что они происходят парами (так как нет вызова HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x3 , PCD_SNG_BUF, 0x0);
).
Обновление 4:
После изменения устройства для использования конечной точки 1 опять значение 0x100
в txaddrs [3] осталось. Это было просто там с последнего запуска, что устраняет небольшую путаницу.
Обновление 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
Это показывает, что конечные точки 0x81
и 0x82
работают, потому что pma[4]
и pma[8]
установлены на 0x100
.
Конечная точка 0x83
не работает, потому что pma[12]
установлена на 0x0
.
Это согласуется с поврежденными данными, имеющими значение 58 00 2c 00
- оборудование USB считывало pma[12]
и, следовательно, отправляло uint16_t из pma[0]
, которые 0x0058 0x002c
, отправлены в обратном порядке из-за порядка байтов. (Примечание: ширина PMA составляет всего 16 бит, поэтому здесь для каждого адреса есть только два байта.)
При вызове HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82, PCD_SNG_BUF, 0x100);
не не устанавливается указатель btable на pma[12]
, он просто отмечает, что адрес PMA для копирования в.
Теперь мне просто нужно найти, где пишется содержимое btable ...