在学习usb 的过程中 看 stm32 的demo, 真心觉得不好,基于状态的 逻辑分析起来忒麻烦,将我劝退了好多年!!!
下定决心去啃过去,看完原理,看 stm32usb转串口的 代码,将不必要的文件 删掉,将原来的 发送一个大包的数据 经过多次中断的发送,要记住发送到那个位置 ...
改装为 在 ucos 的任务里面 每发送一个小包 等待发送完毕的消息 再发送下一个小包,看起来就很舒服了,
然后移植了 stm原来的 usb转串口的 demo
再移植了 stm32 转ch340 串口的demo
INT8U SendEp0Data(INT8U *pSrc,INT16U reqlen,INT16U contentlen)
{
INT32U msg;
INT16U sendcnt,len;
INT8U pagesize,err=OS_ERR_NONE,flag0;
if(pSrc==NULL)
{
flag0=1;
len=0;
}
else
{
if(reqlen<=contentlen)
{
len=reqlen;
flag0=0;
}
else
{
len=contentlen;
flag0=((contentlen%EP0Size)==0);
}
}
for(sendcnt=0;sendcnt<len ;sendcnt+=EP0Size)
{
pagesize=(len-sendcnt)>EP0Size?EP0Size:(len-sendcnt);
UserToPMABufferCopy(pSrc+sendcnt, GetEPTxAddr(ENDP0), pagesize);
SetEPTxCount(ENDP0, pagesize);
SetEPRxValid(ENDP0);
SetEPTxValid(ENDP0);
msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
if(err!=OS_ERR_NONE)
{
break;
}
if((msg & EP_CTR_TX)== 0)
{
OSQPostFront(OSQUsbEP0, (void *)msg);
break;
}
}
if(flag0 && err==OS_ERR_NONE)
{
//发送空输入
SetEPTxCount(ENDP0, 0);
SetEPTxValid(ENDP0);
SetEPRxValid(ENDP0);
msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
if((msg & EP_CTR_TX)== 0 && err!=OS_TIMEOUT)
{
OSQPostFront(OSQUsbEP0, (void *)msg);
}
}
if(reqlen!=0 && err==OS_ERR_NONE)
{
//等待空输出返回
SetEPRxValid(ENDP0);
msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
}
SetEPRxValid(ENDP0);
return err;
}
在移植的过程中,
主要改 usb_desc.c 的描述符
和usb_prop.c的端点设置,还有添加一些特殊的 setup 命令的处理,hw_config.c 根据自己的硬件 做相应的修改即可
两个demo的下载, ch340 的demo 比较新一点,里面的一些函数 更优化一点