天天看點

[單片機][at32][填坑日記] [USB卡包] usb上電過程中快速發包導緻卡包(終章)

現象:pc重新開機過程中,不斷發送按鍵資料,導緻pc未能應答,緻使下位機資料出現卡包現象。

MCU發送’B’,PC顯示’C’,MCU發送’E’,PC顯示’B’

原因造成如下:

  1. 序列槽外設優先級大于USB中斷(USBOTG_IRQn),導緻序列槽資料打斷USB,緻使PC或MCU丢包。
  2. [單片機][at32][填坑日記] [USB卡包] usb上電過程中快速發包導緻卡包(終章)
  3. 當PC請求usb裝置描述符字元串時,USB的其他通道不能發送資料,不然會導緻通道0資料異常,導緻PC丢包。
  4. 系統隻會請求字元串0-2,是以在此設定标志位即可。
  5. USB整個發送邏輯
// 此處解決PC開機過程中usb資料卡包問題。因為當pc請求字元串時,其他通道的資料發送會導緻異常。
    if (get_usb_string_bus)
    {
        get_usb_string_bus = false;
        biz_usb_queue_init();
#if BS_BLE_SUPPORT
        biz_ble_queue_init();
#endif
        g_key_trigger_flag = false;
        g_combined_key_val = 0;
        g_usb_send_delay_tick = 0;
        LOG_D("<DEBUG> [USB] get_usb_string_bus\r\n");
        return;
    }
    // 按鍵資料發送
    if (g_key_trigger_flag)
    {
        g_free_tick = 0;
        g_key_trigger_flag = false;
        biz_prot_hwic_usb_send_key_data(g_combined_key_val);
        sys_time_reset();
    }
    if (g_usb_send_delay_tick % 1400 == 0 && g_usb_send_delay_tick != 0)
    {
        if (get_usb_device_status())
        {
            // 發送USB資訊(将USB消息隊列的内容,依次發送)
            if (biz_usb_data_dispose())
            {
                LOG_D("<DEBUG> [USB] send ok!!!\r\n");
                g_free_tick = 0;
                return;
            }
        }
    }
    g_free_tick++;
    if (g_free_tick % 10000 == 0 &&  g_free_tick != 0)
    {
        // 判斷usb fifo是否卡包
        get_usb_fifo_state();
    }      
/**
 * @brief  usb發送資料給usb自定義通道(消息入隊,非實時發送)
 * @param  *data: 欲發送内容
 * @param  len: 内容長度(位元組大小)
 */
void biz_usb_send_data(uint8_t *data, uint16_t len)
{
    if (get_usb_string_bus)
    {
        LOG_D("<DEBUG> [biz_usb_send_data] queue bus fail\r\n");
    }
    if (!queue_en(&m_usb_recv_q, data, len))
    {
        LOG_D("<DEBUG> [biz_usb_send_data] queue full fail\r\n");
    }
}      
/**
 * @brief  處理消息隊列中的消息,通過usb發送(放在空閑線程使用)
 */
bool biz_usb_data_dispose(void)
{
    if(!get_usb_device_is_free())
    {
        LOG_D("<DEBUG> [USB] send Fail not free\r\n");
        get_usb_fifo_state();
        biz_usb_queue_init();
        return false;
    }
    if(get_usb_tx_flag())
    {
        LOG_D("<DEBUG> [USB] send Fail send flag\r\n");
        return false;
    }
    if (!queue_de(&m_usb_drive_recv_q, g_usb_recv_data))
    {
        if (!queue_de(&m_usb_recv_q, g_usb_recv_data))
        {
            return false;
        }
    }
    if (usb_send(g_usb_recv_data, USB_RECV_Q_ITEM_SIZE) == false)
    {
        LOG_D("<DEBUG> [USB] send Fail BUS\r\n");
        biz_usb_send_data(g_usb_recv_data, USB_RECV_Q_ITEM_SIZE);
        return false;
    }
    return true;
}      

繼續閱讀