分享一个 FreeRTOS 任务通知的例子,基于C++的混合开发尝试

首先创建一个 led.h 和一个 led.cpp,文件内容如下:

led.h

#pragma once
#include "FreeRTOS.h"
#include "task.h"
#include "at32f413.h"

class Led
{
public:
    Led(gpio_type* _gpiox, uint32_t _pins);
    void gpio_config(void);
    void toggle();
    void on();
    void off();

private:
    uint32_t m_pins;
    gpio_pull_type m_pull;
    crm_periph_clock_type m_crm_periph_clock;
    gpio_type* m_gpiox;
};

led.cpp

#include "led.h"


#define USER_LED_TASK_PRIO 2			/* 定义任务优先级 */
#define USER_LED_TASK_STACK_SIZE 120	/* 定义任务堆栈大小 */
TaskHandle_t user_led_handle;			/* 定义任务句柄 */
void led_task(void* pvParameters); /* 任务函数 */
extern Led led;

/// @brief LED 构造函数,必须提供必要的参数
/// @param _gpiox 
/// @param _pins 
Led::Led(gpio_type* _gpiox, uint32_t _pins)
{
    xTaskCreate(
        (TaskFunction_t)led_task,
        (const char*)"led_task",
        (uint16_t)USER_LED_TASK_STACK_SIZE,
        (void*)NULL,
        (UBaseType_t)USER_LED_TASK_PRIO,
        (TaskHandle_t*)user_led_handle
    );

    m_gpiox = _gpiox;
    m_pins = _pins;
	if (_gpiox == GPIOA)
	{
		m_crm_periph_clock = CRM_GPIOA_PERIPH_CLOCK;
	}
    else if (_gpiox == GPIOB)
    {
        m_crm_periph_clock = CRM_GPIOB_PERIPH_CLOCK;
    }
    else if (_gpiox == GPIOC)
    {
        m_crm_periph_clock = CRM_GPIOC_PERIPH_CLOCK;
    }
    else if (_gpiox == GPIOD)
    {
        m_crm_periph_clock = CRM_GPIOD_PERIPH_CLOCK;
    }
}

/** @brief gpio config
  *	@biref LED IO Config
  */
void Led::gpio_config(void)
{
    /* 定义 GPIO 初始化结构体 */
    gpio_init_type gpio_init_struct;

    /* 使能 GPIOA 外设时钟 */
    crm_periph_clock_enable(m_crm_periph_clock, TRUE);

    /* 设置默认参数 */
    gpio_default_para_init(&gpio_init_struct);

    /* 配置 GPIO 参数 */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; /* 较大电流推动/吸入能力 */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; /* 推挽输出 */
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = m_pins;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(m_gpiox, &gpio_init_struct);
}

/// @brief led FreeRTOS 任务函数
/// @param pvParameters 
void led_task(void* pvParameters)
{
    led.gpio_config();
    uint32_t num = 0;
    uint32_t ul_notify_value;
    while (1)
    {
        ul_notify_value = ulTaskNotifyTake(pdTRUE, 0);
        if (ul_notify_value>0)
        {
            led.toggle();
        }
    }
}

void Led::toggle()
{
    m_gpiox->odt ^= m_pins;
}

void Led::on()
{
    gpio_bits_write(m_gpiox, m_pins, TRUE);
}

void Led::off()
{
    gpio_bits_write(m_gpiox, m_pins, FALSE);
}

main.cpp

该例子通过 Tick 钩子函数发送通知的方式来使 LED 函数,任务通知的代码如下:

 xTaskNotifyGive(xTaskGetHandle("led_task"));

由于 led_task 任务函数的定义在 led.cpp 中定义的,所以使用 xTaskGetHandle() 函数来获取任务句柄。

创建任务的函数 xTaskCreate() 我们放到了 Led 的构造函数中,这样在实例化 Led 时就会自动创建任务了。

#include "at32f413_clock.h"
#include "FreeRTOS.h"
#include "task.h"
#include "led.h"
#include "xtp_defines.h"

Led led(GPIOA, GPIO_PINS_0);

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
    system_clock_config();

    /* 开启任务调度器 */
    vTaskStartScheduler();
    while (1)
    {

    }
}

// Tick 钩子函数
void vApplicationTickHook(void)
{
    global_num_1++;
    if(global_num_1>=500)
    {
		global_num_1 = 0;
        // 给 led_task 任务发送通知
        xTaskNotifyGive(xTaskGetHandle("led_task"));
    }
}
posted @ 2023-10-22 02:31  小土坡  阅读(121)  评论(0编辑  收藏  举报