第一章? ?Mentor USB Controller 系列之寄存器解析? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
第六章? ?Mentor USB Controller EDA仿真系列之Bulk Out传输
第七章? ?Mentor USB Controller EDA仿真系列之Bulk In传输
目录
? ? ?本文主要介绍Mentor USB Controller传输Bulk In包的整个流程,包括前期phy上电、控制器上电以及内部相关状态机运作情况,以及host和device两种情况下的软件配置。并重点介绍了该包传输的整体flow。文章最后对仿真过程中遇到的问题做了介绍并给出了解决该问题的一种方法。
提示:以下是本篇文章正文内容,下面案例可供参考
首先,保证控制器的时钟、复位、phy的接口时序全部是否OK的。
其次,如果传输数据位宽采用16bit模式,则要求控制器时钟要求至少大于30,因为控制器会处理xclk domain到ahb domain的异步转换,而对于16bit的数据位宽xclk为30M,因此要求hclk至少是30M的配置。
step1:置位VBUS
step2:使能conn连接中断并配置session有效
step3:while等待device连接中断
step4:配置reset并至少保持协议规定的时间后撤销,force TM=1可以加速仿真(1.5ms足够)
step5:设置REG_FADDR寄存器,配置target device地址
step6:设置REG_INDEX,选择某个端点用于传输
step7:设置REG_EP_RXMAXP,配置最大的接收packet字节数
step8:设置REG_EP_RXTYPE,配置传输包类型为BULK,以及目标端点num
step9:设置REG_EP_RXCSR,开始发送bulk in请求,然后等命令发送完成,拉低该请求
step10:host等着收数据即可
更详细的代码如下:
//-------------------------------------------------------
//start session
MCU_WRITE(REG_INTRUSBE,8'h10,1); //配置connect intr enable
MCU_WRITE(REG_DEVCTL,8'h01,1); //host set session valid
//host wait device conncet
ReadReg(REG_INTRUSB,4'h0,rdata);
while(rdata & 8'h10 != 8'h10)begin
ReadReg(REG_INTRUSB,4'h0,rdata);
end
//-------------------------------------------------------
//after detect device connect, host should send reset
ReadReg(REG_POWER,4'h0,rdata);
rdata = rdata | 8'h08;
MCU_WRITE(REG_POWER,4'h0,rdata); //cfg reset
#1.5ms; //reset time
ReadReg(REG_POWER,4'h0,rdata);
rdata = rdata & 8'hF7;
MCU_WRITE(REG_POWER,4'h0,rdata); //clr reset
//-------------------------------------------------------
//setup EP1 Rx point
MCU_WRITE(REG_FADDR,{1'b0,7'h04},BE_8_0); //按byte写function地址为4
MCU_WRITE(REG_INDEX,{4'h0,4'h1},BE_8_0}; //配置endpoint为1,这个需要跟device match
MCU_WRITE(REG_EP_RXMAXP,8'h08,BE_8_0); //配置最大包长为8byte
MCU_WRITE(REG_EP_RXTYPE,BULK | 4'h1,BE_8_0); //设置包类型为bulk包,且断点为1
//-------------------------------------------------------
//send bulk request, every 500us, host send once bulk in req,这里可以根据需求设任意次
repeat(2) begin
MCU_WRITE(REG_EP_RXCSR,RXCSR1_REQP,BE_8_0);
USB_waitforpacket;
SYS_wait(TYP_HSIP_DEL);
MCU_WRITE(REG_EP_RXCSR,8'h0,BE_8_0);
#500us;
end
//-------------------------------------------------------
//wait EP1 intr coming, actually is RXCSR的rxpktrdy bit
ReadReg(REG_INTRRX,4'h0,rdata)
while(rdata&8'h2 != 8'h2)begin
ReadReg(REG_INTRRX,4'h0,rdata)
end
后续可以读接收FIFO的数据进行数据比对
step1:完成系统时钟选择,相关中断配置等基础配置
step2:配置soft_con,然后等待reset中断
step3:一定要等待复位完成后再进行下面的配置,否则配置可能会被reset掉
step4:配置SIE_FAddr,该值需要和host的配置目标device地址一致
step5:配置SIE_Index,该值需要和host的配置的endpoint num一致,大家选择同一端点进行传输
step6:配置SIE_InMax,配置最大packet
step7:向FIFO中填写待发送的数据,然后配置TxPktRdy为1,该bit当发送完成后,且收到ACK后USB controller会自动清掉TxPktRdy。
SET_INTRUSBE_RESET; //首先设置usb复位中断使能
SET_SOFT_CONN; //device配置soft connect,准备建立连接
//wait host 发送reset
while(rest_int != 0x1); //rest_int定义为临时变量,在复位中断handler到来时置位1
REG8(SIE_FADDR) = 0x4; //功能地址,与host match
REG8(SIE_INTRINE) = 0x2; //使能endpoint1的中断,因为我们利用endpoint1进行传输
REG8(SIE_Index) = 0x1; //设置index,准备配置端点1
REG16(USB_CTRL_BASE+0x64) = 0x1; //start address of the enpoint fifo
REG8(USB_CTRL_BASE+0x62) = 0x0; //max packet size is 8byte
REG8(SIE_INMax) = 0x8; //set max packet
//提前填好待发送的FIFO数据
REG32(EP1_FIFOEn) = 0x12345678;
REG32(EP1_FIFOEn) = 0x01020304;
REG16(SIE_InCSR) |= 0x1; //set txpktrdy
while(tx_ep1_int != 0x1); //等待endpoint1发送完成中断
1. 首先保证phy能正常输出xclk,该clk是接给controller使用的,要想phy能正确产生xclk,则phy的driver必须正确
2. 其次,xclk的hclk的关系必须满足条件,否则异步转换数据可能不正确
3. 对于host端,一旦握手成功后,可以在任意时刻发送request,当device端没有填写数据也没有把txpktrdy置1时,接收到了host发送的数据请求,那么device会把CSR里面的overrun bit置起来,然后一旦CPU填写了数据,也置了txpktrdy=1, underrun就硬件自动拉低。
4. 首先,对于中断寄存器INTRTX/INTRRX里面定义的是每个endpoint的中断,每个bit又对于CSR里面的一堆中断状态。