Linux下实现Freertos模拟器
1.下载源码
2.创建文件夹
一共三个文件夹FreeRTOS_Kernel,inc,src
3.往文件夹内添加文件
(1)FreeRTOS_Kernel
进入FreeRTOSv202111.00\FreeRTOS\Source
include目录中全部拷贝过来
.c文件只需要拷贝croutine.c, list.c, queue.c以及tasks.c即可。
portable文件夹 1 拷贝MemMang 保留里面的heap_3.c
2 从示例代码中复制GCC文件
(2)Inc
将官方示例的simulator的根目录下的FreeRTOSConfig.h拷贝到inc目录下。
(3)Src
在src目录下创建main.c文件,在其中定义一个空的main函数即可。
4.Makefile编写
Makefile:
RM := rm -rf
PROJ_ROOT :=.
BUILD_TMP :=$(PROJ_ROOT)/tmp
TARGET_INC := -I$(PROJ_ROOT)/inc \
-I$(PROJ_ROOT)/FreeRTOS_Kernel/include \
-I$(PROJ_ROOT)/FreeRTOS_Kernel/portable/GCC/Posix
-include subdir.mk
-include FreeRTOS_Kernel/subdir.mk
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(strip $(C_DEPS)),)
-include $(C_DEPS)
endif
endif
all:simulator_linux.bin
simulator_linux.bin: $(OBJS)
@echo 'Building target: $@'
gcc -pthread -lrt -o"simulator_linux.bin" $(OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
clean:
-$(RM) $(OBJS)$(C_DEPS)$(EXECUTABLES) simulator_linux.bin
-@echo ' '
.PHONY: all clean dependents
.SECONDARY:
subdir.mk:用来编译需要的该文件夹对应的.o
C_SRCS += \
$(PROJ_ROOT)/src/main.c
OBJS += \
$(BUILD_TMP)/main.o
C_DEPS += \
$(BUILD_TMP)/main.d
# Each subdirectory must supply rules for building sources it contributes
$(BUILD_TMP)/%.o: $(PROJ_ROOT)/src/%.c
@echo 'Building file: $<'
gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
@echo 'Finished building: $<'
@echo ' '
FreeRTOS_Kernel/subdir.mk 用来编译需要的该文件夹对应的.o
C_SRCS += \
$(PROJ_ROOT)/FreeRTOS_Kernel/croutine.c \
$(PROJ_ROOT)/FreeRTOS_Kernel/list.c \
$(PROJ_ROOT)/FreeRTOS_Kernel/queue.c \
$(PROJ_ROOT)/FreeRTOS_Kernel/tasks.c \
$(PROJ_ROOT)/FreeRTOS_Kernel/portable/GCC/Posix/port.c \
$(PROJ_ROOT)/FreeRTOS_Kernel/portable/MemMang/heap_3.c
OBJS += \
$(BUILD_TMP)/croutine.o \
$(BUILD_TMP)/list.o \
$(BUILD_TMP)/queue.o \
$(BUILD_TMP)/tasks.o \
$(BUILD_TMP)/port.o \
$(BUILD_TMP)/heap_3.o
C_DEPS += \
$(BUILD_TMP)/croutine.d \
$(BUILD_TMP)/list.d \
$(BUILD_TMP)/queue.d \
$(BUILD_TMP)/tasks.d \
$(BUILD_TMP)/port.d \
$(BUILD_TMP)/heap_3.d
$(BUILD_TMP)/%.o: $(PROJ_ROOT)/FreeRTOS_Kernel/%.c
@echo 'Building file: $<'
gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
@echo 'Finished building: $<'
@echo ' '
$(BUILD_TMP)/%.o: $(PROJ_ROOT)/FreeRTOS_Kernel/portable/GCC/Posix/%.c
@echo 'Building file: $<'
gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
@echo 'Finished building: $<'
@echo ' '
$(BUILD_TMP)/%.o: $(PROJ_ROOT)/FreeRTOS_Kernel/portable/MemMang/%.c
@echo 'Building file: $<'
gcc -DUSE_STDIO=1 -D__GCC_POSIX__=1 $(TARGET_INC) -O2 -Wall -c -fmessage-length=0 -pthread -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o"$@" "$<"
@echo 'Finished building: $<'
@echo ' '
SConstruct 编译多个文件
obj = Object([
'./FreeRTOS_Kernel/croutine.c',
'./FreeRTOS_Kernel/list.c',
'./FreeRTOS_Kernel/queue.c',
'./FreeRTOS_Kernel/tasks.c',
'./FreeRTOS_Kernel/portable/GCC/Posix/port.c',
'./FreeRTOS_Kernel/portable/MemMang/heap_3.c',
'./src/main.c'
],
CCFLAGS= '-DUSE_STDIO=1 -D__GCC_POSIX__=1',
CPPPATH =
['./inc', './FreeRTOS_Kernel/include', './FreeRTOS_Kernel/portable/GCC/Posix']
)
Program('simulator_linux.bin', obj, LIBS=['pthread'])
5.编译运行
写mian.c函数
make all 编译
(1)FreeRTOS挂起与恢复
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
//开始任务
#define START_STK_SIZE 128
#define START_TASK_PRIO 1
TaskHandle_t StartTask_Handler ;
void start_task( void * pvParameters );
//Task1任务
#define TASK1_STK_SIZE 128
#define TASK1_TASK_PRIO 4
TaskHandle_t Task1Task_Handler ;
void task1_task( void * pvParameters );
//Task2任务
#define TASK2_STK_SIZE 128
#define TASK2_TASK_PRIO 4
TaskHandle_t Task2Task_Handler ;
void task2_task( void * pvParameters );
//Key任务
#define Key_STK_SIZE 128
#define Key_TASK_PRIO 2
TaskHandle_t KeyTask_Handler ;
void Key_task( void * pvParameters );
int main(void)
{
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
// delay_init(); //延时函数初始化
// uart_init(115200); //初始化串口
// LED_Init(); //初始化LED
//创建开始任务
xTaskCreate( (TaskFunction_t) start_task,
(char * ) "start_task",
(uint32_t) START_STK_SIZE,
(void * ) NULL,
(UBaseType_t) START_TASK_PRIO,
(TaskHandle_t *) &StartTask_Handler );
vTaskStartScheduler(); //开启任务调度
}
void start_task( void * pvParameters )
{
xTaskCreate( (TaskFunction_t) task1_task,
(char * ) "task1_task",
(uint32_t) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t) TASK1_TASK_PRIO,
(TaskHandle_t *) &Task1Task_Handler );
xTaskCreate( (TaskFunction_t) task2_task,
(char * ) "task2_task",
(uint32_t) TASK2_STK_SIZE,
(void * ) NULL,
(UBaseType_t) TASK2_TASK_PRIO,
(TaskHandle_t *) &Task2Task_Handler );
xTaskCreate( (TaskFunction_t) Key_task,
(char * ) "Key_task",
(uint32_t) Key_STK_SIZE,
(void * ) NULL,
(UBaseType_t) Key_TASK_PRIO,
(TaskHandle_t *) &KeyTask_Handler );
vTaskDelete(StartTask_Handler); //删除任务
}
void task1_task( void * pvParameters )
{
char task1_num = 0;
while(1)
{
if(task1_num == 3 )
{
// printf("task1 run %d\r\n",task1_num);
vTaskDelete(Task1Task_Handler);
}
task1_num++;
// LED1= ~LED1;
vTaskDelay(1000);
printf("task1 run %d\r\n",task1_num);
}
}
void task2_task( void * pvParameters )
{
char task2_num = 0;
while(1)
{
task2_num++;
// LED1= ~LED1;
vTaskDelay(1000);
printf("task2 run %d\r\n",task2_num);
}
}
void Key_task( void * pvParameters )
{
char key_num = 0;
while(1)
{
key_num++;
if( key_num == 6)
{
vTaskDelay(100);
vTaskSuspend(Task2Task_Handler);
printf("Task1 is Suspend! \r\n");
}
if( key_num == 9)
{
vTaskDelay(100);
vTaskResume(Task2Task_Handler);
printf("Task1 is Suspend! \r\n");
}
printf("key_num = %d\n",key_num);
vTaskDelay(1000);
}
}
/********************************************************/
/* This is a stub function for FreeRTOS_Kernel */
void vMainQueueSendPassed( void )
{
return;
}
/* This is a stub function for FreeRTOS_Kernel */
void vApplicationIdleHook( void )
{
return;
}
运行结果
Running as PID: 35508
Timer Resolution for Run TimeStats is 100 ticks per second.
key_num = 1
task1 run 1
task2 run 1
key_num = 2
task1 run 2
task2 run 2
key_num = 3
task1 run 3
task2 run 3
key_num = 4
task2 run 4
key_num = 5
task2 run 5
Task2 is Suspend!
key_num = 6
key_num = 7
key_num = 8
task2 run 6
Task2 is Resume!
key_num = 9
task2 run 7
key_num = 10
task2 run 8
key_num = 11
task2 run 9
key_num = 12
task2 run 10
key_num = 13
(2)列表项和任务状态查询
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
//开始任务
#define START_STK_SIZE 128
#define START_TASK_PRIO 1
TaskHandle_t StartTask_Handler ;
void start_task( void * pvParameters );
//Task1任务
#define TASK1_STK_SIZE 128
#define TASK1_TASK_PRIO 4
TaskHandle_t Task1Task_Handler ;
void task1_task( void * pvParameters );
//LIST任务
#define LIST_STK_SIZE 200
#define LIST_TASK_PRIO 2
TaskHandle_t LISTTask_Handler ;
void LIST_task( void * pvParameters );
//QUERY任务
#define QUERY_STK_SIZE 128
#define QUERY_TASK_PRIO 3
TaskHandle_t QUERYTask_Handler ;
void QUERY_task( void * pvParameters );
List_t TestList;
ListItem_t ListItem1;
ListItem_t ListItem2;
ListItem_t ListItem3;
char InfoBuffer[1000];
int main(void)
{
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
// delay_init(); //延时函数初始化
// uart_init(115200); //初始化串口
// LED_Init(); //初始化LED
//创建开始任务
xTaskCreate( (TaskFunction_t) start_task,
(char * ) "start_task",
(uint32_t) START_STK_SIZE,
(void * ) NULL,
(UBaseType_t) START_TASK_PRIO,
(TaskHandle_t *) &StartTask_Handler );
vTaskStartScheduler(); //开启任务调度
}
void start_task( void * pvParameters )
{
xTaskCreate( (TaskFunction_t) task1_task,
(char * ) "task1_task",
(uint32_t) TASK1_STK_SIZE,
(void * ) NULL,
(UBaseType_t) TASK1_TASK_PRIO,
(TaskHandle_t *) &Task1Task_Handler );
//创建QUERY任务
xTaskCreate( (TaskFunction_t) QUERY_task,
(char * ) "QUERY_task",
(uint32_t) QUERY_STK_SIZE,
(void * ) NULL,
(UBaseType_t) QUERY_TASK_PRIO,
(TaskHandle_t *) &QUERYTask_Handler );
//创建LIST任务
xTaskCreate( (TaskFunction_t) LIST_task,
(char * ) "LIST_task",
(uint32_t) LIST_STK_SIZE,
(void * ) NULL,
(UBaseType_t) LIST_TASK_PRIO,
(TaskHandle_t *) &LISTTask_Handler );
vTaskDelete(StartTask_Handler); //删除任务
}
void task1_task( void * pvParameters )
{
char task1_num = 0;
while(1)
{
if(task1_num == 6 )
{
// printf("task1 run %d\r\n",task1_num);
vTaskDelete(Task1Task_Handler);
}
task1_num++;
// LED1= ~LED1;
vTaskDelay(1000);
printf("task1 run %d\r\n",task1_num);
}
}
void QUERY_task( void * pvParameters )
{
UBaseType_t Priority;
TaskStatus_t *TaskStatusArray;
UBaseType_t ArraySize;
uint32_t TotalRunTime;
TaskHandle_t TaskHandle;
Priority = uxTaskPriorityGet(QUERYTask_Handler);
printf("任务优先级:%d \n",(int)Priority);
ArraySize = uxTaskGetNumberOfTasks();
TaskStatusArray = pvPortMalloc(ArraySize*sizeof(TaskStatus_t));
if(TaskStatusArray != NULL)
{
ArraySize = uxTaskGetSystemState( (TaskStatus_t *) TaskStatusArray,
(UBaseType_t) ArraySize,
(uint32_t *) TotalRunTime );
printf("TaskName\t\tTaskPri\t\ttNumber\t\t\r\n");
for(int i=0;i<ArraySize;i++){
printf("%s\t\t%d\t\t%d\t\t\r\n",
TaskStatusArray[i].pcTaskName,
(int)TaskStatusArray[i].uxCurrentPriority,
(int)TaskStatusArray[i].xTaskNumber);
}
}
TaskHandle = xTaskGetHandle("QUERY_task");
printf("TaskHandle is %#x \n",TaskHandle);
printf("TaskHandle is %#x \n",QUERYTask_Handler);
vTaskDelete(QUERYTask_Handler);
while(1)
{
}
}
void LIST_task( void * pvParameters )
{
vListInitialise(&TestList);
vListInitialiseItem(&ListItem1);
vListInitialiseItem(&ListItem2);
vListInitialiseItem(&ListItem3);
ListItem1.xItemValue = 40;
ListItem2.xItemValue = 60;
ListItem3.xItemValue = 50;
printf("---------列表与列表项地址-------- \n");
printf("项目 地址 \n");
printf("TestList %#x \n",(int)&TestList);
printf("TestList->pxIndex %#x \n",(int)TestList.pxIndex);
printf("TestList->xListEnd %#x \n",(int)&TestList.xListEnd);
printf("ListItem1 %#x \n",(int)&(ListItem1));
printf("ListItem2 %#x \n",(int)&(ListItem2));
printf("ListItem3 %#x \n",(int)&(ListItem3));
// 插入列表项ListItem1
vListInsert(&TestList,&ListItem1);
printf("-----------------添加列表项ListTtem1--------------- \n");
printf("项目 地址 \n");
printf("TestList->xlistEnd->pxNext %#x \n",(int)(TestList.xListEnd.pxNext));
printf("ListItem1->pxNext %#x \n",(int)(ListItem1.pxNext));
printf("------------------前后连接分割线--------------------\n");
printf("TestList->xListEnd.pxPrevious %#x \n",(int)(TestList.xListEnd.pxPrevious));
printf("ListItem1->pxPrevious %#x \n",(int)(ListItem1.pxPrevious));
printf("-------------------------结束---------------------- \n");
// 插入列表项ListItem2
vListInsert(&TestList,&ListItem2);
printf("-----------------添加列表项ListTtem2--------------- \n");
printf("项目 地址 \n");
printf("TestList->xlistEnd->pxNext %#x \n",(int)(TestList.xListEnd.pxNext));
printf("ListItem1->pxNext %#x \n",(int)(ListItem1.pxNext));
printf("ListItem2->pxNext %#x \n",(int)(ListItem2.pxNext));
printf("------------------前后连接分割线--------------------\n");
printf("TestList->xListEnd.pxPrevious %#x \n",(int)(TestList.xListEnd.pxPrevious));
printf("ListItem1->pxPrevious %#x \n",(int)(ListItem1.pxPrevious));
printf("ListItem2->pxPrevious %#x \n",(int)(ListItem2.pxPrevious));
printf("-------------------------结束---------------------- \n");
// 插入列表项ListItem3
vListInsert(&TestList,&ListItem3);
printf("-----------------添加列表项ListTtem3--------------- \n");
printf("项目 地址 \n");
printf("TestList->xlistEnd->pxNext %#x \n",(int)(TestList.xListEnd.pxNext));
printf("ListItem1->pxNext %#x \n",(int)(ListItem1.pxNext));
printf("ListItem2->pxNext %#x \n",(int)(ListItem2.pxNext));
printf("ListItem3->pxNext %#x \n",(int)(ListItem3.pxNext));
printf("------------------前后连接分割线--------------------\n");
printf("TestList->xListEnd.pxPrevious %#x \n",(int)(TestList.xListEnd.pxPrevious));
printf("ListItem1->pxPrevious %#x \n",(int)(ListItem1.pxPrevious));
printf("ListItem2->pxPrevious %#x \n",(int)(ListItem2.pxPrevious));
printf("ListItem3->pxPrevious %#x \n",(int)(ListItem3.pxPrevious));
printf("-------------------------结束---------------------- \n");
// 删除列表项ListItem2
uxListRemove(&ListItem2);
printf("-----------------删除列表项ListTtem3--------------- \n");
printf("项目 地址 \n");
printf("TestList->xlistEnd->pxNext %#x \n",(int)(TestList.xListEnd.pxNext));
printf("ListItem1->pxNext %#x \n",(int)(ListItem1.pxNext));
printf("ListItem3->pxNext %#x \n",(int)(ListItem3.pxNext));
printf("------------------前后连接分割线--------------------\n");
printf("TestList->xListEnd.pxPrevious %#x \n",(int)(TestList.xListEnd.pxPrevious));
printf("ListItem1->pxPrevious %#x \n",(int)(ListItem1.pxPrevious));
printf("ListItem3->pxPrevious %#x \n",(int)(ListItem3.pxPrevious));
printf("-------------------------结束---------------------- \n");
// 尾部插曲列表项ListItem2
TestList.pxIndex = TestList.pxIndex->pxNext;
vListInsertEnd(&TestList,&ListItem2);
printf("-----------------删除列表项ListTtem3--------------- \n");
printf("项目 地址 \n");
printf("TestList->xlistEnd->pxNext %#x \n",(int)(TestList.xListEnd.pxNext));
printf("ListItem1->pxNext %#x \n",(int)(ListItem1.pxNext));
printf("ListItem2->pxNext %#x \n",(int)(ListItem2.pxNext));
printf("ListItem3->pxNext %#x \n",(int)(ListItem3.pxNext));
printf("------------------前后连接分割线--------------------\n");
printf("TestList->xListEnd.pxPrevious %#x \n",(int)(TestList.xListEnd.pxPrevious));
printf("ListItem1->pxPrevious %#x \n",(int)(ListItem1.pxPrevious));
printf("ListItem2->pxPrevious %#x \n",(int)(ListItem2.pxPrevious));
printf("ListItem3->pxPrevious %#x \n",(int)(ListItem3.pxPrevious));
printf("-------------------------结束---------------------- \n");
while(1)
{
}
}
/********************************************************/
/* This is a stub function for FreeRTOS_Kernel */
void vMainQueueSendPassed( void )
{
return;
}
/* This is a stub function for FreeRTOS_Kernel */
void vApplicationIdleHook( void )
{
return;
}
运行结果
Running as PID: 35384
Timer Resolution for Run TimeStats is 100 ticks per second.
任务优先级:3
TaskName TaskPri tNumber
QUERY_task 3 4
start_task 1 1
IDLE 0 2
task1_task 4 3
TaskHandle is 0xb8001520
TaskHandle is 0xb8001520
---------列表与列表项地址--------
项目 地址
TestList 0x22b54200
TestList->pxIndex 0x22b54210
TestList->xListEnd 0x22b54210
ListItem1 0x22b54280
ListItem2 0x22b542c0
ListItem3 0x22b54240
-----------------添加列表项ListTtem1---------------
项目 地址
TestList->xlistEnd->pxNext 0x22b54280
ListItem1->pxNext 0x22b54210
------------------前后连接分割线--------------------
TestList->xListEnd.pxPrevious 0x22b54280
ListItem1->pxPrevious 0x22b54210
-------------------------结束----------------------
-----------------添加列表项ListTtem2---------------
项目 地址
TestList->xlistEnd->pxNext 0x22b54280
ListItem1->pxNext 0x22b542c0
ListItem2->pxNext 0x22b54210
------------------前后连接分割线--------------------
TestList->xListEnd.pxPrevious 0x22b542c0
ListItem1->pxPrevious 0x22b54210
ListItem2->pxPrevious 0x22b54280
-------------------------结束----------------------
-----------------添加列表项ListTtem3---------------
项目 地址
TestList->xlistEnd->pxNext 0x22b54280
ListItem1->pxNext 0x22b54240
ListItem2->pxNext 0x22b54210
ListItem3->pxNext 0x22b542c0
------------------前后连接分割线--------------------
TestList->xListEnd.pxPrevious 0x22b542c0
ListItem1->pxPrevious 0x22b54210
ListItem2->pxPrevious 0x22b54240
ListItem3->pxPrevious 0x22b54280
-------------------------结束----------------------
-----------------删除列表项ListTtem3---------------
项目 地址
TestList->xlistEnd->pxNext 0x22b54280
ListItem1->pxNext 0x22b54240
ListItem3->pxNext 0x22b54210
------------------前后连接分割线--------------------
TestList->xListEnd.pxPrevious 0x22b54240
ListItem1->pxPrevious 0x22b54210
ListItem3->pxPrevious 0x22b54280
-------------------------结束----------------------
-----------------删除列表项ListTtem3---------------
项目 地址
TestList->xlistEnd->pxNext 0x22b542c0
ListItem1->pxNext 0x22b54240
ListItem2->pxNext 0x22b54280
ListItem3->pxNext 0x22b54210
------------------前后连接分割线--------------------
TestList->xListEnd.pxPrevious 0x22b54240
ListItem1->pxPrevious 0x22b542c0
ListItem2->pxPrevious 0x22b54210
ListItem3->pxPrevious 0x22b54280
-------------------------结束----------------------
task1 run 1
task1 run 2
task1 run 3
task1 run 4
task1 run 5
task1 run 6