完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
找了网上大量的资料,最后发现这个东西人家还出售源码。又不是什么算法级的东西,实在理解不了。 至于为什么要用HID,不用官方的DFU,因为驱动呀,DFU识别USB的时候还是要装驱动,客户你永远理解不了他的水平,所以研发需要cover住所有case. 我是在STM32F4的平台上做的,Cubemax配置工程。以前反感这个UI配置,现在这个东西BUG少了,以前定义一个局部的结构体变量都不初始化。下面是配置图,注意RCC配置USB的时钟。 CubeMax配置完生成代码打开,ST已经给你弄好代码框架,你只需要修改设备描述符,传输的字节,轮询的时间,中断回调函数接收。 __ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = { /* USER CODE BEGIN 0 */ 0x05, 0x8c, /* USAGE_PAGE (ST Page) */ 0x09, 0x01, /* USAGE (Demo Kit) */ 0xa1, 0x01, /* COLLECTION (Application) */ // The Input report 0x09,0x03, // USAGE ID - Vendor defined 0x15,0x00, // LOGICAL_MINIMUM (0) 0x26,0x00, 0xFF, // LOGICAL_MAXIMUM (255) 0x75,0x08, // REPORT_SIZE (8bit) 0x95,0x40, // REPORT_COUNT (64Byte) 0x81,0x02, // INPUT (Data,Var,Abs) // The Output report 0x09,0x04, // USAGE ID - Vendor defined 0x15,0x00, // LOGICAL_MINIMUM (0) 0x26,0x00,0xFF, // LOGICAL_MAXIMUM (255) 0x75,0x08, // REPORT_SIZE (8bit) 0x95,0x40, // REPORT_COUNT (64Byte) 0x91,0x02, // OUTPUT (Data,Var,Abs) /* USER CODE END 0 */ 0xC0 /* END_COLLECTION */ }; 相关的宏修改 #define USBD_CUSTOM_HID_REPORT_DESC_SIZE 33U//2 #define CUSTOM_HID_EPIN_ADDR 0x81U #define CUSTOM_HID_EPIN_SIZE 0x40U //64字节 #define CUSTOM_HID_EPOUT_ADDR 0x01U #define CUSTOM_HID_EPOUT_SIZE 0x40U #define CUSTOM_HID_FS_BINTERVAL 0x01U//1ms轮询 这个是USB的中断接收函数,根据USB设备的ID来接收字节,库生成的时候只能接收2个字节的, 当我们改成0x40,就能接收64个字节,USB HID一包只能64个字节 static int8_t CUSTOM_HID_OutEvent_FS(uint8_t event_idx, uint8_t state) { /* USER CODE BEGIN 6 */ return (USBD_OK); /* USER CODE END 6 */ } 梳理USB HID库里面的接收思路,我们可以单独定义一个接收64字节的函数 CUSTOM_HID_OutDulBuf_FS USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_FS = { CUSTOM_HID_ReportDesc_FS, CUSTOM_HID_Init_FS, CUSTOM_HID_DeInit_FS, CUSTOM_HID_OutEvent_FS, CUSTOM_HID_OutDulBuf_FS }; static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf) { return (0); } 重点关注这个函数,这个函数是完成中断接收缓存的,Report_buf[],我们插入 ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutDulBuf(hhid->Report_buf);完成64字节包的接收 static uint8_t USBD_CUSTOM_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) { USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef*)pdev->pClassData; ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(hhid->Report_buf[0], hhid->Report_buf[1]); ((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutDulBuf(hhid->Report_buf); USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR , hhid->Report_buf, USBD_CUSTOMHID_OUTREPORT_BUF_SIZE); return USBD_OK; } 自此,USB HID64字节包的接收我们就完成,关于HID的发送,官方声明了一个static函数,注释掉了,调用发送就好了 有些宏定义的查找,不需要去翻文件了,编译然后goto definition /* static int8_t USBD_CUSTOM_HID_SendReport_FS(uint8_t *report, uint16_t len) { return USBD_CUSTOM_HID_SendReport(&hU***DeviceFS, report, len); } */ 上面的工作已经完成了USB HID的双向通信。重点来,IAP升级,我之前用官方的串口IAP升级做过,用的Ymodem协议传输,波特率921600,Ymodem我们可以使用secureCRT去进行升级传输,官方库的下位机Ymodem已经做的很好了,也有防错机制。现在我们用USB传输,64字节一包,尴尬的是没有上位机去升级,网上或许有下载,但是人家有握手协议,以及包协议,所以基本不能用。由于没有上位机开发经验,甚至一度下载了QT Crator准备开发,后面思考了下还是偷懒了,我用BUS Hound去抓包人家上位机传输的USB格式,关键是这个USB上位机只负责发,没有握手协议。还是被我下载到了。 当你的板子下载程序USB HID识别成功之后,输入VID 0483 PID 5750 连接打开设备。 下面是stm32 APP端的bin文件输出了,在app里面重新映射中断向量表,以及代码flash段,我的是Loader 0x4000 16K 所以APP的开始地址是0x08004000 然后在工程选项下的C++栏 生成bin文件选项 记得勾选After build。 生成app端的bin文件之后,需要想的是,这个USB上位机虽然不握手,只负责发送,但是人家到底有没有发送格式呢,这就需要我们对比它发送的文件,以及我们bin文件的内容。所以用到了visual studio2015 和 Bus hound两个工具,嵌入式工程师必备吧,工具的使用是人类的进化的标志。 咳咳,暴露了我双显示器的配置。 对比发现这个USB上位机就是发送的bin文件,发送完成最后发了一个空包,全是0,这就好办了,空包作为传输结束标志。 下面的函数就是缓冲接收64字节包的代码,这只是demo,在中断回调里面缓冲,并且写了flash,道理上是不合理的哈。 但是loder又不需要多任务处理,干就完事了。调试的时候思路卡了一会在flash烧写的地方,一个是需要先擦除app位置的flash,另一个flash的API需要32位对齐,所以需要64/4,其它就没啥了 __IO uint32_t flashdestination=APPLICATION_ADDRESS; __IO uint32_t transfer_error=0; static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf) { unsigned char j=0; //memcpy(IAP_buff,DulBuf,64);//缓存64字节数据 for(unsigned char i=0;i<64;i++) { IAP_buff=DulBuf; if(IAP_buff==0x00) j++; } if(j==64) USB_Received_Flag=1; if(j<64&&FLASH_If_Write(flashdestination, (uint32_t*)IAP_buff, (uint32_t)64/4)== FLASHIF_OK) { flashdestination+=(uint32_t)64; } else transfer_error++; return (0); } 再上传一个loader跳转到APP,APP跳转到Loader的代码 loader跳转到APP __set_FAULTMASK(1);//关闭所用中断 至于考虑APP是否使用了RTOS,加上__set_CONTROL(0); 吧 void LoderToApp(void) { if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)//栈顶地址检查 { HAL_RCC_DeInit(); //时钟失能 HAL_DeInit(); //外设失能 __set_FAULTMASK(1);//关闭所用中断 JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);//跳转到APP地址 JumpToApplication = (pFunction) JumpAddress; __set_CONTROL(0); //RTOS指针使能 SCB->VTOR = FLASH_BASE |0x4000;//中断向量表重映射 __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);//MSP指针跳转 JumpToApplication(); } } void AppToLoder(void) { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); __set_FAULTMASK(1); HAL_NVIC_SystemReset(); } APP跳转到Loader就简单点吧HAL_NVIC_SystemReset();干脆高效 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1780 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1081 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1679 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
556浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 20:08 , Processed in 0.712519 second(s), Total 42, Slave 37 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号