USB30设计资源 cypress芯片程序解读Word格式.docx

上传人:b****3 文档编号:17888619 上传时间:2022-12-11 格式:DOCX 页数:30 大小:41.64KB
下载 相关 举报
USB30设计资源 cypress芯片程序解读Word格式.docx_第1页
第1页 / 共30页
USB30设计资源 cypress芯片程序解读Word格式.docx_第2页
第2页 / 共30页
USB30设计资源 cypress芯片程序解读Word格式.docx_第3页
第3页 / 共30页
USB30设计资源 cypress芯片程序解读Word格式.docx_第4页
第4页 / 共30页
USB30设计资源 cypress芯片程序解读Word格式.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

USB30设计资源 cypress芯片程序解读Word格式.docx

《USB30设计资源 cypress芯片程序解读Word格式.docx》由会员分享,可在线阅读,更多相关《USB30设计资源 cypress芯片程序解读Word格式.docx(30页珍藏版)》请在冰豆网上搜索。

USB30设计资源 cypress芯片程序解读Word格式.docx

这个变量是一个BOOL型先设为FALSE.

程序然后定义了一个错误处理,我们不处理错误,故是一个死循环语句。

然后,定义一个debug_init用串口来显示一些信息。

初始化串口,设波特率—只允许发不允许收,另外,采用DMA模式来处理UART。

注意到这个函数:

CyU3PDebugInit(CY_U3P_LPP_SOCKET_UART_CONS,8)表示只处理8以下的显示,大于8将不显示。

接下来就是一个回调处理函数

CyFxSlFifoUtoPDmaCallback(

CyU3PDmaChannel*chHandle,

CyU3PDmaCbType_ttype,

CyU3PDmaCBInput_t*input)

CyU3PReturnStatus_tstatus=CYU3P_SUCESS;

If(type==CY_U3P_DMA_CB_PROD_EVENT){

Status=

CyU3PDmaChannelCommitBuffer(chHandler,input->

buff_p.count,0);

glDMARxCount++;

}

其中,CommitBuffer这个函数通常在手动DMA方式下被调用,它3个参数的含义分别为:

DMA的句柄号,处理的字节数及当前的状态。

其中地址由通道描述符隐含着。

这个函数发送一个buffer向消费者socket.

接下来,是一个比较复杂的程序

VoidCyFxSlFifoApplnStart(void)

这个函数启动一个slavefifo应用。

当从USB接口收到一个SET_CONF事件时,即设置配置事件时,它被调用。

在这个函数中,端点被配置,DMA管道被建立。

我们稍后将看到它就是在USB配置时被调用的。

首先,根据USB的接口速度,决定这个DMA缓冲区的大小为多少字节。

对于3。

0是1024。

然后,端点配置。

而得到速度是一个库函数,如何得到速度不得而知。

不过,由于配置是在设备描述符得到后,并且是设置地址后调用的。

故此时估计PC机已经与下位机协商好速度了。

例如PC为2。

0则速度只能设为2。

端口设为BULK方式,且被允许。

突发长度为1。

尺寸也被设为1024。

先配置生产者:

允许端点1的收,尺寸按速度设置好,其它没什么。

不过IN端点1定义成0x81OUT定义成0x01

接下来,要产生一个DMA_MANUAL通道为UTOP

看dmaCfg的一些参数填充:

尺寸,即1024。

缓冲区个数,2个。

生产者ID号从0X401开始的。

消费者socket端口,从0X103开始的。

DMA模式:

为0表示按字节计数。

DMA事件:

CY_U3P_DMA_CB_PROD_EVENT表示收到一个生产者发来的缓冲

DMA的回调函数UtoP

头0

尾0

消费socket的头的编移0

最少要多少个空的缓冲才会在生产者激活前。

0表示任何时候都要激活它。

在接收PtoU的DMA通道中,修改了这些:

产生者socketID被定义为0x100

消费者socketID被定义为0x301

回调函数改变了。

然后是生成DMA通道。

再就是刷新生产者端点EP。

再就是刷新消费者端点EP

设置DMA传输尺寸。

设为0表示无限。

最后将glIsApplnActive=CyTrue;

将这个全局变量设为TRUE。

下面是一个停止FIFO循环的程序。

断开时或复位时会被调用。

此处暂不管它。

再下面是一个当USB在SETUP时的回调处理

由于SETUP时交由DRIVER缺省处理,故直接返回一个FALSE.

USB事件处理回调函数

当设置配置时,调用AppStart()但是如果已激活又来这么一下,则直接调用ApplnStop()

复位和断开时,调用ApplnStop()

下面又定义一个比较重要的函数:

用于初始化GPIF和USB接口。

CyFxSlFifoApplnInit(void)///下面将这个函数写于此

CyU3PPibClock_tpitClock;

CyU3PReturnStatus_tapiRetStatus=CY_U3P_SUCCESS;

//以下初始化p-port块

pibClock.clkDiv=2;

pibClock.clkSrc=CY_U3P_SYS_CLK;

pibClock.isHanfDiv=CyFalse;

pibClock.isDllEnable=CyFalse;

apiRetStatus=CyU3PPibInit(CyTrue,&

pibClock);

//这里是设置好时钟

///以下装载GPIFSlave_Fifo----未明白它是如何配置的。

apiRetStatus=CyU3PGpifLoad(&

Sync_Slave_Fifo_2Bit_CyFxGpifConfig);

///接下来是启动状态机(略),启动USB函数:

apiRetStatus=CyU3PUsbStart(0;

---开始USB功能

接下来

注册回调函数用于USB的SETUP过程。

但它是一个返回FALSE的函数。

CyU3PUsbRegisterSetupCallback(CyFxSlFifoApplnUSBSetupCB,CyTrue);

CyU3PUsbRegisterEventCallback(CyFxSlFifoApplnUSBEventCB);

事务处理不是缺省的,而是我们上面定义过的。

例如ApplnStart()就是在配置过程中启动的。

接下来,要开始配置设备描述符了,因为描述符中含有PID和VID的值。

所以必须配置。

apiRetStatus=CyU3PUsbSetDesc(CY_U3P_USB_SET_SS_DEVICE_DESCR,NULL,(uint8*)CyFxUSB30DeviceDscr);

接下来是二进对象存储描述符的设置。

接下来是设备量化描述符。

接下来是超速配置描述符,高速设备配置描述符,

重点看一下超速配置描述符,它含配置描述符主要指明了接口数,配置数,配置字符串(无)

特性-自供电,远端唤醒功能

电流消耗400mA

接口描述符有:

端口数量,2个。

接口类FF,子类00接口协议0接口协议字符串0

生产者端点描述符如下:

端点地址0x01生产者。

最大包的长度1024,数据间隔传输类型0表示BULK。

超速端点公司描述符,基本上全是0。

消费者端点,与生产者基本类似。

只是端口地址不一样,其它一样的。

接下来是高速,全速描述符。

接下来是语言描述符。

接下来是制造厂名描述符。

为CYPRESS

接下来是产品描述符FX3

最后连接USB物理层。

至此枚举将开始。

然后定义了一个线程进入点,如下:

SlFifoAppThread_Entry(uint32input)

CyFxSlFifoApplnDegugInit();

///这里是UART串口初始化

CyFxSlFifoApplnInit();

///初始化FIFO应用在这中间是GPIF和USB的初始化程序。

for(;

;

{CyU3PThreadSleep(1000);

//sleep

If(glIsApplnActive)///如果还是激活状态

CyU3PDebugPring(6,”Datatracker:

…%d,buffersend:

%d\n”,glDMARxCount,glDMATxCount);

/////

下面是应用定义函数,估计这个函数名是不能改的。

在这个函数中,我们先分配一个堆栈空间

Ptr=CyU3PMemAlloc(CY_FX_SLFIFO_THREAD_STACK);

//然后产生一个线程

retThrdCreate=CyU3PThreadCreate(*slFifoAppThread,

“21:

Slave_FIFO_syne”,

slFifoAppThread_Entry,

0,ptr,

CY_FX_SLFIFO_THREAD_STACK,

CY_FX_SLFIFO_THREAD_PRIOITY,

CY_FX_SLFIFO_THREAD_PRIORITY,

CYU3P_NO_THIME_SLICE,

CYU3P_AUTO_START

);

 

最后是主程序main()

首先初始化设备,设备指的是CPU,主要是时钟和堆栈等。

然后cachecontrol不用DATACACHE。

在开发板上,由于53:

56脚被连接到UART,这意味着我们要么选择DQ32模式,要么选择LppMode.

不然UART就没办法用了。

Lpp模式好象是GPIO+UART模式,见datasheet33页。

几个参数用UART,不用IIC不用IIS,不用SPI。

没有GPIO使用到(简单复杂都没有)。

然后就是设置配置了。

最后进入到内核。

不返回。

结束主程序。

内核于是调用某一个函数,也就是CyFxApplicationDefine(void)。

程序就从此开始了。

问:

1程序是如何下载到USB中去的。

要怎么做。

例如将这个编译好的代码放到什么目录里还是怎么办,还是启动时,安装driver时,自动下载,这个下载的东西是个什么文件格式?

该放在哪里?

不明白

2.难道GPIF口上没接任何东西,如何将PC机发下来的数据发回到PC机上去?

生产者:

USB的OUT接口1,向GPIF发送一批数据

消费者:

GPIF向IN接口81,由它消费掉一批数据。

然后通过IN发回PC机。

再看一个简单一点的GPIO的例子

1先是一个错误处理的函数,我们不需要它,故这是一个死循环。

2CyFxDebugInit这个函数,将串口作为调试口用115200bps

3voidCyFxGpioIntrCb(

uint8_tgpioId/*Indicatesthepinthattriggeredtheinterrupt*/

这个函数是一个中断回调函数。

必须在某个地方注册一下。

它有下列过程:

apiRetStatus=CyU3PGpioGetValue(gpioID,&

gpioValue);

//这个函数得到某个端口中断的值

这个gpioValue是一个BOOL值。

而ID则是某一个端口的端口号。

这个函数只能返回一个引脚。

等会看这个ID是什么指定的。

CyU3PEventSet(&

glFxGpioAppEvent,CY_FX_GPIOAPP_GPIO_HIGH_EVENT,CYU3P_EVENT_OR);

如果为高,则设置一个事件。

是一个高事件发生。

注意到事件是一个全局变量,而这个事件中有许多参数,其中比较重要的是一个回调函数。

应该在某个地方将这个事件与一个回调函数联系起来。

一会要补充这里

5.VoidCyFxGpioInit(void)

apiRetStatus=CyU3PGpioInit(&

gpioClock,CyFxGpioIntrCB);

这个函数是设定gpio的时钟,以及中断的回调函数。

这与4中部分形成对照。

然后将gpio45定义为输入且允许中断

gpioConfig.intrMode=CY_U3P_GPIO_INTR_BOTH_EDGE;

apiRetStatus=CyU3PGpioSetSimpleConfig(45,&

gpioConfig);

GPIO的21脚本来作为GPIF的控制信号的。

不能用CyU3PDeviceConfigureIOMatrix来将它作为GPIFIOs.

这个过载API调用必须进行必须小心当改变这个引脚的功能时。

如果IO脚作为GPIF的一部分连到外部设备上。

则它不能再作为GPIFIO使用。

在这里CTL4是不使用的,所以用它用IO脚是安全的。

apiRetStatus=CyU3PDeviceGpioOverride(21,CyTrue);

接下来apiRetStatus=CyU3PGpioSetSimpleConfig(21,&

6接下来有两个线程,一个是输出线程,一个是输入线程,先看输出线程:

apiRetStatus=CyFxDebugInit();

////初始化调试模式。

这个在2中定义的。

CyFxGpioInit();

这个也在前面5定义过。

后面是一个闪灯程序。

apiRetStatus=CyU3PGpioSetValue(21,true);

将输出置为高。

延时2秒,将输出变为低。

延进2秒。

7下面再来看输入线程:

是一个循环,等事件发生。

txApiRetStatus=CyU3PEventGet(&

glFxGpioAppEvent,

(CY_FX_GPIOAPP_GPIO_HIGH_EVENT|CY_FX_GPIOAPP_GPIO_LOW_EVENT),

CYU3P_EVENT_OR_CLEAR,&

eventFlag,CYU3P_WAIT_FOREVER);

这里表示永远等下去。

等到后要清除事件,另返回事件的标志,这个标志我们没有用。

如果等到高的标志,就打印一个引脚为高,如果为低,就打印一个引脚为低的标志。

估计这个等事件标志将被block.

这样整个过程清楚了,IO脚触发引起一个中断。

这个中断回调函数中将触发一个事件。

在这个线程中将等事件发生,如果发生了,就打印出引脚的状态。

事件在什么地方初始化呢?

还是不需要初始化?

8果然,事件是要初始化的。

在应用程序中初始化了,下面就看这个应用程序

先创建一个输出线程。

再创建一个输入线程

然后retThrdCreate=CyU3EventCreate(&

glFxGpioAppEvent);

9最后看一下main()

Main()中主要是将GPIO引脚初始化一下。

io_cfg.gpioSimpleEn[0]=0;

io_cfg.gpioSimpleEn[1]=0x00002000;

/*GPIO45*/

io_cfg.gpioComplexEn[0]=0;

io_cfg.gpioComplexEn[1]=0;

45引脚为什么对应的是0x2000.这是因为它是32位的,45引脚=32+13这个D13位正好是0X2000

从main开始看起:

再看一下几个定义:

输出线程,输入线程及事件在文件一开始就定义了。

CyU3PThreadgpioOutputThread;

/*GPIOthreadstructure*/

CyU3PThreadgpioInputThread;

CyU3PEventglFxGpioAppEvent;

/*GPIOinputeventgroup.*/

它主要是调用了一个串口设置函数,然后就进入到cache控制设置,再后来就是设置一个IO脚,45脚使之使能。

并且选用配置模式(即LPP模式)。

允许了UART,不允许IIC,IIS,SPI,另外isDQ32bit也不允许。

这个表示它不支持GPIF的32位模式。

然后我们再看应用程序启动,这是由系统自动调用的。

我们可能修改它的内容,但是它是必须的。

这个函数中,它创建了两个线程。

一个是输入线程,一个是输出线程。

另外,容易遗忘的一件事是它创建了一个事件。

事件的创建只要这样就可以了:

retThrdCreate=Cy3U3PEventCreate(&

再往上,就是输入线程了。

这个线程看输入引脚的变化,而这个变化由中断回调函数引起,中断回调函数中,它会产生一个事件,而我们的线程就监视这个事件。

如果有事件高发生,就串口打印一个引脚高,如果低,就打印一个引脚低。

看它是如何实现的:

txApiRetStatus=CyU3PEventGet(&

(CY_FX_GPIOAPPP_GPIO_HIGH_EVENT|CY_FX_GPIOAPP_GPIO_LOW_EVENT),

CYU3P_EVENT_OR_CLEAR,&

eventFlag,CYU3P_WAIT_FOREVER);

这是个等事件的函数,这个函数无法找到它的定义,它是一个API函数。

我们找API,发现它的参数含义。

这里有一个CYU3P_EVENT_OR_CLEAR表示只要上面有一个位被设置就返回且清除标志。

----OR。

而真正的事件就放在标志中返回了。

既然有读事件,就必有设置事件,事件的设置应该在中断回调中实现。

而中断回调的注册,应该在初始化时实现。

下面应该可以很快看到这点。

---事实上,在下面的输出线程中就实现了注册

输出线程实现,输出线程比较有意思的是其DebugInit()居然是在它中间实现的。

这有点不合常理。

而接下来,它又调用了初始化GpioInit()这个函数。

在这个函数中,先初始化GPIO,这个GPIO居然还要将时钟也设置一下,有点不合常理。

在这个初始化中,它还指明了GPIO中断回调函数的注册。

尽管这个中断函数应该是在输入线程中注册似更合理一些。

接下来,45脚要用之为输入,所以要将配置设一下:

gpioConfig.outValue=CyTrue;

//输出为高因为是输入,要将它设为高

gpioConfig.inputEn=CyTrue;

//输入使能

gpioConfig.driveLowEn=CyFalse;

//不要驱动低也不要驱动高

gpioConfig.driveHighEn=CyFalse;

//允许中断

如此这般配置了45脚。

接下来,要配置21脚,因为21脚比较特殊本来是用于GPIF的CTRL4的。

现在要使用它就要重载一下:

这样的IO脚是不可以象在主程序中哪样,将它直接设为输出的,而是要先重载。

同样,看输出脚是如何定义的

gpioConfig.outValue=CyFalse;

///低电平

gpioConfig.driveLowEn=CyTrue;

//允许低输出

gpioConfig.driveHighEn=CyTrue;

///允许高输出

gpioConfig.inputEn=CyFalse;

//方向设为输出,(假的输入就是输出)

gpioConfig.intrMode=CY_U3P_GPIO_NO_INTR;

//不用中断

再看一下回调函数,如何实现它的:

当引脚有跳变时,这个函数被调用。

首先,它得到引脚的值。

这个回调函数是带参数的。

当它发生时,会带过来一个参数。

表明是哪一个引脚触发了这个事件。

这在库函数中可能已经处理了,提供给用户程序就不用麻烦再去看原因了。

我想可能有一个机制,即有一个中断状态寄存器,表示是哪一个引脚变化了。

在这里调用了一个函数:

CyU3PGpioGetValue(gpioId,&

注意到这个值是一个BOOL型的。

然后根据情况来设置事件:

glFxGpioAppEvent,CY_FX_GPIOAPP_GPIO_HIGH_EVENT,CYU3P_EVENT_OR);

我们看,其中有要设置的事件指针,有什么事件,以什么方式设置,它是以OR的方式设置的。

这个OR表示的是将这个第2个参数与当前的事件标志进行或。

显然,如果相或的话,则事件标志将被置1,而如果与则完全不同,它没效果。

(在得到事件中,有一个AND表示全部标志都符合才生成事件,所以也是用OR的,不然,不可能全部符合的,永远不会发生事件了,因为不可能既变高又变低的)

至此整个程序解读完了。

在这个例子中,似乎没用到USB有关的部分。

有了这个基础后,再看一下原来syncFifo的文档。

方法同样从后向前看。

先看main()

1main基本上没有什么变化,除了不用配置45脚之外。

2再看应用程序启动部分,只创建了一个线程。

3再看在这个线程中做什么事,事实上,它就是每秒钟打一些串口信息,接收了多少包,发送了多少包。

不过在开始时,它增加了2个初始化设置,第一个初始化设置设置了串口,第2个初始化,是一个非常关键的初

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1