tag 标签: 标准外设库

相关博文
  • 热度 19
    2013-10-12 15:00
    2613 次阅读|
    1 个评论
      简介:笔记记录了如何建立含 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相关文件。
  • 热度 21
    2013-10-10 00:42
    5367 次阅读|
    0 个评论
      移植过程基于 STM32 标准外设库,在库内提供的例程基础上,将 FreeRTOS 移植进去。     相关资源:   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 )。     移植过程:   以下以 STM32F103VCT6 为例进行移植,其他型号类似。   解压 FreeRTOS,打开关于 STM32F103 的例程(Keil版本),目录“..\FreeRTOSV7.5.2\FreeRTOS\Demo\CORTEX_STM32F103_Keil”。   解压 STM32 标准外设库,进入工程模板目录“..\STM32F10x_StdPeriph_Lib_V3.5.0\Project”,复制“STM32F10x_StdPeriph_Template”并根据项目重命名。进入目录“..\STM32F10x_StdPeriph_Lib_V3.5.0\Project\ProjectRoot\MDK-ARM” 下打开工程文件,对应STM32F103VCT6,选择“STM3210E-EVAL”。   目录“..\STM32F10x_StdPeriph_Lib_V3.5.0\Project\ProjectRoot\” (以下用..\ProjectRoot\表示)下新建“FreeRTOS”文件夹,拷贝Source(直接copy FreeRTOS源码Source目录)、Common(直接copy FreeRTOS源码\demo\Common目录)到”..\ProjectRoot\FreeRTOS\”下。   在Source/portable目录下,保留RVDS和MemMang目录,其余删除。复制 FreeRTOS目录\Demo\CORTEX_STM32F103_Keil\FreeRTOSConfig.h 到 ..\ProjectRoot\ 下。   在 MDK-ARM 中进行设置: Target options -Device中,选择STM32F103VC。 Target options - C/C++ 中 Preprocessor Symbols 中 Include path 设定头文件路径: ..\ ..\..\..\Libraries\CMSIS\CM3\CoreSupport ..\..\..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x ..\..\..\Libraries\STM32F10x_StdPeriph_Driver\inc ..\..\..\Utilities\STM32_EVAL ..\..\..\Utilities\STM32_EVAL\Common ..\..\..\Utilities\STM32_EVAL\STM3210E_EVAL ..\FreeRTOS\Source\include ..\FreeRTOS\Source\portable\RVDS\ARM_CM3 ..\FreeRTOS\Common\include   复制 Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_hd.s 至 ..\ProjectRoot\ 。若使用其他容量器件,请自行选择对应的startup files。   参照 FreeRTOS 中的 STM32F10x.s 修改startup_stm32f10x_hd.s 在 __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()初始化了时钟,这个根据目标板不同,注意此段代码。   使用修改后的 startup_stm32f10x_hd.s 替换MDK-ARM组下的同名文件。参照 FreeRTOS 例程在 STM32 的外设库例程中加入 FreeRTOS 组,并加入文件: tasks.c、list.c、queue.c、port.c、heap_2.c,截图如下。     至此,设定完成,修改 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); }