UCOS-II ucGUI的完美移植
ucos_II移植总结
Ucos_II移植总结:之前已经基本算是成功的移植过ucos-II(内存管理部分没有处理),但是由于可恶的硬盘故障,让我的劳动成果付诸东流。
其间的一些移植经验没有及时总结,现在想来颇有点从头再来的悲壮!鉴于之前的教训,这次,边移植边总结,以防重蹈覆辙。
还好之前的移植过程已经解决了部分棘手的难题,现在复现一下权当是复习一下arm和ucos_II了。
这次的移植还是基于SEP4020芯片,其中的一些引导代码和中断处理代码还是照搬已经写好的代码吧,现在已经没有自己动手写的激情了!下面按照自己的移植步骤一步步总结吧:第一步:创建工程,将基本的启动代码照搬过来,建立一个最小系统,能够在开发板上运行成功。
第二步:将ucos-II源代码copy过来。
第三步:对基本的语法错误进行改正。
对工程进行编译,根据提示进行基本语法的改正。
主要包括:INCLUDES.h中头文件的调用第四步:对需要自己手动编写的函数首先要清空,防止编译报错,然后一步步手动编写代码。
1、临界段代码:os_cpu.h中OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()两个宏重新定义为我们自己写的开关中断函数。
Os_cpu_a.s文件添加如下代码:AREA MCUINIT , CODE, READONLYENTRY;/* 开启IRQ中断*/;voidEnableInterrupt(void);{EXPORT EnableInterruptEnableInterruptmrs r0,CPSRbic r0, r0, #0x80 ;set bit7 to 0msr CPSR_cxsf,r0movpc,lr ;Return to caller;};/* 关闭IRQ中断*/;voidDisableInterrupt(void);{EXPORT DisableInterruptDisableInterruptmrs r0,CPSRorr r0, r0, #0x80 ;set bit7 to 1msr CPSR_cxsf,r0movpc,lr ;Return to caller;}END2、OS_CPU_A.S文件代码编写AREA MCUINIT , CODE, READONLYENTRY;/* 开启IRQ中断*/;voidEnableInterrupt(void);{EXPORT EnableInterruptEnableInterruptmrs r0,CPSRbic r0, r0, #0x80 ;set bit7 to 0msr CPSR_cxsf,r0movpc,lr ;Return to caller;};/* 关闭IRQ中断*/;voidDisableInterrupt(void);{EXPORT DisableInterruptDisableInterruptmrs r0,CPSRorr r0, r0, #0x80 ;set bit7 to 1msr CPSR_cxsf,r0movpc,lr ;Return to caller;};任务切换代码OSCTXSWEXPORT OS_TASK_SW_ARMOS_TASK_SW_ARMSTMFD sp!, {lr} ; save pcSTMFD sp!, {lr} ; save lrMRS r14, SPSRSTMFD sp!, {r14} ; save current PSRSTMFD sp!, {r0-r12} ; save register file and ret address ;; OSPrioCur = OSPrioHighRdyIMPORT OSPrioCurIMPORT OSPrioHighRdyLDR r4, =OSPrioCurLDR r5, =OSPrioHighRdyLDRB r6, [r5]STRB r6, [r4]; Get current task TCB addressIMPORT OSTCBCurLDR r4, =OSTCBCurLDR r5, [r4]STR sp, [r5] ; store sp in preempted taskss TCB; Get highest priority task TCB addressIMPORT OSTCBHighRdyLDR r6, =OSTCBHighRdyLDR r6, [r6]LDR sp, [r6] ; get new tasks stack pointer; OSTCBCur = OSTCBHighRdySTR r6, [r4] ; set new current task TCB address;LDMFD sp!, {r0-r12} ; YYY+LDMFD sp!, {r14} ; YYY+; LDR r14, =0x000000D3MSR CPSR_cxsf, r14 ; YYY+;调试时屏掉此句才会跑的通,待解决LDMFD sp!, {lr,pc} ; YYY+;OS启动时开始运行创建的最高优先级任务; void OSStartHighRdy(void); ; Start the task with the highest priority;;EXPORT OSStartHighRdyOSStartHighRdyIMPORT OSTCBCurIMPORT OSTCBHighRdyIMPORT OSRunningLDR r4, =OSTCBCur ; Get current task TCB addressLDR r5, =OSTCBHighRdy ; Get highest priority task TCB addressLDR r5, [r5] ; get stack pointerLDR sp, [r5] ; switch to the new stackSTR r5, [r4] ; set new current task TCB address;OSRunning = 1 'TURE'LDR r4, =0x01 ; Get current task TCB addressLDR r5, =OSRunning ; Get highest priority task TCB addressSTRB r4, [r5];LDMFD sp!, {r0-r12} ; start the new taskLDMFD sp!, {r14} ; get new state from top of the stackMSR CPSR_cxsf, r14 ; CPSR should be SVC32ModeLDMFD sp!, {lr,pc};中断级任务切换EXPORT OSIntCtxSwOSIntCtxSwIMPORT OSTCBCurIMPORT OSPrioCurIMPORT OSTCBHighRdyIMPORT OSPrioHighRdyIMPORT OSTaskSwHookBL OSTaskSwHook;OSTCBCur = OSTCBHighRdyLDR r4, =OSTCBCurLDR r5, =OSTCBHighRdyLDR r6, [r5]STR r6, [r4];OSPrioCur = OSPrioHighRdyLDR r4, =OSPrioCurLDR r5, =OSPrioHighRdyLDRB r6, [r5]STRB r6, [r4];sp = OSTCBHighRdy->OSTCBStkPtrLDR r6, =OSTCBHighRdyLDR r6, [r6]LDR sp, [r6] ; get new tasks stack pointerLDMFD sp!,{r0, r1};在timedly中断服务程序中,函数开始压栈两个寄存器,为保证堆栈中数据一致,需出栈对齐;resume registersLDMFD sp!, {r0-r12} ; start the new taskLDMFD sp!, {r14} ; get new state from top of the stack; LDR r14, =0x000000D3MSR CPSR_cxsf, r14 ; CPSR SVC32Mode调试时屏掉此句才会跑的通,待解决LDMFD sp!, {lr,pc}END中断服务程序代码IRQ_DOstmfd sp!, {r0,r1}ldr r0, =IRQ_R1str r1, [r0]ldmfd sp!, {r0}ldr r1, =IRQ_R0str r0, [r1] ;保存R0和R1寄存器(因为这两个寄存器再后面要用到)add r13, r13, #4 ;restore the sp_irq top to original irq topsub r14, r14, #4mov r0, r14 ;LR_irq(R14)减4并保存在R0mrs r1, spsrorr r1, r1, #0x80 ;将SPSR_irq的中断屏蔽位置‘1’(屏蔽中断),并保存再R1 中msr cpsr_cxsf, r1 ;将模式切换到中断前的模式;---------------------------------------------------------------------------------------------bic r1, r1, #0x80 ;将原先保存的SPSR_irq的R1的中断屏蔽位清零(允许中断)stmfd sp!, {r0}stmfd sp!, {r14}stmfd sp!, {r1} ;依次将R0,R14,R1的值压入中断前模式下的堆栈(当前R0,R14,R1中存放的分别是LR_irq-4,中断前模式下的LR,SPSR_irq)ldr r0, =IRQ_R1ldr r1, [r0]stmfd sp!, {r1}ldr r1, =IRQ_R0ldr r0, [r1]stmfd sp!, {r0}ldmfd sp!, {r0,r1} ;恢复原先保存的R0和R1stmfd sp!, {r0-r12} ;将r0--r12全部压入中断以前模式下的堆栈;; Get current task TCB addressIMPORT OSTCBCurLDR r4, =OSTCBCur;及时保存当前任务中断,因为可能会进行任务切换LDR r5, [r4]STR sp, [r5] ; store sp in preempted taskss TCB;-----------------------------IMPORT int_vector_handlerbl int_vector_handler ;跳转到中断源判断和中断处理程序;----------------------------- ;restore the registerldmfd sp!, {r0-r12} ;恢复原先保存的R0-R12ldmfd sp!, {r14}msr cpsr_cxsf, r14ldmfd sp!, {r14} ;将原先保存的SPSR_irq恢复到CPSR中ldmfd sp!, {pc}3、堆栈初始化函数OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) {unsignedint *stk;opt = opt; /* 'opt' is not used, prevent warning */stk = (unsigned int *)ptos; /* Load stack pointer *//* build a context for the new task */*--stk = (unsigned int) task; /* pc */*--stk = (unsigned int) task; /* lr */*--stk = (0x60000053); /* cpsr IRQ, FIQ disable*/*--stk = 0; /* r12 */*--stk = 0; /* r11 */*--stk = 0; /* r10 */*--stk = 0; /* r9 */*--stk = 0; /* r8 */*--stk = 0; /* r7 */*--stk = 0; /* r6 */*--stk = 0; /* r5 */*--stk = 0; /* r4 */*--stk = 0; /* r3 */*--stk = 0; /* r2 */*--stk = 0; /* r1 */*--stk = (unsigned int) pdata; /* r0 */// *--stk = (0x0); /* spsr IRQ, FIQ disable */return ((void *)stk);}4、timertick函数void Timer_IRQ_Service1(void){U32 dummyread;U8 y;dummyread = *(RP)TIMER_T1ISCR;/* timerflag = 1;*///OSIntNesting = OSIntNesting + 1;clear_reg( TIMER_T1CR, 0);//关闭通道1中断OSTimeTick ();set_reg( TIMER_T1CR, 0);//使能通道1中断OS_ENTER_CRITICAL();if ((OSIntNesting == 0) && (OSLockNesting == 0)) { /* Sched. only if all ISRs done & not locked */y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to HPT ready to run */OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);if (OSPrioHighRdy != OSPrioCur) { /* No CtxSw if current task is highest rdy */OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++; /* Increment context switch counter *///OS_TASK_SW(); /* Perform a context switch */OSIntCtxSw();}}OS_EXIT_CRITICAL();}第五步:对移植好的代码进行调试。
UCGUI移植
移植UCGUI只需要修改3个文件:GUIConf.h,LCDConf.h,LCDDummy.c,并从源代码的Sample/GUI_X文件夹下复制GUI_X.c文件到工程的GUILib/Config目录下1、GUIConf.h刚开始移植的时候是没有RTOS的,LCD也不是触摸屏,所以GUI_OS和GUI_SUPPORT_TOUCH都定义为0,其他宏不需要修改2、LCDConf.hLCD_XSIZE、LCD_YSIZE和LCD_BITSPERPIXEL根据开发板LCD的配置定义,我用的屏的分辨率是480*272的,16位RGB;LCD_CONTROLLER必须定义成-1,表示使用自己定义的LCD驱动,这个LCD驱动是通过修改LCDDummy.c模板来实现的,因为LCDDummy.c中开始部分要判断宏LCD_CONTROLLER是否等于-1,如果不等于-1,LCDDummy.c中的内容不会被编译,当然LCD_CONTROLLER也可以定义成其他植,但和LCDDummy.c中一定要对应起来,而且不能等于UCGUI自带的LCD驱动号LCD_ON和LCD_OFF一定要定义,因为LCDDummy.c中的LCD_On()和LCD_Off()函数先判断相应的宏是否被定义,如果没定义则不会执行函数体中的内容UCGUI的初始化过程中的LCD部分是通过GUI_Init()(GUICore.c)->LCD_Init()(LCD.c)->LCD_L0_Init()(LCD_Dummy.c)实现的,因为LCDDummy.c中的LCD初始化函数LCD_L0_Init()调用LCD_INIT_CONTROLLER()宏来调用自定义的LCD初始化函数,所以要将宏LCD_INIT_CONTROLLER()定义成自定义的LCD 初始化函数GLCD_Init()。
也可以在不用修改LCD_INIT_CONTROLLER()宏,而是在LCD_L0_Init()直接调用GLCD_Init()3、LCDDummy.cLCDDummy.c文件中需要修改的函数有:1)、void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)2)、void LCD_L0_GetPixelIndex(int x, int y)3)、void LCD_On(void)4)、void LCD_Off(void)5)、int LCD_L0_Init(void)修改如下:其中395行的SetPixelIndex函数,422行的GetPixelIndex函数,536行的GLCD_On函数,542行GLCD_Off函数都是自己在LCD驱动文件中定义的函数,LCD_INIT_CONTROLLER()也被定义成LCD驱动文件中的LCD初始化函数4、LCD驱动文件1)、头文件drv_glcd.h:#include "lpc_types.h"#include "sdram_mt48lc2m32lfb5.h"#ifndef __GLCD_DRV_H#define __GLCD_DRV_H#define C_GLCD_PIX_CLK 9000000#define C_GLCD_REFRESH_FREQ (50HZ)#define C_GLCD_H_SIZE 480#define C_GLCD_H_PULSE 41#define C_GLCD_H_FRONT_PORCH 2#define C_GLCD_H_BACK_PORCH 2#define C_GLCD_V_SIZE 272#define C_GLCD_V_PULSE 10#define C_GLCD_V_FRONT_PORCH 2#define C_GLCD_V_BACK_PORCH 2#define LCD_RED 0xf800 /* red color */#define LCD_GREEN 0x07e0 /* green color */#define LCD_BLUE 0x001f /* blue color */#define LCD_BLACK 0x0000 /* black color */#define LCD_WHITE 0xffff /* white color */#define C_GLCD_PWR_ENA_DIS_DL Y 10000#define C_GLCD_ENA_DIS_DL Y 10000extern uint16_t LCD_Frame_Buffer[C_GLCD_H_SIZE * C_GLCD_V_SIZE];void GLCD_Init(void);void GLCD_Ctrl(BOOLEAN bEna);void SetPixelIndex(int x, int y, int PixelIndex);uint16_t GetPixelIndex(int x, int y);void GLCD_On(void);void GLCD_Off(void);#endif // __GLCD_DRV_H2)、drv_glcd.c文件#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "board.h"#include "sdram_mt48lc2m32lfb5.h"#include "drv_glcd.h"#include "lpc177x_8x_clkpwr.h"#include "lpc177x_8x_pinsel.h"uint16_t LCD_Frame_Buffer[C_GLCD_H_SIZE * C_GLCD_V_SIZE];/************************************************************************** Function Name: GLCD_Init* Parameters: const uint32_t *pPain, const uint32_t * pPallete** Return: none** Description: GLCD controller init**************************************************************************/ void GLCD_Init(void){uint32_t i;//uint32_t *pDst = (uint32_t *)LCD_Frame_Buffer;//uint32_t p0,p1,p2,p3;/*Back light enable*///Turn on LCD clockCLKPWR_ConfigPPWR(CLKPWR_PCONP_PCLCD, ENABLE);// Disable cursorLPC_LCD->CRSR_CTRL &=~(1<<0);// disable GLCD controllerLPC_LCD->CTRL = 0;// 16 bppLPC_LCD->CTRL &= ~(0x07 <<1);LPC_LCD->CTRL |=(6<<1);// TFT panelLPC_LCD->CTRL |= (1<<5);// single panelLPC_LCD->CTRL &= ~(1<<7);// notmal output// LPC_LCD->CTRL &= ~(1<<8);LPC_LCD->CTRL |= (1<<8);// little endian byte orderLPC_LCD->CTRL &= ~(1<<9);// little endian pix orderLPC_LCD->CTRL &= ~(1<<10);// disable powerLPC_LCD->CTRL &= ~(1<<11);// init pixel clockLPC_SC->LCD_CFG = 1;//CLKPWR_GetCLK(CLKPWR_CLKTYPE_PER) / ((uint32_t)C_GLCD_PIX_CLK);// bypass inrenal clk dividerLPC_LCD->POL |=(1<<26);// clock source for the LCD block is HCLKLPC_LCD->POL &= ~(1<<5);// LCDFP pin is active LOW and inactive HIGHLPC_LCD->POL |= (1<<11);// LCDLP pin is active LOW and inactive HIGH// LPC_LCD->POL |= (1<<12);LPC_LCD->POL &= ~(1<<12);// data is driven out into the LCD on the falling edge// LPC_LCD->POL |= (1<<13);LPC_LCD->POL &= ~(1<<13);// active highLPC_LCD->POL &= ~(1<<14);LPC_LCD->POL &= ~(0x3FF <<16);LPC_LCD->POL |= (C_GLCD_H_SIZE-1)<<16;// init Horizontal TimingLPC_LCD->TIMH = 0; //reset TIMH before set valueLPC_LCD->TIMH |= (C_GLCD_H_BACK_PORCH - 1)<<24;LPC_LCD->TIMH |= (C_GLCD_H_FRONT_PORCH - 1)<<16;LPC_LCD->TIMH |= (C_GLCD_H_PULSE - 1)<<8;LPC_LCD->TIMH |= ((C_GLCD_H_SIZE/16) - 1)<<2;// init Vertical TimingLPC_LCD->TIMV = 0; //reset TIMV value before settingLPC_LCD->TIMV |= (C_GLCD_V_BACK_PORCH)<<24;LPC_LCD->TIMV |= (C_GLCD_V_FRONT_PORCH)<<16;LPC_LCD->TIMV |= (C_GLCD_V_PULSE - 1)<<10;LPC_LCD->TIMV |= C_GLCD_V_SIZE - 1;// Frame Base Address doubleword alignedLPC_LCD->UPBASE = (uint32_t)LCD_Frame_Buffer & ~7UL ;LPC_LCD->LPBASE = (uint32_t)LCD_Frame_Buffer & ~7UL ;for(i = C_GLCD_ENA_DIS_DL Y; i; i--);return ;}/************************************************************************* * Function Name: GLCD_Ctrl* Parameters: Bool bEna** Return: none** Description: GLCD enable disabe sequence**************************************************************************/void GLCD_Ctrl (BOOLEAN bEna){volatile uint32_t i;if (bEna){// LCD_CTRL_bit.LcdEn = 1;LPC_LCD->CTRL |= (1<<0);for(i = C_GLCD_PWR_ENA_DIS_DL Y; i; i--);// LCD_CTRL_bit.LcdPwr= 1; // enable powerLPC_LCD->CTRL |= (1<<11);}else{// LCD_CTRL_bit.LcdPwr= 0; // disable powerLPC_LCD->CTRL &= ~(1<<11);for(i = C_GLCD_PWR_ENA_DIS_DL Y; i; i--);// LCD_CTRL_bit.LcdEn = 0;LPC_LCD->CTRL &= ~(1<<0);}}void SetPixelIndex(int x, int y, int PixelIndex){if ((x < C_GLCD_H_SIZE) && (y < C_GLCD_V_SIZE)) {LCD_Frame_Buffer[x + y * C_GLCD_H_SIZE] = (uint16_t)PixelIndex;}}uint16_t GetPixelIndex(int x, int y){if ((x < C_GLCD_H_SIZE) && (y < C_GLCD_V_SIZE)) {return LCD_Frame_Buffer[x + y * C_GLCD_H_SIZE];}return 0;}void GLCD_On(void){uint32_t i;// LCD_CTRL_bit.LcdEn = 1;LPC_LCD->CTRL |= (1<<0);for(i = C_GLCD_PWR_ENA_DIS_DL Y; i; i--);// LCD_CTRL_bit.LcdPwr= 1; // enable powerLPC_LCD->CTRL |= (1<<11);}void GLCD_Off(void){uint32_t i;// LCD_CTRL_bit.LcdPwr= 0; // disable power LPC_LCD->CTRL &= ~(1<<11);for(i = C_GLCD_PWR_ENA_DIS_DL Y; i; i--); // LCD_CTRL_bit.LcdEn = 0;LPC_LCD->CTRL &= ~(1<<0);}。
实验一 uCOS-II的移植
实验一uC/OS-II的移植1.实验目的(1)理解uCOS-II实时内核的工作原理;(2)熟悉uCOS-II在XS128上的移植过程;(3)掌握uCOS-II移植的细节。
2.实验任务(1)观察示例程序中的代码,体会实时操作系统与前后台程序的不同之处。
(2)完成由前后台程序编程到基于实时操作系统编程的思想转变。
3.预习要求(1)参考《嵌入式实时操作系统uCOS-II》(第2版),熟悉uCOS-II各模块的基本工作原理。
(2)参考《单片机与嵌入式系统开发方法》第9章内容以及《uCOS-II移植说明文档》。
熟悉uCOS-II在XS128上的移植过程。
4.实验步骤(1)打开示例程序,观察程序结构。
(2)识别出哪些是与硬件无关的文件,哪些是移植需要修改和添加的文件。
(3)打开OS_CPU.H文件,该文件定义CPU的数据类型,定义相关的宏。
打开OS_CPU_C文件,分析文件里各个函数的作用。
这两个文件是与CPU特性有关的文件。
(4)分别打开OS_CFG.H, INCLUDES.H. OS_CFG.H这三个文件,了解这三个文件的作用。
用户根据自己的应用系统来定制合适的内核服务功能.包括两个文件:OS_CFG.H, INCLUDES.H. OS_CFG.H是来配置内核, 用户根据需要对内核进行定制, 留下需要的部分, 去掉不需要的部分, 设置系统的基本情况. 比如系统可提供的最大任务数量, 是否定制邮箱服务, 是否需要系统提供任务挂起功能, 是否提供任务优先级动态改变功能等等;头文件INCLUDES.H为整个实时系统程序所需要的文件,包括了内核和用户的头文件。
(5)修改.prm文件中的中断向量,将其中的ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;改为ROM_C000 = READ_ONLYDATA_NEAR IBCC_NEAR 0xC000 TO 0xEEFF;将结尾处原有的VECTOR 0 _Startup;改为VECTOR ADDRESS 0xEFFE _Startup;再添加上VECTOR ADDRESS 0xEFF6 OSCtxSw;VECTOR ADDRESS 0xEFF0 OSTickISR两个中断向量。
关于UCOS-Ⅱ的移植
关于UC/OS-II的移植网上介绍的已经很多了,比较流行的几款处理器(例如ARM)在网上都可以直接下载移植好的代码。
由于最近选修了一门嵌入式系统的课,用的处理器是EPSON公司的S1C33系列,做实验的时候要进行操作系统的移植,这个周末花了一天半的时间学习了一下,因为毕业设计的时候做过ARM 上的移植,于是将两者比较了一下,给出一般的移植要点。
由于将来实验还要设计到GUI的移植以及文件系统的移植和网络协议的移植,我会将自己的学习笔记都记录下来。
大家下载到源码后,针对Intel 80x86的代码在uCOS-II\Ix86L目录下。
代码是80x86实模式,且在编译器大模式下编译的。
移植部分的代码可在下述文件中找到:OS_CPU.H, OS_CPU_C.C, 和OS_CPU_A.ASM。
大家可以参考这个例子,对它进行修改。
INCLUDES.H 是主头文件,在所有后缀名为.C的文件的开始都包含INCLUDES.H文件。
使用INCLUDES.H 的好处是所有的.C文件都只包含一个头文件,程序简洁,可读性强。
缺点是.C文件可能会包含一些它并不需要的头文件,额外的增加编译时间。
与优点相比,多一些编译时间还是可以接受的。
用户可以改写INCLUDES.H文件,增加自己的头文件,但必须加在文件末尾。
//////////////////////////////////////////////////////////一、(1)OS_CPU.H文件的移植(针对S1C33209)//////////////////////////////////////////////////////////OS_CPU.H 文件中包含与处理器相关的常量,宏和结构体的定义。
#ifdef OS_CPU_GLOBALS#define OS_CPU_EXT //全局变量#else#define OS_CPU_EXT extern#endif//////////////////////////////////////////////////////////由于不同的处理器有不同的字长,µC/OS-II的移植需要重新定义一系列的数据结构。
uCGUI简单移植
嵌入式图形用户界面uc/gui在nios II上的移植uc/gui是一个优秀的嵌入式图形用户界面,这几天的工作就是将它移植到nios II系统上。
前人也做了一些工作,不过大部分都是针对其他硬核处理器,针对nios II软核处理器的移植资料那简直是凤毛麟角。
在阅读了相关文档后,我决定自己亲自动手实践,这下面的很多过程都是自己摸索出来的,并通过了实验的验证。
这只是一个初步的移植,也许在以后的更复杂的应用中,还需要对其进行调整。
但对目前我的应用而言,应该足够了。
写这篇文章的目的一是由于自己记性不好,所以需要给自己留个备忘,免得以后忘的一干二净;二是给有需要的朋友提供一些参考,也好相互交流,共同进步。
请大家多提宝贵意见。
一、源码和文档下载/上有很多不同版本的源码下载,目前能下到的最新版本是3.98,不过还有一些组件不是很完整,但作基础开发已经够用了。
ucgui3.98源码下载地址:uC-GUI-V3-98.zip。
ucgui最新版用户手册下载地址:uC-GUI-user.rar。
开发软件:quartus II 6.0, Nios II IDE 6.0。
二、移植过程先来看看解压后都有些什么东西:如图,核心的东西包括Config和GUI两个文件夹,这里面是ucgui的所有源码和配置文件。
ConvertColor包含彩色转换函数,ConvertMono包含灰度到彩色转换的函数,Core包含核心程序,Font是字体文件,LCDDriver包含多种控制器驱动,Widget是窗口控件库,WM是窗口库,提供复杂的功能。
其他文件夹包含一些应用范例以及一些有用的工具,留待慢慢探索。
1、config文件的移植:Config文件夹是ucgui的配置文件夹,里面有3个文件:GUIConf.h:gui的基本属性配置文件,有很多开关可以配置,具体可以参考ucgui的用户手册,这里只需配置几个必要的参数如下:#ifndef GUICONF_H#define GUICONF_H#define GUI_OS (1) /* 支持操作系统,nios系统自带了ucosII,所以我们选择此项,使gui支持该操作系统*/#define GUI_SUPPORT_TOUCH (0) /* 支持触摸屏,由于暂时没有用触摸屏,所以关掉这个开关*/#define GUI_SUPPORT_MOUSE (0) /* 支持鼠标,暂时关闭*/#define GUI_SUPPORT_UNICODE (1) /* Unicode字符串支持*/#define GUI_DEFAULT_FONT &GUI_Font6x8/* 默认字体*/#define GUI_ALLOC_SIZE 12500/* WM和memery device分配的内存*/ #define GUI_WINSUPPORT 1 /* Window manager available */#define GUI_SUPPORT_MEMDEV 0 /* Memory devices available,由于下载到的源代码中缺少memery device组件的源码,所以关闭此项*/#define GUI_SUPPORT_AA 1 /* Anti aliasing available */#endif /* Avoid multiple inclusion */LCDConf.h:LCD控制器的硬件配置文件,这个文件与硬件直接相关,一般是根据你所使用的LCD的类型和所用的LCD控制器的类型来配置。
uCOS-II移植实验
17
五
基础知识
OS_CPU.S的移植 -OSStartHighRd
OSStartHighRd()函数是在OSStart()多任务启动之后,从最高优先 级任务的TCB控制块中获得该任务的堆栈指针sp,通过sp依次将cpu现 场恢复,这时系统就将控制权交给用户创建的该任务进程,直到该任 务被阻塞或者被其他更高优先级的任务抢占cpu.该函数仅仅在多任务 启动时被执行一次,用来启动第一个,也就是最高优先级的任务执行.
void OSIntCtxSw(void) { need_to_swap_context = 1; }
12
五
基础知识
OS_CPU.S的移植 -时钟节拍中断服务函数
时钟节拍是特定的周期性中断.这个中断可以看作是系统 心脏的脉动. 时钟的节拍式中断使得内核可以将任务延时若干个整数时 钟节拍,及当任务等待事件发生时,提供等待超时的依据. 时钟节拍率越快,系统的额外开销就越大.中断之间的时 间间隔取决于不同的应用,本系统使用S3C44B0的timer 0 作为时钟节拍源,产生间隔10mS的时钟节拍. OSTickISR()就是时钟节拍中断服务函数,也就是S3C44B0 的timer 0的中断处理函数.
jx44b0实验系统教案ucosii移植实验jx44b0实验系统教案ucosii移植实验武汉创维特信息技术有限公司201969提纲11113333222244445555基础知识实验目的实验内容预备知识实验设备6666实验过程7777实验报告要求实验目的实验目的了解ucosii内核的基本原理和主要结构掌握将ucosii内核移植到arm处理器上的基本方法掌握ucosii下基本多任务应用程序的编写实验内容实验内容学习ucosii再arm处理器上的移植过程编写简单的多任务应用程序同时实现跑马灯和数码管显示的功能预备知识预备知识了解嵌入式操作系统的构架以及具体的ucosii的组成了解操作系统的移植方法实验设备实验设备jx44b0教学实验箱adt1000仿真器和adtide集成开发环境串口连接线基础知识ucosii概述ucosii在特定处理器上的移植工作绝大部分集中在多任务切换的实现上因为这部分代码主要是用来保存和恢复处理器现场许多操作如读写寄存器操作不能用c语言只能使用特定的处理器的汇编语言来完成
uCGUI NIOS II移植及应用笔记
uC/GUI NIOS II移植及应用笔记这是前些日子在使用uc/GUI的时候即下来的一些东西原来发布在EDACN的bbs上面。
现在不知道沉到哪里去了。
现在把它重新整理发布在这里。
随后在明年过年的时候把后续的几个高级主题整理出来。
下面开始我的笔记!有兴趣的兄弟们可以来看看。
step1.下载uC/GUI的代码。
(废话没有源代码移植个鸟)我下载的时uC/GUI3.32这是能得到的源代码中最全的一个版本。
看看里面都有些什么东西。
由于这里的发间大小的限制的问题不能上传源代码。
很是郁闷。
有需要的同志可以联系我。
Email:william7447@首先看看所有名叫Simulation的东西这是uC/GUI在VC中仿真的VC工程,他的仿真功能非常的实用可以在没有具体硬件的情况下先行开发软件,而丝毫不影响软件的兼容性。
但是有一个问题比较郁闷,就是速度的问题。
大家知道嵌入式系统的CPU运算能力有限,而电脑的cpu.........我的整个项目的gui是在电脑上完成的。
拿到目标系统上面编译.......通过。
经过紧张的下载.....................运行..........显示出了第一个画面,无比的兴奋。
但测试发现极其郁闷而几乎无法解决的问题......目标系统的处理能力只有100mips而我的电脑的cpu是P4 3.0。
速度的差别太大了。
解决这个问题几乎成了我后半段工作的主题。
GUI文件夹存放全部uC/GUI源代码的地方看看它的属性有多达390个文件,全部是.c和.h。
可以看出GUI系统是一个庞大复杂的东西。
我在调试系统的时候跟踪过完整的消息循环再进入了60多个子函数调用后还没有看到希望,就彻底的放弃了跟踪的想法。
下来会具体说明这里面都有些什么东西。
config文件夹uC/GUI的配置文件夹。
里面存放的是uC/GUI的配置头文件。
改动里面的相应的就可以改动uC/GUI的配置。
这个GUI功能十分强大。
uCOS-II多核移植
uC/OS-II是源码开放、可固化、可移植、可裁剪、可剥夺的实时多任务OS 内核,适用于任务多、对实时性要求较高的场合。
uC/OS-II适合小型系统,具有执行效率高、占用空间小、实时性优良和可扩展性等特点,最小内核可编译至2K。
uC/OS-II内核提供任务调度与管理、时间管理、任务间同步与通信、内存管理和中断服务等功能。
所谓RTOS移植,就是使一个实时内核能在某个微处理器或微控制器上运行。
大部分的uC/OS-II代码试用C写的,但仍需要用C和ASM写一些与处理器相关的代码,这是因为uC/OS-II在读写处理器寄存器时只能通过ASM实现。
要是uC/OS-II正常运行,处理器必须满足一定的条件:处理器的C编译器能产生可重入代码;用C语言就可以打开和关闭中断;处理器支持中断,并能产生定时中断;处理器支持能够容纳一定量数据的硬件堆栈;处理器有将SP和其他CPU reg读出和存储到堆栈或内存中的指令;uC/OS-II移植工作主要包括以下三个方面的内容:(1)修改与处理器核编译器相关的代码:主要在includes.h中,修改数据类型定义说明,OS_ENTER_CRITICAL()、OS_EXIT_CRITICAL()和堆栈增长方向定义OS_STK_GROWTH。
(2)用C语言编写10个移植相关的函数:主要在OS_CPU_C.C中,包括堆栈初始化OSTaskStkInit()和各种回调函数。
(3)编写4个汇编语言函数:主要在OS_CPU_A.ASM中,包括:_OSTickISR //时钟中断处理函数_OSIntCtxSW //从ISR中调用的任务切换函数_OSCtxSW //从任务中调用的任务切换函数_OSStartHighRdy //启动最高优先级的任务uC/OS-II移植的关键问题:(1)临界区访问:uC/OS-II需要先禁止中断再访问代码临界段,并且在访问完毕后重新允许中断,这就使得uC/OS-II能够保护临界段代码免受多任务或ISR的破坏。
uCOS-II嵌入式操作系统介绍与移植
退出/进入临界区函数 ARMDisableInt/ARMEnableInt
1、直接操作CPSR的I、F位
2、 ARMDisableInt将CPSR的I、F位设置为1, 关闭所有中断
3、 ARMEnableInt将CPSR的I、F位设置为0, 打开中断
任务级上下文切换函数 OS_TASK_SW
ARM处理器相关宏定义
1、退出临界区
#defineOS_ENTER_CRITICAL() ARMDisableInt()
2、进入临界区
#defineOS_EXIT_CRITICAL() ARMEnableInt()
堆栈增长方向
1、堆栈由高地址向低地址增长,这个也 是和编译器有关的,当进行函数调用时, 入口参数和返回地址一般都会保存在当 前任务的堆栈中,编译器的编译选项和 由此生成的堆栈指令就会决定堆栈的增 长方向。 #define OS_STK_GROWTH 1
1、该函数当任务因为被阻塞而主动请求cpu 调度时被执行,由于此时的任务切换都是在 非异常模式下进行的,因此区别于中断级别 的任务切换。 2、它先将当前任务的cpu现场保存到该任务 堆栈中,然后获得最高优先级任务的堆栈指 针,从该堆栈中恢复此任务的cpu现场,使之 继续执行。这样就完成了一次任务切换。
多任务应用程序、调用函数ARMTargetInit初始化ARM处理器; 2、调用OSInit进行操作系统初始化; 3、调用OSTaskCreate函数两个任务:TaskLED 和TaskSEG; 4、调用ARMTargetStart函数启动时钟节拍中断; 5、调用OSStart启动系统任务调度。
OS_CPU_A.S的移植
uCOS-II移植总结
u C/OS-II移植总结RTOS移植牵涉到软件平台—编译器、硬件平台—CPU,移植前需要了解CPU及编译器的一些基本特点。
1、编译器a、堆栈运行原理本次移植的软件平台为CodeVision编译器,它的堆栈由两部分组成:硬件堆栈(HardStack)用来保存中断及函数调用的返回地址,它的大小将影响函数调用嵌套的深度,实际大小应根据中断及函数嵌套的深度来决定,并留有一定的裕度。
硬件堆栈由CPU中的指针SP实现。
软件堆栈(SoftStack)用来分配局部变量及传递参数。
在此次移植中,由CPU中的Y指针模拟实现。
b、堆栈指针所指向的单元是否为可用单元大多数编译器生成的代码,其堆栈指针所指向的单元为可用单元,也就是说在将数据压入堆栈前不用再调整堆栈指针,堆栈指针在上一次使用完后已经调整好了。
前面所说的硬件堆栈(HardStack)即为这种类型。
还有一种堆栈,其指针所指向的单元为不可用单元,在向堆栈压入数据前需调整堆栈指针,软件堆栈(SoftStack)即为这种类型。
软件堆栈设计为这种形式完全是为了适应A VR指令和软件堆栈增长方向与硬件堆栈增长方向相同。
软件堆栈(SoftStack)由Y指针模拟实现,但在A VR的指令集中只有:LD Rd,Y+ LD Rd,–Y ST Y+,Rr ST –Y,Rr要实现向下增长的堆栈就只能使用ST –Y,Rr和LD Rd,Y+。
指针指向的单元已压入数据,因此使用前需调整指针,而ST –Y,Rr正好能完成这个动作。
c、多字节变量在宽度为单字节的存储器中的分配规则多字节变量指定义为int、long int、float、double等类型的变量。
在CodeVision编译器遵循的原则是:变量低字节部分分配在内存的低地址单元,变量高字节部分分配在内存高地址单元。
如:int a a为双字节变量,其低字节保存在内存的0x24H,则高字节保存在内存的0x25H。
了解这些变量在内存中存储形式是为了能够在在线汇编中正确操作它们。
uCOS-II的移植及使用
uC/OS-II 概述-性能特点
• 源代码公开 • 可移植(Portable) – 大部分代码用ANSI C写,与处理器无关,移植时不 需修改 – 少量与微处理器硬件相关的部分用C与汇编编写, 移植时需修改:
• OS_CPU.H //与硬件相关,移植时需修改 • OS_CPU_A.ASM //集中了所有与处理器相关的汇编语言 代码 • OS_CPU.C //集中了所有与处理器相关的汇编语言代码
uC/OS-II 概述--文件结构
应用软件 (用户代码) μC/OS-II (与处理器类型无关的代码) μC/OS-II配置文件 (与应用程序有关) OS_CFG.H INCLUDES.H
体系 结构
OS_CORE.C OS_FLAG.C OS_MBOX.C OS_MEM.C OS_MUTEX.C
OS_Q.C OS_SEM.C OS_TASK.C OS_TIME.C uC/OS-II.C uC/OS-II.H
任务控制块就相当于是一个任务的身份证,没 有任务控制块的任务是不能被系统承认和管理 的。
任务控制块的结构
typedef struct os_tcb { OS_STK *OSTCBStkPtr;
//指向当前任务堆栈栈顶的指针。每个任务的堆栈容量可以是任意的。
#if OS_TASK_CREATE_EXT_EN
为了有效的对中断进行控制,在任务的代码里可使用UC/OS-II定义的宏 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()来控制何时响应中断, 何时屏蔽中断。在运行这两个宏之间的代码时是不会响应中断的,这种受保 护的代码段叫临界段。
2.1.2 uC/OS-II的任务—任务控制块(TCB)
uC/OS-II 概述-性能特点
设计任务二 uCOS-Ⅱ的移植与应用
设计任务二uC/OS-Ⅱ的移植与应用一、设计目的:1.了解嵌入式实时操作系统u C/OS-Ⅱ可移植、可裁剪等性能特点,正确理解实时操作系统中任务、信号、消息、中断等基本概念以及u C/OS-Ⅱ多任务管理的调度算法;2.掌握u C/OS-Ⅱ在ARM7上移植的方法;3.能将u C/OS-Ⅱ移植在LPC2106中,并根据具体要求创建用户任务,解决实际问题;二、具体任务:1.u C/OS-Ⅱ移植在LPC2106中。
2.编写用户任务程序,完成实时温度的采集控制。
硬件电路见参考硬件电路图,图中用滑动变阻器代替温度传感器转换后的电压,用ADC0809完成A/D转换,并用数码管显示出来。
三、参考硬件电路。
(用文字对所设计的电路功能、原理做详细说明)附图:四、源程序。
(只将C语言应用程序附在后面,其它项目文档不要提供,C语言应用程序要有一定的注释说明)源程序:/******************************************************************** ************************************/#include "config.h"#define TASK_STK_SIZE 64INT32U NUM=0;INT32U LED[10]={0x3F,0x06,0x5b,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴级数码管显示段码表INT32U P8=0x00000100; //管脚P0.8INT32U P9=0x00000200; //管脚P0.9INT32U P10=0x00000400; //管脚P0.10INT32U P11=0x00000800; //管脚P0.11INT32U P12=0x00001000; //管脚P0.12INT32U P13=0x00002000; //管脚P0.13INT32U P14=0x00004000; //管脚P0.14OS_STK Task1Stk[TASK_STK_SIZE];OS_STK Task2Stk[TASK_STK_SIZE];OS_STK Task3Stk[TASK_STK_SIZE];void Task1(void *data);void Task2(void *data);void Task3(void *data);void IO_init(void);void delay(INT32U n);/******************************************************************** *************************************** 函数名称: main** 功能描述: c语言的主函数,由它启动多任务环境********************************************************************* ***********************************/int main (void){OSInit();OSTaskCreate(Task1, (void *)0, &Task1Stk[TASK_STK_SIZE - 1], 4);OSTaskCreate(Task2, (void *)0, &Task2Stk[TASK_STK_SIZE - 1], 5);OSTaskCreate(Task3, (void *)0, &Task3Stk[TASK_STK_SIZE - 1], 6);OSStart();return 0;}/******************************************************************** *************************************** 函数名称: Task1** 功能描述: μCOS-II的第一个任务,通常由它初始化目标板和建立其它任务********************************************************************* ***********************************/void Task1(void *p_arg){p_arg = p_arg; /* 避免编译警告*/TargetInit(); /* 初始化*/IO_init();while(1){while((IOPIN&P12)!=0);IO_init();while((IOPIN&P12)==0);IOCLR=0x0000FFFF; //输出引脚清零OSTaskSuspend(4); //任务切换}}/******************************************************************** *************************************** 函数名称: Task2** 功能描述: μCOS-II的第二个任务********************************************************************* ***********************************/void Task2(void *p_arg){p_arg = p_arg; /* 避免编译警告*/ IO_init();while(1){IOCLR=P13;delay(10); //送单次脉冲启动A/D转换IOSET=P13;delay(10);IOCLR=P13;delay(10);IO_init();while((IOPIN&P14)==0);IOSET=P11; //打开传送数据开关NUM=IOPIN; //读取数据NUM=NUM>>15;OSTaskSuspend(5); //切换任务}}/******************************************************************** *************************************** 函数名称: Task3** 功能描述: μCOS-II的第三个任务********************************************************************* ***********************************/void Task3(void *p_arg){INT32U n;INT32U A,B,C;p_arg = p_arg; /* 避免编译警告*/while(1){A=NUM/100;B=NUM%100/10;C=NUM%10;IOCLR=0x000000FF;IOSET=0x00000700;for(n=0;n<500;n++){IOCLR=P10;IOSET=LED[C];delay(20);IOCLR=0x000000FF;IOSET=P10;IOCLR=P9;IOSET=LED[B]+0x0000080;delay(20);IOCLR=0x000000FF;IOSET=P9;IOCLR=P8;IOSET=LED[A];delay(20);IOCLR=0x000000FF;IOSET=P8;}OSTaskResume(5);}}/******************************************************************** *************************************** 函数名称: 其他子函数** 功能描述: 供给多任务调用********************************************************************* ***********************************/void IO_init(){PINSEL0=0x0;PINSEL1=0x0; // PO口为普通io口IODIR=0x00002FFF; // 设置PO口的方向}void delay(INT32U n){INT32U i;for(i=0;i<=n;i++);}/******************************************************************** *************************************** End Of File********************************************************************* ***********************************/五、仿真效果。
uCOS-II嵌入式实时操作系统原理与移植
1,决定是否进行上下文切换 2,保存当前执行进程的上下文
包括程序计数器PC、通用寄存器、 与任务有关的数组、表格、链等。
uC/OS-II采用可
剥夺实时内核,
含义是最高优先
0
级任务一旦就绪,
总能得到CPU使
1
用权。
系统保留4个
2
最高优先级
3
4
5
执行该任务
6
7
……
uC/OS-II 的中断(ISR)
任务2—TCB--就绪—任务堆栈
任务3--TCB--等待—任务堆栈
任务4--TCB --睡眠—任务堆栈
uC/OS-II的任务之间通信
任务之间共享的信息成为事件,同一时刻只能有一个任务使 用共享信息,因此为每个事件构建一个事件控制块ECB来保 证任务之间安全共享信息。事件控制块总数由OS_CFG.H中的 OS_MAX_EVENTS定义。事件包括信号量、邮箱、消息队列。
内存组配置文件 储存器映射MMU初始化与操作 Nand flash控制器初始化与操作
与CPU相关的配置选项 开机画面BMP文件 开机画面BMP文件 开机画面BMP文件 初始化mini2440目标板 定义任务优先级、堆栈大小及函数原型声明 初始化操作系统定时器0 开机画面BMP文件
关于信号量和等待的API功能函数
//任务循环
{
OSPrintf("\nEnter Main Task\n");
OSTimeDly(OS_TICKS_PER_SEC); //将任务延迟一段时间,进入等待态
}
}
uC/OS-II的任务都运行在无限循环中。
欢迎访问机电技术博客:/spurtltl@126/
uCOS-II实时操作系统在嵌入式平台上进行移植的一般方法和技巧.
uC/OS-II实时操作系统在嵌入式平台上进行移植的一般方法和技巧引言---实时操作系统的使用,能够简化嵌入式系统的应用开发,有效地确保稳定性和可靠性,便于维护和二次开发。
μC/OS-II是一个基于抢占式的实时多任务内核,可固化、可剪裁、具有高稳定性和可靠性,除此以外,μC/OS-II的鲜明特点就是源码公开,便于移植和维护。
在μC/OS-II官方的主页上可以查找到一个比较全面的移植范例列表。
但是,在实际的开发项目中,仍然没有针对项目所采用芯片或开发工具的合适版本。
那么,不妨自己根据需要进行移植。
本文则以在TMS320C6711 DSP上的移植过程为例,分析了μC/OS-II在嵌入式开发平台上进行移植的一般方法和技巧。
μC/OS-II移植的基本步骤在选定了系统平台和开发工具之后,进行μC/OS-II的移植工作,一般需要遵循以下的几个步骤:●深入了解所采用的系统核心●分析所采用的C语言开发工具的特点●编写移植代码●进行移植的测试●针对项目的开发平台,封装服务函数(类似80x86版本的PC.C和PC.H)系统核心无论项目所采用的系统核心是MCU、DSP、MPU,进行μC/OS-II的移植时,所需要关注的细节都是相近的。
首先,是芯片的中断处理机制,如何开启、屏蔽中断,可否保存前一次中断状态等。
还有,芯片是否有软中断或是陷阱指令,又是如何触发的。
此外,还需关注系统对于存储器的使用机制,诸如内存的地址空间,堆栈的增长方向,有无批量压栈的指令等。
在本例中,使用的是TMS320C6711 DSP。
这是TI公司6000系列中的一款浮点型号,由于其时钟频率非常高,且采用了超常指令字(VLIW)结构、类RISC指令集、多级流水等技术,所以运算性能相当强大,在通信设备、图像处理、医疗仪器等方面都有着广泛的应用。
在C6711中,中断有3种类型,即复位、不可屏蔽中断(NMI)和可屏蔽中断(INT4-INT15)。
可屏蔽中断由CSR寄存器控制全局使能,此外也可用IER寄存器分别置位使能。
ucos ii移植过程详解
uCOS-II移值过程实例讲解我将uCOS-II 移植到了EPONS 的C33209的平台上,接下来我就基于我移植好的代码讲解如何将uCOS-II从一种MCU移植到另一种MCU。
首先介绍uCOS-II的文件,如下表:ucos_ii.hos_cfg.hos_cpu.hos_core.cos_dbg_r.cos_flag.cos_mbox.cos_mem.cos_mutex.cos_q.cos_sem.cos_task.cos_time.cucos_ii.cos_cpu_c.cos_cpu_a.asm其中我们和硬件平台相关的文件的文件名被加粗了,也就是说若要将uCOS-II移植到新的平台上只要关心被以上四个文件就行了。
当然你也可以根据需要再添加你自己的和平台相关的文件,事实上我也是这么做的。
在我移植的例子中就添加了四个和平台相关的文件,文件如下表:crt0.cdrv_rtc.cvector.cext.scrt0.c是用来初始化系统的比如说MCU的一些特殊寄存器、设置外围的总线接口,等。
drv_rtc.c是用来初始化系统中的一个RTC的,这个RTC可以为内核提供必要的基于时间片调度的时基。
同时提供了对RTC开始和停止的操作函数。
在我的例子中RTC会每秒产生32次中断。
vector.c顾名思义,它是系统上电后为系统提供矢量入口表的文件,当然也包括中断向量表。
ext.s是为uc/OS-II 提供OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()函数的具体实现以及在用户程序的中断函数出入时要调用的状态保护和状态恢复函数OS_SA VEALL ()和OS_RESTOREALL ()。
前面两个函数的功能是:OS_ENTER_CRITICAL()屏蔽中断;OS_EXIT_CRITICAL()恢复原来的中断使能状态。
1. os_cpu_a.asm的说明要想顺利的移植首先要了解uCOS-II的一些基本概念。
UCGUI移植教程
UCGUI移植教程
1. 环境搭建:首先,需要准备开发板和相应的编译工具链。
可以选择使用适合的开发环境,例如Keil、IAR或者GCC等。
2.移植UCGUI的底层驱动:UCGUI的底层驱动负责和硬件进行通信,并提供一系列函数接口给上层应用。
通常需要编写底层驱动的源代码,并将其与UCGUI的库文件链接。
3.配置移植环境:UCGUI提供了一个配置文件,该文件包含了各种编译选项和参数设置,可以根据具体的硬件平台进行修改。
通过修改这些配置文件,可以让UCGUI适应不同的平台。
4.移植字体和图像资源:UCGUI支持多种字体和图像格式,但并不包含实际的字体和图像资源。
因此,需要将所需的字体和图像资源转换成UCGUI支持的格式,并将其添加到应用程序中。
5.界面设计和调试:UCGUI提供了一套界面设计工具,通常可以在PC 机上进行界面设计和调试。
可以使用该工具创建界面,并将其转换成C代码,然后添加到应用程序中进行测试和调试。
6.运行UCGUI应用程序:最后,将编写的应用程序与UCGUI的库文件进行链接,生成可执行文件。
将该可执行文件烧写至开发板并运行,即可看到UCGUI的界面效果。
以上是UCGUI的移植过程的基本步骤,具体的移植过程可能会因不同的硬件平台而有所不同。
在进行移植时,可以参考UCGUI提供的官方文档和示例代码,也可以参考其他人的移植经验和教程。
需要注意的是,UCGUI的移植过程可能会遇到一些问题,例如显示效果不符合预期、界面响应速度慢等。
这时候可以通过调试和优化来解决这些问题,例如检查驱动程序的正确性、优化界面渲染算法等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
stm32 UCGUI 完美移植作者:Changing发表时间:09-16 04:13分类:电子相关1 Comment前一篇:stm32 DA 数模转换后一篇:Stm32 SWD 下载 调试配置UCGUI是一种嵌入式应用中的图形支持系统。
它设计用于为任何使用LCD图形显示的应用提供高效的独立于处理器及LCD控制器的图形用户接口,它适用单任务或是多任务系统环境, 并适用于任意LCD控制器和CPU下任何尺寸的真实显示或虚拟显示。
它的设计架构是模块化的,由不同的模块中的不同层组成,由一个LCD驱动层来包含所有对LCD的具体图形操作。
UCGUI可以在任何的CPU上运行,因为它是100%的标准C代码编写的。
类似程序还有国产的一个MINIGUI (/zhcn/),MiniGUI 是一个自由软件项目。
其目标是提供一个快速、稳定、跨操作系统的图形用户界面(GUI)支持系统,尤其是基于 Li nux/uClinux、eCos 以及其他传统 RTOS(如 VxWorks、ThreadX、uC/OS-II、Nucleus 等)的实时嵌入式操作系统。
有机会尝试下,支持下国产,毕竟国内这样的公司不多。
这里移植的UCGUI3.90a版本,虽然已经有更新的版本,比如UCGUI3.98、甚至4.04版本。
但是目前来说只有这个版本的代码是最全的,包括了JPEG , MULTILAYER , MEMDEV ,AntiAlias等模块。
一直想尝试做一个数码相册,JEPG模块自然少不了,所以移植了这个版本。
UCGUI390a 下载整个移植过程,让LCD显示图案倒是没花多少时间,资料也比较多,但是在移植触摸屏的时候卡了好几天,然后又是 UCGUI 指针图标 移动有重影(LCD读取像素颜色函数有问题)。
总之移植是个累人的活首先需要保证你的LCD驱动和触摸屏驱动是有效的,如果你的LCD也是ili93xx 控制器 XPT2046控制器的触摸屏可以参考 stm32 驱动 T F T LCD stm32 驱动 触摸屏 两篇文章UCGUI的文件数量很大,主要用到UCGUI390a/Start/Con f ig 和 UCGUI390a/Start/GUI两个文件夹下文件,不过文件数量也已经很多了 。
相关文件介绍如下:将Con f ig和GUI下所有文件加入工程,MD K中新建工程需要划分好结构,这是UCGUI官方推荐的结构:JPEG, MemDe v, MultiLa y er , Widget , Wm 这5个文件夹的内容可以暂时不加入MD K 工程。
因为这些文件起到的是扩展功能,在移植阶段可以先不添加,等到以后用到其中的功能时再选择添加。
但是建议都添加进去,避免遇到各种无解问题。
当然前提是在配置时要把相应的功能开关关掉,在下面的步骤中会提到。
Con v erMono , Con v erColor ,Core ,F ont 这四个目录下的文件是不用修改的。
要修改的文件在LCDDri v er ,Con f ig 这两个目录下。
LCDDri v er 是LCD的驱动接口函数文件,需要将自己的LCD驱动函数提供给UCGUI调用。
需要提供3个LCD底层驱动函数:•v oid LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) LCD画点函数, 用指定颜色填充一个像素•unsigned int LCD_L0_GetPixelIndex(int x, int y) LCD读取定点颜色函数,读取一个像素点的16位RG B颜色值•v oid LCD_L0_F illRect(int x0, int y0, int x1, int y1)矩形填充函数,用指定颜色填充一个矩形 。
这个函数也可以不改使用UCGUI的函数,用一个一个的像素点填充成一个矩形。
也可以在底层驱动根据像素个数直接往GRAM 中写数据,封装成函数,供这个函数调用。
速度会快很多。
其他的画线画图形函数,也可以同样优化。
LCDDri v er 下有三个文件, LCDDumm y.c 、LCDNull.c 和LCDWin.c。
这三个都是UCGUI LCD接口模板文件。
功能一样,只是移植时修改的细节不一样。
我们可以选用其中一个,稍作修改作为接口文件。
以LCDDumm y.c为例:v iew sourceprint?0 1#include "LCD_Private.h" /* private modul definitions &config */02#include "GUI_Private.h"03#include "GUIDebug.h"0405/*#if (LCD_CONTROLLER == -1) \0 6&& (!defined(WIN32) | defined(LCD_SIMCONTROLLER))*///必须注释,否则不会编译070 8#include "ili93xx.h" //包含你的LCD驱动函数声明09#if (LCD_CONTROLLER == -1) //这句对应Config/LCDConf.h 1011........12........1314void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) { 151 6POINT_COLOR = PixelIndex; //我的画点函数使用了一个全局变量设定颜色1 7LCD_DrawPoint(x,y); //画点函数1819}2021........22........2324unsigned int LCD_L0_GetPixelIndex(int x, int y) {2526return LCD_ReadPoint(x,y); //我的读取像素颜色函数 27}28........29........3031void LCD_L0_FillRect(int x0, int y0, int x1, int y1) {3233LCD_Fill(x0,y0,x1,y1,LCD_COLORINDEX); //填充矩形函数 34/*for (; y0 <= y1; y0++) {35LCD_L0_DrawHLine(x0, y0, x1);36}*/37}UCGUI提供了一些LCD控制器的驱动函数,但是这种配置方法,可以适用于任何控制IC。
到这就算完成三分之一了,接下来修改Con f ig文件夹下文件,Con f ig下有三个文件:GUICon f.h LCDCon f.h GUITouchCon f.h还需要加入一个GUI_X.c文件,要不然编译的时候会有错误。
直接复制UCGUI390a\Sample\GUI_ X\GUI_X.c即可。
如果打开了触摸功能还需要加入一个UCGUI390a\Sample\GUI_X\GUI_X_Touch.c 。
这三个文件是UCGUI的上层配置文件,也就是GUI 一些功能的开关。
GUICon f.h:v iew sourceprint?01#ifndef GUICONF_H02#define GUICONF_H030 4#define GUI_OS (0) /* 操作系统的支持,当用到ucos 时需要打开 Compile with multitasking support */0 5#define GUI_SUPPORT_TOUCH (1) /* 触摸屏的支持 Support a touch screen (req. win-manager) */0 6#define GUI_SUPPORT_UNICODE (0) /* 用汉字库时再打开 S upport mixed ASCII/UNICODE strings */070 8#define GUI_DEFAULT_FONT &GUI_Font6x8 /* 定义字体大小 */0 9#define GUI_ALLOC_SIZE 12500 /*分配的动态内存空间 Size of dynamic memory ... For WM and memory devices*/101 1/*********************************************************************12*13* Configuration of available packages 14*/151 6#define GUI_WINSUPPORT 1 /* 窗口功能支持 要使用指针图标 必须打开 Window manager package available */1 7#define GUI_SUPPORT_MEMDEV 1 /* 内存管理 Memory devices available */1 8#define GUI_SUPPORT_AA 1 /* 抗锯齿功能,打开后可以提高显示效果 Anti aliasing available */1920#endif /* Avoid multiple inclusion */ LCDCon f.hv iew sourceprint?01#ifndef LCDCONF_H02#define LCDCONF_H030 4#define LCD_XSIZE (240) /* lcd 的水平分辨率 X-resolution of LCD, Logical coor. */0 5#define LCD_YSIZE (320) /* lcd 的垂直分辨率 Y-resolution of LCD, Logical coor. */060 7#define LCD_BITSPERPIXEL (16) /* 16位颜色RGB值 颜色深度*/08#define LCD_SWAP_RB (1) /*红蓝反色交换 */ 0910/* lcd 控制器的具体型号11*12* 设置为 -1时 会编译LCDDriver 下 LCDDummy.c13* 设置为 -2时 会编译LCDDriver 下 LCDNull.c14*15* 还需要修改LCDDriver 下文件的宏定义 才可以被编译 16* eg. LCDDummy.c:17*1 8* #if (LCD_CONTROLLER == -1) && (!defin ed(WIN32) |defined(LCD_SIMCONTROLLER))19* 改为20* #if (LCD_CONTROLLER == -1) 21*/2 2#define LCD_CONTROLLER -1 //设置为-1\-2,因为UCGUI没有相应LCD 控制IC驱动232 4#define LCD_INIT_CONTROLLER() LCD_Config(); //绑定相关LCD底层驱动的初始化函数配置完这两个文件,如果不启用触摸屏的话,UCGUI已经可以正常运行。