硬汉嵌入式论坛

 找回密码
 立即注册
查看: 615|回复: 11
收起左侧

[FreeRTOS] 遇到一个freertos问题,2天还没搞出来问题出在哪了

[复制链接]

0

主题

7

回帖

7

积分

新手上路

积分
7
发表于 2025-3-6 16:13:10 | 显示全部楼层 |阅读模式
本帖最后由 hy2270139582 于 2025-3-6 16:19 编辑

我在搞一个汽车仪表盘项目,使用awtk开发gui界面,使用freertos系统,目前一共有3个任务,awtk任务,can接收任务,按键扫描任务,awtk任务负责显示gui界面,can接收任务负责接收can盒传过来的数据,按键扫描任务负责切换awtk的界面,目前是有按键扫描任务和can任务的话,can盒发送的数据,可以正常接收并显示,一旦加上awtk任务,can盒发送任务就会失败,也接收不到数据,有按键扫描任务和awtk任务时也可以正常执行,即按键切换界面。有按键扫描任务和can接收任务时也可以正常执行。   然后现在是确定了加入awtk任务后,使用can盒发数据,无法触发can接收数据的中断   ,一旦加上awtk任务,can盒发送任务就会失败,也接收不到数据,只要加上awtk任务就会发现发送数据触发不了can的接收中断。不知道该怎么解决了

回复

使用道具 举报

44

主题

230

回帖

362

积分

高级会员

积分
362
发表于 2025-3-6 22:02:55 | 显示全部楼层
看下占用率,把awtk GUI任务放到最低优先级。can发送是可以阻塞发的,这个不可能影响,所以我判断是优先级问题。
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 08:12:11 | 显示全部楼层
snakeemail 发表于 2025-3-6 22:02
看下占用率,把awtk GUI任务放到最低优先级。can发送是可以阻塞发的,这个不可能影响,所以我判断是优先级 ...

好的,谢谢,awtk目前的优先级最小,can也是处于阻塞状态,在fifo接收到新消息后,触发中断释放信号量,can任务执行
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 08:46:01 | 显示全部楼层
[C] 纯文本查看 复制代码
#include <stdio.h>
#include "board.h"
#include "hpm_debug_console.h"
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_Data.h"
#include <assert.h>
#include "hpm_sysctl_drv.h"
#include "hpm_mcan_drv.h"
#include "hpm_clock_drv.h"  // 确保包含时钟驱动头文件

SemaphoreHandle_t xCANRXSemaphore; 
static volatile bool has_new_rcv_msg;

static volatile bool has_sent_out;

static volatile bool has_error;

static volatile bool tx_event_occurred;

static volatile bool timeout_event_occurred;

static volatile bool rxfifo0_event_occurred;

static volatile bool rxfifo1_event_occurred;

static volatile mcan_rx_message_t s_can_rx_buf;

static volatile mcan_tx_event_fifo_elem_t s_can_tx_evt;
//can中断源
SDK_DECLARE_EXT_ISR_M(BOARD_APP_CAN_IRQn, board_can_isr);
void board_can_isr(void)
{
    static uint32_t irq_count = 0;
    printf("[ISR] Enter CAN ISR #%lu\n", ++irq_count);
    BaseType_t canrxHigherPriorityTaskWoken = pdFALSE;
    MCAN_Type *base = BOARD_APP_CAN_BASE;
    uint32_t flags = mcan_get_interrupt_flags(base);
    if ((flags& MCAN_INT_RXFIFO0_NEW_MSG) != 0) {
        mcan_read_rxfifo(base, 0, (mcan_rx_message_t *) &s_can_rx_buf);
        //has_new_rcv_msg = true;
        rxfifo0_event_occurred = true;
        xSemaphoreGiveFromISR(xCANRXSemaphore, &canrxHigherPriorityTaskWoken);
        printf("RXFIFO0 interrupt\n");
        mcan_clear_interrupt_flags(BOARD_APP_CAN_BASE, flags);
        //portYIELD_FROM_ISR(canrxHigherPriorityTaskWoken);  // 强制任务切换
  }
}


void check_can_clock_status(void) {
    // 获取CAN时钟频率
    MCAN_Type *base = BOARD_APP_CAN_BASE;    
    uint32_t can_src_clk_freq = board_init_can_clock(base);    
    printf("[CAN Clock Check]\n");
    printf("  Clock Source: %s\n", BOARD_APP_CAN_BASE);
    printf("  Frequency: %lu Hz\n", can_src_clk_freq);
    
    if (can_src_clk_freq == 0) {
        printf("  ERROR: CAN clock not running!\n");
    } else if (can_src_clk_freq != 80000000) { // 假设预期CAN时钟为100MHz(根据实际情况调整)
        printf("  WARNING: CAN clock frequency mismatch!\n");
    }
}
void can_init(void)
{
    MCAN_Type *base = BOARD_APP_CAN_BASE;    
    uint32_t can_src_clk_freq = board_init_can_clock(base);
    mcan_config_t can_config;
    mcan_filter_elem_t can_filters[16];
    mcan_get_default_config(base, &can_config);
    can_config.baudrate = 1000000; /* 1M */
    can_config.mode = mcan_mode_normal;
    board_init_can(base);
    hpm_stat_t status = mcan_init(base, &can_config, can_src_clk_freq);
    if (status != status_success) {
        printf("CAN initialization failed, error code: %d\n", status);
        return;
    }
    uint32_t interrupt_mask = MCAN_EVENT_RECEIVE;
    uint32_t rxbuf_index = 1;
    can_filters[0].filter_type = MCAN_FILTER_TYPE_CLASSIC_FILTER;
    can_filters[0].filter_config = MCAN_FILTER_ELEM_CFG_STORE_INTO_RX_BUFFER_OR_AS_DBG_MSG;
    can_filters[0].can_id_type = MCAN_CAN_ID_TYPE_STANDARD;
    can_filters[0].match_id = 0x000;
    can_filters[0].offset = rxbuf_index;
    can_filters[0].filter_event = 0;
    can_filters[0].store_location = 0;
    can_config.all_filters_config.ext_id_filter_list.mcan_filter_elem_count = 0;
    can_config.all_filters_config.std_id_filter_list.filter_elem_list = &can_filters[0];
    can_config.all_filters_config.std_id_filter_list.mcan_filter_elem_count = 1;
    can_config.all_filters_config.global_filter_config.accept_non_matching_std_frame_option =
    MCAN_ACCEPT_NON_MATCHING_FRAME_OPTION_IN_RXFIFO0;
    can_config.all_filters_config.global_filter_config.accept_non_matching_ext_frame_option =
    MCAN_ACCEPT_NON_MATCHING_FRAME_OPTION_REJECT;
    can_config.all_filters_config.global_filter_config.reject_remote_std_frame = true;
    can_config.all_filters_config.global_filter_config.reject_remote_ext_frame = true;
    can_config.txbuf_trans_interrupt_mask = ~0UL;
    can_config.interrupt_mask = interrupt_mask;
    mcan_enable_interrupts(base, interrupt_mask);
    intc_m_enable_irq_with_priority(BOARD_APP_CAN_IRQn, 1);
    //xSemaphoreGive(xCANRXSemaphore);
}

void task_can_rx(void *pvParameters) {
    while (1) {
         /*  if (has_new_rcv_msg) {
            has_new_rcv_msg = false;  // 重置标志
            printf("New message received, ID=%08x, Data: ", s_can_rx_buf.std_id);
            for (int i = 0; i < 8; i++) {
                printf("%02X ", s_can_rx_buf.data_8[i]);
            }
            printf("\n");
            vTaskDelay(pdMS_TO_TICKS(20)); 
            debug_print_task_status();
        }*/
        if (xSemaphoreTake(xCANRXSemaphore, portMAX_DELAY) == pdTRUE) {
            printf("New message received, ID=%08x, Data: ", s_can_rx_buf.std_id);
            for (int i = 0; i < 8; i++) {
                printf("%02X ", s_can_rx_buf.data_8[i]);
            }
            printf("\n");
            vTaskDelay(pdMS_TO_TICKS(20)); 
              static TickType_t last_print_time = 0;
            if (xTaskGetTickCount() - last_print_time > pdMS_TO_TICKS(10000)) {
                debug_print_task_status();
                last_print_time = xTaskGetTickCount();
           }
            }
        }
}

void task_can_entry(void) {
    BaseType_t stat;
    xCANRXSemaphore = xSemaphoreCreateBinary();
    can_init();
    if (xCANRXSemaphore == NULL) {
        printf("Failed to create semaphore.xCANRXSemaphore\n");
        for (;;) {
        }
    }
    if (xTaskCreate(task_can_rx, "can_rx", 
                    TASK_CAN_RX_STACK_SIZE , NULL, 
                    PRIORITY_TASK_CAN_RX, NULL) != pdPASS) {
        printf("can_rx creation failed!.\n");
        for (;;) {
        }
    }

    printf("task_can complete!.\n");

}
     这是目前can任务的代码
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 08:46:28 | 显示全部楼层
[C] 纯文本查看 复制代码
#include <stdio.h>
#include "board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_Data.h"
#include "hpm_gpio_drv.h"
#include "hpm_mchtmr_drv.h"
SemaphoreHandle_t xKeyScanSemaphore; 
//extern SemaphoreHandle_t xCANRXSemaphore; 

extern int window_cnt;  
extern void switch_window(void);
extern  void gui_preload_image(void);
#define DEBOUNCE_TIME_MS 200  
uint32_t last_key1_time = 0;
uint32_t last_key2_time = 0;
SDK_DECLARE_EXT_ISR_M(BOARD_APP_GPIO_IRQ, isr_gpio)
#define MCHTMR_CLK_NAME (clock_mchtmr0)
void configure_gpio_for_key_scan(void) {
    gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_KEY1_GPIO_INDEX, BOARD_KEY1_GPIO_PIN);
    gpio_set_pin_input(BOARD_APP_GPIO_CTRL, BOARD_KEY2_GPIO_INDEX, BOARD_KEY2_GPIO_PIN);
    gpio_interrupt_trigger_t trigger = gpio_interrupt_trigger_edge_falling;
    gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_KEY1_GPIO_INDEX, BOARD_KEY1_GPIO_PIN, trigger);
    gpio_config_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_KEY2_GPIO_INDEX, BOARD_KEY2_GPIO_PIN, trigger);
    gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_KEY1_GPIO_INDEX, BOARD_KEY1_GPIO_PIN);
    gpio_enable_pin_interrupt(BOARD_APP_GPIO_CTRL, BOARD_KEY2_GPIO_INDEX, BOARD_KEY2_GPIO_PIN);
    intc_m_enable_irq_with_priority(BOARD_APP_GPIO_IRQ, 3);
}

void isr_gpio(void)
{
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  BaseType_t canrxHigherPriorityTaskWoken = pdFALSE;
  gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_KEY1_GPIO_INDEX,
                        BOARD_KEY1_GPIO_PIN);
  gpio_clear_pin_interrupt_flag(BOARD_APP_GPIO_CTRL, BOARD_KEY2_GPIO_INDEX,
                        BOARD_KEY2_GPIO_PIN);
  //xSemaphoreGiveFromISR(xCANRXSemaphore, &canrxHigherPriorityTaskWoken);
  xSemaphoreGiveFromISR(xKeyScanSemaphore, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 

}

void task_key_scan(void *pvParameters) {
    while (1) {
        if (xSemaphoreTake(xKeyScanSemaphore, portMAX_DELAY) == pdTRUE) {
            debug_print_task_status();
            uint32_t current_time = xTaskGetTickCount(); // 获取当前系统时间(ticks)
            if (gpio_read_pin(BOARD_APP_GPIO_CTRL,BOARD_KEY1_GPIO_INDEX,BOARD_KEY1_GPIO_PIN) == 0) {
             if (current_time - last_key1_time >= pdMS_TO_TICKS(DEBOUNCE_TIME_MS)){
                printf("KEY1 window_cnt=%d\n",window_cnt);
                last_key1_time = current_time;
                gui_preload_image();
                if (window_cnt >= 3) {
                    window_cnt =  0;  
                    printf("window_cnt >  3 KEY1 window_cnt=%d\n",window_cnt);
                }
                window_cnt++;
                switch_window(); 
              }
            }

            if (gpio_read_pin(BOARD_APP_GPIO_CTRL,BOARD_KEY2_GPIO_INDEX,BOARD_KEY2_GPIO_PIN) == 0) {
            if (current_time - last_key2_time >= pdMS_TO_TICKS(DEBOUNCE_TIME_MS))
            {
                window_cnt--;
                printf("KEY2 window_cnt=%d\n",window_cnt);
                last_key2_time = current_time;
                gui_preload_image();
                if (window_cnt <= 0) {
                    window_cnt =  3;  
                    printf("window_cnt < 0 KEY2 window_cnt=%d\n",window_cnt);
                }
                  switch_window();        
              }
            }
              vTaskDelay(pdMS_TO_TICKS(20));
        }
    }
}
void task_scan_key_entry(void) {
    BaseType_t stat;
    xKeyScanSemaphore = xSemaphoreCreateBinary();
    if (xKeyScanSemaphore == NULL) {
        printf("Failed to create semaphore.\n");
        for (;;) {
        }
    }
    configure_gpio_for_key_scan();
    printf("intake task_scan_key!.\n");
    if (xTaskCreate(task_key_scan, "key_scan", 
                    TASK_KEY_SCAN_STACK_SIZE , NULL, 
                    PRIORITY_TASK_KEY_SCAN, NULL) != pdPASS) {
        printf("key_scan creation failed!.\n");
        for (;;) {
        }
    }
    printf("task_scan_key complete!.\n");

} 
键盘扫描任务代码
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 08:47:18 | 显示全部楼层
[C] 纯文本查看 复制代码
#include <stdio.h>
#include "board.h"
#include "hpm_debug_console.h"
#include "FreeRTOS.h"
#include "task.h"
#include "FreeRTOS_Data.h"
#include "awtk.h"
#include "display_support.h"
#include "vglite_support.h"
extern check_can_clock_status();
extern int gui_app_start(int lcd_w, int lcd_h);
static void task_awtk(void *pvParameters) {
    vglite_init();
    hpm_lcdc_init();
    gui_app_start(LCD_WIDTH, LCD_HEIGHT);
    while (1) {
      vTaskDelay(pdMS_TO_TICKS(100)); 
        printf("task_awtk \n");
    }
    
}

void task_awtk_entry(void) {
    BaseType_t stat;
    if (xTaskCreate(task_awtk, "task_awtk", 
                    TASK_AWTK_STACK_SIZE, NULL, 
                    PRIORITY_TASK_AWTK, NULL) != pdPASS) {
        printf("task_awtk creation failed!.\n");
        for (;;) {
        }
    }
    check_can_clock_status();  //  初始化后检查
}
  awtk任务的代码
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 08:49:20 | 显示全部楼层
这个awtk任务是进入    gui_app_start(LCD_WIDTH, LCD_HEIGHT);
函数后,跳进一个inc后缀的文件,在这个文件里进入这个函数   ret_t application_init(void) {
  switch_window();
  vTaskDelay(1000);
  check_can_clock_status();  
  return RET_OK;
}进行按键切换界面
回复

使用道具 举报

0

主题

7

回帖

7

积分

新手上路

积分
7
 楼主| 发表于 2025-3-7 09:12:23 | 显示全部楼层
[C] 纯文本查看 复制代码
/*AWTK任务*/
#define PRIORITY_TASK_AWTK      (2)
#define TASK_AWTK_STACK_SIZE    (6*1024) 
/*CAN接收任务*/
#define PRIORITY_TASK_CAN_RX        (3)
#define TASK_CAN_RX_STACK_SIZE    (2*1024) 
/*按键扫描任务*/
#define PRIORITY_TASK_KEY_SCAN          (4)
#define TASK_KEY_SCAN_STACK_SIZE      (2*1024) 
#define PRIORITY_TASK_MAIN      (5)
#define TASK_MAIN_STACK_SIZE    (512)
任务优先级代码
回复

使用道具 举报

0

主题

14

回帖

14

积分

新手上路

积分
14
发表于 2025-3-13 23:21:46 | 显示全部楼层
问题解决了吗
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2025-3-14 16:50:22 | 显示全部楼层
你的can接收中断只是给信号出去,中断的优先级怎么设计都应该是高于任务的。所以你的can中断必然是能够进去的,如果不确定,可以用示波器观察can的波形。
你的按键任务优先级是最高的,里面会执行窗口的切换,窗口切换里面会设计到资源锁吗?会不会是资源锁导致的呢?

再不行,就点灯,或者通过测试IO观察任务进出的波形。
回复

使用道具 举报

95

主题

528

回帖

828

积分

金牌会员

积分
828
发表于 2025-3-15 08:11:07 | 显示全部楼层
加个守护进程的任务,把当前你在运行的任务状态打印出来,看看是不是任务没跑起来?
[C] 纯文本查看 复制代码
/*
/*---------- includes ----------*/
#include "task_daemon.h"
#include "radio.h"

#include "cmsis_os2.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#include "SEGGER_RTT.h"

#define LOG_TAG "daemon"
#include "fplog.h"
/*---------- macro ----------*/
/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
static void log_output_handler(const char *log, int len);
static void log_lock_handler(void);
static void log_unlock_handler(void);
/*---------- variable ----------*/
size_t g_heap_size;

log_info_t log_info = {
    .log_output_handler = log_output_handler,
    .log_lock_handler = log_lock_handler,
    .log_unlock_handler = log_unlock_handler,
};

static SemaphoreHandle_t logmutex;
/*---------- function ----------*/
static void log_output_handler(const char *log, int len)
{
    SEGGER_RTT_Write(0, log, len);
}
static void log_lock_handler(void)
{
    xSemaphoreTake(logmutex, portMAX_DELAY);
}
static void log_unlock_handler(void)
{
    xSemaphoreGive(logmutex);
}
uint16_t count;
static void _task(void *p)
{
    char pcBuffer[512];
    while (1) {
        if (count < 1500) {
            count++;
        } else {
            vTaskList(pcBuffer);
            log_i("\nVtaskList:\n%s", pcBuffer);
            g_heap_size = xPortGetFreeHeapSize();
            log_i("\nFreeHeapSize:%d", g_heap_size);
            count = 0;
        }
        vTaskDelay(10);
    }
}

void task_daemon_create(void)
{
    logmutex = xSemaphoreCreateRecursiveMutex();
    log_init(&log_info);
    xTaskCreate(_task, "daemon", configMINIMAL_STACK_SIZE * 2, NULL, osPriorityHigh, NULL);
}
/*---------- end of file ----------*/

共产主义一定胜利!
回复

使用道具 举报

95

主题

528

回帖

828

积分

金牌会员

积分
828
发表于 2025-3-15 08:15:40 | 显示全部楼层
本帖最后由 会飞的猪_2020 于 2025-3-15 08:20 编辑

我的经验:

1.可能是程序没跑起来。比如说你创建任务都是在一个初始任务中创建的,那么这个任务的栈如果不够大,那么就有可能任务创建不成功。
2.确认任务跑起来了之后,可能是你互斥信号量没处理好,你可以尝试把你的代码里的互斥信号量先全部去掉,看看是否就跑起来了。
3.如果去掉互斥信号量跑起来,那你就检查一下是否有地方死锁了。


另外你CAN中断代码里面的这段被你注释掉了。我记得中断里面调用需要这个api的。
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);


共产主义一定胜利!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-26 00:21 , Processed in 0.297872 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表