最近测试USB HID设备,发现多次接收数据后崩溃,在线DEBUG测试,程序最终进入到HardFault中断,源代码如下:
void USBD_LP_CAN0_RX0_IRQHandler (void)
{
uint8_t rece_buffer[CUSTOMHID_OUT_PACKET] = {0};
/*该中断函数包含USB的多种中断*/
usbd_isr();
/*读取接收到的数据*/
custom_hid_report_receive (&usb_device_dev, rece_buffer, CUSTOMHID_OUT_PACKET);
/*处理接收到的数据*/
if(rece_buffer[0] == 0x12)
{
}
}
经过查询GD32官方USBD设备资料,发现中断处理已集成在usbd_isr()函数中,进入到该函数中:
void usbd_isr (void)
{
__IO uint16_t interrupt_flag = 0U;
__IO uint16_t ctlr = 0U;
interrupt_flag = USBD_REG_GET(USBD_INTF);
if (g_interrupt_mask & INTF_STIF & interrupt_flag) {
/* the endpoint successful transfer interrupt service */
usbd_intf_lpst(&usb_device_dev);
}
..................
..................
}
进一步查找,找到端点传输中断函数usbd_intf_lpst(&usb_device_dev),该函数包括输入、输出端点的中断处理。函数如下:
static uint8_t usbd_intf_lpst (usbd_core_handle_struct *pudev)
{
uint8_t ep_num = 0U;
__IO uint16_t int_status = 0U;
__IO uint16_t ep_value = 0U;
usb_ep_struct *ep = NULL;
/* wait till interrupts are not pending */
while (0U != ((int_status = USBD_REG_GET(USBD_INTF)) & (uint16_t)INTF_STIF)) {
/* get endpoint number and the value of control and state register */
ep_num = (uint8_t)(int_status & INTF_EPNUM);
ep_value = USBD_REG_GET(USBD_EPxCS(ep_num));
if (0U == (int_status & INTF_DIR)) {
/* handle the in direction transaction */
/* 处理发送端点中断*/
}
else/* 处理接收端点中断*/
{
/* handle the out direction transaction */
uint16_t count = 0U;
ep = &(pudev->out_ep[ep_num]);
if (0U != (ep_value & EPxCS_RX_ST)) {
/* clear successful receive interrupt flag */
USBD_ENDP_RX_STAT_CLEAR(ep_num);
count = (pbuf_reg + ep_num)->rx_count & (uint16_t)EPRCNT_CNT;
if (0U != count) {
if (0U != (ep_value & EPxCS_SETUP)) {
/* handle setup packet */
usbd_ep_data_read(&(pudev->setup_packet[0]), pbuf_reg->rx_addr, count);
/* enter setup status */
usbd_setup_transaction(pudev);
return USBD_OK;
} else {
usbd_ep_data_read(ep->trs_buf, (pbuf_reg + ep_num)->rx_addr, count);
}
/*读取接收到的数据,并进行标志位处理*/
rece_buffer[0] = ep->trs_buf[0];
if(rece_buffer[0] == 0x12)
{
s_Device.Key_Val++;
}
............................
}
从该函数可以看出,先是判断端点中断类型,发送or接收;接收中又分为枚举过程和数据接收过程,在接收函数 usbd_ep_data_read()之后,获取数据进行处理,置位对应的标志位,然后在中断外部具体处理事件。
按上面过程处理后,再次进行测试,程序没有崩溃,能正常工作。
不知道,之前在中断处理函数usbd_isr()之外,读取接收的数据的操作,是否引起哪里冲突了?在此标记一下,欢迎补充。