(此部分參考了tomato的介紹)
os_cpu.h
與編譯器相關(guān)的數據類(lèi)型
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; /* 堆棧類(lèi)型為32位 Each stack entry is 32-bit wide */
typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */
與ARM 處理器相關(guān)的代碼
#define OS_CRITICAL_METHOD 3 //進(jìn)入臨界段的方法
#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} //關(guān)中斷
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} //開(kāi)中斷
#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);
設置堆棧的增長(cháng)方向
#define OS_STK_GROWTH 1 /*堆棧由高地址向低地址增長(cháng)*/
OS_CPU_C.C
用C 語(yǔ)言編寫(xiě)六個(gè)操作系統相關(guān)的函數
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;//防止編譯時(shí)出現警告 }
void OSTaskDelHook (OS_TCB *ptcb) { ptcb=ptcb;//防止編譯時(shí)出現警告 }
void OSTaskSwHook (void)
void OSTaskStatHook (void)
void OSTimeTickHook (void)
后5 個(gè)函數為鉤子函數,可以不加代碼。
OS_CPU_A.ASM
用匯編語(yǔ)言編寫(xiě)四個(gè)與處理器相關(guān)的函數
;// 引用外部變量的聲明
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個(gè)函數在os_cpu_c.c文件下有聲明
PUBLIC PendSVC ;//此函數在stm3210x_it.c stm32f10x_it.h stm32f10x_vector.c文件下有聲明
;//***********************************************************************************************
;// PendSV 所使用的幾個(gè)寄存器
;//***********************************************************************************************
NVIC_INT_CTRL EQU 0xE000ED04 ;// 中斷控制及狀態(tài)寄存器
NVIC_SYSPRI14 EQU 0xE000ED22 ;// 控制PendSV優(yōu)先級的寄存器
NVIC_PENDSV_PRI EQU 0xFF ;// PendSV 異常優(yōu)先級(最低)
NVIC_PENDSVSET EQU 0x10000000 ;// PendSV 異常觸發(fā)位掩碼
(1) OSStartHighRdy( );運行優(yōu)先級最高的就緒任務(wù)
OSStartHighRdy
LDR R0, =NVIC_SYSPRI14 ;// 設置PendSV優(yōu)先級
LDR R1, =NVIC_PENDSV_PRI
STRB R1, [R0]
MOVS R0, #0 ;// 初始化線(xiàn)程PSP
MSR PSP, R0
LDR R0, =OSRunning ;// OSRunning = TRUE
MOVS R1, #1
STRB R1, [R0]
LDR R0, =NVIC_INT_CTRL ;// 觸發(fā)PendSV異常, 讓PendSv任務(wù)切換開(kāi)始
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
CPSIE I ;// 打開(kāi)總中斷
OSStartHang
B OSStartHang ;// while(1);
(2)OSCtxSw();任務(wù)級的任務(wù)切換函數
OSCtxSw
LDR R0, =NVIC_INT_CTRL ;// 觸發(fā)PendSV異常
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
(3)OSIntCtxSw();中斷級的任務(wù)切換函數
OSIntCtxSw
LDR R0, =NVIC_INT_CTRL ;// 觸發(fā)PendSV異常
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
(4)OSTickISR();中斷服務(wù)函數
未添加
(5)臨界段代碼
OS_CPU_SR_Save
MRS R0, PRIMASK
CPSID I
BX LR
OS_CPU_SR_Restore
MSR PRIMASK, R0
BX LR
(6)PendSVC代碼
在cm3內核下,真正的任務(wù)文本切換是靠本函數實(shí)現
PendSVC
CPSID I ;// 任務(wù)context切換是關(guān)閉中斷
MRS R0, PSP ;// 獲取PSP
CBZ R0, OS_CPU_PendSVHandler_nosave ;// 在多任務(wù)初始化時(shí),PSP被初始化為0
;// PSP如果是0,標示任務(wù)沒(méi)有運行過(guò),那么不需要壓棧
;// 直接加載任務(wù)context
SUBS R0, R0, #0x20 ;// 調整PSP指針, R4-R11 共32字節
STM R0, {R4-R11} ;// 壓棧R4-R11, 其他8個(gè)寄存器是在異常時(shí)自動(dòng)壓棧的
LDR R1, =OSTCBCur ;// 獲取OSTCBCur->OSTCBStkPtr
LDR R1, [R1]
STR R0, [R1] ;// 將當前任務(wù)的堆棧保存到自己的任務(wù)控制塊
;// OSTCBCur->OSTCBStkPtr = PSP
;// 程序運行此位置,已經(jīng)保存了當前任務(wù)的context了
OS_CPU_PendSVHandler_nosave
;// 使能OSTaskSwHook的時(shí)候去掉注釋
;//PUSH {R14}
;//LDR R0, =OSTaskSwHook
;//BLX R0
;//POP {R14}
;// 在調度之前,系統內核已經(jīng)計算好
;// OSPrioHighRdy 和 OSTCBHighRdy
LDR R0, =OSPrioCur ;// 當前任務(wù)優(yōu)先級 = 就緒任務(wù)優(yōu)先級
LDR R1, =OSPrioHighRdy ;// OSPrioCur = OSPrioHighRdy;
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ;// 當前任務(wù)控制塊 = 就緒任務(wù)控制塊;
LDR R1, =OSTCBHighRdy ;// OSTCBCur = OSTCBHighRdy;
LDR R2, [R1] ;//
STR R2, [R0] ;// 此時(shí) [R2] = 新任務(wù)的PSP
LDR R0, [R2] ;// R0 = 新任務(wù)的PSP
LDM R0, {R4-R11} ;// 出棧 R4 - R11
ADDS R0, R0, #0x20 ;// 調整PSP
MSR PSP, R0 ;//
;// 當前異常使用的堆棧是MPS
ORR LR, LR, #0x04 ;// 修改LR的BIT2=1, 確保異常退出時(shí)堆棧使用PSP
;// 類(lèi)似修改CONTROL[1] = 1
CPSIE I
BX LR ;// 異常返回
END
在引用頭文件中需要包含宏定義 #define OS_GLOBALS
在源文件夾的Start\GUI\LCDDriver下有個(gè)LCDDummy.c文件,主要修改此文件與自己的lcd驅動(dòng)文件進(jìn)行鏈接。
主要修改以下這兩個(gè)函數就可以了:
unsigned int LCD_L0_GetPixelIndex(int x, int y)
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)
移植步驟:
第一步:首先,得把你的TFT底層驅動(dòng)和觸摸驅動(dòng)寫(xiě)好,既在裸機下,可以正常顯示并實(shí)現觸摸。
第二步:加入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個(gè)函數和一個(gè)宏判斷,并添加自己的lcd驅動(dòng)頭文件
#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 以下部分需要自己去寫(xiě)的,對應自己的lcd驅動(dòng)文件*/
{
/* ... */
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 //根據自己的觸摸屏參數填寫(xiě)
#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(); //對應觸摸驅動(dòng)中的讀取x值函數
}
int GUI_TOUCH_X_MeasureY(void)
{
return Touch_MeasurementY(); //對應觸摸驅動(dòng)中的讀取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 未定義,會(huì )提示出錯,因此將他們分別改為 0和1
/*WM空閑時(shí)調用*/
void GUI_X_ExecIdle (void)
{
//OS_X_Delay(1); 原內容
OSTimeDly(50); //新內容
}
聯(lián)系客服