|
本帖最后由 刘海兵 于 2024-12-2 17:55 编辑
在客户应用中(比如常见的HID键鼠项目),会使用到USB的多个EP, 在操作EP之前,需要先选择对应的EP号WRITE_REG(USB->INDEX, “EP号”); 然后接下来再进行IN/OUT数据处理。
比如键盘通过EP1端点上报一包数据,流程如下:
WRITE_REG(USB->INDEX, 1); // 选择指定的EP号
USB_Write((uint32_t)1, KEYBOARD_STANDARD_KEY_SIZE, (void *)key_data); //往EP1里填充数据
WRITE_REG(USB->CSR0_INCSR1, M_INCSR_IPR);
在USB_Write写的过程中,用户可能默认USB->INDEX的指是保持不变的,此时功能如预期运行。
但是如果程序中其它高优先线程或者中断还存在操作其它EP的情况,就有概率导致EP1异常。
原因如下,假设上述流程中,执行完“WRITE_REG(USB->INDEX, 1); ”之后,还没来得及执行
“USB_Write((uint32_t)1, KEYBOARD_STANDARD_KEY_SIZE, (void *)key_data);”
此时来个EP0/EP1/EP2 OUT中断,此时会先跳转到中断回调函数中执行对应的处理,比如EP0:
void Endpoint0_Rx(void)
{
uint8_t rec_data[64] = { 0 };
uint8_t recbytes;
uint8_t index_before;
WRITE_REG(USB->INDEX, 0); // 切换至EP0
recbytes = READ_REG(USB->OUT_COUNT1);
USB_Read(0, recbytes, rec_data);
led_kb_status_indicate_update(rec_data[0]);
WRITE_REG(USB->INDEX, 0);
WRITE_REG(USB->CSR0_INCSR1, M_CSR0_SVDOUTPKTRDY);
}
在EP0的中断处理中,USB->INDEX的值被设置为了0,执行结束后返回线程,接着执行
“USB_Write((uint32_t)1, KEYBOARD_STANDARD_KEY_SIZE, (void *)key_data);” 就会异常。
因为“USB->INDEX”的值被异常修改了。
解决思路:
在中断处理函数中加入INDEX值的保护机制,在结束之后能还原之前的值。
void Endpoint0_Rx(void)
{
uint8_t rec_data[64] = { 0 };
uint8_t recbytes;
uint8_t index_before;
index_before = USB->INDEX; // 保存EP1的值
WRITE_REG(USB->INDEX, 0); // 切换至EP0
recbytes = READ_REG(USB->OUT_COUNT1);
USB_Read(0, recbytes, rec_data);
led_kb_status_indicate_update(rec_data[0]);
WRITE_REG(USB->INDEX, 0);
WRITE_REG(USB->CSR0_INCSR1, M_CSR0_SVDOUTPKTRDY);
WRITE_REG(USB->INDEX, index_before); // 还原EP1
}
|
|