[转载]USB固件的执行过程

本文详细解析了FX3 USB3.0固件的启动流程,包括固件入口、工具链初始化、设备初始化等关键步骤,并深入介绍了USB模块初始化及配置过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个USB3.0的固件运行的过程大致如下面的图所示

[转载]USB固件的执行过程

首先是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++;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值