STM32F4基础工程移植FreeRTOS

本篇目标:基于上一篇的基础工程(stm32f4_first_demo)上,移植freertos,建立移植工程(stm32f4_freertos)。

资料准备:


Freertos源文件目录说明

.
├─FreeRTOS                          //只展示了会用到的子文件夹
│  ├─Demo
│  │  └─CORTEX_M4F_STM32F407ZG-SK   //应用示例,会用到文件夹下的FreeRTOSConfig.h文件
│  ├─License
│  └─Source                         //源代码文件夹
│      ├─include                    //头文件
│      └─portable                   //移植相关文件
│          ├─GCC
│          │  └─ARM_CM4F            //在stm32cubeide(gcc)环境下的stm32移植文件
│          ├─MemMang                //内存管理文件
│          └─RVDS
│              └─ARM_CM4F           //在keil环境下的stm32移植文件
└─FreeRTOS-Plus                     //其他freertos应用文件

ps:上述是freertos源文件目录,一些用不到的目录做了一些过滤,主要关注这几个目录文件就可以了:

  • source 文件目录,目录下的 .c 文件为freertos的核心文件。
  • ARM_CM4F 文件夹下是对应各种stm32的移植文件。
  • MemMang 文件夹下是内存管理文件,一般场景都选择 heap_4,具体可以在后面分析的时候看。
  • FreeRTOSConfig.h 用于配置 freertos ,可以在demo工程中copy一个然后结合自己的情况修改。

Freertos源文件移植改动

这部分主要涉及的是 freertos 部分的改动。

  1. 我们创建一个 stm32_port 文件夹专门来存放移植相关的配置文件,这样可以更好的模块化。
    在这里插入图片描述

  2. 复制 MemMang 文件夹到 stm32_port 下,实际用到的是 heap_4.c 文件。

  3. keil环境复制 portable目录下的 RVDS 文件夹到 stm32_port 下;stm32cubeide复制 portable目录下的 GCC 文件夹到 stm32_port 下。

  4. 复制 demo 工程中 CORTEX_M4F_STM32F407ZG-SK 文件夹下的 FreeRTOSConfig.h 到 stm32_port 下。
    在这里插入图片描述
    以上是修改建立直观的移植目录,接下来就是代码修改,修改 FreeRTOSConfig.h 相关配置项:

// 1. ------------------------------------------------------
//源--45行
#ifdef __ICCARM__
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif
// 修改后:增加不同编译环境的配置
#if defined (__ICCARM__) || defined (__CC_ARM) || defined (__GNUC__)
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif

// 2. ------------------------------------------------------
// 源--51、52、64、66行,修改宏定义为0,暂时不需要使用到这些钩子函数
#define configUSE_IDLE_HOOK				0//1
#define configUSE_TICK_HOOK				0//1
#define configCHECK_FOR_STACK_OVERFLOW	0//2
#define configUSE_MALLOC_FAILED_HOOK	0//1

// 3. ------------------------------------------------------
// 源--124行,注释宏定义,该中断函数我们自己实现
//#define xPortSysTickHandler SysTick_Handler

上面是修改的内容,贴一份实际修改后的配置文件:

/*
 * FreeRTOS Kernel V10.3.1
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * 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
 *----------------------------------------------------------*/

/* Ensure stdint is only used by the compiler, and not the assembler. */
#if defined (__ICCARM__) || defined (__CC_ARM) || defined (__GNUC__)
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif

#ifndef USE_OS
#define USE_OS
#endif

#define configUSE_PREEMPTION			1
#define configUSE_IDLE_HOOK				0
#define configUSE_TICK_HOOK				0
#define configCPU_CLOCK_HZ				( SystemCoreClock )
#define configTICK_RATE_HZ				( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES			( 5 )
#define configMINIMAL_STACK_SIZE		( ( unsigned short ) 130 )
#define configTOTAL_HEAP_SIZE			( ( size_t ) ( 75 * 1024 ) )
#define configMAX_TASK_NAME_LEN			( 10 )
#define configUSE_TRACE_FACILITY		1
#define configUSE_16_BIT_TICKS			0
#define configIDLE_SHOULD_YIELD			1
#define configUSE_MUTEXES				1
#define configQUEUE_REGISTRY_SIZE		8
#define configCHECK_FOR_STACK_OVERFLOW	0
#define configUSE_RECURSIVE_MUTEXES		1
#define configUSE_MALLOC_FAILED_HOOK	0
#define configUSE_APPLICATION_TASK_TAG	0
#define configUSE_COUNTING_SEMAPHORES	1
#define configGENERATE_RUN_TIME_STATS	0

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

/* Software timer definitions. */
#define configUSE_TIMERS				1
#define configTIMER_TASK_PRIORITY		( 2 )
#define configTIMER_QUEUE_LENGTH		10
#define configTIMER_TASK_STACK_DEPTH	( configMINIMAL_STACK_SIZE * 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	1
#define INCLUDE_vTaskSuspend			1
#define INCLUDE_vTaskDelayUntil			1
#define INCLUDE_vTaskDelay				1

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
	/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
	#define configPRIO_BITS       		__NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       		4        /* 15 priority levels */
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! 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 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
	
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }	
	
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
// #define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */



stm32f4移植改动

这一部分为涉及到stm32的代码,主要就是我们自己实现的 SysTick_Handler 中断。

  1. 在 stm32_port 文件夹下创建 stm_config.c ,用于涉及 stm32 部分的代码与初始化接口。

  2. 实现 SysTick_Handler 中断函数:

    void SysTick_Handler(void)
    {
        extern void xPortSysTickHandler( void );
        /* USER CODE END SysTick_IRQn 0 */
        #if (INCLUDE_xTaskGetSchedulerState == 1 )
        if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
        {
        #endif /* INCLUDE_xTaskGetSchedulerState */
            xPortSysTickHandler();
        #if (INCLUDE_xTaskGetSchedulerState == 1 )
        }
        #endif /* INCLUDE_xTaskGetSchedulerState */
    }
    

初始化Freertos并搭建应用任务

至上,移植工作已经做完了,但是需要把配置好的 freertos 用起来,所以少不了初始化与应用任务的建立。

  1. 在 stm_config.c 实现以下内容:

    #include "FreeRTOS.h"
    #include "task.h"
    
    static TaskHandle_t xTask_creat;
    
    /**
      * @note   This function is used to creat app task and delect self.
      * @brief  None
      * @param  *p
      * @retval None
      */
    static void creat_task(void *p)
    {
        log_d("%s", __FUNCTION__);
        int cnt = 0;
    
        /* creat app task in this 在这里创建应用任务 */
        taskENTER_CRITICAL();
    
        //user_main(NULL);     //调用自己的应用函数接口
    
        taskEXIT_CRITICAL();
        /* creat app task in this 在这里创建应用任务 */
    
    #if 1
        /* delay task 延时退出,并删除本任务 */
        while(1){
            log_d("this is creat task:idle-%d", cnt++);
            vTaskDelay(1000);
    
            if (cnt >= 10){
                break;
            }
        }
    #endif
    
        log_d("delete creat task");
    
        vTaskDelete(xTask_creat);
    }
    
    /**
      * @note   This function is used to creat app task and delect self.
      * @brief  None
      * @param  *p
      * @retval None
      */
    int rtos_init(void)
    {
        /* stm32 NVIC config */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    
        BaseType_t xReturn = pdPASS;
    
        log_i("Freertos v10.3.1 start ");
    
        /* first creat task in this 创建rtos第一个任务,用于创建其他任务 */
        xReturn = xTaskCreate(  (TaskFunction_t )creat_task,
                                (const char *   )"creat_task",
                                (unsigned short )1024,
                                (void *         )NULL,
                                (UBaseType_t    )1,
                                (TaskHandle_t * )&xTask_creat);
    
        if (pdPASS != xReturn){
            return -1;
        }
    
        /* start task 开启任务调度 */
        vTaskStartScheduler();
    
        return xReturn;
    }
    
  2. 在 main函数中调用封装好的初始化接口 rtos_init 即可。

    //main函数调用示例
    int main(void)
    {
        /* stm32系统配置 */
        Sys_Config();
    
        extern int rtos_init(void);
        rtos_init();
    
        log_e("never get here");
    
        while(1)
        {
        }
    }
    

同样贴上 stm_config.c 的全部代码:

/**
  *****************************************************************************
  * @file    : stm_config.c
  * @author  : Tuu
  * @version : 1.0.0
  * @date    : 2020-04-01
  * @brief   : stm32f407 freertos config file
  ******************************************************************************
  * @lasteditors  : Tuu
  * @lasteditTime : 2020-06-02
  ******************************************************************************
  * @atten   : Copyright (C) by Tuu Inc
  *
  *****************************************************************************
  */

/* Includes -------------------------------------------------------------------*/
#include "config.h"

#include "FreeRTOS.h"
#include "task.h"


/* Defines --------------------------------------------------------------------*/


/* Variables ------------------------------------------------------------------*/
static TaskHandle_t xTask_creat;

/* Functions ------------------------------------------------------------------*/
extern void user_main(void *p);

/**
  * @note   This function is used to creat app task and delect self.
  * @brief  None
  * @param  *p
  * @retval None
  */
static void creat_task(void *p)
{
    log_d("%s", __FUNCTION__);
    int cnt = 0;

    /* creat app task in this 在这里创建应用任务 */
    taskENTER_CRITICAL();

    user_main(NULL);

    taskEXIT_CRITICAL();
    /* creat app task in this 在这里创建应用任务 */

#if 1
    /* delay task 延时退出,并删除本任务 */
    while(1){
        log_d("this is creat task:idle-%d", cnt++);
        vTaskDelay(1000);

        if (cnt >= 10){
            break;
        }
    }
#endif

    log_d("delete creat task");

    vTaskDelete(xTask_creat);
}

/**
  * @note   This function is used to creat app task and delect self.
  * @brief  None
  * @param  *p
  * @retval None
  */
int rtos_init(void)
{
    /* stm32 NVIC config 必须配置成分组4 */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    BaseType_t xReturn = pdPASS;

    log_i("Freertos v10.3.1 start ");

    /* first creat task in this 创建rtos第一个任务,用于创建其他任务 */
    xReturn = xTaskCreate(  (TaskFunction_t )creat_task,
                            (const char *   )"creat_task",
                            (unsigned short )1024,
                            (void *         )NULL,
                            (UBaseType_t    )1,
                            (TaskHandle_t * )&xTask_creat);

    if (pdPASS != xReturn){
        return -1;
    }

    /* start task 开启任务调度 */
    vTaskStartScheduler();

    return xReturn;
}

/* systick */
#if 1
void SysTick_Handler(void)
{
    extern void xPortSysTickHandler( void );
    /* USER CODE END SysTick_IRQn 0 */
    #if (INCLUDE_xTaskGetSchedulerState == 1 )
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
    #endif /* INCLUDE_xTaskGetSchedulerState */
        xPortSysTickHandler();
    #if (INCLUDE_xTaskGetSchedulerState == 1 )
    }
    #endif /* INCLUDE_xTaskGetSchedulerState */
}
#endif


/************************ (C) COPYRIGHT Tuu ********END OF FILE****************/



实际运行

上面基本的移植,初始化 freertos 的工作基本完成了,可以编译烧录运行看一下效果:(可以根据自己的环境打开 stm32f4_freertos 中的工程来运行看看)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


小结

做个小结,移植 freertos 涉及到的几个方面:

  1. 与移植硬件相关的 portable 文件,有能力的同学可以自己编写,像stm32比较大众的有现有的文件,可以直接拿来使用,如上移植。
  2. 内存管理默认情况下都使用 heap_4.c 文件,在特殊多内存管理的时候才会用到 heap_5.c等。
  3. 修改 FreeRTOSConfig.h 的配置,将刚开始不必要的HOOK宏定义去除,只编译基本的功能。
  4. 自己定义 SysTick_Handler 函数,方便后续拓展,以及完成初始化创建任务的代码。

ps:为什么要重新创建一个 stm_config.c 文件?因为将所有有关 freertos 移植的文件以及与硬件相关的代码都放在了 stm32_port 文件夹下,这样后续跨平台移植的时候,修改该文件夹下和硬件相关的内容即可,不需要大动工程与框架,保证后续应用移植开发的方便性。

想要不基于上面的基础工程,移植到自己的 stm32f4 工程当中,只需要将 thirdlib 文件夹下的 FreeRTOSv10.3.1 拷贝到自己的工程中,然后调用初始化 rtos_init 即可。


如有其它移植上面的问题可以问我哦~后续会对移植相关及freertos部分源码进行解析,深入理解才可以更好的运用。

Tuu

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 这个问题中混杂了很多不同的概念。我会分别解释: 1. stm32f4xx: 这是指STMicroelectronics(意法半导体)推出的一款32位微控制器系列,它们应用广泛,有很多种型号。 2. lwIP: 这是指"lightweight IP",它是一个开源的TCP/IP协议栈。它具有轻量级、可移植、可扩展等优点,所以在一些嵌入式系统中得到应用。 3. FreeRTOS: 这是指"Free Real-time Operating System",它是一个开源的实时操作系统。它具有小巧、快速、可移植等优点,以及很多年的实战经验,所以在很多嵌入式系统中得到应用。 4. 移植: 指将特定系统的软件、驱动程序等适应不同系统,开发时多数情况下需要将软件适配到具体系统中。 综上所述, "stm32f4xx lwip freertos移植"意为适配lwIP协议栈和FreeRTOS操作系统到stm32f4xx处理器平台。 ### 回答2: STM32F4xx是属于嵌入式系统中的一种芯片,它具有高性能、低功耗、丰富外设等优点。在进行网络通信时,常常会使用到LWIP协议栈(LightWeight IP),LWIP是一个轻量级的开源TCP/IP协议栈,具有跨平台、高度可移植等特性。而FreeRTOS是一种优秀的实时操作系统,能够支持多任务、多线程、中断处理等功能,因此,将这两者进行移植,实现STM32F4xx芯片的网络通信,特别是TCP/IP通信,将是一个很有挑战的任务。 移植LWIP协议栈需要进行以下步骤: 第一步:根据STM32F4xx芯片的电路板、内存大小、外设特性等环境,进行LWIP协议栈的移植。主要包括系统初始化、网络驱动、网络协议栈、网络接口等方面的内容。 第二步:通过LWIP的API接口,实现协议的配置,包括IP地址、掩码、网关、DNS服务器等,并根据不同的协议类型(如TCP、UDP、ICMP等)进行配置。 第三步:通过FreeRTOS的API接口,将网络协议栈与操作系统进行整合,实现多任务并发处理、中断处理、定时器计数等功能,并保证系统稳定性和实时性。 在进行STM32F4xx lwip freertos移植时,需要注意以下几个方面: 一、内存管理:STM32F4xx芯片的RAM和Flash比较小,需要合理地分配内存,避免资源浪费和系统崩溃。 二、时钟配置:LWIP和FreeRTOS都需要使用操作系统的时钟进行计数和同步。因此,需要把选定的操作系统时钟映射到芯片上的RC/XTAL或内部晶振,保证时钟精度和稳定性。 三、中断处理:由于网络协议栈需要进行中断处理,因此需要注意中断的优先级和中断处理函数的编写。中断处理函数需要精简、高效,不影响系统的实时性和稳定性。 四、网络接口:STM32F4xx芯片支持多种不同的网络接口,在移植中需要根据具体的需求,选择相应的硬件接口进行配置。并根据不同的接口类型,进行网络驱动程序的编写和配置。 总之,STM32F4xx lwip freertos移植并不是一项简单的任务,需要开发者具备深厚的嵌入式开发经验和相关技能。通过合理的规划、持续的优化,可以实现高效稳定的网络通信。 ### 回答3: 随着物联网应用的日益普及,嵌入式系统中使用lwIP和FreeRTOS的需求越来越大。STM32F4系列是一种高性能的嵌入式微控制器,它支持lwIP和FreeRTOS,因此很适合用于物联网领域的开发。这篇文章将介绍STM32F4xx lwip和FreeRTOS移植步骤。 1. 系统架构 在移植前,需要先了解STM32F4xx系列的架构。STM32F4xx系列的主要子系统有: - Cortex-M4内核 - 系统存储器(SRAM)和闪存 - 外设:USART、SPI、I2C、USB、以太网等 - DMA控制器 lwIP是一个轻量级的IP协议组件库,它能够在嵌入式系统中实现TCP/IP协议栈。在STM32F4xx系列中,lwIP和FreeRTOS可以运行在主内存中。为了获得更好的性能,建议采用SRAM作为系统存储器,并为lwIP和FreeRTOS预留足够的内存空间。 2. 移植步骤 2.1. 配置IDE开发环境 移植lwIP和FreeRTOS需要用到IDE工具,比如Keil、IAR和TrueStudio等。在开发过程中,需要配置好编译器、调试器和开发板等相关环境。 2.2. 配置FreeRTOS FreeRTOSSTM32F4xx系列中的线程操作提供支持。在移植过程中,需要设置线程的优先级、任务管理器、内存管理器和时间管理器等。同时,还需要对FreeRTOS进行适当的调优,以获得更好的性能和可靠性。 2.3. 配置lwIP lwIP的移植涉及到网络协议栈,需要对其进行详细的配置。首先要配置网络接口,包括MAC和IP地址、子网掩码、网关和DNS服务器等。然后需要配置协议栈参数,包括缓冲区的大小、超时时间和最大传输单元(MTU)等。最后还需要配置协议栈服务,包括DHCP、NAT、HTTP、FTP和SMTP等。 2.4. 配置硬件平台 在移植过程中,需要配置硬件平台,包括外设控制器、DMA控制器和引脚映射等。在使用网卡时,还需要配置PHY芯片。 3. 移植测试 在完成lwIP和FreeRTOS移植后,需要进行测试以确保其功能正常。测试方法包括: - 使用ping测试网络连接 - 使用telnet实现远程命令 - 使用HTTP服务器进行数据交互 移植过程中可能会遇到各种问题,比如芯片引脚分配不当、外设驱动程序错误、协议栈配置不正确等。为了快速诊断问题,可以使用调试工具(比如JTAG调试器)或日志文件进行调试。 总之,STM32F4xx lwip和FreeRTOS移植并不是一件容易的事,它需要开发人员具备扎实的嵌入式系统和网络编程技能。当然,一旦成功地移植了它们,就可以让设备更好地应用于物联网领域,为用户提供更为方便、高效和安全的服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图图Tuu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值