认识FreeRTOS多任务同步和通信机制

时间:2021-08-19 21:39:06

FreeRTOS多任务同步和通信机制的掌握

本周课堂任务为:

  • 在github上,Fork例程项目(https://github.com/cbhust/

  • STM32F429_Discovery_FreeRTOS_9.git) 到自己的个人账号。

  • clone项目到本地电脑的Ubuntu虚拟机中(虚拟机环境在第一次作业中已搭建)。

  • 按照/Projects/Demo1/README.md中的提示编译Demo1例程并通过Qemu运行例程。

  • 在Demo1的框架基础上完成自己的本次编程作业(具体要求见第3点)。

  • 代码完成后提交到自己的github账号上,确保助教可以正常的clone并编译运行。

  • 在作业博客上给出代码的github链接、代码说明以及运行结果展示。

clone项目并初运行

参考第一次作业的内容,按照指示,fork老师的代码后,在终端输入:
git clone https://github.com/czphappy/STM32F429_Discovery_FreeRTOS_9.git
获得相应编程环境。如图

认识FreeRTOS多任务同步和通信机制

认识FreeRTOS多任务同步和通信机制

根据老师的提示,按照README.md中的流程,安装QEMU(如图)

认识FreeRTOS多任务同步和通信机制

接着是为qemu加入环境变量,在终端输入: (这一步每次重启终端都需要重新输入,谢谢老师的提醒,少走许多弯路)

#cd ~/work
#tar xvf gnuarmeclipse-qemu-debian64-2.8.0-201612271623-dev.tgz
#chmod -R -w ./qemu
#export PATH=~/work/qemu/2.8.0-201612271623-dev/bin/:$PATH
#qemu-system-gnuarmeclipse --version

结果如图,配置成功。
认识FreeRTOS多任务同步和通信机制

接着按照指示,在Demo1下make之后,在终端输入:
#./qemu.sh
运行结果如下,验证完毕,环境已经建好。:
认识FreeRTOS多任务同步和通信机制

GDB调试

继续依照指示,在终端输入:
#./qemu_gdb.sh
开启UI后,新开一个终端,输入:

#arm-none-eabi-gdb  
(gdb)target remote localhost:1234
(gdb)continue

得到如下结果(验证完毕)
认识FreeRTOS多任务同步和通信机制

新建通信任务

这个问题我想主要难点在于Monitor_Task的书写,由于三个任务同步进行,Monitor_Task如果设置不恰当很有可能错误判断,因为最常见的结果是Sender_Task已经把数据传出,只是 Receiver_Task还没有接收,但我发现sender每次传输的值和其传输的次数是相同的(或者具体说是除10000的余数),所以我就设置两个全局变量,一个用于存储Receiver_Task最新接收的值,另外一个用于存储传输次数,通过比较两者是否相等,就可以直接进行判断。

以下是具体实现流程,在老师给的main.c的框架下,我设置的全局变量

void Hardware_Init(void);
void Monitor_Task( void *pvParameters );
void Sender_Task( void *pvParameters );
void Receiver_Task( void *pvParameters );
void Red_LED_On(void);
void Red_LED_Off(void);
void Green_LED_On(void);
void Green_LED_Off(void);
extern unsigned long ReceiverFlag =0;
extern unsigned long nflag=0;

ReceiverFlag用于存储Receiver_Task最新接收的值,nflag存储传输次数,以下是我新建的三个任务:

      
xTaskCreate(
Sender_Task, /* Function pointer */
( signed portCHAR * )"Sender_Task", /* Task name - for debugging only*/
configMINIMAL_STACK_SIZE, /* Stack depth in words */
(void*) NULL, /* Pointer to tasks arguments ````(parameter) */
tskIDLE_PRIORITY + 2UL, /* Task priority*/
NULL /* Task handle */
);

xTaskCreate(
Receiver_Task, /* Function pointer */
( signed portCHAR * )"Receiver_Task", /* Task name - for debugging only*/
configMINIMAL_STACK_SIZE, /* Stack depth in words */
(void*) NULL, /* Pointer to tasks arguments (parameter) */
tskIDLE_PRIORITY + 4UL, /* Task priority*/
NULL /* Task handle */
);
xTaskCreate(
Monitor_Task, /* Function pointer */
( signed portCHAR * )"Monitor_Task", /* Task name - for debugging only*/
configMINIMAL_STACK_SIZE, /* Stack depth in words */
(void*) NULL, /* Pointer to tasks arguments (parameter) */
tskIDLE_PRIORITY + 3UL, /* Task priority*/
NULL /* Task handle */
);

其中优先级取为Sender_Task<Receiver_Task<Monitor_Task(其实后两者可以一样) ,结果是一致的。

void Sender_Task(void *pvParameters)
{
unsigned long SendNum = 1;
unsigned long SenderSum =0;
for( ;; )
{
vTaskDelay(2);
/* 向队列中填充内容 */
xQueueSend( MsgQueue, ( void* )&SendNum, 0 );
SenderSum=SendNum+SenderSum;
SendNum=(SendNum+1)%10000;
}
}

sender_Task的任务比较简单,只需要有个累加值以及一个基数即刻,优先级较低。

void Receiver_Task(void *pvParameters)
{
unsigned long ReceiverSum = 0;
unsigned long ReceiverNum =1;
for( ;; )
{

vTaskDelay(1000);
/* 从队列中获取内容 */
for( ;xQueueReceive( MsgQueue,&ReceiverNum, 0 ) == pdPASS;)
{
ReceiverSum = ReceiverNum+ReceiverSum;
nflag++;
ReceiverFlag=ReceiverNum;
}
}
}

Receiver_Task的任务相对复杂,除了两个累加值之外,还需要设置两个全局变量,取出值和累加值

void Monitor_Task(void *pvParameters)
{
for( ;; )
{
vTaskDelay(10000);
if( ReceiverFlag == (nflag % 10000))
{
Green_LED_On();
vTaskDelay(1000);
Green_LED_Off();
}
else
{
Red_LED_On();
vTaskDelay(1000);
Red_LED_Off();
}
}
}

正如前面所说,Monitor_Task就是简单判断两个全局变量是否相等,正确则绿灯亮,错误则红灯亮。
认识FreeRTOS多任务同步和通信机制
结果是绿灯持续闪烁,说明传输没有问题。
完成后将我的代码push到远程仓库。
以下是我的github链接
https://github.com/czphappy/STM32F429_Discovery_FreeRTOS_9


此次实验,我的进度把握不是很好,师兄也是一在把时间延后,从一开始什么都不知道,到现在的任务完成,期间遇到各种问题,多谢师兄和同学们也耐心讲解,让我完成这个作业,对于GitHub和FreeRTOS也有了一定的认识。谢谢!