共2条
1/1 1 跳转至页
keil,ARTX,ARTX,Config keil ARTX,调整ARTX_Config.c,增加关中断时,保存原状态寄存器
问
答 1: 先将我的问题以及个人看法贴出来第一:原配置文件设置内核每核切换次数不太方便,不像ucos-II那么方便,我参考了一下;
第二:由于本人无法将Startup.s中的配置数取出用在此配置文件中,所以又增加了倍频和分频,如果哪位能配置好,希望告诉我一声;
第三:我将低功耗和看门狗增加到配置文件,方便调试和最终产品发布;
第四:本人无法像ucos那样关闭中断,其实关中断在有些时候是必须的,还请各位帮帮忙。
下面代码未在版上真正运行,只在keil中仿真过,如果有问题,会有更好办法,希望各位指教,本人贴出来,也是让大家帮忙找找毛病。 答 2: 原文件如下,keil编译器版本为2.11,评估版/*----------------------------------------------------------------------------
* A R T X - K e r n e l
*----------------------------------------------------------------------------
* Name: ARTX_CONFIG.C
* Purpose: Configuration of ARTX Kernel by user.
* Rev.: V1.00b / 9-feb-2005
*----------------------------------------------------------------------------
* This code is part of the ARTX-ARM kernel package of Keil Software.
* Copyright (c) 2004 Keil Software. All rights reserved.
*---------------------------------------------------------------------------*/
#pragma SAVE
#pragma OPTIMIZE(7)
#define NOFRAME __ARM __task
#include <LPC22xx.H> /* LPC21xx definitions */
#include <ARTX_Config.h> /* ARTX user configuration header */
/*----------------------------------------------------------------------------
* ARTX User configuration part BEGIN
*---------------------------------------------------------------------------*/
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//
// <e>空闲时进入低功耗
#define OS_CPU_IDL_EN 1 /* 系统空闲时,是否进入IDLE mode */
// </e>
// <e>空闲时复位看门狗
#define OS_CPU_WDG_EN 1 /* 系统空闲时,是否喂一次看门狗 */
// <o>OS_WDG_NUM: 每秒复位看门狗次数<1-100>
#define OS_WDG_NUM 2
// </e>
// <h>配置任务参数
// ===================
//
// <o>OS_TASKCNT: 当前运行的任务数 <0-250>
// <i> CAN be less than the number of defined tasks or more if
// <i> multi instances of tasks will run. This define is used
// <i> to calculate the the memory block size that is reserved
// <i> for fixed memory block management.
// <i> Default: 6
#define OS_TASKCNT 6
// <o>OS_PRIVCNT: 使用私有用户栈的任务数 <0-250>
// <i> Some tasks may require bigger user stack than OS_STKSIZE.
// <i> In this case the memory space for user stack must be
// <i> provided by the user and is not assigned by the system.
// <i> Default: 0
#define OS_PRIVCNT 0
// <o>OS_STKSIZE: 任务栈大小(单位:字节) <20-4096:4><#/4>
// <i> This stack is used for task's stack and context switch
// <i> for registers and system stack storage.
// <i> Default: 200
#define OS_STKSIZE 64
// <o>OS_TIMERCNT: 用户定时器数 <0-250>
// <i> Define max. number of user timers running. They act as
// <i> a watchdog timer counting down on each system clock tick.
// <i> On timeout the user provided function is called.
// <i> Default: 0 (User timers disabled)
#define OS_TIMERCNT 0
// </h>
// <h>系统时钟设置
// =============================
// <o>OS_FOSC: 晶体频率(与实际一致) <10000000-25000000>
#define OS_FOSC 12000000 /*晶振频率,10MHz~25MHz,应与实际一至*/
// <o>OS_PLL: PLL倍频数(与Startup文件一致) <1-32>
#define OS_PLL 5 //如果能直接与Startup一致就好了,可惜本人不会呀
#define OS_FCCLK OS_FOSC*OS_PLL;
// <o>OS_VPB: VPB分频数(与Startup文件一致) <1-4>
#define OS_VPB 4 //如果能直接与Startup一致就好了,可惜本人不会呀
#define OS_FPCLK (double)OS_FOSC*OS_PLL/OS_VPB;
// <o>OS_TICKS: 系统调度频率 <10-10000>
#define OS_TICKS 100 /* Set the number of ticks in one second */
#define OS_CLOCK (double)OS_FOSC*OS_PLL/(OS_VPB*OS_TICKS); //设置比较值,每秒产生OS_TICKS个时钟
// <o>OS_TIMER: ARTX核使用定时器 <0=> Timer 0 <1=> Timer 1
// <i> Define the ARM timer used as a system tick timer
// <i> Default: Timer 0
#define OS_TIMER 0
// </h>
// <e>时间片轮番调度法
#define OS_ROBIN 1
// <o>OS_ROBINTOUT: 时间配额(单位:时间片) <1-1000>
// <i> This is the time slice assigned to a running task.
// <i> When this expires, round robin task switch takes place.
// <i> Default: 5
#define OS_ROBINTOUT 5
// </e>
//------------- <<< end of configuration section >>> -----------------------
/*----------------------------------------------------------------------------
* ARTX User configuration part END
*---------------------------------------------------------------------------*/
#if (OS_TIMER == 0) /* Timer 0 */
#define OS_TREG T0TC
#define OS_TIE 0x00000010
#define OS_VIC_VCNT 0x00000024
#define OS_TOVF (T0IR & 1)
#define OS_TIACK() T0IR = 1; \
VICVectAddr = 0; \
VICSoftIntClr = 0x10;
#define OS_TINIT() T0TCR = 1; \
T0MCR = 3; \
T0MR0 = OS_CLOCK;
#elif (OS_TIMER == 1) /* Timer 1 */
#define OS_TREG T1TC
#define OS_TIE 0x00000020
#define OS_VIC_VCNT 0x00000025
#define OS_TOVF (T1IR & 1)
#define OS_TIACK() T1IR = 1; \
VICVectAddr = 0; \
VICSoftIntClr = 0x20;
#define OS_TINIT() T1TCR = 1; \
T1MCR = 3; \
T1MR0 = OS_CLOCK;
#else
#error OS_TIMER invalid
#endif
/* WARNING ! Do not use IDLE mode if you are using a JTAG interface */
/* for debugging your application. */
#define _idle_() PCON = 1;
#define INITIAL_CPSR 0x40000010
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
extern P_TCB os_runtask;
extern struct OS_XCB os_rdy;
extern struct OS_TCB os_clock_TCB;
extern WORD os_time;
WORD const os_maxtaskrun = OS_TASKCNT;
/* Export following defines to uVision debugger. */
WORD const os_stacksize = OS_STKSIZE * 4;
DWORD const os_clockrate = (double)OS_FOSC*OS_PLL/(OS_VPB*OS_TICKS);
DWORD const os_timernum = (OS_TIMER << 16) | OS_TIMERCNT;
DWORD const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
/*----------------------------------------------------------------------------
* Local Variables
*---------------------------------------------------------------------------*/
/* Memory pool for TCB allocation */
static DWORD m_tcb[(sizeof(struct OS_TCB) * OS_TASKCNT)/4 + 3];
/* Memory pool for System stack allocation. Need to allocate 2 additional */
/* entries for 'os_clock_demon()' and 'os_idle_demon()'. */
static DWORD m_stk[OS_STKSIZE * (OS_TASKCNT-OS_PRIVCNT+2) + 3];
/* An array of Active task pointers. */
P_TCB os_active_TCB[OS_TASKCNT];
#if (OS_ROBIN == 1)
static WORD os_robin_time;
static P_TCB os_tsk_robin;
#endif
#if (OS_TIMERCNT != 0)
/* Memory pool for User Timer allocation */
static DWORD m_tmr[(sizeof(struct OS_TMR) * OS_TIMERCNT)/4 + 3];
#endif
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- Disable interrupts -----------------------------*/
void OS_ENTER_CRITICAL() {
}
/*--------------------------- Restore interrupts ----------------------------*/
void OS_EXIT_CRITICAL() {
}
/*--------------------------- os_idle_demon ---------------------------------*/
void os_idle_demon (void) __task {
/* The idle demon is a system task. It is running when no other task is */
/* ready to run (idle situation). It must not terminate. Therefore it */
/* should contain at least an endless loop. */
//如果看门狗使用,在空闲任何初始化时,顺带初始化看门狗定时器
#if OS_CPU_WDG_EN>0
WDTC=(double)OS_FOSC*OS_PLL/OS_VPB/4/OS_WDG_NUM;
WDMOD=0x03; //使能看门定时器中断和复位
#endif
for (;;) {
/* HERE: include here optional user code to be executed when no task runs.*/
//如果喂狗使能,每次进入空闲状态,均喂一次看门狗
#if OS_CPU_WDG_EN>0
OS_ENTER_CRITICAL(); //喂狗前关断中断
WDFEED=0xaa;
WDFEED=0x55;
OS_EXIT_CRITICAL(); //喂狗后打开中断
#endif
//如果空闲状态进入IDL使能,则空闲状态时,进入IDL状态
#if OS_CPU_IDL_EN>0
_idle_();
#endif
}
} /* end of os_idle_demon */
/*--------------------------- os_tmr_call -----------------------------------*/
void os_tmr_call (WORD info) {
/* This function is called when the user timer has expired. */
/* Parameter "info" is the parameter defined when the timer was created. */
/* HERE: include here optional user code to be executed on timeout. */
info = info;
} /* end of os_tmr_call */
/*--------------------------- os_clock_interrupt ----------------------------*/
void os_clock_interrupt (void) NOFRAME {
/* Do task switch to clock demon: entered upon a clock interrupt. */
__asm {
STMDB SP!,{R0-R1} ; Save Full Context
STMDB SP,{SP}^ ; User SP
LDMDB SP,{R0}
MRS R1,SPSR ; User CPSR
SUB LR,LR,#0x4
STMDB R0!,{R1,LR} ; Push PC, CPSR
STMDB R0,{LR}^ ; Push User LR
SUB R0,R0,#0x4 ; Write back problem !!
STMDB R0!,{R2-R12} ; Push R12-R2
LDMIA SP!,{R2-R3}
STMDB R0!,{R2-R3} ; Push R1-R0
LDR R1,=os_runtask ; os_runtask
LDR R1,[R1,#0x0] ; os_runtask
STR R0,[R1,#TCB_TSTACK] ; os_runtask->tsk_stack
}
OS_TIACK();
tsk_lock ();
os_runtask->full_ctx = TRUE;
os_runtask->state = READY;
os_put_rdy_first (os_runtask);
os_runtask = &os_clock_TCB;
os_clock_TCB.state = RUNNING;
__asm {
LDR R0,=os_runtask ; os_runtask
LDR R0,[R0,#0x0] ; os_runtask
LDR R0,[R0,#TCB_TSTACK] ; os_runtask->tsk_stack
LDMIA R0!,{R4-R8,R12}
MSR SPSR_cxsf,R8
STMDB SP,{R0} ; Set User SP
LDMDB SP,{SP}^
MOVS PC,R12 ; RETI
}
} /* end of os_clock_interrupt */
/*--------------------------- os_def_interrupt ------------------------------*/
void os_def_interrupt (void) __irq {
/* Default Interrupt Function: may be called when timer ISR is disabled */
}
/*--------------------------- os_tmr_init -----------------------------------*/
void os_tmr_init (void) {
/* Initialize hardware timer as system tick timer. This function is */
/* called at the system startup. */
OS_TINIT();
/* VIC vector for unassigned VIC interrupts. */
VICDefVectAddr = (DWORD)os_def_interrupt;
VICVectAddr15 = (DWORD)os_clock_interrupt;
VICVectCntl15 = OS_VIC_VCNT;
#if (OS_ROBIN == 1)
os_robin_time = OS_ROBINTOUT;
#endif
} /* end of os_tmr_init */
/*--------------------------- os_tmr_reload ---------------------------------*/
void os_tmr_reload (void) {
/* Reload system timer for next period if a timer requires reload. */
;
} /* end of os_tmr_reload */
/*--------------------------- os_tmr_set_ovf --------------------------------*/
void os_tmr_set_ovf (void) {
/* Set timer overflov flag. */
VICSoftInt |= OS_TIE;
} /* end of os_tmr_set_ovf */
/*--------------------------- os_tmr_inspect_cnt ----------------------------*/
DWORD os_tmr_inspect_cnt (void) {
/* Inspect current value of rtx timer. */
return (OS_TREG);
} /* end of os_tmr_inspect_cnt */
/*--------------------------- os_tmr_inspect_ovf ----------------------------*/
BOOL os_tmr_inspect_ovf (void) {
/* Inspect current state of timer overflow flag. */
return (OS_TOVF);
} /* end of os_tmr_inspect_ovf */
/*--------------------------- tsk_lock --------------------------------------*/
void tsk_lock (void) {
/* Lock out tasks: prevents task switching by locking out scheduler */
/* activation on interrupt. . */
VICIntEnClr = OS_TIE;
} /* end of tsk_lock */
/*--------------------------- tsk_unlock ------------------------------------*/
void tsk_unlock (void) {
/* Enable AR System Tick Timer Interrupts. */
VICIntEnable |= OS_TIE;
} /* end of tsk_unlock */
/*--------------------------- os_init_mem -----------------------------------*/
void os_init_mem (void) {
WORD i;
for (i = 0; i < OS_TASKCNT; i++) {
os_active_TCB[i] = NULL;
}
_init_box (&m_tcb, sizeof(m_tcb), sizeof(struct OS_TCB));
_init_box (&m_stk, sizeof(m_stk), OS_STKSIZE*4);
#if (OS_TIMERCNT != 0)
_init_box (&m_tmr, sizeof(m_tmr), sizeof(struct OS_TMR));
#endif
} /* end of os_init_mem */
/*--------------------------- os_alloc_TCB ----------------------------------*/
P_TCB os_alloc_TCB () {
return (_alloc_box (m_tcb));
} /* end of os_alloc_TCB */
/*--------------------------- os_free_TCB -----------------------------------*/
void os_free_TCB (P_TCB p_TCB) {
/* Free allocated memory resources for the task "p_TCB" */
_free_box (m_stk, p_TCB->stack);
_free_box (m_tcb, p_TCB);
} /* end of os_free_TCB */
/*--------------------------- os_alloc_TMR ----------------------------------*/
P_TMR os_alloc_TMR () {
#if (OS_TIMERCNT != 0)
return (_alloc_box (m_tmr));
#else
return (NULL);
#endif
} /* end of os_alloc_TMR */
/*--------------------------- os_free_TMR -----------------------------------*/
void os_free_TMR (P_TMR timer) {
/* Free allocated memory resources for user timer 'timer' */
#if (OS_TIMERCNT != 0)
_free_box (m_tmr, timer);
#else
timer = timer;
#endif
} /* end of os_free_TMR */
/*--------------------------- os_init_context -------------------------------*/
void os_init_context (P_TCB p_TCB, BYTE priority,
FUNCP task_body, BYTE full_context) {
/* Prepare TCB and saved context for a first time start of a task */
/* "p_TCB" points to TCB to be initialised. "priority" indicates desired */
/* execution priority. "task_body" is the start address of the task. */
/* "full_context" identifies context type. */
DWORD *stk,i;
/* Initialise general part of TCB */
p_TCB->cb_type = TCB;
p_TCB->state = READY;
p_TCB->prio = priority;
p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL;
p_TCB->delta_time = 0;
p_TCB->interval_time = 0;
p_TCB->events = 0;
p_TCB->waits = 0;
/* Initialise ARM specific part of TCB */
p_TCB->full_ctx = full_context;
/* Prepare a complete interrupt frame for first task start */
if (p_TCB->priv_stack != 0) {
/* User has provided a memory space for the stack. */
stk = &p_TCB->stack[p_TCB->priv_stack>>2];
}
else {
/* Allocate the memory space for the stack. */
p_TCB->stack = _alloc_box (m_stk);
/* Write to the top of stack. */
stk = &p_TCB->stack[OS_STKSIZE];
}
/* Initial PC and default CPSR */
*--stk = (DWORD)task_body;
i = INITIAL_CPSR;
/* If a task in THUMB mode, set T-bit. */
if ((DWORD)task_body & 1) {
i |= 0x00000020;
}
*--stk = i;
/* Write initial registers. */
for (i = full_context ? 13 : 4; i; i--) {
*--stk = 0;
}
/* For "full_context" assing a void pointer to R0. */
if (full_context) {
*--stk = (DWORD)p_TCB->p_msg;
}
/* Initial Task stack pointer. */
p_TCB->tsk_stack = (DWORD)stk;
/* Task entry point. */
p_TCB->ptask = task_body;
} /* end of os_init_context */
/*--------------------------- os_set_env ------------------------------------*/
void os_set_env (P_TCB p_TCB) {
/* Fix up runtime environment to fit idle task. It is called after the */
/* idle task TCB initialization. "p_TCB" identifies the TCB to be used. */
p_TCB = p_TCB;
__asm {
LDR R0,[R0,#TCB_TSTACK] ; p_TCB in R0
MOV SP,R0
ADD SP,SP,#24 ; ignore default context
}
} /* end of os_set_env */
/*--------------------------- os_switch_tasks -------------------------------*/
void os_switch_tasks (P_TCB p_new) __swi (0) {
/* Switch to next task (identified by "p_new"). Saving old and restoring */
/* new context is written in assembly (module: Swi_ARTX.s) */
os_runtask->full_ctx = FALSE;
os_runtask = p_new;
p_new->state = RUNNING;
#if (OS_ROBIN == 1)
os_tsk_robin = p_new;
#endif
/* Tsk_Unlock */
VICIntEnable |= OS_TIE;
} /* end of os_switch_tasks */
/*--------------------------- os_chk_robin ----------------------------------*/
void os_chk_robin (void) {
/* Check if Round Robin timeout expired and switch to the next ready task.*/
/* This function is called from the "os_clock_demon()" task scheduler. */
#if (OS_ROBIN == 1)
P_TCB p_new;
if (os_rdy.p_lnk != os_tsk_robin) {
os_robin_time = os_time + OS_ROBINTOUT;
return;
}
if (os_robin_time == os_time) {
/* Round Robin timeout has expired. */
os_robin_time += OS_ROBINTOUT;
p_new = os_get_first (&os_rdy);
os_put_prio ((P_XCB)&os_rdy, p_new);
}
#endif
} /* end of os_chk_robin */
#pragma RESTORE
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
答 3: 不错的创意!真是个不错的创意哦!能不能把加密的那几句代码也加进去啊? 答 4: 不是不能呀,是没有想到呀,比在ADS中还容易实现
答 1: 先将我的问题以及个人看法贴出来第一:原配置文件设置内核每核切换次数不太方便,不像ucos-II那么方便,我参考了一下;
第二:由于本人无法将Startup.s中的配置数取出用在此配置文件中,所以又增加了倍频和分频,如果哪位能配置好,希望告诉我一声;
第三:我将低功耗和看门狗增加到配置文件,方便调试和最终产品发布;
第四:本人无法像ucos那样关闭中断,其实关中断在有些时候是必须的,还请各位帮帮忙。
下面代码未在版上真正运行,只在keil中仿真过,如果有问题,会有更好办法,希望各位指教,本人贴出来,也是让大家帮忙找找毛病。 答 2: 原文件如下,keil编译器版本为2.11,评估版/*----------------------------------------------------------------------------
* A R T X - K e r n e l
*----------------------------------------------------------------------------
* Name: ARTX_CONFIG.C
* Purpose: Configuration of ARTX Kernel by user.
* Rev.: V1.00b / 9-feb-2005
*----------------------------------------------------------------------------
* This code is part of the ARTX-ARM kernel package of Keil Software.
* Copyright (c) 2004 Keil Software. All rights reserved.
*---------------------------------------------------------------------------*/
#pragma SAVE
#pragma OPTIMIZE(7)
#define NOFRAME __ARM __task
#include <LPC22xx.H> /* LPC21xx definitions */
#include <ARTX_Config.h> /* ARTX user configuration header */
/*----------------------------------------------------------------------------
* ARTX User configuration part BEGIN
*---------------------------------------------------------------------------*/
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
//
// <e>空闲时进入低功耗
#define OS_CPU_IDL_EN 1 /* 系统空闲时,是否进入IDLE mode */
// </e>
// <e>空闲时复位看门狗
#define OS_CPU_WDG_EN 1 /* 系统空闲时,是否喂一次看门狗 */
// <o>OS_WDG_NUM: 每秒复位看门狗次数<1-100>
#define OS_WDG_NUM 2
// </e>
// <h>配置任务参数
// ===================
//
// <o>OS_TASKCNT: 当前运行的任务数 <0-250>
// <i> CAN be less than the number of defined tasks or more if
// <i> multi instances of tasks will run. This define is used
// <i> to calculate the the memory block size that is reserved
// <i> for fixed memory block management.
// <i> Default: 6
#define OS_TASKCNT 6
// <o>OS_PRIVCNT: 使用私有用户栈的任务数 <0-250>
// <i> Some tasks may require bigger user stack than OS_STKSIZE.
// <i> In this case the memory space for user stack must be
// <i> provided by the user and is not assigned by the system.
// <i> Default: 0
#define OS_PRIVCNT 0
// <o>OS_STKSIZE: 任务栈大小(单位:字节) <20-4096:4><#/4>
// <i> This stack is used for task's stack and context switch
// <i> for registers and system stack storage.
// <i> Default: 200
#define OS_STKSIZE 64
// <o>OS_TIMERCNT: 用户定时器数 <0-250>
// <i> Define max. number of user timers running. They act as
// <i> a watchdog timer counting down on each system clock tick.
// <i> On timeout the user provided function is called.
// <i> Default: 0 (User timers disabled)
#define OS_TIMERCNT 0
// </h>
// <h>系统时钟设置
// =============================
// <o>OS_FOSC: 晶体频率(与实际一致) <10000000-25000000>
#define OS_FOSC 12000000 /*晶振频率,10MHz~25MHz,应与实际一至*/
// <o>OS_PLL: PLL倍频数(与Startup文件一致) <1-32>
#define OS_PLL 5 //如果能直接与Startup一致就好了,可惜本人不会呀
#define OS_FCCLK OS_FOSC*OS_PLL;
// <o>OS_VPB: VPB分频数(与Startup文件一致) <1-4>
#define OS_VPB 4 //如果能直接与Startup一致就好了,可惜本人不会呀
#define OS_FPCLK (double)OS_FOSC*OS_PLL/OS_VPB;
// <o>OS_TICKS: 系统调度频率 <10-10000>
#define OS_TICKS 100 /* Set the number of ticks in one second */
#define OS_CLOCK (double)OS_FOSC*OS_PLL/(OS_VPB*OS_TICKS); //设置比较值,每秒产生OS_TICKS个时钟
// <o>OS_TIMER: ARTX核使用定时器 <0=> Timer 0 <1=> Timer 1
// <i> Define the ARM timer used as a system tick timer
// <i> Default: Timer 0
#define OS_TIMER 0
// </h>
// <e>时间片轮番调度法
#define OS_ROBIN 1
// <o>OS_ROBINTOUT: 时间配额(单位:时间片) <1-1000>
// <i> This is the time slice assigned to a running task.
// <i> When this expires, round robin task switch takes place.
// <i> Default: 5
#define OS_ROBINTOUT 5
// </e>
//------------- <<< end of configuration section >>> -----------------------
/*----------------------------------------------------------------------------
* ARTX User configuration part END
*---------------------------------------------------------------------------*/
#if (OS_TIMER == 0) /* Timer 0 */
#define OS_TREG T0TC
#define OS_TIE 0x00000010
#define OS_VIC_VCNT 0x00000024
#define OS_TOVF (T0IR & 1)
#define OS_TIACK() T0IR = 1; \
VICVectAddr = 0; \
VICSoftIntClr = 0x10;
#define OS_TINIT() T0TCR = 1; \
T0MCR = 3; \
T0MR0 = OS_CLOCK;
#elif (OS_TIMER == 1) /* Timer 1 */
#define OS_TREG T1TC
#define OS_TIE 0x00000020
#define OS_VIC_VCNT 0x00000025
#define OS_TOVF (T1IR & 1)
#define OS_TIACK() T1IR = 1; \
VICVectAddr = 0; \
VICSoftIntClr = 0x20;
#define OS_TINIT() T1TCR = 1; \
T1MCR = 3; \
T1MR0 = OS_CLOCK;
#else
#error OS_TIMER invalid
#endif
/* WARNING ! Do not use IDLE mode if you are using a JTAG interface */
/* for debugging your application. */
#define _idle_() PCON = 1;
#define INITIAL_CPSR 0x40000010
/*----------------------------------------------------------------------------
* Global Variables
*---------------------------------------------------------------------------*/
extern P_TCB os_runtask;
extern struct OS_XCB os_rdy;
extern struct OS_TCB os_clock_TCB;
extern WORD os_time;
WORD const os_maxtaskrun = OS_TASKCNT;
/* Export following defines to uVision debugger. */
WORD const os_stacksize = OS_STKSIZE * 4;
DWORD const os_clockrate = (double)OS_FOSC*OS_PLL/(OS_VPB*OS_TICKS);
DWORD const os_timernum = (OS_TIMER << 16) | OS_TIMERCNT;
DWORD const os_rrobin = (OS_ROBIN << 16) | OS_ROBINTOUT;
/*----------------------------------------------------------------------------
* Local Variables
*---------------------------------------------------------------------------*/
/* Memory pool for TCB allocation */
static DWORD m_tcb[(sizeof(struct OS_TCB) * OS_TASKCNT)/4 + 3];
/* Memory pool for System stack allocation. Need to allocate 2 additional */
/* entries for 'os_clock_demon()' and 'os_idle_demon()'. */
static DWORD m_stk[OS_STKSIZE * (OS_TASKCNT-OS_PRIVCNT+2) + 3];
/* An array of Active task pointers. */
P_TCB os_active_TCB[OS_TASKCNT];
#if (OS_ROBIN == 1)
static WORD os_robin_time;
static P_TCB os_tsk_robin;
#endif
#if (OS_TIMERCNT != 0)
/* Memory pool for User Timer allocation */
static DWORD m_tmr[(sizeof(struct OS_TMR) * OS_TIMERCNT)/4 + 3];
#endif
/*----------------------------------------------------------------------------
* Global Functions
*---------------------------------------------------------------------------*/
/*--------------------------- Disable interrupts -----------------------------*/
void OS_ENTER_CRITICAL() {
}
/*--------------------------- Restore interrupts ----------------------------*/
void OS_EXIT_CRITICAL() {
}
/*--------------------------- os_idle_demon ---------------------------------*/
void os_idle_demon (void) __task {
/* The idle demon is a system task. It is running when no other task is */
/* ready to run (idle situation). It must not terminate. Therefore it */
/* should contain at least an endless loop. */
//如果看门狗使用,在空闲任何初始化时,顺带初始化看门狗定时器
#if OS_CPU_WDG_EN>0
WDTC=(double)OS_FOSC*OS_PLL/OS_VPB/4/OS_WDG_NUM;
WDMOD=0x03; //使能看门定时器中断和复位
#endif
for (;;) {
/* HERE: include here optional user code to be executed when no task runs.*/
//如果喂狗使能,每次进入空闲状态,均喂一次看门狗
#if OS_CPU_WDG_EN>0
OS_ENTER_CRITICAL(); //喂狗前关断中断
WDFEED=0xaa;
WDFEED=0x55;
OS_EXIT_CRITICAL(); //喂狗后打开中断
#endif
//如果空闲状态进入IDL使能,则空闲状态时,进入IDL状态
#if OS_CPU_IDL_EN>0
_idle_();
#endif
}
} /* end of os_idle_demon */
/*--------------------------- os_tmr_call -----------------------------------*/
void os_tmr_call (WORD info) {
/* This function is called when the user timer has expired. */
/* Parameter "info" is the parameter defined when the timer was created. */
/* HERE: include here optional user code to be executed on timeout. */
info = info;
} /* end of os_tmr_call */
/*--------------------------- os_clock_interrupt ----------------------------*/
void os_clock_interrupt (void) NOFRAME {
/* Do task switch to clock demon: entered upon a clock interrupt. */
__asm {
STMDB SP!,{R0-R1} ; Save Full Context
STMDB SP,{SP}^ ; User SP
LDMDB SP,{R0}
MRS R1,SPSR ; User CPSR
SUB LR,LR,#0x4
STMDB R0!,{R1,LR} ; Push PC, CPSR
STMDB R0,{LR}^ ; Push User LR
SUB R0,R0,#0x4 ; Write back problem !!
STMDB R0!,{R2-R12} ; Push R12-R2
LDMIA SP!,{R2-R3}
STMDB R0!,{R2-R3} ; Push R1-R0
LDR R1,=os_runtask ; os_runtask
LDR R1,[R1,#0x0] ; os_runtask
STR R0,[R1,#TCB_TSTACK] ; os_runtask->tsk_stack
}
OS_TIACK();
tsk_lock ();
os_runtask->full_ctx = TRUE;
os_runtask->state = READY;
os_put_rdy_first (os_runtask);
os_runtask = &os_clock_TCB;
os_clock_TCB.state = RUNNING;
__asm {
LDR R0,=os_runtask ; os_runtask
LDR R0,[R0,#0x0] ; os_runtask
LDR R0,[R0,#TCB_TSTACK] ; os_runtask->tsk_stack
LDMIA R0!,{R4-R8,R12}
MSR SPSR_cxsf,R8
STMDB SP,{R0} ; Set User SP
LDMDB SP,{SP}^
MOVS PC,R12 ; RETI
}
} /* end of os_clock_interrupt */
/*--------------------------- os_def_interrupt ------------------------------*/
void os_def_interrupt (void) __irq {
/* Default Interrupt Function: may be called when timer ISR is disabled */
}
/*--------------------------- os_tmr_init -----------------------------------*/
void os_tmr_init (void) {
/* Initialize hardware timer as system tick timer. This function is */
/* called at the system startup. */
OS_TINIT();
/* VIC vector for unassigned VIC interrupts. */
VICDefVectAddr = (DWORD)os_def_interrupt;
VICVectAddr15 = (DWORD)os_clock_interrupt;
VICVectCntl15 = OS_VIC_VCNT;
#if (OS_ROBIN == 1)
os_robin_time = OS_ROBINTOUT;
#endif
} /* end of os_tmr_init */
/*--------------------------- os_tmr_reload ---------------------------------*/
void os_tmr_reload (void) {
/* Reload system timer for next period if a timer requires reload. */
;
} /* end of os_tmr_reload */
/*--------------------------- os_tmr_set_ovf --------------------------------*/
void os_tmr_set_ovf (void) {
/* Set timer overflov flag. */
VICSoftInt |= OS_TIE;
} /* end of os_tmr_set_ovf */
/*--------------------------- os_tmr_inspect_cnt ----------------------------*/
DWORD os_tmr_inspect_cnt (void) {
/* Inspect current value of rtx timer. */
return (OS_TREG);
} /* end of os_tmr_inspect_cnt */
/*--------------------------- os_tmr_inspect_ovf ----------------------------*/
BOOL os_tmr_inspect_ovf (void) {
/* Inspect current state of timer overflow flag. */
return (OS_TOVF);
} /* end of os_tmr_inspect_ovf */
/*--------------------------- tsk_lock --------------------------------------*/
void tsk_lock (void) {
/* Lock out tasks: prevents task switching by locking out scheduler */
/* activation on interrupt. . */
VICIntEnClr = OS_TIE;
} /* end of tsk_lock */
/*--------------------------- tsk_unlock ------------------------------------*/
void tsk_unlock (void) {
/* Enable AR System Tick Timer Interrupts. */
VICIntEnable |= OS_TIE;
} /* end of tsk_unlock */
/*--------------------------- os_init_mem -----------------------------------*/
void os_init_mem (void) {
WORD i;
for (i = 0; i < OS_TASKCNT; i++) {
os_active_TCB[i] = NULL;
}
_init_box (&m_tcb, sizeof(m_tcb), sizeof(struct OS_TCB));
_init_box (&m_stk, sizeof(m_stk), OS_STKSIZE*4);
#if (OS_TIMERCNT != 0)
_init_box (&m_tmr, sizeof(m_tmr), sizeof(struct OS_TMR));
#endif
} /* end of os_init_mem */
/*--------------------------- os_alloc_TCB ----------------------------------*/
P_TCB os_alloc_TCB () {
return (_alloc_box (m_tcb));
} /* end of os_alloc_TCB */
/*--------------------------- os_free_TCB -----------------------------------*/
void os_free_TCB (P_TCB p_TCB) {
/* Free allocated memory resources for the task "p_TCB" */
_free_box (m_stk, p_TCB->stack);
_free_box (m_tcb, p_TCB);
} /* end of os_free_TCB */
/*--------------------------- os_alloc_TMR ----------------------------------*/
P_TMR os_alloc_TMR () {
#if (OS_TIMERCNT != 0)
return (_alloc_box (m_tmr));
#else
return (NULL);
#endif
} /* end of os_alloc_TMR */
/*--------------------------- os_free_TMR -----------------------------------*/
void os_free_TMR (P_TMR timer) {
/* Free allocated memory resources for user timer 'timer' */
#if (OS_TIMERCNT != 0)
_free_box (m_tmr, timer);
#else
timer = timer;
#endif
} /* end of os_free_TMR */
/*--------------------------- os_init_context -------------------------------*/
void os_init_context (P_TCB p_TCB, BYTE priority,
FUNCP task_body, BYTE full_context) {
/* Prepare TCB and saved context for a first time start of a task */
/* "p_TCB" points to TCB to be initialised. "priority" indicates desired */
/* execution priority. "task_body" is the start address of the task. */
/* "full_context" identifies context type. */
DWORD *stk,i;
/* Initialise general part of TCB */
p_TCB->cb_type = TCB;
p_TCB->state = READY;
p_TCB->prio = priority;
p_TCB->p_lnk = NULL;
p_TCB->p_rlnk = NULL;
p_TCB->p_dlnk = NULL;
p_TCB->p_blnk = NULL;
p_TCB->delta_time = 0;
p_TCB->interval_time = 0;
p_TCB->events = 0;
p_TCB->waits = 0;
/* Initialise ARM specific part of TCB */
p_TCB->full_ctx = full_context;
/* Prepare a complete interrupt frame for first task start */
if (p_TCB->priv_stack != 0) {
/* User has provided a memory space for the stack. */
stk = &p_TCB->stack[p_TCB->priv_stack>>2];
}
else {
/* Allocate the memory space for the stack. */
p_TCB->stack = _alloc_box (m_stk);
/* Write to the top of stack. */
stk = &p_TCB->stack[OS_STKSIZE];
}
/* Initial PC and default CPSR */
*--stk = (DWORD)task_body;
i = INITIAL_CPSR;
/* If a task in THUMB mode, set T-bit. */
if ((DWORD)task_body & 1) {
i |= 0x00000020;
}
*--stk = i;
/* Write initial registers. */
for (i = full_context ? 13 : 4; i; i--) {
*--stk = 0;
}
/* For "full_context" assing a void pointer to R0. */
if (full_context) {
*--stk = (DWORD)p_TCB->p_msg;
}
/* Initial Task stack pointer. */
p_TCB->tsk_stack = (DWORD)stk;
/* Task entry point. */
p_TCB->ptask = task_body;
} /* end of os_init_context */
/*--------------------------- os_set_env ------------------------------------*/
void os_set_env (P_TCB p_TCB) {
/* Fix up runtime environment to fit idle task. It is called after the */
/* idle task TCB initialization. "p_TCB" identifies the TCB to be used. */
p_TCB = p_TCB;
__asm {
LDR R0,[R0,#TCB_TSTACK] ; p_TCB in R0
MOV SP,R0
ADD SP,SP,#24 ; ignore default context
}
} /* end of os_set_env */
/*--------------------------- os_switch_tasks -------------------------------*/
void os_switch_tasks (P_TCB p_new) __swi (0) {
/* Switch to next task (identified by "p_new"). Saving old and restoring */
/* new context is written in assembly (module: Swi_ARTX.s) */
os_runtask->full_ctx = FALSE;
os_runtask = p_new;
p_new->state = RUNNING;
#if (OS_ROBIN == 1)
os_tsk_robin = p_new;
#endif
/* Tsk_Unlock */
VICIntEnable |= OS_TIE;
} /* end of os_switch_tasks */
/*--------------------------- os_chk_robin ----------------------------------*/
void os_chk_robin (void) {
/* Check if Round Robin timeout expired and switch to the next ready task.*/
/* This function is called from the "os_clock_demon()" task scheduler. */
#if (OS_ROBIN == 1)
P_TCB p_new;
if (os_rdy.p_lnk != os_tsk_robin) {
os_robin_time = os_time + OS_ROBINTOUT;
return;
}
if (os_robin_time == os_time) {
/* Round Robin timeout has expired. */
os_robin_time += OS_ROBINTOUT;
p_new = os_get_first (&os_rdy);
os_put_prio ((P_XCB)&os_rdy, p_new);
}
#endif
} /* end of os_chk_robin */
#pragma RESTORE
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
答 3: 不错的创意!真是个不错的创意哦!能不能把加密的那几句代码也加进去啊? 答 4: 不是不能呀,是没有想到呀,比在ADS中还容易实现
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 | |
【FRDM-MCXN947评测】核间通信MUTEX被打赏50分 |