stm32F103上如何移植ucosIII
移植准备工作: 1:准备一份裸机基础工程 2:准备ucosIII源码一份,官网源码下载地址:官网源码下载地址;csdn下载地址UCOSIII移植: 向工程中添加相应的文件1.在工程目录中新建文件夹Ucosiii2.复制源码目录下的三个文件到工程文件夹ucosiii下。3.在工程文件目录ucosiii下面,再新建两个文件夹,UCOS_BSP和UCOS_CONFIG。打开源码文件夹里面的官方历程
移植准备工作:
1:准备一份裸机基础工程
2:准备ucosIII源码一份,官网源码下载地址:官网源码下载地址;csdn下载地址
UCOSIII移植:
向工程中添加相应的文件
1.在工程目录中新建文件夹Ucosiii
2.复制源码目录下的三个文件到工程文件夹ucosiii下。
3.在工程文件目录ucosiii下面,再新建两个文件夹,UCOS_BSP和UCOS_CONFIG。打开源码文件夹里面的官方历程f107文件夹:找我们需要的文件,然后添加到我们的工程中。
(1):向config里面添加8个文件;
(2):向bsp里面添加bsp.c和bsp.h两个文件
此时我们得工程目录ucosiii下有五个文件夹:
4.在keil中添加分组,把这些文件添加到我们得工程中,在keil中的分组如下:
把相应的.c和.h文件添加到对应的分组里
5.添加相应的头文件
到此,添加文件结束。
修改bsp.c和bsp.h文件
bsp.c文件修改后如下:
#define BSP_MODULE
#include <bsp.h>
#define BSP_REG_DEM_CR (*(CPU_REG32 *)0xE000EDFC) //DEMCR寄存器
#define BSP_REG_DWT_CR (*(CPU_REG32 *)0xE0001000) //DWT控制寄存器
#define BSP_REG_DWT_CYCCNT (*(CPU_REG32 *)0xE0001004) //DWT时钟计数寄存器
#define BSP_REG_DBGMCU_CR (*(CPU_REG32 *)0xE0042004)
//DEMCR寄存器的第24位,如果要使用DWT ETM ITM和TPIU的话DEMCR寄存器的第24位置1
#define BSP_BIT_DEM_CR_TRCENA DEF_BIT_24
//DWTCR寄存器的第0位,当为1的时候使能CYCCNT计数器,使用CYCCNT之前应当先初始化
#define BSP_BIT_DWT_CR_CYCCNTENA DEF_BIT_00
/*
*********************************************************************************************************
* 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); //返回HCLK时钟频率
}
/*$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; //使用DWT /* Enable Cortex-M4's DWT CYCCNT reg. */
BSP_REG_DWT_CYCCNT = (CPU_INT32U)0u; //初始化CYCCNT寄存器
BSP_REG_DWT_CR |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;//开启CYCCNT
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
修改后bsp.h如下:
#ifndef BSP_PRESENT
#define BSP_PRESENT
#ifdef BSP_MODULE
#define BSP_EXT
#else
#define BSP_EXT extern
#endif
#include <stdio.h>
#include <stdarg.h>
#include <cpu.h>
#include <cpu_core.h>
#include <lib_def.h>
#include <lib_ascii.h>
#include <stm32f10x_conf.h>
#endif
修改os_cpu_a.asm文件
修改后文件为:
;********************************************************************************************************
; uC/CPU
; CPU CONFIGURATION & PORT LAYER
;
; (c) Copyright 2004-2011; Micrium, Inc.; Weston, FL
;
; All rights reserved. Protected by international copyright laws.
;
; uC/CPU is provided in source form to registered licensees ONLY. It is
; illegal to distribute this source code to any third party unless you receive
; written permission by an authorized Micrium representative. 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.
;
; You can contact us at www.micrium.com.
;********************************************************************************************************
;********************************************************************************************************
;
; CPU PORT FILE
;
; ARM-Cortex-M3
; RealView Development Suite
; RealView Microcontroller Development Kit (MDK)
; ARM Developer Suite (ADS)
; Keil uVision
;
; Filename : cpu_a.asm
; Version : V1.29.01.00
; Programmer(s) : BAN
;********************************************************************************************************
;********************************************************************************************************
; PUBLIC FUNCTIONS
;********************************************************************************************************
EXPORT CPU_IntDis
EXPORT CPU_IntEn
EXPORT CPU_SR_Save
EXPORT CPU_SR_Restore
EXPORT CPU_WaitForInt
EXPORT CPU_WaitForExcept
EXPORT CPU_CntLeadZeros
EXPORT CPU_CntTrailZeros
EXPORT CPU_RevBits
;********************************************************************************************************
; CODE GENERATION DIRECTIVES
;********************************************************************************************************
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
;$PAGE
;********************************************************************************************************
; DISABLE and ENABLE INTERRUPTS
;
; Description : Disable/Enable interrupts.
;
; Prototypes : void CPU_IntDis(void);
; void CPU_IntEn (void);
;********************************************************************************************************
CPU_IntDis
CPSID I
BX LR
CPU_IntEn
CPSIE I
BX LR
;********************************************************************************************************
; CRITICAL SECTION FUNCTIONS
;
; Description : Disable/Enable interrupts by preserving the state of interrupts. Generally speaking, the
; state of the interrupt disable flag is stored in the local variable 'cpu_sr' & interrupts
; are then disabled ('cpu_sr' is allocated in all functions that need to disable interrupts).
; The previous interrupt state is restored by copying 'cpu_sr' into the CPU's status register.
;
; Prototypes : CPU_SR CPU_SR_Save (void);
; void CPU_SR_Restore(CPU_SR cpu_sr);
;
; Note(s) : (1) These functions are used in general like this :
;
; void Task (void *p_arg)
; {
; CPU_SR_ALLOC(); /* Allocate storage for CPU status register */
; :
; :
; CPU_CRITICAL_ENTER(); /* cpu_sr = CPU_SR_Save(); */
; :
; :
; CPU_CRITICAL_EXIT(); /* CPU_SR_Restore(cpu_sr); */
; :
; }
;********************************************************************************************************
CPU_SR_Save
MRS R0, PRIMASK ; Set prio int mask to mask all (except faults)
CPSID I
BX LR
CPU_SR_Restore ; See Note #2.
MSR PRIMASK, R0
BX LR
;$PAGE
;********************************************************************************************************
; WAIT FOR INTERRUPT
;
; Description : Enters sleep state, which will be exited when an interrupt is received.
;
; Prototypes : void CPU_WaitForInt (void)
;
; Argument(s) : none.
;********************************************************************************************************
CPU_WaitForInt
WFI ; Wait for interrupt
BX LR
;********************************************************************************************************
; WAIT FOR EXCEPTION
;
; Description : Enters sleep state, which will be exited when an exception is received.
;
; Prototypes : void CPU_WaitForExcept (void)
;
; Argument(s) : none.
;********************************************************************************************************
CPU_WaitForExcept
WFE ; Wait for exception
BX LR
;$PAGE
;********************************************************************************************************
; CPU_CntLeadZeros()
; COUNT LEADING ZEROS
;
; Description : Counts the number of contiguous, most-significant, leading zero bits before the
; first binary one bit in a data value.
;
; Prototype : CPU_DATA CPU_CntLeadZeros(CPU_DATA val);
;
; Argument(s) : val Data value to count leading zero bits.
;
; Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'.
;
; Caller(s) : Application.
;
; This function is an INTERNAL CPU module function but MAY be called by application
; function(s).
;
; Note(s) : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h
; CPU WORD CONFIGURATION Note #1').
;
; (b) For 32-bit values :
;
; b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros
; --- --- --- --- --- --- --- --- ---------------
; 1 x x x x x x x 0
; 0 1 x x x x x x 1
; 0 0 1 x x x x x 2
; : : : : : : : : :
; : : : : : : : : :
; 0 0 0 1 x x x x 27
; 0 0 0 0 1 x x x 28
; 0 0 0 0 0 1 x x 29
; 0 0 0 0 0 0 1 x 30
; 0 0 0 0 0 0 0 1 31
; 0 0 0 0 0 0 0 0 32
;
;
; (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_LEAD_ZEROS_ASM_PRESENT is
; #define'd in 'cpu_cfg.h' or 'cpu.h'.
;********************************************************************************************************
CPU_CntLeadZeros
CLZ R0, R0 ; Count leading zeros
BX LR
;$PAGE
;********************************************************************************************************
; CPU_CntTrailZeros()
; COUNT TRAILING ZEROS
;
; Description : Counts the number of contiguous, least-significant, trailing zero bits before the
; first binary one bit in a data value.
;
; Prototype : CPU_DATA CPU_CntTrailZeros(CPU_DATA val);
;
; Argument(s) : val Data value to count trailing zero bits.
;
; Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
;
; Caller(s) : Application.
;
; This function is an INTERNAL CPU module function but MAY be called by application
; function(s).
;
; Note(s) : (1) (a) Supports 32-bit data value size as configured by 'CPU_DATA' (see 'cpu.h
; CPU WORD CONFIGURATION Note #1').
;
; (b) For 32-bit values :
;
; b31 b30 b29 b28 b27 ... b02 b01 b00 # Trailing Zeros
; --- --- --- --- --- --- --- --- ----------------
; x x x x x x x 1 0
; x x x x x x 1 0 1
; x x x x x 1 0 0 2
; : : : : : : : : :
; : : : : : : : : :
; x x x x 1 0 0 0 27
; x x x 1 0 0 0 0 28
; x x 1 0 0 0 0 0 29
; x 1 0 0 0 0 0 0 30
; 1 0 0 0 0 0 0 0 31
; 0 0 0 0 0 0 0 0 32
;
;
; (2) MUST be defined in 'cpu_a.asm' (or 'cpu_c.c') if CPU_CFG_TRAIL_ZEROS_ASM_PRESENT is
; #define'd in 'cpu_cfg.h' or 'cpu.h'.
;********************************************************************************************************
CPU_CntTrailZeros
RBIT R0, R0 ; Reverse bits
CLZ R0, R0 ; Count trailing zeros
BX LR
;$PAGE
;********************************************************************************************************
; CPU_RevBits()
; REVERSE BITS
;
; Description : Reverses the bits in a data value.
;
; Prototypes : CPU_DATA CPU_RevBits(CPU_DATA val);
;
; Argument(s) : val Data value to reverse bits.
;
; Return(s) : Value with all bits in 'val' reversed (see Note #1).
;
; Caller(s) : Application.
;
; This function is an INTERNAL CPU module function but MAY be called by application function(s).
;
; Note(s) : (1) The final, reversed data value for 'val' is such that :
;
; 'val's final bit 0 = 'val's original bit N
; 'val's final bit 1 = 'val's original bit (N - 1)
; 'val's final bit 2 = 'val's original bit (N - 2)
;
; ... ...
;
; 'val's final bit (N - 2) = 'val's original bit 2
; 'val's final bit (N - 1) = 'val's original bit 1
; 'val's final bit N = 'val's original bit 0
;********************************************************************************************************
CPU_RevBits
RBIT R0, R0 ; Reverse bits
BX LR
;$PAGE
;********************************************************************************************************
; CPU ASSEMBLY PORT FILE END
;********************************************************************************************************
END
修改os_cpu_c.c文件
修改后的文件为:
/*
*********************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
*
* (c) Copyright 2009-2010; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* ARM Cortex-M3 Port
*
* File : OS_CPU_C.C
* Version : V3.01.2
* By : JJL
* BAN
*
* LICENSING TERMS:
* ---------------
* uC/OS-III is provided in source form to registered licensees ONLY. It is
* illegal to distribute this source code to any third party unless you receive
* written permission by an authorized Micrium representative. 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.
*
* You can contact us at www.micrium.com.
*
* For : ARMv7M Cortex-M3
* Mode : Thumb2
* Toolchain : RealView
*********************************************************************************************************
*/
#define OS_CPU_GLOBALS
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const CPU_CHAR *os_cpu_c__c = "$Id: $";
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include <os.h>
/*
*********************************************************************************************************
* IDLE TASK HOOK
*
* Description: This function is called by the idle task. This hook has been added to allow you to do
* such things as STOP the CPU to conserve power.
*
* Arguments : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSIdleTaskHook (void)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppIdleTaskHookPtr)();
}
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* OS INITIALIZATION HOOK
*
* Description: This function is called by OSInit() at the beginning of OSInit().
*
* Arguments : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSInitHook (void)
{
CPU_STK_SIZE i;
CPU_STK *p_stk;
p_stk = OSCfg_ISRStkBasePtr; /* Clear the ISR stack */
for (i = 0u; i < OSCfg_ISRStkSize; i++) {
*p_stk++ = (CPU_STK)0u;
}
OS_CPU_ExceptStkBase = (CPU_STK *)(OSCfg_ISRStkBasePtr + OSCfg_ISRStkSize - 1u);
}
/*$PAGE*/
/*
*********************************************************************************************************
* STATISTIC TASK HOOK
*
* Description: This function is called every second by uC/OS-III's statistics task. This allows your
* application to add functionality to the statistics task.
*
* Arguments : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSStatTaskHook (void)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppStatTaskHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppStatTaskHookPtr)();
}
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK CREATION HOOK
*
* Description: This function is called when a task is created.
*
* Arguments : p_tcb Pointer to the task control block of the task being created.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSTaskCreateHook (OS_TCB *p_tcb)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTaskCreateHookPtr != (OS_APP_HOOK_TCB)0) {
(*OS_AppTaskCreateHookPtr)(p_tcb);
}
#else
(void)p_tcb; /* Prevent compiler warning */
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK DELETION HOOK
*
* Description: This function is called when a task is deleted.
*
* Arguments : p_tcb Pointer to the task control block of the task being deleted.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSTaskDelHook (OS_TCB *p_tcb)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTaskDelHookPtr != (OS_APP_HOOK_TCB)0) {
(*OS_AppTaskDelHookPtr)(p_tcb);
}
#else
(void)p_tcb; /* Prevent compiler warning */
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK RETURN HOOK
*
* Description: This function is called if a task accidentally returns. In other words, a task should
* either be an infinite loop or delete itself when done.
*
* Arguments : p_tcb Pointer to the task control block of the task that is returning.
*
* Note(s) : None.
*********************************************************************************************************
*/
void OSTaskReturnHook (OS_TCB *p_tcb)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTaskReturnHookPtr != (OS_APP_HOOK_TCB)0) {
(*OS_AppTaskReturnHookPtr)(p_tcb);
}
#else
(void)p_tcb; /* Prevent compiler warning */
#endif
}
/*$PAGE*/
/*
**********************************************************************************************************
* INITIALIZE A TASK'S STACK
*
* Description: This function is called by OS_Task_Create() or OSTaskCreateExt() to initialize the stack
* frame of the task being created. This function is highly processor specific.
*
* Arguments : p_task Pointer to the task entry point address.
*
* p_arg Pointer to a user supplied data area that will be passed to the task
* when the task first executes.
*
* p_stk_base Pointer to the base address of the stack.
*
* stk_size Size of the stack, in number of CPU_STK elements.
*
* opt Options used to alter the behavior of OS_Task_StkInit().
* (see OS.H for OS_TASK_OPT_xxx).
*
* Returns : Always returns the location of the new top-of-stack' once the processor registers have
* been placed on the stack in the proper order.
*
* Note(s) : 1) Interrupts are enabled when task starts executing.
*
* 2) All tasks run in Thread mode, using process stack.
**********************************************************************************************************
*/
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
void *p_arg,
CPU_STK *p_stk_base,
CPU_STK *p_stk_limit,
CPU_STK_SIZE stk_size,
OS_OPT opt)
{
CPU_STK *p_stk;
(void)opt; /* Prevent compiler warning */
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */
/* Registers stacked as if auto-saved on exception */
*--p_stk = (CPU_STK)0x01000000u; /* xPSR */
*--p_stk = (CPU_STK)p_task; /* Entry Point */
*--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */
*--p_stk = (CPU_STK)0x12121212u; /* R12 */
*--p_stk = (CPU_STK)0x03030303u; /* R3 */
*--p_stk = (CPU_STK)0x02020202u; /* R2 */
*--p_stk = (CPU_STK)p_stk_limit; /* R1 */
*--p_stk = (CPU_STK)p_arg; /* R0 : argument */
/* Remaining registers saved on process stack */
*--p_stk = (CPU_STK)0x11111111u; /* R11 */
*--p_stk = (CPU_STK)0x10101010u; /* R10 */
*--p_stk = (CPU_STK)0x09090909u; /* R9 */
*--p_stk = (CPU_STK)0x08080808u; /* R8 */
*--p_stk = (CPU_STK)0x07070707u; /* R7 */
*--p_stk = (CPU_STK)0x06060606u; /* R6 */
*--p_stk = (CPU_STK)0x05050505u; /* R5 */
*--p_stk = (CPU_STK)0x04040404u; /* R4 */
return (p_stk);
}
/*$PAGE*/
/*
*********************************************************************************************************
* TASK SWITCH HOOK
*
* Description: This function is called when a task switch is performed. This allows you to perform other
* operations during a context switch.
*
* Arguments : None.
*
* Note(s) : 1) Interrupts are disabled during this call.
* 2) It is assumed that the global pointer 'OSTCBHighRdyPtr' points to the TCB of the task
* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCurPtr' points
* to the task being switched out (i.e. the preempted task).
*********************************************************************************************************
*/
void OSTaskSwHook (void)
{
#if OS_CFG_TASK_PROFILE_EN > 0u
CPU_TS ts;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS int_dis_time;
#endif
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppTaskSwHookPtr)();
}
#endif
#if OS_CFG_TASK_PROFILE_EN > 0u
ts = OS_TS_GET();
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
}
OSTCBHighRdyPtr->CyclesStart = ts;
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
}
#endif
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
/* Keep track of per-task scheduler lock time */
if (OSTCBCurPtr->SchedLockTimeMax < OSSchedLockTimeMaxCur) {
OSTCBCurPtr->SchedLockTimeMax = OSSchedLockTimeMaxCur;
}
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* TICK HOOK
*
* Description: This function is called every tick.
*
* Arguments : None.
*
* Note(s) : 1) This function is assumed to be called from the Tick ISR.
*********************************************************************************************************
*/
void OSTimeTickHook (void)
{
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppTimeTickHookPtr)();
}
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* SYS TICK HANDLER
*
* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick
* interrupt.
*
* Arguments : None.
*
* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M3 vector table.
*********************************************************************************************************
*/
void OS_CPU_SysTickHandler (void)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
OSIntNestingCtr++; /* Tell uC/OS-III that we are starting an ISR */
CPU_CRITICAL_EXIT();
OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */
OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
}
/*$PAGE*/
/*
*********************************************************************************************************
* INITIALIZE SYS TICK
*
* Description: Initialize the SysTick.
*
* Arguments : cnts Number of SysTick counts between two OS tick interrupts.
*
* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization.
*********************************************************************************************************
*/
void OS_CPU_SysTickInit (CPU_INT32U cnts)
{
CPU_INT32U prio;
CPU_REG_NVIC_ST_RELOAD = cnts - 1u;
/* Set SysTick handler prio. */
prio = CPU_REG_NVIC_SHPRI3;
prio &= DEF_BIT_FIELD(24, 0);
prio |= DEF_BIT_MASK(OS_CPU_CFG_SYSTICK_PRIO, 24);
CPU_REG_NVIC_SHPRI3 = prio;
/* Enable timer. */
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_CLKSOURCE |
CPU_REG_NVIC_ST_CTRL_ENABLE;
/* Enable timer interrupt. */
CPU_REG_NVIC_ST_CTRL |= CPU_REG_NVIC_ST_CTRL_TICKINT;
}
修改os_cfg_app.h文件
修改后文件为:
/*
************************************************************************************************************************
* uC/OS-III
* The Real-Time Kernel
*
* (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
* All rights reserved. Protected by international copyright laws.
*
* OS CONFIGURATION (APPLICATION SPECIFICS)
*
* File : OS_CFG_APP.H
* By : JJL
* Version : V3.03.01
*
* LICENSING TERMS:
* ---------------
* uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
* for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
* product then, you need to contact Micrium to properly license uC/OS-III for its use in your
* application/product. We provide ALL the source code for your convenience and to help you
* experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
* it commercially without paying a licensing fee.
*
* 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.
*
* You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
************************************************************************************************************************
*/
#ifndef OS_CFG_APP_H
#define OS_CFG_APP_H
/*
************************************************************************************************************************
* CONSTANTS
************************************************************************************************************************
*/
/* --------------------- MISCELLANEOUS ------------------ */
#define OS_CFG_MSG_POOL_SIZE 100u /* Maximum number of messages */
#define OS_CFG_ISR_STK_SIZE 128u /* Stack size of ISR stack (number of CPU_STK elements) */
#define OS_CFG_TASK_STK_LIMIT_PCT_EMPTY 10u /* Stack limit position in percentage to empty */
/* ---------------------- IDLE TASK --------------------- */
#define OS_CFG_IDLE_TASK_STK_SIZE 128u /* Stack size (number of CPU_STK elements) */
/* ------------------ ISR HANDLER TASK ------------------ */
#define OS_CFG_INT_Q_SIZE 10u /* Size of ISR handler task queue */
#define OS_CFG_INT_Q_TASK_STK_SIZE 128u /* Stack size (number of CPU_STK elements) */
/* ------------------- STATISTIC TASK ------------------- */
#define OS_CFG_STAT_TASK_PRIO (OS_CFG_PRIO_MAX-2u) /* Priority 统计任务优先级 */
#define OS_CFG_STAT_TASK_RATE_HZ 10u /* Rate of execution (1 to 10 Hz) */
#define OS_CFG_STAT_TASK_STK_SIZE 128u /* Stack size (number of CPU_STK elements) */
/* ------------------------ TICKS ----------------------- */
#define OS_CFG_TICK_RATE_HZ 200u /* Tick rate in Hertz (10 to 1000 Hz) */
#define OS_CFG_TICK_TASK_PRIO 1u /* Priority 时钟节拍任务,一般设置一个相对较高的优先级 */
#define OS_CFG_TICK_TASK_STK_SIZE 128u /* Stack size (number of CPU_STK elements) */
#define OS_CFG_TICK_WHEEL_SIZE 17u /* Number of 'spokes' in tick wheel; SHOULD be prime */
/* ----------------------- TIMERS ----------------------- */
#define OS_CFG_TMR_TASK_PRIO 2u /* Priority of 'Timer Task' 定时任务优先级 */
#define OS_CFG_TMR_TASK_RATE_HZ 100u /* Rate for timers (100 Hz Typ.) */
#define OS_CFG_TMR_TASK_STK_SIZE 128u /* Stack size (number of CPU_STK elements) */
#define OS_CFG_TMR_WHEEL_SIZE 17u /* Number of 'spokes' in timer wheel; SHOULD be prime */
#endif
修改sys.h文件
打开宏定义:#define SYSTEM_SUPPORT_OS 1 //定义系统文件夹是否支持UCOS
验证移植是否成功,我们简易的设计了一个多任务系统:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"
#include <os_app_hooks.h>
#include "lcd.h"
#include "key.h"
#include "os.h"
#include "malloc.h"
/*************************************************/
//任务优先级
#define START_TASK_PRIO 3
//任务堆栈大小
#define START_STK_SIZE 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);
//任务优先级
#define MAIN_TASK_PRIO 4
//任务堆栈大小
#define MAIN_STK_SIZE 128
//任务控制块
OS_TCB MainTaskTCB;
//任务堆栈
CPU_STK MAIN_TASK_STK[MAIN_STK_SIZE];
void main_task(void *p_arg);
//任务优先级
#define FLAGSPROCESS_TASK_PRIO 5
//任务堆栈大小
#define FLAGSPROCESS_STK_SIZE 128
//任务控制块
OS_TCB FlagsProcessTaskTCB;
//任务堆栈
CPU_STK FLAGSPROCESS_TASK_STK[FLAGSPROCESS_STK_SIZE];
//任务函数
void FlagsProcess_task(void *p_arg);
/*创建统计任务*/
#define STATISTIC_TASK_USEAGE_PRIO 12 //必须为当前所有系统中优先级最低
#define STATISTIC_TASK_USEAGE_SIZE 128
OS_TCB STATISTIC_TASK_TCB;
CPU_STK STATISTIC_TASK_STK[STATISTIC_TASK_USEAGE_SIZE]; //堆栈大小
void statistic_task(void *p_arg);
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED,
GRED, GBLUE, RED, MAGENTA,
GREEN, CYAN, YELLOW,BROWN,
BRRED, GRAY };
/*创建两个信号量对象*/
OS_SEM key0_sem;
OS_SEM key1_sem;
/*******定义一个消息队列*****/
OS_Q os_msg;
/**********************配置主界面************************************/
void ucos_load_main_ui(void)
{
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1");
LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 13-1");
LCD_ShowString(30,50,200,16,16,"Pend Multi");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,90,200,16,16,"2015/5/20");
POINT_COLOR = BLACK;
LCD_DrawRectangle(5,110,234,314);
LCD_DrawLine(5,130,234,130);
POINT_COLOR = RED;
LCD_ShowString(50,111,200,16,16,"ObjRdy_NUM: 0");
POINT_COLOR = BLUE;
}
/***********************主函数******************************/
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
uart_init(115200); //串口波特率设置
LED_Init(); //LED初始化
LCD_Init();
KEY_Init();
FSMC_SRAM_Init(); //初始化SRAM
my_mem_init(SRAMIN);//初始化内部RAM
ucos_load_main_ui();
OSInit(&err); //初始化UCOSIII
OS_CRITICAL_ENTER(); //进入临界区
//创建开始任务
OSTaskCreate( (OS_TCB * )&StartTaskTCB, //任务控制块
(CPU_CHAR * )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启UCOSIII
while(1);
}
//开始任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
#if OS_CFG_APP_HOOKS_EN > 0u
App_OS_SetAllHooks(); //钩子函数
#endif
OS_CRITICAL_ENTER(); //进入临界区
/*创建消息队列*/
OSQCreate ((OS_Q*) &os_msg,
(CPU_CHAR*) "os msg",
(OS_MSG_QTY) 10,
(OS_ERR*) &err);
/*创建两个信号量*/
OSSemCreate((OS_SEM*) &key0_sem,
(CPU_CHAR*) "key0 sem",
(OS_SEM_CTR) 0,
(OS_ERR*) &err);
OSSemCreate((OS_SEM*) &key1_sem,
(CPU_CHAR*) "key1 sem",
(OS_SEM_CTR) 0,
(OS_ERR*) &err);
//创建main_task任务
OSTaskCreate( (OS_TCB * )&MainTaskTCB,
(CPU_CHAR * )"main task",
(OS_TASK_PTR )main_task,
(void * )0,
(OS_PRIO )MAIN_TASK_PRIO,
(CPU_STK * )&MAIN_TASK_STK[0],
(CPU_STK_SIZE)MAIN_STK_SIZE/10,
(CPU_STK_SIZE)MAIN_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
//创建等待多内核对象任务
OSTaskCreate( (OS_TCB * )&FlagsProcessTaskTCB,
(CPU_CHAR * )"FlagsProcess_task",
(OS_TASK_PTR )FlagsProcess_task,
(void * )0,
(OS_PRIO )FLAGSPROCESS_TASK_PRIO,
(CPU_STK * )&FLAGSPROCESS_TASK_STK[0],
(CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE/10,
(CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
/*创建一个统计任务*/
OSTaskCreate( (OS_TCB * )&STATISTIC_TASK_TCB,
(CPU_CHAR * )"STATISTIC_TASK_TCB",
(OS_TASK_PTR )statistic_task,
(void * )0,
(OS_PRIO )STATISTIC_TASK_USEAGE_PRIO,
(CPU_STK * )&STATISTIC_TASK_STK[0],
(CPU_STK_SIZE)STATISTIC_TASK_USEAGE_SIZE/10,
(CPU_STK_SIZE)STATISTIC_TASK_USEAGE_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务
OS_CRITICAL_EXIT(); //进入临界区
}
//led0任务函数
void main_task(void *p_arg)
{
u8 key,num;
u8 *pbuf;
static u8 msg_num;
OS_ERR err;
p_arg = p_arg;
pbuf = mymalloc(SRAMIN,10);
while(1)
{
key = KEY_Scan(0);
switch(key)
{
case KEY0_PRES:
OSSemPost((OS_SEM *)&key0_sem,OS_OPT_POST_1,&err);
break;
case KEY1_PRES:
OSSemPost((OS_SEM *)&key1_sem,OS_OPT_POST_1,&err);
break;
case WKUP_PRES:
msg_num++;
sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
/*发送消息队列*/
OSQPost ((OS_Q*) &os_msg,
(void*) pbuf,
(OS_MSG_SIZE) 10,
(OS_OPT) OS_OPT_POST_FIFO,
(OS_ERR*) &err);
break;
}
num++;
if(num == 50)
{
num = 0;
LED0=~LED0;
}
OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //周期延时1s
}
}
//等待多个内核对象的任务函数
void FlagsProcess_task(void *p_arg)
{
u8 num;
OS_ERR err;
OS_OBJ_QTY index;
// p_arg = p_arg;
OS_PEND_DATA pend_mul_tal[3]; //内核对象个数为3
pend_mul_tal[0].PendObjPtr = (OS_PEND_OBJ*)&key0_sem;
pend_mul_tal[1].PendObjPtr = (OS_PEND_OBJ*)&key1_sem;
pend_mul_tal[2].PendObjPtr = (OS_PEND_OBJ*)&os_msg;
while(1)
{
index = OSPendMulti( (OS_PEND_DATA*) pend_mul_tal,
(OS_OBJ_QTY) 3,
(OS_TICK) 0,
(OS_OPT) OS_OPT_PEND_BLOCKING,
(OS_ERR*) &err);
LCD_ShowNum(147,111,index,1,16);
num++;
LED1=~LED1;
LCD_Fill(6,131,233,313,lcd_discolor[num%14]);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //周期延时1s
}
}
void statistic_task(void *p_arg)
{
OS_ERR err;
CPU_STK_SIZE free,used;
p_arg = p_arg;
while(1)
{
OSTaskStkChk(&MainTaskTCB,&free,&used,&err);
printf("任务MainTaskTCB的堆栈使用率为:%%%d,used=%d,free=%d\r\n",(used*100)/(used+free),used,free);
OSTaskStkChk(&FlagsProcessTaskTCB,&free,&used,&err);
printf("任务FlagsProcessTaskTCB的堆栈使用率为:%%%d,used=%d,free=%d\r\n",(used*100)/(used+free),used,free);
OSTaskStkChk(&STATISTIC_TASK_TCB,&free,&used,&err);
printf("任务STATISTIC_TASK_TCB的堆栈使用率为:%%%d,used=%d,free=%d\r\n",(used*100)/(used+free),used,free);
printf("******************************************************\r\n");
}
}
本次移植大部分是参考正点原子的ucos教程文档,有什么问题可以直接在正点原子的论坛上提出。正点原子论坛
更多推荐
所有评论(0)