FreeRTOS 第一课:移植

1. 前言

    最近发现个买板子的好地方,咸鱼,阿里巴巴旗下的二手交易平台,经过再三考虑,在平台上花费了75元买了个红牛开发版,买它主要看中的是板上带nandflash、norflash、sdram,性价比很高,令我意想不到的是卖主貌似没怎么用过板子,拿到手之后外观新的不行,并且板子上外扩的 io 口排针都没焊上,心里别说有多高兴了,感觉像是捡到钱了似的,哎,最近手里有点拮据,加上了每月一还的房贷,感觉身体被掏空了。

    买个板子来移植 FreeRTOS,这个想法在内心酝酿了很久,最开始的想法来源于上一个公司买来的网络转串口的小板子,在小板子上,我看到了stm32 的某款芯片和一个网络芯片就实现了我认为只有移植个操作系统,最不行也要个linux才能实现功能,让我百思不得其解,限于当时的水平,如今看来,其实只是移植个 lwip 就能实现网络 Tcp/Ip 的功能,后来看到了免费的 FreeRTOS ,在这免费盛行的当下,我想看看这个小的实时系统是如何实现的,废话不多说,正题开始


2.资源简介

【1】stm32f103zet6:

144引脚,512k flash,64k ram,板上外扩512K SRAM,2M NORFLASH,128M nandflash


【2】STM32 使用固件库,版本是3.5.0

【3】FreeRTOS 使用的版本是9.0.0


3. 移植

移植前先来确定整个目录的结构,考虑到固件库和FreeRTOS 的源码不会改动,而其中会有 gpio、i2c、spi、串口等的程序,结构定为如下的结构

最外层只有 3 个文件夹:STM32F10x_StdPeriph_Lib_V3.5.0、PROJ、FreeRTOS9.0.0。

从名字上可以看出分别放置 STM32F10X 的固件库、用户工程和 FreeRTOS 的源码,

(1)STM32F10x_StdPeriph_Lib_V3.5.0 文件夹中有 3 个文件,还是看一下的树状图图吧:

FreeRTOS_for_stm32f103/

├── FreeRTOS9.0.0

├── PROJ

│   └── gpio

│       └── usr

│           ├── main.c

│           ├── stm32f10x_conf.h

│           ├── stm32f10x_it.c

│           └── stm32f10x_it.h

└── STM32F10x_StdPeriph_Lib_V3.5.0

    ├── CMSIS

    │   ├── core_cm3.c

    │   ├── core_cm3.h

    │   ├── startup_stm32f10x_hd.s

    │   ├── stm32f10x.h

    │   ├── system_stm32f10x.c

    │   └── system_stm32f10x.h

    ├── inc

    │   ├── misc.h

    │   ├── stm32f10x_i2c.h

        ......这里省去了其他的大部分文件

    │   └── stm32f10x_wwdg.h

    └── src

        ├── misc.c

        ......这里省去了其他的大部分文件

        ├── stm32f10x_i2c.c

        └── stm32f10x_wwdg.c

inc 和 src 文件夹的内容完全是库见库源码下边的 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver 下边的相同名字的文件夹和里边的所有内容

CMSSIS 中的内容是源码库中的路径 STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS 下的 

CoreSupport 文件夹下的

DeviceSupport 文件夹下的

固件库的启动文件,我们的芯片对应这里边的是高密度的


将以下的内容放到自己工程目录下的 PROJ 目录下的 gpio 下的 usr 下


(2)FreeRTOS 目录构建

源码目录下有两个文件:FreeRTOS、FreeRTOS-Plus,FreeRTOS 是 FreeRTOS 的源码,FreeRTOS-Plus 中是提供的工具,比如有个 CLI,是命令行,在命令行中我们可以输入命令来查看FreeRTOS系统在运行的时候查看 stack 的使用情况

将以下图中内容拷贝到 FreeRTOS 目录中


我们来看看 portable 中哪些文件是需要的

common 我们暂时不要,

IAR目录下的 ARM_CM3 文件夹下有3个文件:port.c、portasm.s、portmacro.h,其中有个 .h 文件,我们为了保持统一,放到 FreeRTOS9.0.0 源码目录下的include 中,其他的两个放到 portable 下的

MemMang目录的整个文件放到 portable 下。这个文件中主要是堆栈的分配。

添加FreeRTOS 的配置文件:拷贝 FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_IAR 下的 FreeRTOSConfig.h 文件拷贝到 PROJ/gpio/usr 下


至此,工程文件夹的目录 构建完成了,接下来是 


(3) iar 下工程文件构建和添加

新建一个 空工程,存到 PROG/gpio 文件夹下

添加后的目录如下:

STM32F10x_StdPeriph_Lib_V3.5.0 目录下的 src 并没有展开,里边的全部内容添加进来,这里需要注意的是只添加 .c 和 .s 文件,不添加 .h 头文件


配置工程中 .c 文件中的搜索头文件的路径:

四个路径是:

D:\stm32f103_wor\FreeRTOS_for_stm32f103\STM32F10x_StdPeriph_Lib_V3.5.0\CMSIS

D:\stm32f103_wor\FreeRTOS_for_stm32f103\STM32F10x_StdPeriph_Lib_V3.5.0\inc

D:\stm32f103_wor\FreeRTOS_for_stm32f103\PROJ\gpio\usr

D:\stm32f103_wor\FreeRTOS_for_stm32f103\FreeRTOS9.0.0\include


定义两个全局的宏:

USE_STDPERIPH_DRIVER

STM32F10X_HD


如果你对 iar for arm 不是很熟,可以查看 iar for arm 第一课


配置 开发板

去掉老的CMSIS 头文件选用iar 默认新的头文件库

 STM32F10x_StdPeriph_Lib_V3.5.0\CMSIS 路径下的 core_cm3.h 改成 core_cm3.h.bat 即 将这个 .h 文件去掉,

将 main.c 中的内容改成:

#include "misc.h"

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#define LED_D1_ON() GPIO_ResetBits(GPIOF, GPIO_Pin_6)
#define LED_D1_OFF() GPIO_SetBits(GPIOF, GPIO_Pin_6)

#define LED_D3_ON() GPIO_ResetBits(GPIOF, GPIO_Pin_8)
#define LED_D3_OFF() GPIO_SetBits(GPIOF, GPIO_Pin_8)

static void LED_Init(void);
static void LED_D1_Task(void *pvParameters);
static void LED_D3_Task(void *pvParameters);


int main(void)
{
    LED_Init(); // 初始化 LED 引脚
   
    xTaskCreate(LED_D1_Task, "LED_D1", 1000, NULL, tskIDLE_PRIORITY + 3, NULL);
    xTaskCreate(LED_D3_Task, "LED_D3", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, NULL); 
  
    /* 启动调度器 */
    vTaskStartScheduler(); 
    while (1);

    return 0;
}

void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); // 使能 GPIOF 的时钟	

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOF, &GPIO_InitStructure);

    LED_D1_ON();
    LED_D3_ON();
}

void LED_D1_Task(void *pvParameters)
{
    while ( 1 )
    {
        LED_D1_ON();
        vTaskDelay(500 / portTICK_RATE_MS);
        LED_D1_OFF();
        vTaskDelay(500 / portTICK_RATE_MS);        
    }
}

void LED_D3_Task(void *pvParameters)
{
    while(1)
    {
        LED_D3_ON();
        vTaskDelay(500 / portTICK_RATE_MS);
        LED_D3_OFF();
        vTaskDelay(500 / portTICK_RATE_MS);        
    }
}


更改固件库中启动文件的中断向量的入口,设置成 FreeRTOS 的 portasm.s 中定义的入口:

然后就可以 make 了:


出现如下错误:

Error[2]: Failed to open #include file 'FreeRTOSConfig.h' D:\stm32f103_wor\FreeRTOS_for_stm32f103\FreeRTOS9.0.0\portable\portasm.s 70 


双击,发现时 portasm.s 文件中的头文件找不到,我们配置汇编语言的头文件查找的路径:

路径添加为 D:\stm32f103_wor\FreeRTOS_for_stm32f103\PROJ\gpio\usr 不要自己写,右边的 .. 按钮选择


再次 make , 0 个错误,通过。。。


选择调试方式,我手上有个 ST-LINK,选中,下载进去,查看运行情况

覆盖 flash 的配置文件:


【1】这个选项如果不勾选上,当你擦除了整个 flash 芯片后,如果没有勾选上这个选项时,会出现 stack pointer 指向 0xFFFF 地址

【2】当你多次更改堆栈和中断向量函数和地址,多次编译,在线调试,发现并不是自己想要的时候,选上这个选项应该作为一个尝试

下载到板子上看到 2 个灯 每隔半秒同时闪烁一次。


多说一部分:

在下载到板子的时候,你可能会想在什么地方下载到板子中的 flash 中呢?尤其是在板子上有外扩的 norflash、nandflash的时候。

这个设置还是在工程中的 Option 选项中:


此部分的值,经过查找 芯片手册中的 地址映射部分 可以得到:



4. 生成文件的大小


  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值