Panchip Cop.

查看: 677|回复: 0

PAN108X : USB EP使用异常问题

[复制链接]

8

主题

52

帖子

1万

积分

磐启员工

Rank: 7Rank: 7Rank: 7

积分
10799
发表于 2024-12-2 16:46:10 | 显示全部楼层 |阅读模式
本帖最后由 刘海兵 于 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
}



回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表