文章目录

  • 一、问题现象
    • 1. 发送频率过快,导致pc或mcu未能及时应答每一包,造成缓存区遗留上一次数据。
    • 2. usb频发拔插枚举,导致pc/mcu数据丢失,
      • ①mcu丢失数据,每次发送都只能发送上次内容。
      • ②pc丢失数据,每次接收只会处理上次内容。
    • 3. 重启电脑过程中,mcu频繁发送usb数据,导致pc端丢失应答数据,PC端卡包(缺一包应答),只能处理上次数据,
  • 二、解决方案如下:
    • 1. usb_dcd_int.c --> USB_device_handle_UsbReset_intsts()
      • 示例代码
    • 2. 补充USB协议忙状态
      • 示例代码
    • 3. mcu端usb卡包解决方案,在主函数里面进行usb状态扫描,如果fifo异常,则推送数据
      • 示例代码
    • 4. 备用方案:usb拔插重新激活USB外设(带电池版本)
      • 示例代码
    • 5. 无电池版本
      • 1. USB上电反初始化
      • 2. 上电稳定300ms再初始化USB。(建议用裸机用定时器,os用软定时器)

一、问题现象

1. 发送频率过快,导致pc或mcu未能及时应答每一包,造成缓存区遗留上一次数据。

2. usb频发拔插枚举,导致pc/mcu数据丢失,

①mcu丢失数据,每次发送都只能发送上次内容。

②pc丢失数据,每次接收只会处理上次内容。

3. 重启电脑过程中,mcu频繁发送usb数据,导致pc端丢失应答数据,PC端卡包(缺一包应答),只能处理上次数据,

现象:按键数据一直发送,且无释放按键数据。

二、解决方案如下:

1. usb_dcd_int.c --> USB_device_handle_UsbReset_intsts()


示例代码

/**
* @brief  USB_device_handle_UsbReset_intsts
*         This interrupt occurs when a USB Reset is detected
* @param  pusbdev: device instance
* @retval status
*/
static uint32_t USB_device_handle_UsbReset_intsts(USB_OTG_CORE_HANDLE *pusbdev)
{USB_OTG_DAINT_TypeDef daintmsk;USB_OTG_DOEPMSK_Type doepmsk;USB_OTG_DIEPMSK_Type diepmsk;USB_OTG_DCFG_Type dcfg;USB_OTG_DCTL_Type dctl;USB_OTG_GINTSTS_Type gintsts;uint32_t i;dctl.u32val = 0;daintmsk.u32val = 0;doepmsk.u32val = 0;diepmsk.u32val = 0;dcfg.u32val = 0;gintsts.u32val = 0;RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_USB, DISABLE);__NOP();RCC_AHBPeriphClockCmd(RCC_AHBPERIPH_USB, ENABLE);/* Clear the Remote Wake-up Signaling */dctl.b.rwkupsig = 1;USB_OTG_MODIFY_R32(&pusbdev->regs.DREGS->DCTRL, dctl.u32val, 0);/* Flush the Tx FIFO */USB_OTG_FlushTxFifo(pusbdev, 0);USB_OTG_FlushTxFifo(pusbdev, EP1_IN);USB_OTG_FlushTxFifo(pusbdev, EP2_IN);
#if BOOT_SUPPORTUSB_OTG_FlushTxFifo(pusbdev, EP3_IN);
#endiffor (i = 0; i < pusbdev->cfg.dev_endpoints; i++){USB_OTG_WRITE_R32(&pusbdev->regs.INEP_REGS[i]->DINEPTINT, 0xFF);USB_OTG_WRITE_R32(&pusbdev->regs.OUTEP_REGS[i]->DOUTEPTINT, 0xFF);}USB_OTG_WRITE_R32(&pusbdev->regs.DREGS->DAINT, 0xFFFFFFFF);daintmsk.ept.in = 1;daintmsk.ept.out = 1;USB_OTG_WRITE_R32(&pusbdev->regs.DREGS->DAINTMASK, daintmsk.u32val);doepmsk.b.setup = 1;doepmsk.b.xferc = 1;doepmsk.b.eptdis = 1;USB_OTG_WRITE_R32(&pusbdev->regs.DREGS->DOUTEPTMASK, doepmsk.u32val);diepmsk.b.xferc = 1;diepmsk.b.timeout = 1;diepmsk.b.eptdis = 1;USB_OTG_WRITE_R32(&pusbdev->regs.DREGS->DINEPTMASK, diepmsk.u32val);/* Reset Device Address */dcfg.u32val = USB_OTG_READ_R32(&pusbdev->regs.DREGS->DCFG);dcfg.b.devaddr = 0;USB_OTG_WRITE_R32(&pusbdev->regs.DREGS->DCFG, dcfg.u32val);/* setup EP0 to receive SETUP packets */USB_OTG_EPT0_OutStart(pusbdev);/* Clear interrupt */gintsts.u32val = 0;gintsts.b.usbrst = 1;USB_OTG_WRITE_R32(&pusbdev->regs.GREGS->GINTSTS, gintsts.u32val);/*Reset internal state machine */USB_DEVICE_DCD_INT_fops->Reset(pusbdev);return 1;
}

2. 补充USB协议忙状态

示例代码

bool usb_tx_flag = false;/*** @brief  USBD_HID 接口函数结构体*/
USBD_Class_cb_Type USBD_HID_cb =
{.Init                = usb_device_hid_init,.Reset               = usb_device_hid_reset,.Setup               = usb_device_hid_setup,.EPT0_TxSent         = NULL,                   /*EPT0_TxSent*/.EPT0_RxReady        = NULL,                   /*EPT0_RxReady*/.Data_In             = usb_device_hid_datain,  /*Data_In*/.Data_Out            = usb_device_hid_dataout, /*Data_Out*/.SOF                 = usb_device_hid_sof,     /*SOF */.IsoINIncomplete     = NULL,.IsoOUTIncomplete    = NULL,.GetConfigDescriptor = usb_device_hid_getcfgdesc,
};bool get_usb_tx_flag(void)
{return usb_tx_flag;
}/*** @brief  usb_device_hid_sof USB_FIFO空闲中断*         sof function* @param  pusbdev: device instance* @retval status*/
uint8_t usb_device_hid_sof(void *pusbdev)
{usb_tx_flag = false;return USB_DEVICE_OK;
}/*** @brief  发送hid报告* @param  pusbdev: usb设备指针* @param  report: 报告头指针* @param  len: 报告长度* @retval status*/
uint8_t usb_device_hid_sendreport(USB_OTG_CORE_HANDLE *pusbdev, uint8_t *report, uint16_t len)
{if (usb_tx_flag){return USB_DEVICE_BUSY;}uint8_t hid_ep;if (report[0] == 0x02){hid_ep = EP3_IN;len = EP3_IN_SIZE;}else if (report[0] == 0x07){hid_ep = EP2_IN;len = EP2_IN_SIZE;}else if (report[0] == 0x09 || report[0] == 0x06 || report[0] == 0x01){hid_ep = EP1_IN;len = EP1_IN_SIZE;}else{LOG_E("<ERR> USB_DEVICE_FAIL2 report:%02x\r\n", report[0]);return USB_DEVICE_FAIL;}memcpy(g_hid_txBuf, report, len);if (pusbdev->dev.device_status == USB_OTG_CONFIGURED){usb_tx_flag = true;USB_DCD_EPT_Tx(pusbdev, hid_ep, g_hid_txBuf, len);}else{LOG_E("<ERR> USB_DEVICE_FAIL state:%02x\r\n", pusbdev->dev.device_status);return USB_DEVICE_FAIL;}return USB_DEVICE_OK;
}

3. mcu端usb卡包解决方案,在主函数里面进行usb状态扫描,如果fifo异常,则推送数据

示例代码

/*** @brief  得到USB节点3,FIFO区状态* @retval 0--正常  1--异常*/
bool get_usb_fifo_state(void)
{// LOG_D("<DEBUG> [get_usb_fifo_state] %d | %02x |\r\n", g_usb_init, USB_OTG_dev.regs.INEP_REGS[3]->DTXFSTS);if (g_usb_init && USB_OTG_dev.regs.INEP_REGS[3]->DTXFSTS != 0x40 && USB_OTG_dev.regs.INEP_REGS[3]->DTXFSTS != 0x20){LOG_E("<ERR> [usb_fifo_ste] Enter Fifo Fail %02x\r\n", USB_OTG_dev.regs.INEP_REGS[3]->DTXFSTS);USBD_HID_cb.Data_In(&USB_OTG_dev, 3|0x80);LOG_E("<ERR> [usb_fifo_ste] Exit  Fifo Fail %02x\r\n", USB_OTG_dev.regs.INEP_REGS[3]->DTXFSTS);return true;}else{return false;}
}

4. 备用方案:usb拔插重新激活USB外设(带电池版本)

示例代码

        if (event.value.signals & SIGNAL_REFRESH_USB){// USB拔出时,清除当前USB消息队列if (!get_usb_state()){biz_usb_queue_init();}else{os_delay(100);usb_init();// 激活USB_DP让PC重新枚举bsp_gpio_set_pin(BOARD_USB_DP_PORT, BOARD_USB_DP_PIN, BOARD_USB_DP_PRESS_LEVEL);// 发送一次按键释放(防止按键按住)g_combined_key_val = 0;g_key_trigger_flag = true;// 判断是否需要开机if(get_sys_state() != SYS_STATE_POWER_ON){main_send_signal(SIGNAL_SYS_POWER_ON);}}if (!get_usb_state() && !get_usb_device_status()){bsp_gpio_set_pin(BOARD_USB_DP_PORT, BOARD_USB_DP_PIN, !BOARD_USB_DP_PRESS_LEVEL);usb_deinit();}LOG_D("<DEBUG> SIGNAL_REFRESH_USB->%d %d\r\n", get_usb_state(), get_usb_device_status());}

5. 无电池版本

1. USB上电反初始化

    // USB拔出时,清除当前USB消息队列if (!get_usb_state()){biz_usb_queue_init();}if (!get_usb_state() && !get_usb_device_status()){bsp_gpio_set_pin(BOARD_USB_DP_PORT, BOARD_USB_DP_PIN, !BOARD_USB_DP_PRESS_LEVEL);usb_deinit();}

2. 上电稳定300ms再初始化USB。(建议用裸机用定时器,os用软定时器)

定时器100ms基准:g_sys_run_times ++;if(g_sys_run_times == 3 && get_usb_state() == false){set_usb_state(true);main_send_signal(SIGNAL_REFRESH_USB);}
if (event.value.signals & SIGNAL_REFRESH_USB)usb_init();// 激活USB_DP让PC重新枚举bsp_gpio_set_pin(BOARD_USB_DP_PORT, BOARD_USB_DP_PIN, BOARD_USB_DP_PRESS_LEVEL);// 发送一次按键释放(防止按键按住)g_combined_key_val = 0;g_key_trigger_flag = true;
}

[单片机][at32][填坑日记] [USB卡包] usb快速发包导致卡包(二)

[单片机][at32][填坑日记] [USB卡包] usb上电过程中快速发包导致卡包(终章)

[单片机][at32][填坑日记] [USB卡包] usb快速发包导致卡包相关推荐

  1. [单片机][at32][填坑日记] [USB卡包] usb上电过程中快速发包导致卡包(终章)

    文章目录 一.原因造成如下: 1. 串口外设优先级大于USB中断(USBOTG_IRQn),导致串口数据打断USB,致使PC或MCU丢包. 2. 当PC请求usb设备描述符字符串时,USB的其他通道不 ...

  2. [单片机][cx32][填坑日记] 从AC5到AC6 flash写入功能异常

    通过keil ide 把编译换成AC6,发现flash写入失效了,通过仿真发现,栈数据全部异常了(错位).于是找到了uint64_td导致的异常. 先看看修复内容:

  3. Vue入门到上手(10)—— VueJs 填坑日记之在项目中使用Amaze UI

    Vue入门到上手(10)-- VueJs 填坑日记之在项目中使用Amaze UI 上一篇博文,我们把jQuery集成到了项目中,今天我们来集成Amaze ui(妹子UI).先来介绍一下妹子UI.Ama ...

  4. 20150726 填坑日记

    三中内填坑: 1. 组合数递推什么的 C(m,n)=C(m,n-1)+C(m-1,n-1).填了个大坑,以前没认真听课QAQ 2. 裸题过河卒 3. 缺角正方形摆放车统计,分上下部分,枚举上部分放几个 ...

  5. android多语言插件,Android 7.0多语言适配,填坑日记(附多语言插件)

    背景 最近项目在适配7.0系统的时候发现一些问题,其中也有多语言适配的问题,就拿出来说说,记记笔记,填填坑. 问题1 因为刚接手项目不久,发现一些奇奇怪怪的bug总是让人头疼,最近发现了在华为荣耀7. ...

  6. WindowsPhoneWindows8.1Windows8Unity3d 填坑日记

    最近的游戏开发大体上接近尾声,总结了不少关于Unity3d面向Windows几大平台开发时遇到的各种坑以及如何填坑的经验.总的来说,Windows8.1 Windows8/RT以及WindowsPho ...

  7. 【灾害学|思考题填坑】关于为什么地下水枯竭会导致地面塌陷这档子事

    [Q/A]为什么地下水枯竭会导致地面塌陷 1 图示 2 解释 2.1 前置条件 2.2 分析 3 举个例子 4 论文怎么说 3.1 关于实验(论文中的规律中提出来了) 3.2 地面塌陷主要原因 3.2 ...

  8. Hadoop Dynamometer工具详细教程,填坑日记

    Dynamometer工具使用步骤 Dynamometer 介绍 准备"材料" 原理 注意事项 流程 1.fsimage 2.hadoop binary 3.Configurati ...

  9. 八、VueJs 填坑日记之参数传递及内容页面的开发

    我们在上一篇博文中,渲染出来了一个列表,并在列表中使用了router-link标签,标签内的:to就是链接地址,昨天咱们是<router-link :to="'/content/' + ...

最新文章

  1. MySQL 跨库分页/ 分表分页/ 跨库分页,为什么这么难?
  2. 机器学习--判别式模型与生成式模型
  3. python读取大文件-强悍的Python读取大文件的解决方案
  4. javascript 给php传值_2020年PHP面试题附答案(实战经验)
  5. 【数据分析】Databricks入门:分析COVID-19
  6. kaggle(一)训练猫狗数据集
  7. 分析mrp主要应用范围_华珀聚脲丨聚脲的主要应用范围
  8. java中随机数边界问题,java 简单Dice问题(随机数的运用)
  9. [翻译] 编写高性能 .NET 代码--第二章 GC -- 配置选项
  10. linux服务器遭攻击,记一次linux服务器被攻击与防护
  11. 吴恩达新公司曝光:签下富士康,要用AI变革制造业
  12. php beanstalkd使用,PHP使用Beanstalkd实例详解
  13. 【numpy】数组增加一维(升维)小结
  14. Atitit java 原生 客户端 native desktop桌面 javafx 浏览器环境 导入jar jfxrt.jar 17M package com.attilax.ui;
  15. 第六次人口普查数据分析
  16. 202012月计算机考试时间,年全国计算机等级考试时间(范文).docx
  17. 解决开启Windows防火墙后,其他电脑ping不通问题
  18. qt打开xls文件_使用QtXlsx来读写excel文件
  19. Fits文件在天文方面的应用(数据处理部分)
  20. 原来酷炫的大屏,用Excel就能做

热门文章

  1. response对象
  2. java Request对象和Response对象详解
  3. android arrayadapter自定义,Android中Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)...
  4. java 创建线程thread_初学Java多线程:用Thread类创建线程
  5. 万维网之父 65 岁创业,原因与你我都有关
  6. Siddhi cep
  7. 图片展示html css代码,纯CSS3实现图片展示特效
  8. 软件安全测试-Web安全测试详解-CSRF攻击
  9. 高效Android开发者必须知道的4个工具
  10. Android Camera 开发你该知道的秘密㊙️-新手入门必备