[单片机][at32][填坑日记] [USB卡包] usb快速发包导致卡包
文章目录
- 一、问题现象
- 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快速发包导致卡包相关推荐
- [单片机][at32][填坑日记] [USB卡包] usb上电过程中快速发包导致卡包(终章)
文章目录 一.原因造成如下: 1. 串口外设优先级大于USB中断(USBOTG_IRQn),导致串口数据打断USB,致使PC或MCU丢包. 2. 当PC请求usb设备描述符字符串时,USB的其他通道不 ...
- [单片机][cx32][填坑日记] 从AC5到AC6 flash写入功能异常
通过keil ide 把编译换成AC6,发现flash写入失效了,通过仿真发现,栈数据全部异常了(错位).于是找到了uint64_td导致的异常. 先看看修复内容:
- Vue入门到上手(10)—— VueJs 填坑日记之在项目中使用Amaze UI
Vue入门到上手(10)-- VueJs 填坑日记之在项目中使用Amaze UI 上一篇博文,我们把jQuery集成到了项目中,今天我们来集成Amaze ui(妹子UI).先来介绍一下妹子UI.Ama ...
- 20150726 填坑日记
三中内填坑: 1. 组合数递推什么的 C(m,n)=C(m,n-1)+C(m-1,n-1).填了个大坑,以前没认真听课QAQ 2. 裸题过河卒 3. 缺角正方形摆放车统计,分上下部分,枚举上部分放几个 ...
- android多语言插件,Android 7.0多语言适配,填坑日记(附多语言插件)
背景 最近项目在适配7.0系统的时候发现一些问题,其中也有多语言适配的问题,就拿出来说说,记记笔记,填填坑. 问题1 因为刚接手项目不久,发现一些奇奇怪怪的bug总是让人头疼,最近发现了在华为荣耀7. ...
- WindowsPhoneWindows8.1Windows8Unity3d 填坑日记
最近的游戏开发大体上接近尾声,总结了不少关于Unity3d面向Windows几大平台开发时遇到的各种坑以及如何填坑的经验.总的来说,Windows8.1 Windows8/RT以及WindowsPho ...
- 【灾害学|思考题填坑】关于为什么地下水枯竭会导致地面塌陷这档子事
[Q/A]为什么地下水枯竭会导致地面塌陷 1 图示 2 解释 2.1 前置条件 2.2 分析 3 举个例子 4 论文怎么说 3.1 关于实验(论文中的规律中提出来了) 3.2 地面塌陷主要原因 3.2 ...
- Hadoop Dynamometer工具详细教程,填坑日记
Dynamometer工具使用步骤 Dynamometer 介绍 准备"材料" 原理 注意事项 流程 1.fsimage 2.hadoop binary 3.Configurati ...
- 八、VueJs 填坑日记之参数传递及内容页面的开发
我们在上一篇博文中,渲染出来了一个列表,并在列表中使用了router-link标签,标签内的:to就是链接地址,昨天咱们是<router-link :to="'/content/' + ...
最新文章
- MySQL 跨库分页/ 分表分页/ 跨库分页,为什么这么难?
- 机器学习--判别式模型与生成式模型
- python读取大文件-强悍的Python读取大文件的解决方案
- javascript 给php传值_2020年PHP面试题附答案(实战经验)
- 【数据分析】Databricks入门:分析COVID-19
- kaggle(一)训练猫狗数据集
- 分析mrp主要应用范围_华珀聚脲丨聚脲的主要应用范围
- java中随机数边界问题,java 简单Dice问题(随机数的运用)
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 配置选项
- linux服务器遭攻击,记一次linux服务器被攻击与防护
- 吴恩达新公司曝光:签下富士康,要用AI变革制造业
- php beanstalkd使用,PHP使用Beanstalkd实例详解
- 【numpy】数组增加一维(升维)小结
- Atitit java 原生 客户端 native desktop桌面 javafx 浏览器环境 导入jar jfxrt.jar 17M package com.attilax.ui;
- 第六次人口普查数据分析
- 202012月计算机考试时间,年全国计算机等级考试时间(范文).docx
- 解决开启Windows防火墙后,其他电脑ping不通问题
- qt打开xls文件_使用QtXlsx来读写excel文件
- Fits文件在天文方面的应用(数据处理部分)
- 原来酷炫的大屏,用Excel就能做
热门文章
- response对象
- java Request对象和Response对象详解
- android arrayadapter自定义,Android中Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)...
- java 创建线程thread_初学Java多线程:用Thread类创建线程
- 万维网之父 65 岁创业,原因与你我都有关
- Siddhi cep
- 图片展示html css代码,纯CSS3实现图片展示特效
- 软件安全测试-Web安全测试详解-CSRF攻击
- 高效Android开发者必须知道的4个工具
- Android Camera 开发你该知道的秘密㊙️-新手入门必备