前言
在实际的项目开发过程中,我一直使用的都是用RTOS系统重构的一套pthread的接口,且对源码知之甚少,只知道如何去使用,而不太懂它内部运行的逻辑。为此在这开启一个新的系列,在对FreeRTOS原生接口的使用和梳理的基础上,去解读它的源码,并试着使用一些调试工具和手动,对RTOS内核进行剖析。
本文使用的调试环境是Ubuntu:4.15.0-143-generic,Freertos:v202212,采用SecureCRT工具远程连接的linux环境。
FreeRTOS编译环境构建
下载链接如下:
FreeRTOS的目录结构如下:
├── FreeRTOS
│ ├── Demo #官方示例代码
│ ├── License
│ ├── README.md
│ ├── Source #源码
│ ├── Test
│ └── links_to_doc_pages_for_the_demo_projects.url
├── FreeRTOS-Plus
├── GitHub-FreeRTOS-Home.url
├── History.txt
├── Quick_Start_Guide.url
└── tools
├── aws_config_offline
├── aws_config_quick_start
├── cmock
└── uncrustify.cfg
在FreeRTOS\Demo目录下有很多模拟器环境,我主要使用Linux环境下的模拟器,其处于FreeRTOS\Demo\Posix_GCC 目录下。
[root&user:]~/FreeRtos/Demo/Posix_GCC$ tree
├── code_coverage_additions.c
├── console.c
├── console.h
├── FreeRTOSConfig.h
├── FreeRTOS-simulator-for-Linux.url #FreeRTOS官网使用说明
├── main_blinky.c
├── main.c
├── main_full.c
├── Makefile #Demo编译脚本
├── Readme.md #模拟器编译与调试环境说明
├── run-time-stats-utils.c
├── Trace_Recorder_Configuration
│ ├── trcConfig.h
│ ├── trcKernelPortConfig.h
│ ├── trcKernelPortSnapshotConfig.h
│ └── trcSnapshotConfig.h
├── trcConfig.h
└── trcKernelPortConfig.h
FreeRTOS Demo的编译与运行
Readme.md中详细介绍了Demo的编译与调试方法,其中对编译需要的环境包括(最小要求):
### gprof
Version as tested: GNU gprof (GNU Binutils) 2.36
### make
Version as tested: GNU Make 3.82
### gcc
Version as tested: gcc (GCC) 11.0.0
Demo的编译与运行方法如下:
#清除编译缓存
[root&user:]~/FreeRtos/Demo/Posix_GCC$ make clean
rm -rf ./build
#指定编译工具为GCC,并执行编译
[root&user:]~/FreeRtos/Demo/Posix_GCC$ make CC=gcc
mkdir -p build
gcc -I. -I./Trace_Recorder_Configuration -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS/Source/include -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS/Source/portable/ThirdParty/GCC/Posix -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS/Demo/Common/include -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/Include -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/config -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/include -I/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS-Plus/Source/FreeRTOS-Plus-Trace/streamports/File/config -DBUILD_DIR=\"/data1/fangqixiang/work/rtos/FreeRTOSv202212.01/FreeRTOS/Demo/Posix_GCC/build\" -D_WINDOWS_ -DTRACE_ON_ENTER=0 -DprojCOVERAGE_TEST=0 -ggdb3 -O3 -MMD -c main.c -o build/main.o
...
#编译成功后生成的文件存放在build目录中
#执行可执行文件
#在命令的末尾加上字符 &。这样做可以将任务放到后台执行,而不会阻塞当前的终端会话
[root&user:]~/FreeRtos/Demo/Posix_GCC$ ./build/posix_demo &
[1] 54546
解读MakeFile文件
在FreeRTOS\Demo\Posix_GCC目录下存在Makefile文件用于编译FreeRTOS Demo,后面也会在此基础上进行增加和修改。本次主要关注Makefile中依赖的源码文件都要哪些,如下图所示,主要包括FreeRTOS\Source、FreeRTOS\portable\ThirdParty\GCC\Posix和FreeRTOS\Demo\Common,其中heap使用的是heap_3.c,后面也会进行调整。
FREERTOS_DIR_REL := ../../../FreeRTOS
FREERTOS_DIR := $(abspath $(FREERTOS_DIR_REL))
KERNEL_DIR := ${FREERTOS_DIR}/Source
... #此处省略
INCLUDE_DIRS += -I${KERNEL_DIR}/include
INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix
INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/utils
INCLUDE_DIRS += -I${FREERTOS_DIR}/Demo/Common/include
... #此处省略
SOURCE_FILES := $(wildcard *.c)
SOURCE_FILES += $(wildcard ${FREERTOS_DIR}/Source/*.c)
#任务栈管理,采用heap_3(use malloc() / free() )
SOURCE_FILES += ${KERNEL_DIR}/portable/MemMang/heap_3.c
# posix库依赖
SOURCE_FILES += ${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c
SOURCE_FILES += ${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/port.c
# Demo library.
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/AbortDelay.c
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/BlockQ.c
SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/blocktim.c
... #此处省略