ucos-ii和ucgui在stm32上的移植及工程

时间:2021-11-19 18:00:21

uc/os-ii移植笔记

(此部分参考了tomato的介绍)

os_cpu.h

与编译器相关的数据类型

 

typedef   unsigned char   BOOLEAN;

typedef   unsigned char   INT8U;                    /* Unsigned  8 bit quantity */

typedef   signed   char   INT8S;                    /* Signed    8 bit quantity  */

typedef   unsigned short   INT16U;                   /* Unsigned 16 bit quantity */

typedef   signed   short  INT16S;                   /* Signed   16 bit quantity */

typedef   unsigned int     INT32U;                   /* Unsigned 32 bit quantity */

typedef   signed   int    INT32S;                   /* Signed   32 bit quantity  */

 

typedef   float           FP32;                     /* Single precision floating point*/

typedef   double         FP64;                     /* Double precision floating point */

 

typedef   unsigned int    OS_STK;                   /* 堆栈类型为32位 Each stack entry is 32-bit wide */

typedef   unsigned int    OS_CPU_SR;                /* Define size of CPU status register (PSR = 32 bits) */

 

与ARM 处理器相关的代码

#define  OS_CRITICAL_METHOD   3      //进入临界段的方法

 

#if      OS_CRITICAL_METHOD == 3

#define  OS_ENTER_CRITICAL()   {cpu_sr = OS_CPU_SR_Save();} //关中断

#define  OS_EXIT_CRITICAL()     {OS_CPU_SR_Restore(cpu_sr);} //开中断

#endif

 

 

 

#if  OS_CRITICAL_METHOD == 3

OS_CPU_SR   OS_CPU_SR_Save(void);

void        OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);

#endif

 

void       OSCtxSw(void);

void       OSIntCtxSw(void);

void       OSStartHighRdy(void);

 

设置堆栈的增长方向

#define  OS_STK_GROWTH    1  /*堆栈由高地址向低地址增长*/

 

 

 

OS_CPU_C.C

用C 语言编写六个操作系统相关的函数

 

OS_STK  *OSTaskStkInit ( void   (*task)(void *p_arg), 

void   *p_arg, 

OS_STK  *ptos,

INT16U  opt)

{

    OS_STK  *stk;

    (void)opt;                                   /* 'opt' is not used, prevent warning                 */

    stk       = ptos;                            /* Load stack pointer                                 */

 

                                                 /* Registers stacked as if auto-saved on exception    */

    *(stk)   = (INT32U)0x01000000L;             /* xPSR                                               */

    *(--stk)  = (INT32U)task;                    /* Entry Point                                        */

    *(--stk)  = (INT32U)0xFFFFFFFEL;             /* R14 (LR) (init value will cause fault if ever used)*/

    *(--stk)  = (INT32U)0x12121212L;             /* R12                                                */

    *(--stk)  = (INT32U)0x03030303L;             /* R3                                                 */

    *(--stk)  = (INT32U)0x02020202L;             /* R2                                                 */

    *(--stk)  = (INT32U)0x01010101L;             /* R1                                                 */

    *(--stk)  = (INT32U)p_arg;                   /* R0 : argument                                      */

 

                                                 /* Remaining registers saved on process stack         */

    *(--stk)  = (INT32U)0x11111111L;             /* R11                                                */

    *(--stk)  = (INT32U)0x10101010L;             /* R10                                                */

    *(--stk)  = (INT32U)0x09090909L;             /* R9                                                 */

    *(--stk)  = (INT32U)0x08080808L;             /* R8                                                 */

    *(--stk)  = (INT32U)0x07070707L;             /* R7                                                 */

    *(--stk)  = (INT32U)0x06060606L;             /* R6                                                 */

    *(--stk)  = (INT32U)0x05050505L;             /* R5                                                 */

    *(--stk)  = (INT32U)0x04040404L;             /* R4                                                 */

 

    return (stk);

}

 

 

void  OSTaskCreateHook (OS_TCB *ptcb)  {ptcb=ptcb;//防止编译时出现警告 } 
void  OSTaskDelHook (OS_TCB *ptcb)   { ptcb=ptcb;//防止编译时出现警告 } 
void  OSTaskSwHook (void) 
void  OSTaskStatHook (void) 
void  OSTimeTickHook (void) 
后5 个函数为钩子函数,可以不加代码。

 

 

 

 

 

OS_CPU_A.ASM

用汇编语言编写四个与处理器相关的函数

 

;// 引用外部变量的声明

    EXTERN  OSRunning    

    EXTERN  OSPrioCur

    EXTERN  OSPrioHighRdy    

    EXTERN  OSTCBCur

    EXTERN  OSTCBHighRdy    

    EXTERN  OSIntNesting    

    EXTERN  OSTaskSwHook

    EXTERN  OSRdyGrp

    EXTERN  OSRdyTbl

    EXTERN  OSPrioHighRdy

 

;// 外部可以调用的函数

    PUBLIC  OS_CPU_SR_Save

    PUBLIC  OS_CPU_SR_Restore

    PUBLIC  OSStartHighRdy

    PUBLIC  OSCtxSw

PUBLIC  OSIntCtxSw ;//以上5个函数在os_cpu_c.c文件下有声明

 

PUBLIC  PendSVC  ;//此函数在stm3210x_it.c   stm32f10x_it.h   stm32f10x_vector.c文件下有声明

 

;//***********************************************************************************************

;//                              PendSV 所使用的几个寄存器

;//***********************************************************************************************

 

NVIC_INT_CTRL   EQU     0xE000ED04                              ;// 中断控制及状态寄存器

NVIC_SYSPRI14   EQU     0xE000ED22                              ;// 控制PendSV优先级的寄存器

NVIC_PENDSV_PRI EQU           0xFF                              ;// PendSV 异常优先级(最低)

NVIC_PENDSVSET  EQU     0x10000000                              ;// PendSV 异常触发位掩码

 

(1) OSStartHighRdy( );运行优先级最高的就绪任务

 

 

OSStartHighRdy

    LDR     R0, =NVIC_SYSPRI14                               ;// 设置PendSV优先级

    LDR     R1, =NVIC_PENDSV_PRI

    STRB    R1, [R0]

 

    MOVS    R0, #0                                          ;// 初始化线程PSP

    MSR     PSP, R0

 

    LDR     R0, =OSRunning                                   ;// OSRunning = TRUE

    MOVS    R1, #1

    STRB    R1, [R0]

 

    LDR     R0, =NVIC_INT_CTRL                               ;// 触发PendSV异常, 让PendSv任务切换开始

    LDR     R1, =NVIC_PENDSVSET

    STR     R1, [R0]

 

    CPSIE   I                                                ;// 打开总中断

 

OSStartHang

B       OSStartHang                                      ;// while(1);

 

(2)OSCtxSw();任务级的任务切换函数

OSCtxSw

    LDR     R0, =NVIC_INT_CTRL                                  ;// 触发PendSV异常

    LDR     R1, =NVIC_PENDSVSET

    STR     R1, [R0]

BX      LR

(3)OSIntCtxSw();中断级的任务切换函数

OSIntCtxSw

    LDR     R0, =NVIC_INT_CTRL                                  ;// 触发PendSV异常

    LDR     R1, =NVIC_PENDSVSET

    STR     R1, [R0]

BX      LR

(4)OSTickISR();中断服务函数

未添加

(5)临界段代码

OS_CPU_SR_Save

    MRS     R0, PRIMASK

    CPSID   I

    BX      LR

 

OS_CPU_SR_Restore

    MSR     PRIMASK, R0

BX      LR

 

 

 

(6)PendSVC代码

在cm3内核下,真正的任务文本切换是靠本函数实现

 

PendSVC

    CPSID   I                                       ;// 任务context切换是关闭中断

    MRS     R0, PSP                                 ;// 获取PSP

    CBZ     R0, OS_CPU_PendSVHandler_nosave          ;// 在多任务初始化时,PSP被初始化为0

                                                    ;// PSP如果是0,标示任务没有运行过,那么不需要压栈

                                                    ;// 直接加载任务context

    SUBS    R0, R0, #0x20                             ;// 调整PSP指针, R4-R11 共32字节

    STM     R0, {R4-R11}                              ;// 压栈R4-R11, 其他8个寄存器是在异常时自动压栈的

 

    LDR     R1, =OSTCBCur                             ;// 获取OSTCBCur->OSTCBStkPtr

    LDR     R1, [R1]

    STR     R0, [R1]                                  ;// 将当前任务的堆栈保存到自己的任务控制块

                                                    ;// OSTCBCur->OSTCBStkPtr = PSP

                                                    ;// 程序运行此位置,已经保存了当前任务的context了

OS_CPU_PendSVHandler_nosave

    ;// 使能OSTaskSwHook的时候去掉注释

    ;//PUSH    {R14}

    ;//LDR     R0, =OSTaskSwHook

    ;//BLX     R0

    ;//POP     {R14}

    

                                                      ;// 在调度之前,系统内核已经计算好

                                                     ;// OSPrioHighRdy 和 OSTCBHighRdy

    LDR     R0, =OSPrioCur                             ;// 当前任务优先级 = 就绪任务优先级

    LDR     R1, =OSPrioHighRdy                          ;// OSPrioCur = OSPrioHighRdy;

    LDRB    R2, [R1]

    STRB    R2, [R0]

 

    LDR     R0, =OSTCBCur                             ;// 当前任务控制块 = 就绪任务控制块;

    LDR     R1, =OSTCBHighRdy                         ;// OSTCBCur  = OSTCBHighRdy;

    LDR     R2, [R1]                                   ;// 

    STR     R2, [R0]                                   ;// 此时 [R2] = 新任务的PSP

 

    LDR     R0, [R2]                                  ;// R0 = 新任务的PSP

    LDM     R0, {R4-R11}                              ;// 出栈 R4 - R11

    ADDS    R0, R0, #0x20                              ;// 调整PSP

    MSR     PSP, R0                                    ;//

    

                                                      ;// 当前异常使用的堆栈是MPS

    ORR     LR, LR, #0x04                              ;// 修改LR的BIT2=1, 确保异常退出时堆栈使用PSP

                                                      ;// 类似修改CONTROL[1] = 1

 

    CPSIE   I

    BX      LR                                         ;// 异常返回

 

END

 

在引用头文件中需要包含宏定义   #define  OS_GLOBALS

 

 

 

 

 

 

 

 

 

 

 

 

 

ucgui移植笔记

 

在源文件夹的Start/GUI/LCDDriver下有个LCDDummy.c文件,主要修改此文件与自己的lcd驱动文件进行链接。

 

主要修改以下这两个函数就可以了:

unsigned int  LCD_L0_GetPixelIndex(int x, int y)

void  LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)

 

移植步骤: 
第一步:首先,得把你的TFT底层驱动和触摸驱动写好,既在裸机下,可以正常显示并实现触摸。 
第二步:加入UCGUI程序包。 
第三步:配置LCDConf.h  GUIConf.h  GUITouchConf.h

配置LCDConf.h文件如下:

#ifndef  LCDCONF_H

#define  LCDCONF_H

 

#define  LCD_XSIZE      (240)   /*X轴分辨率 */

#define  LCD_YSIZE      (320)   /* Y轴分辨率 */

 

#define  LCD_BITSPERPIXEL  (16) //像素位数

#define  LCD_FIXEDPALETTE  (565) //颜色模板

//#define  LCD_SWAP_RB        (1)

 

//以下两部分在LCDDummy.c文件中要用到

#define  LCD_CONTROLLER  9320 //控制器型号的配置

#define LCD_INIT_CONTROLLER() Touch_Initializtion();ili9320_Initializtion()   //LCD初始化                                                            

 

#endif 

 

 

在LCDDummy.c文件中,需要修改以下3个函数和一个宏判断,并添加自己的lcd驱动头文件

 

(1)宏修改

#if (LCD_CONTROLLER == -1) /

&& (!defined(WIN32) | defined(LCD_SIMCONTROLLER))

此处 将  -1  改为  9320 ,以对应上面的配置。

 

(2)LCD_L0_Init   初始化lcd函数

int  LCD_L0_Init(void) 

{

  LCD_INIT_CONTROLLER() ;          //对应LCDConf.h文件中的宏定义

  return 0;

}

 

(3)LCD_L0_GetPixelIndex  

unsigned int  LCD_L0_GetPixelIndex(int  x , int  y)

 {

  LCD_PIXELINDEX PixelIndex;

  /* Convert logical into physical coordinates (Dep. on LCDConf.h) */

  #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y

    int xPhys = LOG2PHYS_X(x, y);

    int yPhys = LOG2PHYS_Y(x, y);

  #else

    #define xPhys x

    #define yPhys y

  #endif

  /* Read from hardware ... Adapt to your system 需要自己添加的部分*/

  {

    PixelIndex = 0;

    /* ... */

    ili9320_SetCursor(x,y);

    LCD_WriteRAM_Prepare();

    PixelIndex = LCD_ReadRAM();

    return PixelIndex;

  }

  return PixelIndex;

}

 

(4)LCD_L0_SetPixelIndex

void  LCD_L0_SetPixelIndex (int  x , int  y , int  PixelIndex) 

{

  /* Convert logical into physical coordinates (Dep. on LCDConf.h) */

  #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y

    int xPhys = LOG2PHYS_X(x, y);

    int yPhys = LOG2PHYS_Y(x, y);

  #else

    #define xPhys x

    #define yPhys y

  #endif

  /* Write into hardware ... Adapt to your system 以下部分需要自己去写的,对应自己的lcd驱动文件*/

  {

    /* ... */

    ili9320_SetCursor(x,y);

    LCD_WriteRAM_Prepare();

    LCD_WriteRAM(PixelIndex);

  }

}

 

 

配置GUIConf.h文件如下:

#define GUI_OS                    (1)    /* Compile with multitasking support */

#define GUI_SUPPORT_TOUCH        (1)   /* Support a touch screen (req. win-manager) */

#define GUI_SUPPORT_UNICODE      (1)    /* Support mixed ASCII/UNICODE strings */

 

#define GUI_DEFAULT_FONT          &GUI_Font6x8

#define GUI_ALLOC_SIZE          1024*2    /* Size of dynamic memory ... For WM and memory devices*/

 

 

#define GUI_WINSUPPORT            1   /* Window manager package available */

#define GUI_SUPPORT_MEMDEV       1   /* Memory devices available */

#define GUI_SUPPORT_AA            1   /* Anti aliasing available */

 

 

配置GUITouchConf.h文件如下:

 

#define  GUI_TOUCH_AD_LEFT   400    //模拟电压值,左、右、上、下

#define  GUI_TOUCH_AD_RIGHT   3800  //根据自己的触摸屏参数填写

#define  GUI_TOUCH_AD_TOP         3730

#define  GUI_TOUCH_AD_BOTTOM      400 

 

#define   GUI_TOUCH_XSIZE 240

#define    GUI_TOUCH_YSIZE 320

  

#define GUI_TOUCH_SWAP_XY     0

#define  GUI_TOUCH_MIRROR_X   1

#define  GUI_TOUCH_MIRROR_Y    0

 

 

在源文件夹的Sample/GUI_X下GUI_X_Touch.c文件中,包含触摸相关函数,需要对其进行修改,将自己的触摸驱动添加进去即可。

 

#include "GUI.h"

#include "GUI_X.h"

 

void GUI_TOUCH_X_ActivateX(void) {

}

 

void GUI_TOUCH_X_ActivateY(void) {

}

 

int  GUI_TOUCH_X_MeasureX(void) 

{

  return   Touch_MeasurementX(); //对应触摸驱动中的读取x值函数

}

 

int  GUI_TOUCH_X_MeasureY(void) 

{

  return  Touch_MeasurementY(); //对应触摸驱动中的读取y值函数

}

 

 

 

在源文件夹的Sample/GUI_X下GUI_X.c文件中,只保留以下内容

 

#include "GUI.h"

#include "GUI_X.h"

 

void  GUI_X_Log (const char *s)  { GUI_USE_PARA(s); }

void  GUI_X_Warn (const char *s)  { GUI_USE_PARA(s); }

void  GUI_X_ErrorOut(const char *s)  { GUI_USE_PARA(s); }

 

 

 

在源文件夹的Sample/GUI_X下GUI_X_uCOS.c文件中,只修改以下内容:

static  void  CheckInit (void) 

{

if (KeyIsInited == FALSE) 

{

        KeyIsInited = TRUE;

        GUI_X_Init();

    }

}

由于 FALSE和TRUE 未定义,会提示出错,因此将他们分别改为   0和1

 

/*WM空闲时调用*/

void GUI_X_ExecIdle (void) 

{

    //OS_X_Delay(1); 原内容

    OSTimeDly(50); //新内容

}

 

 

 

最后将上面提到的三个文件加入工程就可以了。至此移植结束。

转自http://blog.ednchina.com/qwert1213131/1855929/message.aspx