(此部分参考了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
在源文件夹的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
#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驱动头文件
#if (LCD_CONTROLLER == -1) /
&& (!defined(WIN32) | defined(LCD_SIMCONTROLLER))
此处 将 -1 改为 9320 ,以对应上面的配置。
int LCD_L0_Init(void)
{
LCD_INIT_CONTROLLER() ; //对应LCDConf.h文件中的宏定义
return 0;
}
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;
}
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);
}
}
#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 */
#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
#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值函数
}
#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); }
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