[转载]USB固件的执行过程
2017-12-27 16:18
393 查看
一个USB3.0的固件运行的过程大致如下面的图所示
首先是Firmware Entry
FX3的切入点是CyU3PFirmwareEntry()这个函数,这个函数定义在了FX3的API 库里面的,而且对用户是不可见的!这个函数规定了程序的入口,
这个入口函数做了以下的几个工作:
1:禁用Cache,说是为了Bootload。具体不知道cypress是怎么弄的了!
2:初始化MMU和CACHE
3:初始化FIQ(快速中断)、IRQ(普通中断)、SYS(系统模式)、SVC(管理模式)的栈。
4:执行完毕是去调用CyU3PToolChainInit()函数。
其次就是Tool
Chain 初始化
CyU3PToolChainInit:
# clear the BSS area
__main:
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
1:cmp R1, R2
strlo R0, [R1], #4
blo 1b
b main
代码如上可以看出来代码里面就做了两个工作
1:清理BSS段
2:将程序跳转到main()
接下来就是Device Initialization设备初始化
下面进行的就是main函数里面的操作了
分三步
1:首先是调用CyU3PDeviceInit (NULL);这个函数,
这个函数做了三个操作:
a:配置主时钟,传递的参数是NULL说明CLOCK是默认的形式配置好的!
b:VIC外设部件的中断管理模块初始化
c: 配置GCTL和 PLLs
2;配置cache使用CyU3PDeviceCacheControl (CyTrue, CyFalse, CyFalse);
这个FX3设备有8K的数据cache,还有8K指令cache。上面的代码说明数据cache没有打开,指令cache打开了!一般在有大数据处理的时候才会打开数据cache,如果是简单的处理打开了cache可能会降低整个系统的效率!
3.一些外部设备的管脚使能
io_cfg.useUart = CyTrue;
io_cfg.useI2C = CyFalse;
io_cfg.useI2S = CyFalse;
io_cfg.useSpi = CyFalse;
#if (CY_FX_SLFIFO_GPIF_16_32BIT_CONF_SELECT == 0)
io_cfg.isDQ32Bit = CyFalse;
io_cfg.lppMode = CY_U3P_IO_MATRIX_LPP_UART_ONLY;
#else
io_cfg.isDQ32Bit = CyTrue;
io_cfg.lppMode = CY_U3P_IO_MATRIX_LPP_DEFAULT;
#endif
io_cfg.gpioSimpleEn[0] = 0;
io_cfg.gpioSimpleEn[1] = 0;
io_cfg.gpioComplexEn[0] = 0;
io_cfg.gpioComplexEn[1] = 0;
status = CyU3PDeviceConfigureIOMatrix (&io_cfg);
if (status != CY_U3P_SUCCESS)
{
goto handle_fatal_error;
}
4:俗称召唤OS,听着挺吓人呵呵,通过调用CyU3PKernelEntry()
主要做的事情是初始化OS
下一步是OS Timer
然后是应用程序的定义
ptr = CyU3PMemAlloc (CY_FX_SLFIFO_THREAD_STACK);
retThrdCreate = CyU3PThreadCreate (&slFifoAppThread,
"21:Slave_FIFO_sync",
SlFifoAppThread_Entry,
0,
ptr,
CY_FX_SLFIFO_THREAD_STACK,
CY_FX_SLFIFO_THREAD_PRIORITY,
CY_FX_SLFIFO_THREAD_PRIORITY,
CYU3P_NO_TIME_SLICE,
CYU3P_AUTO_START
);
然后定义 线程,
void BulkSrcSinkAppThread_Entry (uint32_t input)
{
CyU3PReturnStatus_t stat;
uint32_t eventMask = CYFX_USB_CTRL_TASK | CYFX_USB_HOSTWAKE_TASK;
uint32_t eventStat;
CyFxUartLpApplnInit();
CyFxBulkSrcSinkApplnInit();
int a = 1;
for (;;)
{
;
}
}
USB的模块初始化
这里主要是CyFxBulkSrcSinkApplnInit();
的执行上一个 CyFxUartLpApplnInit();函数式执行串口的程序是用来帮忙调试的毕竟固件不能在线调试只能通过串口来做简单的辅助测试了;下面重点来说
CyFxBulkSrcSinkApplnInit();他的执行过程
这里面是主要是分两大步:
第一是:GPIF-II Initialization
pibClock.clkDiv = 2;
pibClock.clkSrc = CY_U3P_SYS_CLK;
pibClock.isHalfDiv = CyFalse;
pibClock.isDllEnable = CyFalse;
apiRetStatus = CyU3PPibInit(CyTrue,&pibClock);
以上是模块的时钟的初始化,
接下来是将GPIF设置成Slavefifo的模式。
apiRetStatus = CyU3PGpifLoad (&Sync_Slave_Fifo_2Bit_CyFxGpifConfig);
然后打开状态机
apiRetStatus = CyU3PGpifSMStart (SYNC_SLAVE_FIFO_2BIT_RESET,
SYNC_SLAVE_FIFO_2BIT_ALPHA_RESET);
下面就是USB部分的启动和配置了,首先是启动USB的环境
调用
apiRetStatus = CyU3PUsbStart();
然后为了能够响应一系列的操作,我们需要注册各种回调函数,这里包括
CyU3PUsbRegisterSetupCallback(CyFxSlFifoApplnUSBSetupCB, CyTrue);
CyU3PUsbRegisterEventCallback(CyFxSlFifoApplnUSBEventCB);
设置USB的各个描述字!
使用
apiRetStatus = CyU3PUsbSetDesc(CY_U3P_USB_SET_HS_DEVICE_DESCR, NULL,
(uint8_t *)CyFxUSB20DeviceDscr);注册描述字!
链接USB的引脚
apiRetStatus = CyU3PConnectState(CyTrue, CyTrue);
在事件的Callback函数里面有会调用EDP的配置DMA的配置
EDP的配置
CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
epCfg.enable = CyTrue;
epCfg.epType = CY_U3P_USB_EP_BULK;
epCfg.burstLen = 1;
epCfg.streams = 0;
epCfg.pcktSize = size;
apiRetStatus = CyU3PSetEpConfig(CY_FX_EP_PRODUCER, &epCfg);
DMA的配置
dmaCfg.size = size;
dmaCfg.count = CY_FX_SLFIFO_DMA_BUF_COUNT;
dmaCfg.prodSckId = CY_FX_PRODUCER_USB_SOCKET;
dmaCfg.consSckId = CY_FX_CONSUMER_PPORT_SOCKET;
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
dmaCfg.cb = CyFxSlFifoUtoPDmaCallback;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,
CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
紧接着使能DMA
apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoUtoP,
CY_FX_SLFIFO_DMA_TX_SIZE);
再来就是设计DMA的事件响应函数,
void
CyFxSlFifoUtoPDmaCallback (
CyU3PDmaChannel *chHandle,
CyU3PDmaCbType_t type,
CyU3PDmaCBInput_t *input
)
{
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
if (type == CY_U3P_DMA_CB_PROD_EVENT)
{
status = CyU3PDmaChannelCommitBuffer (chHandle, input-
>buffer_p.count, 0);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer failed, Error
code = %d\n", status);
}
glDMARxCount++;
}
}
首先是Firmware Entry
FX3的切入点是CyU3PFirmwareEntry()这个函数,这个函数定义在了FX3的API 库里面的,而且对用户是不可见的!这个函数规定了程序的入口,
这个入口函数做了以下的几个工作:
1:禁用Cache,说是为了Bootload。具体不知道cypress是怎么弄的了!
2:初始化MMU和CACHE
3:初始化FIQ(快速中断)、IRQ(普通中断)、SYS(系统模式)、SVC(管理模式)的栈。
4:执行完毕是去调用CyU3PToolChainInit()函数。
其次就是Tool
Chain 初始化
CyU3PToolChainInit:
# clear the BSS area
__main:
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
1:cmp R1, R2
strlo R0, [R1], #4
blo 1b
b main
代码如上可以看出来代码里面就做了两个工作
1:清理BSS段
2:将程序跳转到main()
接下来就是Device Initialization设备初始化
下面进行的就是main函数里面的操作了
分三步
1:首先是调用CyU3PDeviceInit (NULL);这个函数,
这个函数做了三个操作:
a:配置主时钟,传递的参数是NULL说明CLOCK是默认的形式配置好的!
b:VIC外设部件的中断管理模块初始化
c: 配置GCTL和 PLLs
2;配置cache使用CyU3PDeviceCacheControl (CyTrue, CyFalse, CyFalse);
这个FX3设备有8K的数据cache,还有8K指令cache。上面的代码说明数据cache没有打开,指令cache打开了!一般在有大数据处理的时候才会打开数据cache,如果是简单的处理打开了cache可能会降低整个系统的效率!
3.一些外部设备的管脚使能
io_cfg.useUart = CyTrue;
io_cfg.useI2C = CyFalse;
io_cfg.useI2S = CyFalse;
io_cfg.useSpi = CyFalse;
#if (CY_FX_SLFIFO_GPIF_16_32BIT_CONF_SELECT == 0)
io_cfg.isDQ32Bit = CyFalse;
io_cfg.lppMode = CY_U3P_IO_MATRIX_LPP_UART_ONLY;
#else
io_cfg.isDQ32Bit = CyTrue;
io_cfg.lppMode = CY_U3P_IO_MATRIX_LPP_DEFAULT;
#endif
io_cfg.gpioSimpleEn[0] = 0;
io_cfg.gpioSimpleEn[1] = 0;
io_cfg.gpioComplexEn[0] = 0;
io_cfg.gpioComplexEn[1] = 0;
status = CyU3PDeviceConfigureIOMatrix (&io_cfg);
if (status != CY_U3P_SUCCESS)
{
goto handle_fatal_error;
}
4:俗称召唤OS,听着挺吓人呵呵,通过调用CyU3PKernelEntry()
主要做的事情是初始化OS
下一步是OS Timer
然后是应用程序的定义
ptr = CyU3PMemAlloc (CY_FX_SLFIFO_THREAD_STACK);
retThrdCreate = CyU3PThreadCreate (&slFifoAppThread,
"21:Slave_FIFO_sync",
SlFifoAppThread_Entry,
0,
ptr,
CY_FX_SLFIFO_THREAD_STACK,
CY_FX_SLFIFO_THREAD_PRIORITY,
CY_FX_SLFIFO_THREAD_PRIORITY,
CYU3P_NO_TIME_SLICE,
CYU3P_AUTO_START
);
然后定义 线程,
void BulkSrcSinkAppThread_Entry (uint32_t input)
{
CyU3PReturnStatus_t stat;
uint32_t eventMask = CYFX_USB_CTRL_TASK | CYFX_USB_HOSTWAKE_TASK;
uint32_t eventStat;
CyFxUartLpApplnInit();
CyFxBulkSrcSinkApplnInit();
int a = 1;
for (;;)
{
;
}
}
USB的模块初始化
这里主要是CyFxBulkSrcSinkApplnInit();
的执行上一个 CyFxUartLpApplnInit();函数式执行串口的程序是用来帮忙调试的毕竟固件不能在线调试只能通过串口来做简单的辅助测试了;下面重点来说
CyFxBulkSrcSinkApplnInit();他的执行过程
这里面是主要是分两大步:
第一是:GPIF-II Initialization
pibClock.clkDiv = 2;
pibClock.clkSrc = CY_U3P_SYS_CLK;
pibClock.isHalfDiv = CyFalse;
pibClock.isDllEnable = CyFalse;
apiRetStatus = CyU3PPibInit(CyTrue,&pibClock);
以上是模块的时钟的初始化,
接下来是将GPIF设置成Slavefifo的模式。
apiRetStatus = CyU3PGpifLoad (&Sync_Slave_Fifo_2Bit_CyFxGpifConfig);
然后打开状态机
apiRetStatus = CyU3PGpifSMStart (SYNC_SLAVE_FIFO_2BIT_RESET,
SYNC_SLAVE_FIFO_2BIT_ALPHA_RESET);
下面就是USB部分的启动和配置了,首先是启动USB的环境
调用
apiRetStatus = CyU3PUsbStart();
然后为了能够响应一系列的操作,我们需要注册各种回调函数,这里包括
CyU3PUsbRegisterSetupCallback(CyFxSlFifoApplnUSBSetupCB, CyTrue);
CyU3PUsbRegisterEventCallback(CyFxSlFifoApplnUSBEventCB);
设置USB的各个描述字!
使用
apiRetStatus = CyU3PUsbSetDesc(CY_U3P_USB_SET_HS_DEVICE_DESCR, NULL,
(uint8_t *)CyFxUSB20DeviceDscr);注册描述字!
链接USB的引脚
apiRetStatus = CyU3PConnectState(CyTrue, CyTrue);
在事件的Callback函数里面有会调用EDP的配置DMA的配置
EDP的配置
CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof (epCfg));
epCfg.enable = CyTrue;
epCfg.epType = CY_U3P_USB_EP_BULK;
epCfg.burstLen = 1;
epCfg.streams = 0;
epCfg.pcktSize = size;
apiRetStatus = CyU3PSetEpConfig(CY_FX_EP_PRODUCER, &epCfg);
DMA的配置
dmaCfg.size = size;
dmaCfg.count = CY_FX_SLFIFO_DMA_BUF_COUNT;
dmaCfg.prodSckId = CY_FX_PRODUCER_USB_SOCKET;
dmaCfg.consSckId = CY_FX_CONSUMER_PPORT_SOCKET;
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
dmaCfg.cb = CyFxSlFifoUtoPDmaCallback;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,
CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
紧接着使能DMA
apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleSlFifoUtoP,
CY_FX_SLFIFO_DMA_TX_SIZE);
再来就是设计DMA的事件响应函数,
void
CyFxSlFifoUtoPDmaCallback (
CyU3PDmaChannel *chHandle,
CyU3PDmaCbType_t type,
CyU3PDmaCBInput_t *input
)
{
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
if (type == CY_U3P_DMA_CB_PROD_EVENT)
{
status = CyU3PDmaChannelCommitBuffer (chHandle, input-
>buffer_p.count, 0);
if (status != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer failed, Error
code = %d\n", status);
}
glDMARxCount++;
}
}
相关文章推荐
- 好文转载:ELF文件格式及程序加载执行过程总汇
- easyui datagrid 禁止选中行 EF的增删改查(转载) C# 获取用户IP地址(转载) MVC EF 执行SQL语句(转载) 在EF中执行SQL语句(转载) EF中使用SQL语句或存储过程 .net MVC使用Session验证用户登录 PowerDesigner 参照完整性约束(转载)
- 转载:Linux启动过程(从打开电源到执行init之前部分)
- 转载:Linux启动过程(从执行init到用户登录部分)
- 转载:C/C++源代码到可执行程序的过程详解
- 转载:PostgreSQL服务过程中的那些事二:Pg服务进程处理简单查询六:执行器执行
- mysql怎么让一个存储过程定时执行(转载)
- USB的枚举过程--自己写的(转载)
- (转载)JVM学习笔记(二)------Java代码编译和执行的整个过程
- C#完整执行存储过程的代码加实例[转载]
- 行为驱动开发: Cucumber的目录结构和执行过程 (转载)
- C程序编译执行过程(转载)
- 程序执行过程(转载)
- 项目管理的5个基本过程,转载,百度搜索得到,启动--规划--执行--监控--收尾
- C程序编译执行过程(转载)
- [转载]:SQL Server性能调优之执行计划深度剖析 第一节 浅析SQL执行的过程
- webx学习总结之页面流程执行过程详细分析(转载)
- 我对Asp.net页面一系列执行过程的认识 (转载)
- 15个常用sql语句 分支 循环 子查询 存储过程 事务 常用函数 sql语句执行过程(转载备用)
- USB通讯的执行过程 - STM32 USB设计