分享一个 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"));
}
}