m0_49526909 2023-03-07 20:41 采纳率: 0%
浏览 344
已结题

在使用zynq中的freertos时,程序中存在中断引发vtaskdelay卡死,但是没有报错,该如何处理?

在使用zynq中的freertos时,程序中存在中断引发vtaskdelay卡死,但是没有报错,该如何处理?
环境:vivado2017;正点原子的xc7z010clg400-1
我的中断是从原子哥教程里的axi按键中断中复制来的

img

这是中断配置,这个函数的调用位置在一个优先级最低的task_start里,因为不这样的话中断无法触发
具体问题:

img

这个任务是每隔1s改变led的状态,在无中断的另一个application中能正确切换,但是在这个程序中输出情况如下:

img

进去了就出不来了,在task.c里添加了一系列xilprinf后能发现最后一条能成功输出的prinf位于1354行处(即在这一行的if{后的prinf能输出,而1356行的不行

img


另外:中断可以正常触发
不知道是什么原因,已经卡在这个问题上一个月了,网上也搜不到
代码全文:

/*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中断
}


  • 写回答

3条回答 默认 最新

  • m0_49526909 2023-03-15 22:46
    关注

    问题出在这里,freertos的任务调度器vTaskStartScheduler()调用时,会进行中断和定时器的初始化(在portZynq7000.c的115行),使用的是xInterruptController,所以在后面的中断设置部分的代码中,不应再次初始化,而是只要进行connect和enable,并在一开始extern XScuGic xInterruptController
    将原代码

    
    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();
    

    改为

        XScuGic_SetPriorityTriggerType(&xInterruptController, GPIO_INT_ID, 0xA0,0x01);
        //关联中断ID和中断处理函数
        XScuGic_Connect(&xInterruptController, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst);
        //使能AXI GPIO中断
        XScuGic_Enable(&xInterruptController, GPIO_INT_ID);
    

    即可

    评论

报告相同问题?

问题事件

  • 系统已结题 3月16日
  • 修改了问题 3月9日
  • 修改了问题 3月9日
  • 赞助了问题酬金20元 3月8日
  • 展开全部

悬赏问题

  • ¥15 asp写PC网站开通了微信支付,扫码付款不能跳转
  • ¥50 AI大模型精调(百度千帆、飞浆)
  • ¥15 关于#c语言#的问题:我在vscode和codeblocks中编写c语言时出现打不开源文件该怎么办
  • ¥15 非科班怎么跑代码?如何导数据和调参
  • ¥15 福州市的全人群死因监测点死亡原因报表
  • ¥15 Altair EDEM中生成一个颗粒,并且各个方向没有初始速度
  • ¥15 系统2008r2 装机配置推荐一下
  • ¥500 服务器搭建cisco AnyConnect vpn
  • ¥15 悬赏Python-playwright部署在centos7上
  • ¥15 psoc creator软件有没有人能远程安装啊