Zynq中使用FreeRTOS和USB遇到系统Tick不递增的问题
2024-06-11
49
问题描述
最近在Zynq平台上使用FreeRTOS开发应用,其中使用到了USB,将板子当作USB Slave设备,刚开始,将USB配置相关的代码放在了一个Task里,看起来USB是正常的,在上位机端正常识别到了设备,但后来新添加了另外一个Task,发现这个Task居然不运行,通过xTaskGetTickCount()获取到的Tick,也不增加。
问题原因和解决办法
后来发现,问题的主要原因是中断的配置导致的。USB的配置代码是在网上找的源码,其中做了中断的配置,代码如下:
int UsbSetupIntrSystem(XScuGic *IntcInstancePtr,
XUsbPs *UsbInstancePtr, u16 UsbIntrId)
{
int Status;
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.*/
IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig-CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Xil_ExceptionInit();
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, UsbIntrId,
(Xil_ExceptionHandler)XUsbPs_IntrHandler,
(void *)UsbInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the device.
*/
XScuGic_Enable(IntcInstancePtr, UsbIntrId);
/*
* Enable interrupts in the Processor.*/
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
return XST_SUCCESS;
}
而在FreeRTOS的初始化配置中,也配置了中断,代码在portZynq7000.c文件中,如下:
void FreeRTOS_SetupTickInterrupt( void )
{
BaseType_t xStatus;
extern void FreeRTOS_Tick_Handler( void );
XScuTimer_Config *pxTimerConfig;
XScuGic_Config *pxGICConfig;
const uint8_t ucRisingEdge = 3;
/* This function is called with the IRQ interrupt disabled, and the IRQ
interrupt should be left disabled. It is enabled automatically when the
scheduler is started. */
/* Ensure XScuGic_CfgInitialize() has been called. In this demo it has
already been called from prvSetupHardware() in main(). */
pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
xStatus = XScuGic_CfgInitialize( xInterruptController, pxGICConfig, pxGICConfig-CpuBaseAddress );
configASSERT( xStatus == XST_SUCCESS );
( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
/* The priority must be the lowest possible. */
XScuGic_SetPriorityTriggerType( xInterruptController, XPAR_SCUTIMER_INTR, portLOWEST_USABLE_INTERRUPT_PRIORITY portPRIORITY_SHIFT, ucRisingEdge );
/* Install the FreeRTOS tick handler. */
xStatus = XScuGic_Connect( xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) xTimer );
configASSERT( xStatus == XST_SUCCESS );
( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
/* Initialise the timer. */
pxTimerConfig = XScuTimer_LookupConfig( XPAR_SCUTIMER_DEVICE_ID );
xStatus = XScuTimer_CfgInitialize( xTimer, pxTimerConfig, pxTimerConfig-BaseAddr );
configASSERT( xStatus == XST_SUCCESS );
( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
/* Enable Auto reload mode. */
XScuTimer_EnableAutoReload( xTimer );
/* Ensure there is no prescale. */
XScuTimer_SetPrescaler( xTimer, 0 );
/* Load the timer counter register. */
XScuTimer_LoadTimer( xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ );
/* Start the timer counter and then wait for it to timeout a number of
times. */
XScuTimer_Start( xTimer );
/* Enable the interrupt for the xTimer in the interrupt controller. */
XScuGic_Enable( xInterruptController, XPAR_SCUTIMER_INTR );
/* Enable the interrupt in the xTimer itself. */
FreeRTOS_ClearTickInterrupt();
XScuTimer_EnableInterrupt( xTimer );
}
USB的配置在FreeRTOS之后,相当于又重新初始化了一遍中断Gic,所以就出现了USB配置之后,FreeRTOS的Task工作不正常,连正常的Tick都不递增了,所以,解决方法是,将USB配置代码中XScuGic_CfgInitialize和Exception相关的代码都删掉,只保留XScuGic_Connect和XScuGic_Enable就可以了。修改后USB配置中断的代码如下:
int UsbSetupIntrSystem(XScuGic *IntcInstancePtr,
XUsbPs *UsbInstancePtr, u16 UsbIntrId)
{
int Status;
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, UsbIntrId,
(Xil_ExceptionHandler)XUsbPs_IntrHandler,
(void *)UsbInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the device.
*/
XScuGic_Enable(IntcInstancePtr, UsbIntrId);
return XST_SUCCESS;
}
更新于:5个月前赞一波!
相关文章
- LinkWeChat开源系统
- 每一个程序员,都希望能成为分布式系统架构师
- 游戏陪玩系统语音聊天系统商业版源码安装教程
- 【说站】python系统内置方法如何获取
- 【说站】python os怎样处理系统文件
- 系统架构7个非功能性需求
- mac 系统 homebrew 管理 PHP
- TP6.0 空控制器: 健壮系统服务
- 系统的讲解网站的优化
- TP6.0 系统服务的使用和理解
- Windows 系统 PhpStorm 2020无限试用30天
- C#中如何获取当前系统CPU的核心数
- C#获取Windows系统中所有已安装软件的名称和版本号
- 在64位的Windows系统下运行32位的C#程序如何控制重定向
- 怎样在Linux系统 Ubuntu18.04 中安装微信
- cms系统套标签的简单介绍
- CentOS 7 Linux系统中添加新用户并给其授权
- 有哪些C/C++的开源项目可以给系统的学习C/C++语言做参考呢?
- C#中通过代码获取当前系统主板BIOS中序列号等信息的方法
- Java获取系统当前时间年月日
文章评论
评论问答