×
单片机 > 单片机程序设计 > 详情

ucos在AVR ATmega32上的移植(一)

发布时间:2020-08-25 发布时间:
|
前面介绍了基本的调度原理,现在把它应用到ucos的移植上来,如果你还不明白调度,就别急于移植,因为对堆栈的一丝差错都会造成系统崩溃,而你也很难找到原因之所在。

先看一下ucos的程序结构

进过整理,工程这样组成:

我们主要是对ucos移植中的三个文件进行修改。

1.OS_CPU.H

更改的地方,我用汉语标注
/*
*********************************************************************************************************
*                                               uC/OS-II
*                                        The Real-Time Kernel
*
*                         (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
*                                          All Rights Reserved
*
*                                       AVR ATmega32 Specific code
*                                          small memory model
*
*                                      IAR Embedded Workbench 5.0
*
* File         : OS_CPU.H
* By           : CH314156
*********************************************************************************************************
*/

#ifdef  OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT  extern
#endif

/*
*********************************************************************************************************
*                                              DATA TYPES
*                                         (Compiler Specific)
*********************************************************************************************************
*/

typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;                    /* Unsigned  8 bit quantity                           */
typedef signed   char  INT8S;                    /* Signed    8 bit quantity                           */
typedef unsigned int   INT16U;                   /* Unsigned 16 bit quantity                           */
typedef signed   int   INT16S;                   /* Signed   16 bit quantity                           */
typedef unsigned long  INT32U;                   /* Unsigned 32 bit quantity                           */
typedef signed   long  INT32S;                   /* Signed   32 bit quantity                           */
typedef float          FP32;                     /* Single precision floating point                    */
typedef double         FP64;                     /* Double precision floating point                    */

typedef unsigned char  OS_STK;                   /* 每个堆栈宽度是8位                                  */
typedef unsigned char  OS_CPU_SR;                /* 定义CPU状态寄存器的大小(RSEG = 8 bits)             */


/* 
*********************************************************************************************************
*                              AVR ATmega32    small memory model
*
* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
*             will be enabled even if they were disabled before entering the critical section.
*
* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if 
*             interrupts were disabled before entering the critical section, they will be disabled when
*             leaving the critical section.
*
* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to 
*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
*             into the CPU's status register.
*********************************************************************************************************
*/
#define  OS_CRITICAL_METHOD    3                          /* 这里使用方法3,功能最完善                 */

#if      OS_CRITICAL_METHOD == 1
#define  OS_ENTER_CRITICAL()  asm("cli")                  /* Disable interrupts                        */
#define  OS_EXIT_CRITICAL()   asm("sei")                  /* Enable  interrupts                        */
#endif

#if      OS_CRITICAL_METHOD == 2
#define  OS_ENTER_CRITICAL()  asm("PUSH_SREG");asm("cli") /* Disable interrupts                        */
#define  OS_EXIT_CRITICAL()   asm("POP_SREG")             /* Enable  interrupts                        */
#endif

#if      OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()  cpu_sr = SREG;  asm("cli")  /* 关中断                                    */ 
#define  OS_EXIT_CRITICAL()   SREG = cpu_sr               /* 开中断                                    */
#endif

/*
*********************************************************************************************************
*                           AVR ATmega32    small memory model
*********************************************************************************************************
*/

#define  OS_STK_GROWTH        1                       /* Stack grows from HIGH to LOW memory on ATmega32*/

#define  OS_TASK_SW()         OSCtxSw()               /* 这里不需要产生中断,直接调用即可               */

 

2.对OS_CPU_C.C的修改,主要是对其中STaskStkInit函数的修改:
/*
*********************************************************************************************************
*                                        INITIALIZE A TASK'S STACK
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
*              stack frame of the task being created.  This function is highly processor specific.
*
* Arguments  : task          is a pointer to the task code
*
*              pdata         is a pointer to a user supplied data area that will be passed to the task
*                            when the task first executes.
*
*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then 
*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
*                            of the stack.
*
*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
*                            (see uCOS_II.H for OS_TASK_OPT_???).
*
* 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)    : Interrupts are enabled when your task starts executing. You can change this by setting the
*              PSW to 0x0002 instead.  In this case, interrupts would be disabled upon task startup.  The
*              application code would be responsible for enabling interrupts at the beginning of the task
*              code.  You will need to modify OSTaskIdle() and OSTaskStat() so that they enable 
*              interrupts.  Failure to do this will make your system crash!
*********************************************************************************************************
*/

OS_STK  *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
  INT8U *stk = ptos;   //软件指针
  INT8U *stk_hard = stk - SOFT_SIZE;    //调整硬件指针位置

  *stk_hard-- = (INT16U)task&0xff;   //在硬件指针存放该任务的首地址
  *stk_hard-- = (INT16U)task>>8;

  opt = opt;

//一下是软件堆栈,存放R0~R25,X,Z,SP,SREG
  *stk-- = 0x00;         //R0
  *stk-- = 0x01;         //R1
  *stk-- = 0x02;         //R2
  *stk-- = 0x03;         //R3
  *stk-- = 0x04;         //R4
  *stk-- = 0x05;         //R5
  *stk-- = 0x06;         //R6
  *stk-- = 0x07;         //R7
  *stk-- = 0x08;         //R8
  *stk-- = 0x09;         //R9
  *stk-- = 0x10;         //R10
  *stk-- = 0x11;         //R11
  *stk-- = 0x12;         //R12
  *stk-- = 0x13;         //R13
  *stk-- = 0x14;         //R14
  *stk-- = 0x15;         //R15
  *stk-- = (INT16U)pdata & 0xff ;   //R16
  *stk-- = (INT16U)pdata >>8 ;      //R17
  *stk-- = 0x18;         //R18
  *stk-- = 0x19;         //R19  
  *stk-- = 0x20;         //R20
  *stk-- = 0x21;         //R21
  *stk-- = 0x22;         //R22
  *stk-- = 0x23;         //R23
  *stk-- = 0x24;         //R24
  *stk-- = 0x25;         //R25
  *stk-- = 0x26;         //R26
  *stk-- = 0x27;         //R27
  *stk-- = 0x30;         //R30
  *stk-- = 0x31;         //R31
     
  *stk-- = (INT16U)stk_hard & 0xff;   //SPL
  *stk-- = (INT16U)stk_hard >> 8;     //SPH
     
  *stk   = 0x00;         //SREG,禁止中断
    
  return ((OS_STK *)stk);
}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何升级STM32单片机的代码