在使用zynq中的freertos时,程序中存在中断引发vtaskdelay卡死,但是没有报错,该如何处理?
环境:vivado2017;正点原子的xc7z010clg400-1
我的中断是从原子哥教程里的axi按键中断中复制来的
这是中断配置,这个函数的调用位置在一个优先级最低的task_start里,因为不这样的话中断无法触发
具体问题:
这个任务是每隔1s改变led的状态,在无中断的另一个application中能正确切换,但是在这个程序中输出情况如下:
进去了就出不来了,在task.c里添加了一系列xilprinf后能发现最后一条能成功输出的prinf位于1354行处(即在这一行的if{后的prinf能输出,而1356行的不行
另外:中断可以正常触发
不知道是什么原因,已经卡在这个问题上一个月了,网上也搜不到
代码全文:
/*ID define*/
#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL端 AXI GPIO器件 ID
#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL端 AXI GPIO中断 ID
#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //中断控制器 ID
#define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID
/*time define*/
#define DELAY_1_SECOND 1000UL
#define DELAY_001_SECOND 10UL
#define DELAY_05_SECOND 500UL
/*landk define*/
#define MIO_LED0 7 //PS_LED0 连接到 MIO7 8
#define MIO_LED1 8 //PS_LED1 连接到 MIO8 9
#define MIO_KEY0 12 //PS_KEY0 连接到 MIO7
/*axi define*/
#define KEY_CHANNEL 1 //PL按键使用AXI GPIO通道1
#define KEY_MASK XGPIO_IR_CH1_MASK //通道1的位定义
/*led define*/
#define LIANG 0x1
#define AN 0x0
/*task*/
#define SIZE (unsigned short) 1000
static void task_start( void *pvParameters );
static void task_led_t( void *pvParameters );
static void task_led_k( void *pvParameters );
/*intr*/
void axi_gpio_handler(void *CallbackRef); //中断服务函数
/*intr*/
static TaskHandle_t Htask_start;
static TaskHandle_t Htask_led_t;
static TaskHandle_t Htask_led_k;
//static SemaphoreHandle_t Hsem=NULL;
XScuGic scugic_inst; //中断控制器 驱动实例
XScuGic_Config * scugic_cfg_ptr; //中断控制器 配置信息
XGpioPs gpiops_inst; //PS端 GPIO 驱动实例
XGpioPs_Config * gpiops_cfg_ptr; //PS端 GPIO 配置信息
XGpio axi_gpio_inst; //PL端 AXI GPIO 驱动实例
u32 flag;
int flag_task;
int flag_sus=0;
const TickType_t x1second = pdMS_TO_TICKS( DELAY_1_SECOND );
const TickType_t x001second = pdMS_TO_TICKS( DELAY_001_SECOND );
const TickType_t x05second = pdMS_TO_TICKS( DELAY_05_SECOND );
void chushihua(){
gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
XGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED0, 1);
XGpioPs_SetDirectionPin(&gpiops_inst, MIO_LED1, 1);
XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED0, 1);
XGpioPs_SetOutputEnablePin(&gpiops_inst, MIO_LED1, 1);
XGpioPs_SetDirectionPin(&gpiops_inst, MIO_KEY0, 0);
}
int main( void ){
xil_printf( "Hello from Freertos example mainintm\r\n" );
//vSemaphoreCreateBinary(Hsem);
xTaskCreate( task_start,
( const char * ) "start",
SIZE,
NULL,
tskIDLE_PRIORITY+3,
&Htask_start );
vTaskStartScheduler();
for( ;; );
}
void axi_intrcsh(void){
XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_ID);
XGpio_SetDataDirection(&axi_gpio_inst, KEY_CHANNEL, 1); //设置AXI GPIO通道1为输入
XGpio_InterruptEnable(&axi_gpio_inst, KEY_MASK); //使能通道1中断
XGpio_InterruptGlobalEnable(&axi_gpio_inst); //使能AXI GPIO全局中断
scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID);
XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress);
XScuGic_SetPriorityTriggerType(&scugic_inst, GPIO_INT_ID, 0x04, 0x1);
//关联中断ID和中断处理函数
XScuGic_Connect(&scugic_inst, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst);
//使能AXI GPIO中断
XScuGic_Enable(&scugic_inst, GPIO_INT_ID);
//设置并打开中断异常处理功能
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst);
Xil_ExceptionEnable();
}
static void task_start( void *pvParameters )
{
//初始化中断控制器驱动
chushihua();
axi_intrcsh();
portENABLE_INTERRUPTS();
taskENTER_CRITICAL();
xTaskCreate( task_led_t,
( const char * ) "time05",
SIZE,
NULL,
tskIDLE_PRIORITY+2,
&Htask_led_t );
xTaskCreate( task_led_k,
( const char * ) "key",
SIZE,
NULL,
tskIDLE_PRIORITY+1,
&Htask_led_k );
flag_task=1;
taskEXIT_CRITICAL();
vTaskDelete(NULL);
for (;;) {
}
}
static void task_led_t( void *pvParameters ){
for( ;; ){
xil_printf( "tskb\r\n" );
//sleep(1);
vTaskDelay( x1second );
xil_printf( "tska\r\n" );
if ( flag_sus==1 ){
xil_printf( "gus\r\n" );
flag_sus=0;
flag_task=0;
vTaskSuspend(Htask_led_t);
}
XGpioPs_WritePin(&gpiops_inst, MIO_LED1,
XGpioPs_ReadPin(&gpiops_inst, MIO_KEY0));
}
}
static void task_led_k( void *pvParameters ){
for( ;; ){
XGpioPs_WritePin(&gpiops_inst, MIO_LED0,
~XGpioPs_ReadPin(&gpiops_inst, MIO_KEY0));
}
}
void axi_gpio_handler(void *CallbackRef){
int key_value = 1;
XGpio *GpioPtr = (XGpio *)CallbackRef;
print("Interrupt Detected!\n");
XGpio_InterruptDisable(GpioPtr, KEY_MASK); //关闭AXI GPIO中断使能
key_value = XGpio_DiscreteRead(GpioPtr, KEY_CHANNEL); //读取按键数据
if(!key_value){ //判断按键按下
if(flag_task==1){
xil_printf( "gu\r\n" );
flag_sus=1;
}
else{
if(xTaskResumeFromISR(Htask_led_t)== pdTRUE){
portYIELD_FROM_ISR(pdTRUE);
flag_task=1;
};
xil_printf( "fu\r\n" );
}
}
sleep(1); //延时1s,按键消抖
XGpio_InterruptClear(GpioPtr, KEY_MASK); //清除中断
XGpio_InterruptEnable(GpioPtr, KEY_MASK); //使能AXI GPIO中断
}