抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

手动移植FreeRTOS

stm32cubemx内置了freertos,如果不想手动移植,可以参考这个视频:

https://www.bilibili.com/video/BV1To4UeVEHA/

但手动移植可以加深自己的理解,可以参考下面这个视频:
https://www.bilibili.com/video/BV1vUpje9Ej2?p=11

以下内容是手动移植的过程记录

使用stm32cubemx创建裸机项目

注意:在SYS设置timebase source时(即HAL_Delay的时钟源),不能使用SysTick,因为SysTick被FreeRTOS使用了,可以使用其他的(如TIM1、TIM2……)

另外,假设使用了TIM1作为timebase source,记得修改其优先级为较高或最高,比如0或1

Systick的优先级由FreeRTOS设置,我们不用管

移植FreeRTOS

主要包含以下几个步骤:

  1. 下载FreeRTOS

    (我这里选择了9.0.0版本)

  2. 将必要的源码复制到自己的裸机项目中,包括

    • 内核源码(位于FreeRTOS\Source)
    • port代码(位于FreeRTOS\Source\portable)
    • 内存管理代码(位于FreeRTOS\Source\portable\MemMang)
    • FreeRTOSConfig.h头文件(从Demo中寻找适合自己开发板的)
  3. 修改 FreeRTOSConfig.h 文件

  4. 修改 stm32f1xx_it.c文件

接下来依次介绍

第一步,下载,本项目下载的是V9.0.0版本

第二步,在裸机项目目录中新建文件夹FreeRTOS,然后把下面的文件都复制过去
image-20240922200302641

进入【复制的portable文件夹】内,保留2个文件夹,一个是MemMang文件夹,另一个根据自己的编译工具选择,如果是gcc则保留GCC,如果是keil则保留RVDS(注意Keil的移植代码放到RVDS里了),本项目使用GCC编译,所以保留了GCC和MenMang文件夹,其他的都删除了
image-20240922201041846

再进入GCC文件夹内,选择适合自己开发板芯片的部分保留,其他都删除,比如本项目用的是STM32f103,是ARM_Cortex3架构的,所以保留ARM_CM3

然后MemMang文件夹内把heap_4.c保留,其他都删除

最后,还有一个FreeRTOSConfig.h头文件,FreeRTOS内置了很多代码示例,在Demo文件夹内,适配了很多不同的芯片,选择适合自己芯片的示例,进去后找到FreeRTOSConfig.h头文件并把它复制到自己的项目中,我这里是复制到了Core/Inc文件夹下

第三步,修改 FreeRTOSConfig.h 文件

主要是下面2个地方
image-20240922201844776

image-20240922201945892

关于FreeRTOSConfig.h可以从官方文档了解:定制 - FreeRTOS™

修改后的FreeRTOSConfig.h完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
All rights reserved

VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

This file is part of the FreeRTOS distribution.

FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.

***************************************************************************
>>! NOTE: The modification to the GPL is included to allow you to !<<
>>! distribute a combined work that includes FreeRTOS without being !<<
>>! obliged to provide the source code for proprietary components !<<
>>! outside of the FreeRTOS kernel. !<<
***************************************************************************

FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. Full license text is available on the following
link: http://www.freertos.org/a00114.html

***************************************************************************
* *
* FreeRTOS provides completely free yet professionally developed, *
* robust, strictly quality controlled, supported, and cross *
* platform software that is more than just the market leader, it *
* is the industry's de facto standard. *
* *
* Help yourself get started quickly while simultaneously helping *
* to support the FreeRTOS project by purchasing a FreeRTOS *
* tutorial book, reference manual, or both: *
* http://www.FreeRTOS.org/Documentation *
* *
***************************************************************************

http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
the FAQ page "My application does not run, what could be wrong?". Have you
defined configASSERT()?

http://www.FreeRTOS.org/support - In return for receiving this top quality
embedded software for free we request you assist our global community by
participating in the support forum.

http://www.FreeRTOS.org/training - Investing in training allows your team to
be as productive as possible as early as possible. Now you can receive
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
Ltd, and the world's leading authority on the world's leading RTOS.

http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
compatible FAT file system, and our tiny thread aware UDP/IP stack.

http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.

http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
licenses offer ticketed support, indemnification and commercial middleware.

http://www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
mission critical applications that require provable dependability.

1 tab == 4 spaces!
*/

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/* Library includes. */
// #include "stm"

/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/

#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 4 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1

/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
(lowest) to 0 (1?) (highest). */
#define configKERNEL_INTERRUPT_PRIORITY 255
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xb0, or priority 11. */


/* This is the value being used as per the ST library which permits 16
priority values, 0 to 15. This must correspond to the
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
NVIC value of 255. */
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15


#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
#define INCLUDE_xTaskGetSchedulerState 1

#endif /* FREERTOS_CONFIG_H */


第四步,修改 stm32f1xx_it.c文件

首先找到PendSV_Handler和SVC_Handler这2个函数并注释掉(这两函数由FreeRTOS帮我们写好了),然后找到SysTick函数,修改为如下:

1
2
3
4
5
6
7
void SysTick_Handler(void)
{
if (xTaskGetSchedulerState != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}

创建自己的task

在项目根目录下新建application文件夹,添加led.h和led.c这2个文件,内容分别如下:

led.h

1
2
3
4
5
6
#ifndef LED_H__
#define LED_H__

void task_led(void *argument);

#endif

led.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "led.h"
#include "main.h"
#include "stm32f1xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"

void task_led(void *argument){
// taskENTER_CRITICAL(); 进入临界区的代码会被保护(不会被打断)
while(1){
HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_RESET);
vTaskDelay(pdMS_TO_TICKS(500)); // 500ms

HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
vTaskDelay(pdMS_TO_TICKS(500));
}
}

main.c的main函数如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// include ...
#include "FreeRTOS.h" // 必须在include "task" 前面
#include "task.h"
#include "led.h"

int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();

// 创建任务
xTaskCreate(task_led, "ledTask", 128, NULL, 2, NULL);

// 启动任务调度器,调度器自己会管理要运行哪个任务
// 启动rtos调度器后将不会退出了
vTaskStartScheduler();
}

cmakelists修改

  1. 通过 target_sources 添加.c源码文件,主要是FreeRTOS的代码和自己创建的代码文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # Add sources to executable
    file(GLOB src_rtos FreeRTOS/*.c)
    target_sources(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user sources here
    ${src_rtos}
    FreeRTOS/portable/MemMang/heap_4.c
    FreeRTOS/portable/GCC/ARM_CM3/port.c
    application/led.c
    )
  2. 通过 target_include_directories.h 头文件所在目录添加进来,主要是FreeRTOS的头文件和自己创建的头文件

    1
    2
    3
    4
    5
    6
    7
    8
    # Add include paths
    target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
    # Add user defined include paths
    FreeRTOS/include
    FreeRTOS/portable/GCC/ARM_CM3
    application

    )
  3. 生成hex文件

    1
    2
    3
    4
    add_custom_command(
    TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex "${CMAKE_PROJECT_NAME}.elf" "${CMAKE_PROJECT_NAME}.hex"
    )

完整cmakelists.txt如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
cmake_minimum_required(VERSION 3.22)

#
# This file is generated only once,
# and is not re-generated if converter is called multiple times.
#
# User is free to modify the file as much as necessary
#

# Setup compiler settings
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)


# Define the build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()

# Set the project name
set(CMAKE_PROJECT_NAME 1_rtos_led2)

# Include toolchain file
include("cmake/gcc-arm-none-eabi.cmake")

# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)

# Enable CMake support for ASM and C languages
enable_language(C ASM)

# Core project settings
project(${CMAKE_PROJECT_NAME})
message("Build type: " ${CMAKE_BUILD_TYPE})

# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME})

# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)

# Link directories setup
target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined library search paths
)

# Add sources to executable
file(GLOB src_rtos FreeRTOS/*.c)
# aux_source_directory(src_rtos FreeRTOS)
message(${src_rtos})
target_sources(${CMAKE_PROJECT_NAME} PRIVATE
# Add user sources here
${src_rtos}
FreeRTOS/portable/MemMang/heap_4.c
FreeRTOS/portable/GCC/ARM_CM3/port.c
application/led.c
)

# Add include paths
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined include paths
FreeRTOS/include
FreeRTOS/portable/GCC/ARM_CM3
application

)

# Add project symbols (macros)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
# Add user defined symbols
)

# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx

# Add user defined libraries
)

add_custom_command(
TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex "${CMAKE_PROJECT_NAME}.elf" "${CMAKE_PROJECT_NAME}.hex"
)

这样就完成了,可以进行编译了。

image-20240922212320683

完整项目下载

https://gitcode.net/m0_46079750/stm32_freertos_led

评论