STM32F4X UCOSIII移植
什么是uCOSIII
在刚学习MCU的时候,我们接触到基本上都是些简单的程序,通常所有的业务逻辑都是在main函数里面完成。但是随着后续程序越来越复杂,就会发现把所有的业务逻辑都放在一个main里面执行就会显得效率特别低,这时候就需要RTOS的帮忙了。RTOS又叫实时操作系统,大家听到操作系统可能会觉得都像Windows、Linux那些操作系统,都特别复杂,其实不然。RTOS是专门运行在MCU上的操作系统,其特点是实时性,其内核一般都不会很复杂,而且占用的资源都很少。常用的RTOS有uCOS、FreeRTOS、RTThread等。本章就以STM32F4X为平台,移植uCOSIII操作系统。
STM32F4X 移植UCOSIII
UCOSIII源代码下载
在进行UCOSIII移植前,我们首先要下载UCOSIII的源代码。UCOSIII的源代码可以去Micrium的官网下载,网址是https://www.silabs.com/developers/micrium,按照以下步骤下载
因为官网下载很慢,而且还要注册账号,很麻烦,所以下面给出了UCOSIII的源代码下载链接,大家也可以进行下载
链接:https://pan.baidu.com/s/1iP4F5xO8eacWW5QpY2hboA
提取码:38qq
UCOSIII源代码目录结构
首先我们打开UCOSIII 3.04->Micrium->Software
- EvalBoards:MCU板型目录,里面有不同MCU的UCOSIII例程。
- uC-CPU:MCU架构目录,里面放了不同架构CPU的代码
- uC-LIB:UCOSIII的程序库
- uCOS-III:UCOSIII内核代码
工程移植
首先我们先拿一个能够在STM32F4X平台上能运行的工程作为模板,然后才开始移植UCOSIII。我就拿了一个串口的例程作为模板。
添加UCOSIII源码到工程
工程添加UCOSIII代码组
我们需要在工程中添加3个组,分别是uC-CPU(存放跟MCU架构相关的代码),uC-LIB(存放UCOSIII的程序库)和uCOSIII(uCOSIII内核代码)。
添加uC-CPU代码
进入UCOSIII的源码目录UCOSIII 3.04->Micrium->Software->uC-CPU里面,可以看到有以下文件。
因为STM32F4X是Crotex-M4架构,所以我们还要进到ARM-Cortex-M4里面。可以看到UCOSIII的开发者给不同的编译器都编写不同风格的架构代码。
- GNU:GCC编译器的选这个
- IAR:IAR编译器选这个
- RealView:MDK编译器选这个
因为作者用的是MDK编译器,所以选的是RealView。
我们把UCOSIII 3.04->Micrium->Software->uC-CPU下面的3个文件添加到工程中的uC-CPU里面,接着把UCOSIII 3.04->Micrium->Software->uC-CPU->ARM-Cortex-M4\RealView里面的文件也添加到uC-CPU里面
添加uC-LIB代码
进入UCOSIII的源码目录UCOSIII 3.04->Micrium->Software->uC-LIB里面,可以看到有以下文件。这些都是UCOSIII通用的库文件,其中Ports目录下存放是跟CPU架构相关的代码。
我们把UCOSIII 3.04->Micrium->Software->uC-LIB下面的所有文件添加到工程中的uC-LIB里面,接着把UCOSIII 3.04->Micrium->Software->uC-LIB->Ports->ARM-Cortex-M4->RealView里面的文件也添加到uC-LIB里面
添加uCOSIII代码
进入UCOSIII的源码目录UCOSIII 3.04->Micrium->Software->uCOS-III里面,可以看到有以下文件。这些都是UCOSIII的内核代码,其中Ports目录下存放是跟CPU架构相关的代码,Source目录下存放是通用的内核代码
我们把UCOSIII 3.04->Micrium->Software->uCOS-III->Source下面的所有文件添加到工程中的uCOSIII里面,接着把UCOSIII 3.04->Micrium->Software->uCOS-III->Ports->ARM-Cortex-M4->Generic->RealView里面的文件也添加到uCOSIII里面
添加UCOSIII系统时钟
RTOS工作的时候都需要根据一定的时间进行任务的调度,所以在移植RTOS时我们都需要给RTOS一个心跳时钟,简单来说就是给RTOS一个定时器,在定时器里面做任务的调度。因为Crotex-M的架构都会自带一个systick的系统定时器,所以就选择systick作为uCOSIII的系统时钟。
我们先打开startup_stm32f40_41xxx.s文件,找到PendSV_Handler和SysTick_Handler这两个函数,把它们替换成uCOSIII自带的函数。
OS_CPU_PendSVHandler:任务调度函数,汇编语言编写
OS_CPU_SysTickHandler:uCOSIII心跳函数
添加uCOSIII配置文件和初始化文件
因为uCOSIII是可以裁剪的RTOS,所以我们还需要添加uCOSIIII的配置文件。我们打开UCOSIII 3.04->Micrium->Software->EvalBoards->ST->STM32F429II-SK->uCOS-III目录,把以下文件添加到工程
进入UCOSIII 3.04->Micrium->Software->EvalBoards->ST\STM32F429II-SK->BSP,添加bsp.c和bsp.h板级初始化代码。
修改uCOSIII配置文件和初始化文件
添加完配置文件和初始化文件后,我们需要根据不同的开发板和不同芯片进行修改,使其可以成功编译并运行,一般需要做这几步
- 初始化系统时钟,返回系统时钟频率给uCOSIII
- 初始化RTOS的系统心跳时钟
- 初始化开发板外设
- 编译运行
bsp.c
/*
*********************************************************************************************************
* MICIRUM BOARD SUPPORT PACKAGE
*
* (c) Copyright 2013; Micrium, Inc.; Weston, FL
*
* All rights reserved. Protected by international copyright laws.
* Knowledge of the source code may NOT be used to develop a similar product.
* Please help us continue to provide the Embedded community with the finest
* software available. Your honesty is greatly appreciated.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* BOARD SUPPORT PACKAGE (BSP)
*
* IAR Development Kits
* on the
*
* STM32F429II-SK KICKSTART KIT
*
* Filename : bsp.c
* Version : V1.00
* Programmer(s) : FF
* YS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define BSP_MODULE
#include <bsp.h>
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* REGISTERS
*********************************************************************************************************
*/
#define BSP_REG_DEM_CR (*(CPU_REG32 *)0xE000EDFC)
#define BSP_REG_DWT_CR (*(CPU_REG32 *)0xE0001000)
#define BSP_REG_DWT_CYCCNT (*(CPU_REG32 *)0xE0001004)
#define BSP_REG_DBGMCU_CR (*(CPU_REG32 *)0xE0042004)
/* - RCC REGISTER DEFINES - */
#define BSP_REG_RCC_BASE_ADDR ((CPU_INT32U)(0x40023800))
#define BSP_REG32_RCC_CR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x00u ))
#define BSP_REG32_RCC_PLLCFGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x04u ))
#define BSP_REG32_RCC_CFGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x08u ))
#define BSP_REG32_RCC_CIR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x0Cu ))
#define BSP_REG32_RCC_AHB1RSTR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x10u ))
#define BSP_REG32_RCC_AHB2RSTR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x14u ))
#define BSP_REG32_RCC_AHB3RSTR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x18u ))
#define BSP_REG32_RCC_APB1RSTR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x20u ))
#define BSP_REG32_RCC_APB2RSTR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x24u ))
#define BSP_REG32_RCC_AHB1ENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x30u ))
#define BSP_REG32_RCC_AHB2ENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x34u ))
#define BSP_REG32_RCC_AHB3ENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x38u ))
#define BSP_REG32_RCC_APB1ENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x40u ))
#define BSP_REG32_RCC_APB2ENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x44u ))
#define BSP_REG32_RCC_AHB1LPENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x50u ))
#define BSP_REG32_RCC_AHB2LPENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x54u ))
#define BSP_REG32_RCC_AHB3LPENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x58u ))
#define BSP_REG32_RCC_APB1LPENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x60u ))
#define BSP_REG32_RCC_APB2LPENR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x64u ))
#define BSP_REG32_RCC_BDCR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x70u ))
#define BSP_REG32_RCC_CSR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x74u ))
#define BSP_REG32_RCC_SSCGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x80u ))
#define BSP_REG32_RCC_PLLI2SCFGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x84u ))
#define BSP_REG32_RCC_PLLSAICFGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x88u ))
#define BSP_REG32_RCC_DCKCFGR (*(CPU_REG32 *)( BSP_REG_RCC_BASE_ADDR + 0x8Cu ))
/* - FLASH REGISTER DEFINES - */
#define BSP_REG_FLASH_BASE_ADDR (( CPU_INT32U )(0x40023C00))
#define BSP_REG32_FLASH_ACR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x00u ))
#define BSP_REG32_FLASH_KEYR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x04u ))
#define BSP_REG32_FLASH_OPTKEYR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x08u ))
#define BSP_REG32_FLASH_SR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x0Cu ))
#define BSP_REG32_FLASH_CR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x10u ))
#define BSP_REG32_FLASH_OPTCR (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x14u ))
#define BSP_REG32_FLASH_OPTCR1 (*(CPU_REG32 *)( BSP_REG_FLASH_BASE_ADDR + 0x18u ))
/*
*********************************************************************************************************
* REGISTER BITS
*********************************************************************************************************
*/
#define BSP_DBGMCU_CR_TRACE_IOEN_MASK 0x10u
#define BSP_DBGMCU_CR_TRACE_MODE_ASYNC 0x00u
#define BSP_DBGMCU_CR_TRACE_MODE_SYNC_01 0x40u
#define BSP_DBGMCU_CR_TRACE_MODE_SYNC_02 0x80u
#define BSP_DBGMCU_CR_TRACE_MODE_SYNC_04 0xC0u
#define BSP_DBGMCU_CR_TRACE_MODE_MASK 0xC0u
#define BSP_BIT_DEM_CR_TRCENA DEF_BIT_24
#define BSP_BIT_DWT_CR_CYCCNTENA DEF_BIT_00
/* - RCC BLOCK - */
#define HSE_TIMEOUT_VAL 0x0500u
#define BSP_MSK_HSECFG 0x00FF0000u
#define BSP_BIT_RCC_CR_HSION DEF_BIT_00
#define BSP_BIT_RCC_CR_HSEBYP DEF_BIT_18
#define BSP_BIT_RCC_CR_HSEON DEF_BIT_16
#define BSP_BIT_RCC_CR_HSERDY DEF_BIT_17
#define BSP_MSK_RCC_CFGR_HPRE 0x000000F0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV1 0x00000000u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV2 0x00000080u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV4 0x00000090u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV8 0x000000A0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV16 0x000000B0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV64 0x000000C0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV128 0x000000D0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV256 0x000000E0u
#define BSP_MSK_RCC_CFGR_SYSCLKDIV512 0x000000F0u
#define BSP_MSK_RCC_CFGR_PPRE1 0x00001C00u
#define BSP_MSK_RCC_CFGR_PPRE2 0x0000E000u
#define BSP_MSK_RCC_CFGR_HCLK_DIV1 0x00000000u
#define BSP_MSK_RCC_CFGR_HCLK_DIV2 0x00001000u
#define BSP_MSK_RCC_CFGR_HCLK_DIV4 0x00001400u
#define BSP_MSK_RCC_CFGR_HCLK_DIV8 0x00001800u
#define BSP_MSK_RCC_CFGR_HCLK_DIV16 0x00001C00u
#define BSP_MSK_RCC_CFGR_SWS_HSI 0x00000000u
#define BSP_MSK_RCC_CFGR_SWS_HSE 0x00000004u
#define BSP_MSK_RCC_CFGR_SWS_PLL 0x00000008u
#define BSP_MSK_RCC_CFGR_SWS 0x0000000Cu
#define BSP_MSK_RCC_CFGR_SW_HSI 0x00000000u
#define BSP_MSK_RCC_CFGR_SW_HSE 0x00000001u
#define BSP_MSK_RCC_CFGR_SW_PLL 0x00000002u
#define BSP_MSK_RCC_CFGR_SW 0x00000003u
/* - PLL BLOCK - */
#define BSP_BIT_RCC_PLLCFGR_PLLM 8u
#define BSP_BIT_RCC_PLLCFGR_PLLN 336u
#define BSP_BIT_RCC_PLLCFGR_PLLP 2u
#define BSP_BIT_RCC_PLLCFGR_PLLQ 7u
#define BSP_BIT_RCC_CR_PLLON DEF_BIT_24
#define BSP_BIT_RCC_CR_PLLRDY DEF_BIT_25
#define BSP_MSK_RCC_PLLCFGR_PLLSRC_HSE 0x00400000u
#define BSP_MSK_RCC_PLLCFGR_RST 0x24003010u
#define BSP_MSK_SYSCLK_SRC_PLLCLK 0x00000002u
#define BSP_MSK_PLLCFGR_PLLSRC_HSE 0x00400000u
#define BSP_MSK_PLLCFGR_PLLSRC_HSI 0x00000000u
/* - FLASH BLOCK - */
#define BSP_BIT_FLASH_ACR_PRFTEN DEF_BIT_08
#define BSP_BIT_FLASH_ACR_ICEN DEF_BIT_09
#define BSP_BIT_FLASH_ACR_DCEN DEF_BIT_10
#define BSP_MSK_FLASHLATENCY_0WS 0x00000000u
#define BSP_MSK_FLASHLATENCY_1WS 0x00000001u
#define BSP_MSK_FLASHLATENCY_2WS 0x00000002u
#define BSP_MSK_FLASHLATENCY_3WS 0x00000003u
#define BSP_MSK_FLASHLATENCY_4WS 0x00000004u
#define BSP_MSK_FLASHLATENCY_5WS 0x00000005u
#define BSP_MSK_FLASHLATENCY_6WS 0x00000006u
#define BSP_MSK_FLASHLATENCY_7WS 0x00000007u
#define BSP_MSK_FLASHLATENCY_8WS 0x00000008u
#define BSP_MSK_FLASHLATENCY_9WS 0x00000009u
#define BSP_MSK_FLASHLATENCY_10WS 0x0000000Au
#define BSP_MSK_FLASHLATENCY_11WS 0x0000000Bu
#define BSP_MSK_FLASHLATENCY_12WS 0x0000000Cu
#define BSP_MSK_FLASHLATENCY_13WS 0x0000000Du
#define BSP_MSK_FLASHLATENCY_14WS 0x0000000Eu
#define BSP_MSK_FLASHLATENCY_15WS 0x0000000Fu
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* BSP_Init()
*
* Description : Initialize the Board Support Package (BSP).
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : (1) This function SHOULD be called before any other BSP function is called.
*
* (2) CPU instruction / data tracing requires the use of the following pins :
* (a) (1) Asynchronous : PB[3]
* (2) Synchronous 1-bit : PE[3:2]
* (3) Synchronous 2-bit : PE[4:2]
* (4) Synchronous 4-bit : PE[6:2]
*
* (c) The application may wish to adjust the trace bus width depending on I/O
* requirements.
*********************************************************************************************************
*/
void BSP_Init (void)
{
NVIC_PriorityGroupConfig(2); // 中断优先级分组
bsp_usart_init(115200); // 初始化串口
}
/*
*********************************************************************************************************
* BSP_CPU_ClkFreq()
*
* Description : Read CPU registers to determine the CPU clock frequency of the chip.
*
* Argument(s) : none.
*
* Return(s) : The CPU clock frequency, in Hz.
*
* Caller(s) : Application.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U BSP_CPU_ClkFreq (void)
{
RCC_ClocksTypeDef rcc_clocks;
RCC_GetClocksFreq(&rcc_clocks);
return ((CPU_INT32U)rcc_clocks.HCLK_Frequency);
}
/*$PAGE*/
/*
*********************************************************************************************************
* CPU_TS_TmrInit()
*
* Description : Initialize & start CPU timestamp timer.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : CPU_TS_Init().
*
* This function is an INTERNAL CPU module function & MUST be implemented by application/
* BSP function(s) [see Note #1] but MUST NOT be called by application function(s).
*
* Note(s) : (1) CPU_TS_TmrInit() is an application/BSP function that MUST be defined by the developer
* if either of the following CPU features is enabled :
*
* (a) CPU timestamps
* (b) CPU interrupts disabled time measurements
*
* See 'cpu_cfg.h CPU TIMESTAMP CONFIGURATION Note #1'
* & 'cpu_cfg.h CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION Note #1a'.
*
* (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR'
* data type.
*
* (1) If timer has more bits, truncate timer values' higher-order bits greater
* than the configured 'CPU_TS_TMR' timestamp timer data type word size.
*
* (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR'
* timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be
* configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
*
* In other words, if timer size is not a binary-multiple of 8-bit octets
* (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple
* octet word size SHOULD be configured (e.g. to 16-bits). However, the
* minimum supported word size for CPU timestamp timers is 8-bits.
*
* See also 'cpu_cfg.h CPU TIMESTAMP CONFIGURATION Note #2'
* & 'cpu_core.h CPU TIMESTAMP DATA TYPES Note #1'.
*
* (b) Timer SHOULD be an 'up' counter whose values increase with each time count.
*
* (c) When applicable, timer period SHOULD be less than the typical measured time
* but MUST be less than the maximum measured time; otherwise, timer resolution
* inadequate to measure desired times.
*
* See also 'CPU_TS_TmrRd() Note #2'.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void CPU_TS_TmrInit (void)
{
CPU_INT32U fclk_freq;
fclk_freq = BSP_CPU_ClkFreq();
BSP_REG_DEM_CR |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA; /* Enable Cortex-M4's DWT CYCCNT reg. */
BSP_REG_DWT_CYCCNT = (CPU_INT32U)0u;
BSP_REG_DWT_CR |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;
CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CPU_TS_TmrRd()
*
* Description : Get current CPU timestamp timer count value.
*
* Argument(s) : none.
*
* Return(s) : Timestamp timer count (see Notes #2a & #2b).
*
* Caller(s) : CPU_TS_Init(),
* CPU_TS_Get32(),
* CPU_TS_Get64(),
* CPU_IntDisMeasStart(),
* CPU_IntDisMeasStop().
*
* This function is an INTERNAL CPU module function & MUST be implemented by application/
* BSP function(s) [see Note #1] but SHOULD NOT be called by application function(s).
*
* Note(s) : (1) CPU_TS_TmrRd() is an application/BSP function that MUST be defined by the developer
* if either of the following CPU features is enabled :
*
* (a) CPU timestamps
* (b) CPU interrupts disabled time measurements
*
* See 'cpu_cfg.h CPU TIMESTAMP CONFIGURATION Note #1'
* & 'cpu_cfg.h CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION Note #1a'.
*
* (2) (a) Timer count values MUST be returned via word-size-configurable 'CPU_TS_TMR'
* data type.
*
* (1) If timer has more bits, truncate timer values' higher-order bits greater
* than the configured 'CPU_TS_TMR' timestamp timer data type word size.
*
* (2) Since the timer MUST NOT have less bits than the configured 'CPU_TS_TMR'
* timestamp timer data type word size; 'CPU_CFG_TS_TMR_SIZE' MUST be
* configured so that ALL bits in 'CPU_TS_TMR' data type are significant.
*
* In other words, if timer size is not a binary-multiple of 8-bit octets
* (e.g. 20-bits or even 24-bits), then the next lower, binary-multiple
* octet word size SHOULD be configured (e.g. to 16-bits). However, the
* minimum supported word size for CPU timestamp timers is 8-bits.
*
* See also 'cpu_cfg.h CPU TIMESTAMP CONFIGURATION Note #2'
* & 'cpu_core.h CPU TIMESTAMP DATA TYPES Note #1'.
*
* (b) Timer SHOULD be an 'up' counter whose values increase with each time count.
*
* (1) If timer is a 'down' counter whose values decrease with each time count,
* then the returned timer value MUST be ones-complemented.
*
* (c) (1) When applicable, the amount of time measured by CPU timestamps is
* calculated by either of the following equations :
*
* (A) Time measured = Number timer counts * Timer period
*
* where
*
* Number timer counts Number of timer counts measured
* Timer period Timer's period in some units of
* (fractional) seconds
* Time measured Amount of time measured, in same
* units of (fractional) seconds
* as the Timer period
*
* Number timer counts
* (B) Time measured = ---------------------
* Timer frequency
*
* where
*
* Number timer counts Number of timer counts measured
* Timer frequency Timer's frequency in some units
* of counts per second
* Time measured Amount of time measured, in seconds
*
* (2) Timer period SHOULD be less than the typical measured time but MUST be less
* than the maximum measured time; otherwise, timer resolution inadequate to
* measure desired times.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR CPU_TS_TmrRd (void)
{
CPU_TS_TMR ts_tmr_cnts;
ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;
return (ts_tmr_cnts);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* CPU_TSxx_to_uSec()
*
* Description : Convert a 32-/64-bit CPU timestamp from timer counts to microseconds.
*
* Argument(s) : ts_cnts CPU timestamp (in timestamp timer counts [see Note #2aA]).
*
* Return(s) : Converted CPU timestamp (in microseconds [see Note #2aD]).
*
* Caller(s) : Application.
*
* This function is an (optional) CPU module application programming interface (API)
* function which MAY be implemented by application/BSP function(s) [see Note #1] &
* MAY be called by application function(s).
*
* Note(s) : (1) CPU_TS32_to_uSec()/CPU_TS64_to_uSec() are application/BSP functions that MAY be
* optionally defined by the developer when either of the following CPU features is
* enabled :
*
* (a) CPU timestamps
* (b) CPU interrupts disabled time measurements
*
* See 'cpu_cfg.h CPU TIMESTAMP CONFIGURATION Note #1'
* & 'cpu_cfg.h CPU INTERRUPTS DISABLED TIME MEASUREMENT CONFIGURATION Note #1a'.
*
* (2) (a) The amount of time measured by CPU timestamps is calculated by either of
* the following equations :
*
* 10^6 microseconds
* (1) Time measured = Number timer counts * ------------------- * Timer period
* 1 second
*
* Number timer counts 10^6 microseconds
* (2) Time measured = --------------------- * -------------------
* Timer frequency 1 second
*
* where
*
* (A) Number timer counts Number of timer counts measured
* (B) Timer frequency Timer's frequency in some units
* of counts per second
* (C) Timer period Timer's period in some units of
* (fractional) seconds
* (D) Time measured Amount of time measured,
* in microseconds
*
* (b) Timer period SHOULD be less than the typical measured time but MUST be less
* than the maximum measured time; otherwise, timer resolution inadequate to
* measure desired times.
*
* (c) Specific implementations may convert any number of CPU_TS32 or CPU_TS64 bits
* -- up to 32 or 64, respectively -- into microseconds.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts)
{
CPU_INT64U ts_us;
CPU_INT64U fclk_freq;
fclk_freq = BSP_CPU_ClkFreq();
ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
return (ts_us);
}
#endif
#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts)
{
CPU_INT64U ts_us;
CPU_INT64U fclk_freq;
fclk_freq = BSP_CPU_ClkFreq();
ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC);
return (ts_us);
}
#endif
app.c
/*
*********************************************************************************************************
* EXAMPLE CODE
*
* (c) Copyright 2013; Micrium, Inc.; Weston, FL
*
* All rights reserved. Protected by international copyright laws.
* Knowledge of the source code may not be used to write a similar
* product. This file may only be used in accordance with a license
* and should not be redistributed in any way.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* EXAMPLE CODE
*
* IAR Development Kits
* on the
*
* STM32F429II-SK KICKSTART KIT
*
* Filename : app.c
* Version : V1.00
* Programmer(s) : YS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include <includes.h>
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/* ----------------- APPLICATION GLOBALS -------------- */
static OS_TCB AppTaskStartTCB;
static CPU_STK AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE];
#define APPTASK1NAME "App Task1"
#define APP_TASK1_PRIO 3
#define APP_TASK1_STK_SIZE 512
static OS_TCB AppTask1TCB;
static void AppTask1 (void *p_arg);
static CPU_STK AppTask1Stk[APP_TASK1_STK_SIZE];
/*
*********************************************************************************************************
* FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void AppTaskStart (void *p_arg);
/*
*********************************************************************************************************
* main()
*
* Description : This is the standard entry point for C code. It is assumed that your code will call
* main() once you have performed all necessary initialization.
*
* Arguments : none
*
* Returns : none
*********************************************************************************************************
*/
int main(void)
{
OS_ERR err;
OSInit(&err); /* Init uC/OS-III. */
OSTaskCreate((OS_TCB *)&AppTaskStartTCB, /* Create the start task */
(CPU_CHAR *)"App Task Start",
(OS_TASK_PTR )AppTaskStart,
(void *)0u,
(OS_PRIO )APP_CFG_TASK_START_PRIO,
(CPU_STK *)&AppTaskStartStk[0u],
(CPU_STK_SIZE )AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE / 10u],
(CPU_STK_SIZE )APP_CFG_TASK_START_STK_SIZE,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void *)0u,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSStart(&err); /* Start multitasking (i.e. give control to uC/OS-III). */
}
/*
*********************************************************************************************************
* STARTUP TASK
*
* Description : This is an example of a startup task. As mentioned in the book's text, you MUST
* initialize the ticker only once multitasking has started.
*
* Arguments : p_arg is the argument passed to 'AppTaskStart()' by 'OSTaskCreate()'.
*
* Returns : none
*
* Notes : 1) The first line of code is used to prevent a compiler warning because 'p_arg' is not
* used. The compiler should not generate any code for this statement.
*********************************************************************************************************
*/
static void AppTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
(void)p_arg;
BSP_Init();
CPU_Init(); /* Initialize the uC/CPU services */
cpu_clk_freq = BSP_CPU_ClkFreq(); /* Determine SysTick reference freq. */
cnts = cpu_clk_freq /* Determine nbr SysTick increments */
/ (CPU_INT32U)OSCfg_TickRate_Hz;
OS_CPU_SysTickInit(cnts); /* Init uC/OS periodic time src (SysTick). */
Mem_Init(); /* Initialize memory managment module */
Math_Init(); /* Initialize mathematical module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_IntDisMeasMaxCurReset();
#endif
#if (APP_CFG_SERIAL_EN == DEF_ENABLED)
App_SerialInit(); /* Initialize Serial communication for application ... */
#endif
OSTaskCreate((OS_TCB *)&AppTask1TCB, /* Create the Led1 task */
(CPU_CHAR *)APPTASK1NAME,
(OS_TASK_PTR ) AppTask1,
(void *) 0,
(OS_PRIO ) APP_TASK1_PRIO,
(CPU_STK *)&AppTask1Stk[0],
(CPU_STK_SIZE) APP_TASK1_STK_SIZE / 10,
(CPU_STK_SIZE) APP_TASK1_STK_SIZE,
(OS_MSG_QTY ) 5u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OSTaskDel ( & AppTaskStartTCB, & err );
}
static void AppTask1 (void *p_arg)
{
OS_ERR err;
while(DEF_TRUE)
{
printf("Task1 Runing\r\n");
OSTimeDly ( 1000, OS_OPT_TIME_DLY, & err ); // 1s运行一次
}
}
总结
除了uCOSIII之外,主流的RTOS还有rtthread和FreeRTOS,但不管哪一款RTOS,移植步骤基本都是一样的
- 下载RTOS的源代码
- 找一个基础工程作为模板开始移植
- 添加RTOS源码和MCU架构相关的源码到工程
- 添加板级初始化代码(初始化时钟、初始化RTOS心跳时钟)
- 编译工程,如果有错误就修改
- 下载观察现象