原创 建立 FreeRTOS 版的 STM32 标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0) 笔记

2013-10-12 15:00 2612 18 19 分类: 消费电子

 

简介:笔记记录了如何建立含 FreeRTOS 的 STM32 标准外设库的过程。

 

相关资源:

1.STM32 标准外设库 V3.5.0 ( 直接下载地址 http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stsw-stm32054.zip )。

2.FreeRTOS V7.5.2 ( 直接下载地址 http://jaist.dl.sourceforge.net/project/freertos/FreeRTOS/V7.5.2/FreeRTOSV7.5.2.zip )。

3.FreeRTOS Real Time Kernel (RTOS) 最新版本下载地址( http://sourceforge.net/projects/freertos/files/ )。

4.STM32F10x standard peripheral library 最新相关信息地址( http://www.st.com/web/cn/catalog/tools/FM147/CL1794/SC961/SS1743/PF257890 )。

 

建立过程:

 

1.解压 FreeRTOS V7.5.2 备用。

 

2.解压 STM32F10x_StdPeriph_Lib_V3.5.0,并重命名文件夹为 STM32F10x_StdPeriph_Lib_V3.5.0_FreeRTOS。

 

3.目录“STM32F10x_StdPeriph_Lib_V3.5.0_FreeRTOS” 下新建“FreeRTOS”文件夹,拷贝“Source(直接copy FreeRTOS源码Source目录)”、“Common(直接copy FreeRTOS源码\demo\Common目录)”到“..\FreeRTOS\”下。

 

4.在“Source/portable”目录下,保留“RVDS”和“MemMang”目录,其余删除。

 

5.复制“FreeRTOSConfig.h  (<FreeRTOS V7.5.2>\Demo\CORTEX_STM32F103_Keil\)”到 “STM32F10x_StdPeriph_Lib_V3.5.0_FreeRTOS\Project\STM32F10x_StdPeriph_Template”下。并删除无用的文件夹,只保留“MDK-ARM”文件夹。

 

6.修改启动文件。进入“STM32F10x_StdPeriph_Lib_V3.5.0_FreeRTOS\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\”,参照 FreeRTOS 中的 STM32F10x.s 修改各startup 文件(注意:修改前需去掉文件只读属性,修改后恢复只读)。

 

在 __heap_limit 区段添加:

IMPORT xPortPendSVHandler

IMPORT xPortSysTickHandler

IMPORT vPortSVCHandler

;IMPORT vUARTInterruptHandler

;IMPORT vTimer2IntHandler

后两个不要添加,因为这不是 FreeRTOS 核心代码,是他demo用到的。

 

__Vectors区段中断向量表,将SVCall Handler、PendSV_Handler、SysTick Handler更名,改由 RTOS 管理,这样 stm32f10x_it.c 就不会影响到这三个中断。后面相应的中断入口地址需要更改

DCD     vPortSVCHandler           ; SVCall Handler

...

DCD     xPortPendSVHandler        ; PendSV Handler

DCD     xPortSysTickHandler       ; SysTick Handler

两者还有一点小小的不同,复位时进入main函数之前的那段代码,新版本外设库的启动代码中,在进入main()函数之前执行函数SystemInit()初始化了时钟,这个根据目标板不同,注意此段代码。

 

7. “STM32F10x_StdPeriph_Lib_V3.5.0_FreeRTOS\Project\STM32F10x_StdPeriph_Template\MDK-ARM” 下打开工程文件。参照 FreeRTOS 例程在 STM32 的外设库例程中加入 FreeRTOS 组,并加入文件: tasks.c、list.c、queue.c、port.c、heap_2.c。

 

8. 在 MDK-ARM 中依次选择各Project Target进行设置:

Target options -> C/C++ 中 Preprocessor Symbols 中 Include path 设定头文件路径:

加入:

..\..\..\FreeRTOS\Source\include

..\..\..\FreeRTOS\Source\portable\RVDS\ARM_CM3

..\..\..\FreeRTOS\Common\include

 

9. 至此,设定完成,修改 main.c 文件,内容如下。需根据使用的开发板修改相关外设设置。因为 FreeRTOS 使用 configTOTAL_HEAP_SIZE 为 0x4400,IRAM的 SIZE 需超过 0x4400(17K),所以选择STM32要注意RAM大小是否满足。

/* main.c */

/* Standard includes. */

#include <stdio.h>

 

/* Scheduler includes. */

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"

#include "misc.h"

 

 

/* Library includes. */

#include "stm32f10x_it.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_gpio.h"

#include "stm32f10x_usart.h"

 

#define LED0_ON()   GPIO_ResetBits(GPIOA,GPIO_Pin_8);

#define LED0_OFF()  GPIO_SetBits(GPIOA,GPIO_Pin_8);

#define LED0B()     GPIOA->ODR ^= 0x0100;

 

#define LED1_ON()   GPIO_ResetBits(GPIOD,GPIO_Pin_2);

#define LED1_OFF()  GPIO_SetBits(GPIOD,GPIO_Pin_2);

#define LED1B()     GPIOD->ODR ^= 0x04;

 

static void prvSetupHardware( void );

 

/* Two demo Tasks*/      

static void vLEDTask( void *pvParameters );

static void vCOMMTask( void *pvParameters );

 

void Led_Init(void);

void Comm_Init(void);

 

int main( void )

{

    prvSetupHardware();

 

    xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL );

    xTaskCreate( vCOMMTask, ( signed portCHAR * ) "COMM", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+2, NULL );

 

    /* Start the scheduler. */

    vTaskStartScheduler();

       

    return 0;

}

/*-----------------------------------------------------------*/

 

void vLEDTask( void *pvParameters )

{

    Led_Init();

    LED0_ON();

    LED1_OFF()

 

    for( ;; )

    {

 

        LED0B();  

        LED1B();

        vTaskDelay( 100 / portTICK_RATE_MS);

    }

}

 

void vCOMMTask( void *pvParameters )

{

    Comm_Init();

    for(;;)

    {

        USART_SendData(USART1, '@');

        vTaskDelay(1000 / portTICK_RATE_MS);

    }

}

/*-----------------------------------------------------------*/

 

static void prvSetupHardware( void )

{

    SystemInit();

}

/*-----------------------------------------------------------*/

 

void Led_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

   

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE );

 

    /*LED0 @ PA8*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init( GPIOA, &GPIO_InitStructure );   

 

    /*LED0 @ PD2*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init( GPIOD, &GPIO_InitStructure );   

 

}

 

void Comm_Init(void)

{

    USART_InitTypeDef USART_InitStructure;

    GPIO_InitTypeDef GPIO_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 

 

    /*UART1 TX @ PA9*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init( GPIOA, &GPIO_InitStructure );  

    

    /*UART1 RX @ PA10*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init( GPIOA, &GPIO_InitStructure );  

   

    /*UART1 Cfg.*/

    USART_InitStructure.USART_BaudRate = 57600; 

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    USART_InitStructure.USART_StopBits = USART_StopBits_1;

    USART_InitStructure.USART_Parity = USART_Parity_No; 

    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_Init(USART1, &USART_InitStructure);

    USART_ClearFlag(USART1, USART_FLAG_TC);

 

    /*UART1 NIVC Cfg.*/

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

 

    USART_Cmd(USART1, ENABLE);

}

 

10. 编译通过后,“FreeRTOS 版的 STM32 标准外设库(STM32F10x_StdPeriph_Lib_V3.5.0) ”完成。压缩、打包、备份。之后可以像使用标准库内“STM32F10x_StdPeriph_Template”一样使用此模板建立使用的FreeRTOS新项目。不必每次重新移植和修改FreeRTOS相关文件。

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户849986 2014-4-14 16:08

优质饮水机、榨汁机等小家方案开发与设计

用户849986 2014-3-17 14:57

饮水机、榨汁机方案

用户1649053 2013-10-19 11:05

路过看看
相关推荐阅读
用户1715188 2013-10-14 09:46
Doxygen 用法举例
  Doxygen 用法举例 在C++程序中写注释,把注释自动生成文档的工具 doxygen 是很有用的,它可以使你不用同时维护程序注释和文档, 自然地把你的文档和程序保持一致...
用户1715188 2013-10-10 00:42
Keil MDK-ARM 下基于 STM32 标准外设库 V3.5.0 的 FreeRTOS 移植笔记
  移植过程基于 STM32 标准外设库,在库内提供的例程基础上,将 FreeRTOS 移植进去。     相关资源:   1.STM32 标准外设库 V3.5.0 ( 直...
用户1715188 2013-10-09 16:11
Keil MDK-ARM 和 IAR EWARM 的选择
最近又要开始编程了,所以忙里偷闲,再一次了解了一下开发平台的发展情况,看看是不是要换个新平台尝个鲜,也就引出了如题的一个选择题。   近几天,主要针对 Keil MDK-ARM 和 IAR...
EE直播间
更多
我要评论
1
18
关闭 站长推荐上一条 /3 下一条