在上位机上熟悉FreeRTOS API

在上位机上熟悉FreeRTOS API------环境配置

前言

我知道一些朋友初入RTOS的时候,都是直接怼着单片机进行学习的,笔者非常赞同这种方式,毕竟RTOS最后是用在咱们的单片机上的,复杂一些的嵌入式设备甚至可能要使用裁剪后的Linux。不过,将单片机的一些特性跟RTOS的独有的概念混在一起,有时候会有一些累。笔者学习的时候就有感触。

笔者前段时间翻FreeRTOS的官网上,就看到了在上位机模拟API的项目,值得一提的是------它实际上是背靠了Linux System API / Win32 System API的,因此这里模拟的RTOS实在是不Real Time,但是对于新手,熟知什么是任务,内存管理,信号量队列等内容是再合适不过的(我相信大家学C语言都是从上位机开始的)。这就是这篇博客的出发点。

本篇博客的方案是使用CMake来管理我们的项目(至少看着干净),由于是CMake,所以构建就跟平台无关了,不管打算是Windows,WSL还是Linux的某一个发行版(比如说咱们的Ubuntu),都可以直接用起来。

从拿到RTOS的源码开始

Git用起来:

bash 复制代码
git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules

PS:注意要用 --recurse-submodules 拉取内核源码和其它依赖,否则编译会找不到头文件。这就是拉东西要拉全,除非有doc告诉你不用拿。


建立工程结构

随便找一个文件夹,我们的项目是这样的,把搞下来的RTOS源码下的FreeRTOS目录(这个目录下面就有Source等文件夹的)放到我们的项目中:

复制代码
freertos-posix-demo/
├── FreeRTOS/               # 官方源码,这就是纯粹的RTOS库,不要动
├── app/                    # 你自己的 FreeRTOS 代码
│   ├── main.c
│   └── FreeRTOSConfig.h
├── CMakeLists.txt          # 顶层 CMake 构建文件
└── README.md

编写 CMakeLists.txt

这是一个最简版的 CMakeLists.txt ,让你能在 Linux/WSL 上构建;如果是Windows的朋友请参考官方文档自己修改下面的CMake。

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(freertos_posix_demo C)

# 设置 FreeRTOS 源码路径
set(FREERTOS_ROOT "${CMAKE_SOURCE_DIR}/FreeRTOS")

# 包含路径
include_directories(
    ${FREERTOS_ROOT}/Source/include
    ${FREERTOS_ROOT}/Source/portable/ThirdParty/GCC/Posix # Windows的主要改这里
    ${FREERTOS_ROOT}/Source/portable/ThirdParty/GCC/Posix/utils # Windows的主要改这里
    ${CMAKE_SOURCE_DIR}/app
)

# Source 文件列表
file(GLOB FREERTOS_KERNEL_SRCS
    "${FREERTOS_ROOT}/Source/*.c"
)

file(GLOB FREERTOS_PORT_SRCS
    "${FREERTOS_ROOT}/Source/portable/ThirdParty/GCC/Posix/port.c" # Windows的主要改这里
    "${FREERTOS_ROOT}/Source/portable/ThirdParty/GCC/Posix/utils/*.c" # Windows的主要改这里
)

# 应用层代码
file(GLOB APP_SRCS "${CMAKE_SOURCE_DIR}/app/*.c")

add_executable(freertos_demo
    ${FREERTOS_KERNEL_SRCS}
    ${FREERTOS_PORT_SRCS}
    ${APP_SRCS}
)

# pthread 和时间库
target_link_libraries(freertos_demo pthread) # Windows的主要改这里, 我记得好像可以不用加

这个 CMake 列出 FreeRTOS 内核源码、POSIX portable 层和你的应用层。

其中:

  • FreeRTOSConfig.h 放在 app/ 目录下
  • 内核文件从 FreeRTOS 主源码引用
  • 最终生成 freertos_demo 可执行文件

📄FreeRTOSConfig.h

RTOS项目需要FreeRTOSConfig.h才能跑起来,在 app/FreeRTOSConfig.h

c 复制代码
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * 应用相关配置
 *----------------------------------------------------------*/

/* Cortex-M3 内核 */
#define configCPU_CLOCK_HZ            ( ( unsigned long ) 72000000 )

/* RTOS Tick 频率:1ms */
#define configTICK_RATE_HZ            ( ( TickType_t ) 1000 )

/* 最大任务优先级(0 ~ 4) */
#define configMAX_PRIORITIES          ( 5 )

/* 最小任务栈大小(单位:word,不是字节) */
#define configMINIMAL_STACK_SIZE      ( ( uint16_t ) 128 )

/* FreeRTOS 堆大小(字节) */
#define configTOTAL_HEAP_SIZE         ( ( size_t ) ( 10 * 1024 ) )

/* 任务名最大长度 */
#define configMAX_TASK_NAME_LEN       ( 16 )

/* 使用抢占式调度 */
#define configUSE_PREEMPTION          1

/* 使用时间片轮转 */
#define configUSE_TIME_SLICING        1

/* 空闲任务钩子 */
#define configUSE_IDLE_HOOK           0

/* Tick 钩子 */
#define configUSE_TICK_HOOK           0

/* 启用 16 位 Tick(STM32F1 内存吃紧可用 1) */
#define configUSE_16_BIT_TICKS        0

/*-----------------------------------------------------------
 * 同步与通信机制
 *----------------------------------------------------------*/

/* 互斥量(一定要开,教学和实战必用) */
#define configUSE_MUTEXES             1

/* 递归互斥量 */
#define configUSE_RECURSIVE_MUTEXES   1

/* 计数信号量 */
#define configUSE_COUNTING_SEMAPHORES 1

/* 任务通知(强烈推荐,性能最好) */
#define configUSE_TASK_NOTIFICATIONS  1

/* 队列注册(调试用) */
#define configQUEUE_REGISTRY_SIZE     8

/*-----------------------------------------------------------
 * 软件定时器(可选,但建议打开)
 *----------------------------------------------------------*/

#define configUSE_TIMERS              1
#define configTIMER_TASK_PRIORITY     ( 2 )
#define configTIMER_QUEUE_LENGTH      5
#define configTIMER_TASK_STACK_DEPTH  ( 256 )

/*-----------------------------------------------------------
 * 中断相关配置(STM32F103 关键部分)
 *----------------------------------------------------------*/

/* STM32F103 NVIC 优先级位数 */
#define configPRIO_BITS               4

/* 最低中断优先级 */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY     15

/* 允许调用 FreeRTOS API 的最高中断优先级 */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

/* 转换为 Cortex-M 内核可识别格式 */
#define configKERNEL_INTERRUPT_PRIORITY  \
    ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
    ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/*-----------------------------------------------------------
 * 断言
 *----------------------------------------------------------*/
#include <assert.h>

#define configASSERT( x )                                     \
    if( ( x ) == 0 )                                          \
    {                                                         \
        taskDISABLE_INTERRUPTS();                             \
        for( ;; );                                           \
    }

/*-----------------------------------------------------------
 * 调试与统计(教学强烈推荐)
 *----------------------------------------------------------*/

/* 启用运行时间统计 */
#define configGENERATE_RUN_TIME_STATS        1

/* 运行时间计数器配置(需提供实现) */
#define configUSE_TRACE_FACILITY             1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

/*-----------------------------------------------------------
 * API 包含控制(建议全开)
 *----------------------------------------------------------*/

#define INCLUDE_vTaskPrioritySet             1
#define INCLUDE_uxTaskPriorityGet            1
#define INCLUDE_vTaskDelete                  1
#define INCLUDE_vTaskSuspend                 1
#define INCLUDE_vTaskDelay                   1
#define INCLUDE_vTaskDelayUntil              1
#define INCLUDE_xTaskGetSchedulerState       1
#define INCLUDE_xTaskGetCurrentTaskHandle    1
#define INCLUDE_xTaskGetIdleTaskHandle       1
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1

#endif /* FREERTOS_CONFIG_H */

这是一个最基本的配置,你可根据教学需要调整。


示例的 main.c

app/main.c

c 复制代码
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

void Task1(void *pv) {
    for (;;) {
        printf("Task1 running\n");
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

int main(void) {
    xTaskCreate(Task1, "t1", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    vTaskStartScheduler();
    return 0;
}

这个例子每秒打印一次任务信息,用于演示调度器工作。


构建与运行

bash 复制代码
mkdir build && cd build
cmake ..
make
./freertos_demo

运行会输出你任务的打印内容。

OK,这样就搞定了!

相关推荐
Gorgous—l20 小时前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
中屹指纹浏览器20 小时前
中屹指纹浏览器底层架构深度解析——基于虚拟化的全维度指纹仿真与环境隔离实现
经验分享·笔记
Hello_Embed20 小时前
libmodbus 移植 STM32(基础篇)
笔记·stm32·单片机·学习·modbus
无聊的小坏坏21 小时前
实习笔记:用 /etc/crontab 实现定期数据/日志清理
笔记·实习日记
香芋Yu21 小时前
【机器学习教程】第04章 指数族分布
人工智能·笔记·机器学习
●VON21 小时前
Flutter for OpenHarmony 21天训练营 Day03 总结:从学习到输出,迈出原创第一步
学习·flutter·openharmony·布局·技术
香芋Yu21 小时前
【大模型教程——第四部分:大模型应用开发】第1章:提示工程与上下文学习 (Prompt Engineering & ICL)
学习·prompt
LYS_061821 小时前
寒假学习10(HAL库1+模数电10)
学习
runningshark21 小时前
【项目】示波器学习与制作
学习
€8111 天前
Java入门级教程24——Vert.x的学习
java·开发语言·学习·thymeleaf·数据库操作·vert.x的路由处理机制·datadex实战