CYusb3014 应用笔记2-FX3 固件结构

接上一个笔记目录 ,本笔记主要讲解FX3 固件代码的结构,有些内容需要读者先了解下USB的协议。

本节内容主要参考官方手册:FX3_Programmers_Manual。也参考了一些其他博主的资料,侵删!

固件需要的内存地址和范围:

5  FX3 固件结构

以 demo:SlaveFifoSync 的FX3 固件为例,demo位置:

\Cypress\EZ-USB FX3 SDK\1.3\firmware\slavefifo_examples\slfifosync

典型应用是 FPGA 通过 slave fifo接口连接到FX3 上。

5.1 固件代码组成

FX3 所有的固件程序都包含两部分(初始化代码和应用代码)
初始化代码:所有应用的初始化代码基本都是相同的
应用代码:每个应用的专用代码

如上图所示:

cyfx_gcc_stratup.s

启动代码,汇编语言


cyfxgpif2config.h

GPIF接口描述文件,由GPIF ii Designer生成,直接导入工程中使用,GPIF II Designer的工程是后缀.cyfx,编译生成.h文件。


cyfxtx.c 官方封装 的一些 库函数,直接调用。


cyfxslfifosync.c 固件程序的主要功能,实现线程的建立,对回调函数的处理,DMA通道的建立,控制传输的实现,对GPIFII的状态机加载等功能。程序入口main函数即在这个文件中。

本例中的流程主要就是在这个函数中实现的


cyfxslfifosync.h

对全局变量的定义以及对 cyfxbulklpauto.c中使用到的函数的声明。


cyfxbulklpdscr.c

USB设备描述符的定义

sensor.c/sensor.h:

本例子中配置的sensor的代码

5.2 初始化代码流程

下面这个流程图是上面这个流程图的举例,使用的一些函数也标出来了,有些流程手册说的有些不容易理解,不过本质是一样的,流程也没有乱,读者看的时候按照这个流程走就行,别纠结哪个函数是属于哪个流程的。

图5.2

5.2.1 CyU3PFirmwareEntry()

FX3 的固件入口 ,该函数定义在了 FX3 API 库中,对用户不可见。
该函数实现了一些初始化功能,比如初始化cache, mmu ,初始化一些堆栈空间等。

5.2.2 Tool Chain Initialization

将BSS 数据段的值清零。BSS 数据段保存了所有应用固件的未初始化数据。针对 ARM 处理器的 GUN GCC 编译器的工具链初始化函数示例如下(本代码位于 cyfx_gcc_startup.S )

在该函数中,执行了以下两个过程
A :清零 BSS 数据段
B: 将程序控制权转交给 main()函数

接下来的流程(函数)是进入main函数了, main函数是应用程序的入口,在 cyfxslfifosync.c 文件中定义。

5.2.3主函数 main

主函数main中执行了很多,上面的流程图中只标出了一部分

main中执行的流程有 4部分:

CyU3PDeviceInit>

CyU3PDeviceCacheControl>

CyU3PDeviceConfigureIOMatrix>

CyU3PKernelEntry

执行完CyU3PKernelEntry以后,函数会跳到CyFxApplicationDefine函数,执行用户函数的线程。

其中上图5.2 的 OS kernel Entry 是指RTOS(Real-Time Operating System)  Kernel ,即RTOS 内核入口,上图5.2的OS timer Configuration 是指RTOS timer Configuration ,这两部分都属于主函数中的CyU3PKernelEntry

5.2.3.1 CyU3PDeviceInit 初始化

位于 main 函数中,如下图,CyU3PDeviceInit 中的 clkcfg 配置了时钟相关设置,中断控制器的初始化,还有 GCTL 和PLL的配置,具体的含义后续再补充

这里注意当设置外部晶振是 19.2Mh或者38.4Mhz的时候,主频是384mhz,当外部晶振是26M或者52Mhz的时候,主屏是416Mhz

当GPIF 跑32bit 100Mhz的速率的时候,主频必须是416Mhz,否则跑不动。

这个更改通过CyU3PDeviceInit() 中的setsysclk400=true 来进行,如果外部是19.2Mhz的,那么内部的频率是403.2mhz d

5.2.3.2  CyU3PDeviceCacheControl 缓存配置

配置缓存,器件包含 8K 字节的数据缓存区和 8K 字节的指令缓存区。在本例中,仅使能了指令缓存区。因为数据缓存区仅在需要 CPU 进行大量的数据存取工作的时候才能体现出效果,而本例是基于 DMA 的数据传输,当完成初始化后,CPU 基本处于旁路状态,无需进行大量的数据存取操作,因此不需要使能数据缓存

CyU3PDeviceCacheControl (CyTrue, CyFalse, CyFalse)函数的三个参数分别为指令缓存、数据
缓存、DMA 是否关联数据缓存的开关

5.2.3.3 CyU3PDeviceConfigureIOMatrix IO配置

IO 矩阵配置:所谓 IO 矩阵配置就是配置 GPIF 或串行外设接口的对应 IO 功能 。

这里注意,I2C 和SPI接口是复用的IO,因此只能二选一。

固件代码中还提到,如果使用GPIF 32bit的位宽,SPI不能使用。看结构框图这里应该是不冲突的不知道为何不能使用??????

5.2.3.4 CyU3PKernelEntry 设置进入RTOS 操作系统

进入RTOS操作系统,设置RTOS 定时器等

5.2.3.5  handle_fatal_error

代码中有些内容是 goto handle_fatal_error;

这意味着有错误发生或者某个操作失败了。此时,程序会跳转到handle_fatal_error标签处执行。

但是DEMO中此处并没有执行什么,我个人认为开发的时候应当增加一些处理逻辑

比如:

handle_fatal_error:

CyU3PDebugPrint("handle_fatal_error ! \n", ); // 打印错误信息

CyU3PGpioSetValue(59, CyTrue); //点灯指示错误

CyU3PThreadSleep(1000); // 等待一段时间观察错误指示灯

CyU3PFreeHeaps();// 释放资源或进行清理工作

CyU3PDeviceReset(isWarmReset); //  最终,如果无法恢复,可以执行软件重启 ,这个函数的重启不会重新加载固件

5.2.3.6 ApplicationDefine 用户代码

接下来进入用户代码了,详见下章节。

5.3 用户代码

用户代码的执行分5部分,分别是  :

1)CyFxApplicationDefine

创建线程

2)SlFifoAppThread_Entry

应用进程实现具体应用相关的初始化操作,例如 GPIF II 和 USB 模块的配置。

在这个模块中,会执行很多函数 ,这个模块和后面的CyFxSlFifoApplnStart和CyFxSlFifoApplnStop是平级的

3)CyFxSlFifoApplnStart
收到 USB SET_CONFIGURATION 请求后,CyFxSlFifoApplnStart 设置 USB和 GPIF 互通所需的端点和 DMA 通道。


4)CyFxSlFifoApplnStop
USB 复位或者连接断开被检测到后,CyFxSlFifoApplnStop 函数被调用,关闭 USB 端
点、释放 DMA 通道。

5)用户回调函数

用于处理一些事务和USB协议,接受上位机的控制指令等。

在这之前需要首先创建用户线程

5.3.1 CyFxApplicationDefine 创建用户线程

当操作系统被调用以后,FX3 的库会调用 CyFxApplicationDefine()函数,在这个函数中,将
创建具体的应用线程

这里首先设置 线程堆栈的大小  ptr = CyU3PMemAlloc (CY_FX_SLFIFO_THREAD_STACK);

然后下面的CyU3PThreadCreate 就是创建一个线程:

  • &slFifoAppThread:这是指向线程结构体的指针,用于存储线程的状态和控制信息。
  • "21:Slave_FIFO_sync":线程的名称和ID,用于调试和识别。
  • SlFifoAppThread_Entry:线程的入口函数,一旦线程启动,就会执行这个函数。这里应该是线程的主要工作函数。
  • 0:传递给线程入口函数的参数,这里没有传递任何参数。
  • ptr:指向分配给线程栈的内存的指针。
  • CY_FX_GPIFTOUSB_THREAD_STACK:线程栈的大小,确定了线程可以使用的最大栈空间。
  • CY_FX_GPIFTOUSB_THREAD_PRIORITY:线程的优先级,这里两次使用相同的值表示固定优先级。
  • CYU3P_NO_TIME_SLICE:线程调度的时间片,这里设置为CYU3P_NO_TIME_SLICE表示线程不使用时间片轮转调度。
  • CYU3P_AUTO_START:这个参数决定线程是否立即启动,CYU3P_AUTO_START表示创建线程后立即运行。

这里的前两个参数按照demo,自己创建就好了,第三个参数SlFifoAppThread_Entry  是你线程的入口函数,后续需要写线程的入口函数

剩下的一些参数仿照demo修改即可。

这里DEMO中如果创建线程失败则没有任何下文了,这里建议修改增加一些功能代码比如:

​


CyU3PDebugPrint("Failed to create thread! \n", ); // 打印错误信息

CyU3PGpioSetValue(59, CyTrue); //点灯指示错误

CyU3PThreadSleep(1000); // 等待一段时间观察错误指示灯

CyU3PFreeHeaps();// 释放资源或进行清理工作

CyU3PDeviceReset(isWarmReset); //  最终,如果无法恢复,可以执行软件重启 ,这个函数的重启不会重新加载固件

​

或者尝试重新创建线程....

这里的CY_FX_SLFIFO_THREAD_PRIORITY 是设置线程优先级,优先级分为0-31个,0是优先级最高的,驱动是优先级最高的线程,官方建议用户线程设置到8 或者更低的优先级

如果要增加线程,就调用函数:CyU3PThreadCreate

5.3.2  进入用户线程SlFifoAppThread_Entry 

应用进程实现具体应用相关的初始化操作,例如 GPIF II 和 USB 模块的配置。

流程图如下:下图流程是一部分,slavefifo的demo还有一些其他的流程。

代码如下:

5.3.2.1 CyFxSlFifoApplnDebugInit 函数初始化UART相关代码
5.3.2.2 CyFxSlFifoApplnInit 应用初始化

流程如下

1)初始化P PORT block

2) 禁用同步GPIF的DLL

3)  加载GPIF的配置

这个配置有些是在GPIF ii工具中指定的,有些是在这里写的,比如GPIF II的时序工具中有些空满标志的参数值是在这里确定的(后续补充介绍),如下图:

4)加载GPIF 的状态机(后续补充解释)

5)初始化和配置GPIO 

6) USB 接口初始化,首先是USB栈初始化

7)注册了一些USB 协议相关的回调函数

后续再介绍这些回调函数

8) 设置 USB 描述符,这是通过调用 USB 设置描述符来完成的。

9) 启用USB 连接

也就是说USB相关设置都配置好了,通过这个函数来开启和上位机的通信。

另外如果要重枚举,可以使用这个函数,先设置false,然后再true。

5.3.2.3  检测是否受到配置数据

这个用于打印的,如果收到了一个USB的配置事务,则会更新这个标志,然后打印收到了配置事务。

glIsApplnActive 是个标志信号,在函数CyFxSlFifoApplnStart 中设置true,在CyFxSlFifoApplnStop中设置false,默认上电是flase,其他代码有很多都调用了这个标志,相当于只有收到 上位机的 配置事务之后才会开始后面的操作

下图是SlFifoAppThread_Entry函数。即用户线程函数的最后的代码

5.3.3 CyFxSlFifoApplnStart 

 端点接收到ET_CONFIGURATION USB协议 事务的时候调用这个函数,就是说基于slave fifo的USB通信要开始启用了

这里面设置了端点的属性,配置 

设置了DMA通道

更新了标志信号:glIsApplnActive 

5.3.4 CyFxSlFifoApplnStop

当端 点收到RESET or DISCONNECT USB协议 事务的时候调用这个函数,相当于slave FIFO的USB通信停止。

这里的操作相对于CyFxSlFifoApplnStart 的就是断开端点,断开DMA通道等等

5.3.5 用户的其他回调函数

1)CyFxApplnUSBSetupCB

USB发送SETUP command 时该回调 函数将会被调用,这里的指令是 USB协议中的Vendor 指令。

2 )CyFxSlFifoApplnUSBEventCB

USB 事务的回调函数:举例说明:

3)CyFxSlFifoUtoPDmaCallback /CyFxSlFifoPtoUDmaCallback

DMA回调函数

本demo中,有两个数据通道分别为 U to P 和 P to U。每个数据通路上的 DMA 事件都会为之注册
一个 DMA 回调函数,当一个 DMA 的缓存中有数据时,该事件发生。该缓存中的数据可以使来
自 USB 输出 或者 GPIF II 套接字。在 DMA 回调函数中,该缓存中的数据被传递给 GPIF-II 套
接字或者 USB 输入端点。

4) CyFxApplnLPMRqtCB

低功耗 模式 回调函数,当返回CyTrue的时候,FX3进入低功耗模式。

5)其他,摘自数据手册:Getting Started with FX3 SDK 章节5.2.3 

流程总结:(从主函数Main开始)

  • 26
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值