STM32F103C8T6移植FreeRTOS

Step1: FreeRTOS的获取

官网资源地址: FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

下载完成后,解压后,可以得到以下文件目录列表:

 

各文件解释:

 

 FreeRTOS文件一览:

Demo文件夹 :就是FreeRTOS一些演示工程,包括各个平台的demo例程,其中后面移植需要的FreeRTOSConfig.h文件就可以到相应平台的demo例程中找到。
License文件夹 :相关许可信息。
Source文件夹 :FreeRTOS源代码,需要重点关注。

 

 portable文件夹里面的东西就是连接软件层面的FreeRTOS操作系统和硬件层面的芯片的桥梁。打开portable文件夹后,可以看到FreeRTOS针对不同的芯片架构和不同编译器提供了不同的移植文件。

 

主要关注以上三个文件夹,其中Keil文件夹是一个套娃式文件夹,直接转到了RVDS。主要就是提供了这些内核芯片的移植文件。需要注意的是:STM32F103C8T6要移植的就是ARM_CM3。

MemMang文件夹是FreeRTOS提供的内存管理文件。

暂时不做深入讨论,直接移植heap_4.c

Step2: STM32F103C8T6 + Keil + FreeRTOS的配置

1.在平时常规的例程中挑选一个简单的,这里挑选了一个Example_WS2812B的例程。在这个例程的文件夹里新建一个FreeRTOS的文件夹。

 2.将FreeRTOS的源代码添加到这个新建的文件夹中。

 值得一提的是,由于Portable文件中,我们只需要特定的文件,所以只保留以下几个文件夹。

3.打开例程,添加文件分组。

STARTUP文件组不用更改。(其中的文件具体参考stm32f103c8t6新建一个工程一节)

CMSIS文件组需要检查是否已经添加了stm32f10x.h和stm32f10x.c。(其中的文件具体参考stm32f103c8t6新建一个工程一节)

FWLIB文件组不用更改。(其中的文件具体参考stm32f103c8t6新建一个工程一节)

USER文件组不用更改。(其中的文件具体参考stm32f103c8t6新建一个工程一节)

新建FreeRTOS_CORE文件组。文件组添加的文件为FreeRTOS文件下一级目录的.c文件。

新建FreeRTOS_PORTABLE文件组。文件组添加的文件为ARM_CM3内核文件夹下的port.c文件以及内存管理文件heap_4.c。

4.打开魔法棒,添加编译路径。

6.然后直接编译工程师,基本上都会提示缺失一个”FreeRTOSConfig.h“文件。然后就可以到上述所说的demo文件夹中找到对应平台文件夹内的”FreeRTOSConfig.h“文件。我们copy以下这个文件。

将”FreeRTOSConfig.h“文件放到FreeRTOS文件夹里的include文件夹中。

7.修改工程配置。

修改堆栈大小:

修改中断函数名:将以下三个中断函数注释掉。

增加FreeRTOS中断

至此,所有的移植工作都可以完成啦。下面是例程源码展示。

#include <stm32f10x.h>
#include "stdio.h"
#include "stdlib.h"
#include "WS2812B.h"
#include "FreeRTOS.h"
#include "task.h"             //必须添加这个头文件,否则任务创建等函数会报错

//LED_GREEN PB14
#define LED_GREEN_GPIO_CLK    RCC_APB2Periph_GPIOB
#define LED_GREEN_PORT        GPIOB
#define LED_GREEN_PIN         GPIO_Pin_14
#define LED_GREEN_ON          GPIO_ResetBits(LED_GREEN_PORT, LED_GREEN_PIN);
#define LED_GREEN_OFF         GPIO_SetBits(LED_GREEN_PORT, LED_GREEN_PIN);

//LED_RED  PB15
#define LED_RED_GPIO_CLK      RCC_APB2Periph_GPIOB
#define LED_RED_PORT          GPIOB
#define LED_RED_PIN           GPIO_Pin_15
#define LED_RED_ON            GPIO_ResetBits(LED_RED_PORT, LED_RED_PIN);
#define LED_RED_OFF           GPIO_SetBits(LED_RED_PORT, LED_RED_PIN);

#define START_TASK_PRIO    1
#define START_STK_SIZE     128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);

#define LED_GREEN_TASK_PRIO    2
#define LED_GREEN_STK_SIZE     50
TaskHandle_t LedGreenTask_Handler;
void led_green_task(void *pvParameters);

#define LED_RED_TASK_PRIO      3
#define LED_RED_STK_SIZE       50
TaskHandle_t LedRedTask_Handler;
void led_red_task(void *pvParameters);

#define WS2812B_TASK_PRIO      4
#define WS2812B_STK_SIZE       128
TaskHandle_t Ws2812bTask_Handler;
void ws2812b_task(void *pvParameters);


void LEDS_GPIO_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(LED_GREEN_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = LED_GREEN_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
    GPIO_Init(LED_GREEN_PORT, &GPIO_InitStructure);

    RCC_APB2PeriphClockCmd(LED_RED_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = LED_RED_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
    GPIO_Init(LED_RED_PORT, &GPIO_InitStructure);
    
    LED_GREEN_OFF;
    LED_RED_OFF;
}

/*常规配置:将一些下载调试口配置为普通IO口*/
void OS_INIT_Configuration(void)                   
{
    
      PWR->CR |= 1<<8; 
      RCC->BDCR &= 0XFFFFFFFE; 
      BKP->CR &= 0XFFFFFFFE;
      PWR->CR &= 0XFFFFFEFF;
    
      GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
      DBGMCU->CR &= 0XFFFFFFDF;
}



int main(void)
{
    OS_INIT_Configuration();     //这里需要特别注意,自己设置的RCC()也就是时钟配置要注释掉,否则会和FreeRTOS的时钟设置冲突
    LEDS_GPIO_INIT();
    WS2812B_GPIO_INIT();
    
    xTaskCreate((TaskFunction_t )start_task,            
              (const char*    )"start_task",          
              (uint16_t       )START_STK_SIZE,        
              (void*          )NULL,                  
              (UBaseType_t    )START_TASK_PRIO,       
              (TaskHandle_t*  )&StartTask_Handler);   
    
  vTaskStartScheduler();                        
}

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();    
    
    xTaskCreate((TaskFunction_t )led_green_task,            
              (const char*    )"led_green_task",          
              (uint16_t       )LED_GREEN_STK_SIZE,        
              (void*          )NULL,                  
              (UBaseType_t    )LED_GREEN_TASK_PRIO,       
              (TaskHandle_t*  )&LedGreenTask_Handler);


    xTaskCreate((TaskFunction_t )led_red_task,            
              (const char*    )"led_red_task",          
              (uint16_t       )LED_RED_STK_SIZE,        
              (void*          )NULL,                  
              (UBaseType_t    )LED_RED_TASK_PRIO,       
              (TaskHandle_t*  )&LedRedTask_Handler);     
                            
    xTaskCreate((TaskFunction_t )ws2812b_task,            
              (const char*    )"ws2812b_task",          
              (uint16_t       )WS2812B_STK_SIZE,        
              (void*          )NULL,                  
              (UBaseType_t    )WS2812B_TASK_PRIO,       
              (TaskHandle_t*  )&Ws2812bTask_Handler);     
                            
  vTaskDelete(StartTask_Handler);    
                            
    taskEXIT_CRITICAL();
}


unsigned char led_green_on_flag = 0;
unsigned char led_red_on_flag = 0;
unsigned char ws2812b_on_flag = 0;

void led_green_task(void *pvParameters)
{
    while(1)
    {
        if(led_green_on_flag)
        {
             LED_GREEN_ON;
        }else
        {
             LED_GREEN_OFF;
        }
        
        led_green_on_flag = ~led_green_on_flag;
        vTaskDelay(500);
    }
}

void led_red_task(void *pvParameters)
{
    while(1)
    {
        if(led_red_on_flag)
        {
             LED_RED_ON;
        }else
        {
             LED_RED_OFF;
        }
        
        led_red_on_flag = ~led_red_on_flag;
        vTaskDelay(500);
    }
}

unsigned char red_num = 0;
unsigned char green_num = 0;
unsigned char blue_num = 0;
void ws2812b_task(void *pvParameters)
{
    while(1)
    {
        if(ws2812b_on_flag)
        {
             red_num   = rand() % 255;
             green_num = rand() % 255;
             blue_num  = rand() % 255;
            
             ws2812b_write_rgb(red_num, green_num, blue_num);
        }else
        {
             ws2812b_write_rgb(0, 0, 0);
        }
        
        ws2812b_on_flag = ~ws2812b_on_flag;
        
        vTaskDelay(500);
    }
}

 

软件调试注意点:

Note1:#include "task.h"                   //必须添加这个头文件,否则任务创建等函数会报错

Note2:OS_INIT_Configuration();     //这里需要特别注意,自己设置的RCC()也就是时钟配置要注释掉,否则会和FreeRTOS的时钟设置冲突

Note3:vTaskDelay(500); 每个任务函数需要有这种可以正常进行系统任务切换的功能函数(如系统延时函数等),否则操作系统无法正常运行。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-08 22:02:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-08 22:02:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-08 22:02:02       82 阅读
  4. Python语言-面向对象

    2023-12-08 22:02:02       91 阅读

热门阅读

  1. 命令模式-C++实现

    2023-12-08 22:02:02       47 阅读
  2. 不同进程共享变量

    2023-12-08 22:02:02       56 阅读
  3. IntelliJ IDEA安装使用教程#intellij idea

    2023-12-08 22:02:02       62 阅读
  4. GO设计模式——12、外观模式(结构型)

    2023-12-08 22:02:02       65 阅读