OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » keil,ARTX,ARTX,Config keil ARTX,调整ARTX_C

共2条 1/1 1 跳转至

keil,ARTX,ARTX,Config keil ARTX,调整ARTX_Config.c,增加关中断时,保存原状态寄存器

院士
2006-12-22 22:43:00    评分
keil,ARTX,ARTX,Config keil ARTX,调整ARTX_Config.c,增加关中断时,保存原状态寄存器



关键词: Config     调整     Config.c     增加     中断         

院士
2006-12-22 22:43:00    评分
2楼

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 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]