转:EZ-USB FX2(68013)固件研究(3)——FW.C文件【1】

[复制链接]
3784|7
 楼主| 相见欢喜 发表于 2011-9-21 00:14 | 显示全部楼层 |阅读模式
FW.C文件,是比较难看懂的了,这个要逐字逐句研读,我当初整整看了一个星期,边理解,边一行一行的注释,可以说,看懂了,USB协议部分也就差不多了。
    从main()函数开始看:
DWORD i;
WORD   offset;
DWORD DevDescrLen;
WORD   IntDescrAddr;
WORD   ExtDescrAddr;

Sleep = FALSE;         //初始化用户变量 休眠使能--禁止
Rwuen = FALSE;         //远程唤醒--禁止
Selfpwr = FALSE;       //
GotSUD = FALSE;        //SetUp令牌包到来标志

   定义了一些变量,具体用途在后面;第二段同时对变量进行初始化,从名字可以看出其用途。
TD_Init();
   紧接着调用TD_Init()函数,是一些我们自己的初始化配置。
 楼主| 相见欢喜 发表于 2011-9-21 00:14 | 显示全部楼层
//定向USB描述符
pDeviceDscr = (WORD)&DeviceDscr;     
pDeviceQualDscr = (WORD)&DeviceQualDscr;
pHighSpeedConfigDscr = (WORD)&HighSpeedConfigDscr;
pFullSpeedConfigDscr = (WORD)&FullSpeedConfigDscr;
pStringDscr = (WORD)&StringDscr;
    这段代码用来获取USB的各个描述符在68013内存中的地址,准确说是在RAM中的地址,在dscrpt.a51文件中有定义,所有的描述符组成了整个的描述符表,后面会用到。
if ((WORD)&DeviceDscr & 0xC000)
    这段代码及以后的,在固件中解释是:
    Is the descriptor table in external RAM (> 16Kbytes)? If yes,
    then relocate.
    Note that this code only checks if the descriptors START in
    external RAM. It will not work if the descriptor table spans
    internal and external RAM.
 楼主| 相见欢喜 发表于 2011-9-21 00:15 | 显示全部楼层
意思是说,这段代码用来判断描述符表首址,也就是前面的DeviceDscr、DeviceQualDscr等是否位于68013的外部RAM区,如果是,则移除,然后将描述符表移到内部RAM区,为什么要移到内部RAM区,因为当描述符表位于外部RAM时,USB是不工作的。那么如何判断描述符地址是否超出内部RAM的地址呢?首先,&DeviceDscr取得整个描述符表的首地址(它也是DeviceDscr设备描述的首址),然后和0XC000相与,为什么要和0XC000相与?这就牵涉到68013 FX2LP(注意是LP)的内部结构图:

       上图针对的是128pin的FX2LP,如果是56或100pin的,那么没有外部RAM,只有内部RAM。可以看到,FX2LP内部RAM从0000-FFFF,其他为外部RAM。而内部RAM中,只有从0000-3FFF和从E000-FFFF的区域可用,其他为系统保留。从0000-3FFF这16K bytes的内部RAM空间,叫做主RAM,对56,100,128pin来说,都可以同时作为程序或数据存储器(对128pin来说,EA=0)。再看&DeviceDscr & 0xC000的结果,要为“真”的话,显然,必须&DeviceDscr>=0X4000,也就是说判断的是描述表首址&DeviceDsc是否大于3FFF,刚好是主RAM区的大小,这就是为什么要用&DeviceDscr 0xC000相与就来判断实现了描述符表首地址的原因了(外部 or 内部 ram?)。
 楼主| 相见欢喜 发表于 2011-9-21 00:15 | 显示全部楼层
// 重定向描述符
IntDescrAddr = INTERNAL_DSCR_ADDR;
ExtDescrAddr = (WORD)&DeviceDscr;
DevDescrLen = (WORD)&UserDscr - (WORD)&DeviceDscr + 2;
for (i = 0; i < DevDescrLen; i++)
*((BYTE xdata *)IntDescrAddr+i) = *((BYTE xdata *)ExtDescrAddr+i);

   判断发现描述符表首址位于外部RAM的后,紧接着就将外部RAM的描述符移到内部RAM。这里就用到了前面定义的变量,IntDescrAddr保存内部RAM首址0X80,ExtDescrAddr保存我们获得的当前描述符表外部RAM的首址 ,DevDescrLen是整个描述表的长度,从DeviceDscr段到UserDscr段,在dscrptr中有定义。然后for循环,将从ExtDescrAddr地址开始的外部RAM中的数据逐个copy到从IntDescrAddr地址开始的内部RAM区。
// 更新描述符指针
pDeviceDscr = IntDescrAddr;
offset = (WORD)&DeviceDscr - INTERNAL_DSCR_ADDR;
pDeviceQualDscr -= offset;
pConfigDscr -= offset;
pOtherConfigDscr -= offset;
pHighSpeedConfigDscr -= offset;
pFullSpeedConfigDscr -= offset;
pStringDscr -= offset;

   完毕后更新描述符指针,指向内部RAM区,通过原指针减去一个偏移量得到。
 楼主| 相见欢喜 发表于 2011-9-21 00:15 | 显示全部楼层
然后是USB的一些初始状态设置:

EZUSB_IRQ_ENABLE();                                                                                // EZUSB中断使能
EZUSB_ENABLE_RSMIRQ();                                                                      // 使能远程唤醒中断
INTSETUP |= (bmAV2EN | bmAV4EN);                                                    //使能INT2,4自动向量跳转
USBIE |= bmSUDAV | bmSUTOK | bmSUSP | bmURES | bmHSGRANT;     // 使能所选择中断
EA = 1;                                                                                                   // 开8051中断

   EZUSB_IRQ_ENABLE();预定义是EZUSB=1,查TRM得知,ezusb是EIE寄存器的第0位,EIE.0=1,使能USB中断;EZUSB_ENABLE_RSMIRQ();EICON |= 0x20,EICON.5=1,使能远程唤醒中断;INTSETUP |= (bmAV2EN | bmAV4EN);使能INT2,4自动向量跳转; USBIE |= bmSUDAV | bmSUTOK | bmSUSP | bmURES | bmHSGRANT;使能所选择中断,相关的中断意义,我也一知半解,后面慢慢学习补充;   EA = 1;    开8051中断。

               写到这里,未完待续。。。
Go_PSoC 发表于 2011-9-21 22:58 | 显示全部楼层
帮你顶
langgq 发表于 2011-9-22 19:13 | 显示全部楼层
liangziusb 发表于 2011-9-26 14:09 | 显示全部楼层
把USB2.0研究通了,再研究USB3.0看来还是可以的呀!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

517

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部