对比几个freertos工程发现main函数写法是一样的,都是
初始化
创建起始任务
开启任务调度
while(1) //一般不会执行到这一步。
系统学了FreeRTOS之后再去看这几个基于FreeRTOS的飞控工程就很自然了,心里也有底,可以很好地去分析他们的源码。真的先系统学好还是挺重要的。
而且我看ucos工程的main函数也类似。
我可以发现这两个freertos工程都是把控制部分放在一个任务里面的,所以其实也不复杂,
这是正点原子的minifly的main.c文件
#include "system.h" /*头文件集合*/
/********************************************************************************
* 本程序只供学习使用,未经作者许可,不得用于其它任何用途
* ALIENTEK MiniFly
* main.c
* 包括系统初始化和创建任务
* 正点原子@ALIENTEK
* 技术论坛:www.openedv.com
* 创建日期:2017/5/12
* 版本:V1.3
* 版权所有,盗版必究。
* Copyright(C) 广州市星翼电子科技有限公司 2014-2024
* All rights reserved
********************************************************************************/
TaskHandle_t startTaskHandle;
static void startTask(void *arg);
int main()
{
systemInit(); /*底层硬件初始化*/
xTaskCreate(startTask, "START_TASK", 300, NULL, 2, &startTaskHandle); /*创建起始任务*/
vTaskStartScheduler(); /*开启任务调度*/
while(1) {};
}
/*创建任务*/
void startTask(void *arg)
{
taskENTER_CRITICAL(); /*进入临界区*/
//maxi:因为是操作系统嘛,所以创建任务。
xTaskCreate(radiolinkTask, "RADIOLINK", 150, NULL, 5, NULL); /*创建无线连接任务*/
xTaskCreate(usblinkRxTask, "USBLINK_RX", 150, NULL, 4, NULL); /*创建usb接收任务*/
xTaskCreate(usblinkTxTask, "USBLINK_TX", 150, NULL, 3, NULL); /*创建usb发送任务*/
xTaskCreate(atkpTxTask, "ATKP_TX", 150, NULL, 3, NULL); /*创建atkp发送任务任务*/
xTaskCreate(atkpRxAnlTask, "ATKP_RX_ANL", 300, NULL, 6, NULL); /*创建atkp解析任务*/ //maxi:我没想到居然这个的任务优先级最高。
xTaskCreate(configParamTask, "CONFIG_TASK", 150, NULL, 1, NULL); /*创建参数配置任务*/
xTaskCreate(pmTask, "PWRMGNT", 150, NULL, 2, NULL); /*创建电源管理任务*/
xTaskCreate(sensorsTask, "SENSORS", 450, NULL, 4, NULL); /*创建传感器处理任务*/
xTaskCreate(stabilizerTask, "STABILIZER", 450, NULL, 5, NULL); /*创建姿态任务*/
//maxi:stabilizerTask:四轴平衡控制任务。该任务运行的内容比较多,也是比较关键的内容。 包括传感器数据读取,数据融合,获取控制数据,空翻检测,异常检测,PID 控制,PWM 输出控制等。
//maxi:stabilizerTask这个函数在stabilizer.c里面,也就是这个任务的具体细节在这个函数里面。
xTaskCreate(expModuleMgtTask, "EXP_MODULE", 150, NULL, 1, NULL); /*创建扩展模块管理任务*/
printf("Free heap: %d bytes\n", xPortGetFreeHeapSize()); /*打印剩余堆栈大小*/
vTaskDelete(startTaskHandle); /*删除开始任务*/
taskEXIT_CRITICAL(); /*退出临界区*/
}
void vApplicationIdleHook( void )
{
static u32 tickWatchdogReset = 0;
portTickType tickCount = getSysTickCnt();
if (tickCount - tickWatchdogReset > WATCHDOG_RESET_MS)
{
tickWatchdogReset = tickCount;
watchdogReset();
}
__WFI(); /*进入低功耗模式*/
}
ACfly的main.c
#include "Basic.hpp"
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "drv_Main.hpp"
#include "MS_Main.hpp"
#include "Parameters.hpp"
#include "FlashIO.h"
#include "Modes.hpp"
#include "MSafe.hpp"
#include "ctrl_Main.hpp"
#include "drv_PWMOut.hpp"
#include "AC_Math.hpp"
#include "Missions.hpp"
#include "debug.hpp"
#if 1 //如果没有这段,则需要在target选项中选择使用USE microLIB
__asm(".global __use_no_semihosting\n\t") ;//注释本行, 方法1
extern "C"
{
// struct __FILE {
// int handle;
// };
// std::FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
//__use_no_semihosting was requested, but _ttywrch was referenced, 增加如下函数, 方法2
void _ttywrch(int ch)
{
ch = ch;
}
char *_sys_command_string(char *cmd, int len)
{
return 0;
}
}
#endif
void DriverInit_task(void* pvParameters)
{
//初始化设备驱动
init_drv_Main();
//初始化解算系统
init_MS_Main();
init_Debug();
init_Modes();
init_MSafe();
init_ControlSystem();
//注册初始化参数
struct
{
uint32_t calib_ESC[2]; //校准电调
}init_cfg;
memset( &init_cfg, 0, sizeof(init_cfg) );
MAV_PARAM_TYPE param_types[] = {
MAV_PARAM_TYPE_UINT32 , //校准电调
};
SName param_names[] = {
"Init_CalibESC", //校准电调
};
ParamGroupRegister( "Init", 1, 1, param_types, param_names, (uint64_t*)&init_cfg );
//完成初始化
//完成后不能再进行初始化操作
while( getInitializationCompleted() == false )
{
setInitializationCompleted();
os_delay(0.1);
}
/*读取初始化参数进行初始化操作*/
//读初始化参数
ReadParamGroup( "Init", (uint64_t*)&init_cfg, 0 );
//校准电调
if( init_cfg.calib_ESC[0] == 21586 )
{
PWM_PullUpAll();
os_delay(4.0);
PWM_PullDownAll();
}
//重置初始化参数
bool need_reset_init_param = false;
for( uint8_t i = 0; i < sizeof(init_cfg); ++i )
{
if( ((uint8_t*)&init_cfg)[i] != 0 )
{
((uint8_t*)&init_cfg)[i] = 0;
need_reset_init_param = true;
}
}
if( need_reset_init_param )
UpdateParamGroup( "Init", (uint64_t*)&init_cfg, 0, sizeof(init_cfg)/8 );
//拉低电机输出
PWM_PullDownAll();
/*读取初始化参数进行初始化操作*/
//飞行任务初始化
init_Missions();
//删除本任务
vTaskDelete(0);
}
int main(void)
{
//初始化芯片时钟
//时间基准等基础功能
init_Basic();
//创建初始化任务并进入任务调度器
xTaskCreate( DriverInit_task , "Init" ,8192,NULL,3,NULL);
vTaskStartScheduler();
while(1);
}
extern "C" void HardFault_Handler()
{
//错误中断拉低所有输出
PWM_PullDownAll();
}
extern "C" void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
static char StackOvTaskName[20];
strcpy( StackOvTaskName, (char*)pcTaskName );
}
《跟工程师学嵌入式开发》最后ucos工程的main函数。
原子的freertos书里面我看到一个main函数,里面也是先创建任务,然后开启任务调度。当然我后来意识到,不都是原子写的么。。。和minifly应该是一个风格。我发现他是在创建的初始任务里面创建任务,也就是可以在任务里面创建任务。似乎ACfly的代码应该也是的,因为mian函数里面就创建了一个任务,其他任务似乎都是在这个任务里面创建的,所以他们是什么关系,平行关系么?是不是这样有个任务树,让我想起linux里面有父进程子进程。搞不好真的是的,父进程和子进程应该是并列的关系吧?
野火的freertos书里面。