标签:老师 另一个 ram 并且 重点 enabled 统计 文件路径 调试
首先运行老师给的范例代码熟悉开发软件和开发板的使用;收集资料简单了解UCOSIII的基本概念,然后进行UCOSIII移植(移植到STM32f407开发板);移植成功后开始进行UCOSIII实例编程(实例老师给了,就只需要进行代码修改与调试运行)
uC/OS-III(Micro C OS Three微型的C语言编写的操作系统第3版)是一个可升级、可固化、基于优先级的实时内核。它管理的任务个数不受限制。它是第三代内核,提供了现代实时内核所期望的所有功能包括资源管理、同步、内部任务交流等。uC/OS-III也提供了很多特性是在其他实时内核中所没有的,比如能在运行时测量运行性能,直接得发送信号或消息给任务,任务能同时等待多个信号量和消息队列。
防止死锁
所谓移植,是指能让uC/OS-III在某个微处理器或者为控制器上能够运行。为了方便移植,uC/OS-III的绝大部分代码使用C语言写的。在移植过程中我们重点是需要用C语言和汇编语言编写一些与处理器有关的代码。而且uC/OS-III中那些与CPU寄存器打交道的代码只能用汇编语言编写(除非C编译器支持内嵌汇编语言)。得益于uC/OS-III在设计时对可移植性的充分考虑,其在各个平台上的移植还是比较容易的。值得一提的是Micrium公司已经在各个主流的处理器上做好了移植工作,这些移植好的代码在官网上是可以直接免费下载的。我们站在巨人的肩膀上从官方移植文件入手。
移植主要涉及三方面的内容:CPU、操作系统和板级代码(板级支持包BSP)。我们的移植对象为STM32F407。
本次实验中,我们用到FSMC驱动LCD,通过前面电路的介绍,我们知道TFTLCD的RS接在FSMC的A18上面,CS接在FSMC_NE4上,并且是16位数据总线,即我们使用的是FSMC的第四区,我们在lcd.h里面定义LCD操作结构体为:
//LCD地址结构体
typedef struct
{
u16 LCD_REG;
u16 LCD_RAM;
} LCD_TypeDef;
//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11 A18作为数据命令区分线
//注意16位数据总线时STM32内部地址会右移一位对齐!
#define LCD_BASE ((u32)(0x6C000000 | 0x0007FFFE))
#define LCD ((LCD_TypeDef *) LCD_BASE)
其中,LCD_BASE,必须根据外部电路的连接设定,我们使用Bank1.sector4就是从地址0X6C000000开始,而0X0007FFFE,是A18的偏移量。我们将这个地址强制转换成LCD_TypeDef的结构体地址,就可以得到LCD->LCD_REG的地址为0X6C07FFFE,而LCD->LCD_RAM的地址为0X6C080000。所以有了这个定义,当我们要往LCD写命令/数据时,可以这样写:
LCD->LCD_REG=CMD;//写命令
LCD->LCD_RAM=DATA;//写数据
而读的时候反过来操作就可以了,如下表示:
CMD =LCD->LCD_REG;//读LCD寄存器
DATA =LCD->LCD_RAM;//读LCD数据
接下来介绍lcd.h里的另一个重要结构体:
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(vu16 regval)
{
regval=regval; //使用-O2优化的时候,必须插入的延时
LCD->LCD_REG=regval;//写入要写的寄存器序号
}
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(vu16 data)
{
data=data; //使用-O2优化的时候,必须插入的延时
LCD->LCD_RAM=data;
}
//读LCD数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
vu16 ram; //防止被优化
ram=LCD->LCD_RAM;
return ram;
}
//写寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要写入的数据
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
LCD->LCD_REG = LCD_Reg; //写入要写的寄存器序号
LCD->LCD_RAM = LCD_RegValue;//写入数据
}
//读寄存器
//LCD_Reg:寄存器地址
//返回值:读到的数据
u16 LCD_ReadReg(u16 LCD_Reg)
{
LCD_WR_REG(LCD_Reg); //写入要读的寄存器序号
delay_us(5);
return LCD_RD_DATA(); //返回读到的值
}
//开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
LCD->LCD_REG=lcddev.wramcmd;
}
//LCD写GRAM
//RGB_Code:颜色值
void LCD_WriteRAM(u16 RGB_Code)
{
LCD->LCD_RAM = RGB_Code;//写十六位GRAM
}
因为FSMC自动控制了WR/RD/CS等这些信号,通过这些函数,我们就可以对LCD进行各种操作了。
接下来要介绍的函数是坐标设置函数,代码如下:
//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏时处理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_REG(lcddev.setxcmd+1);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_REG(lcddev.setycmd+1);
LCD_WR_DATA(Ypos&0XFF);
}else
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//横屏其实就是调转x,y坐标
LCD_WriteReg(lcddev.setxcmd, Xpos);
LCD_WriteReg(lcddev.setycmd, Ypos);
}
}
该函数实现将LCD的当前操作点设置到指定坐标(x,y)。因为不同型号的屏不太一样,所以进行了区别对待。
1.编译结果
2.下载
3.LCD显示高优先级任务
4.LCD显示中优先级任务
5.LCD显示低优先级任务
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
LCD_Init(); //初始化LCD
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"Apollo STM32F4/F7");
LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 10-5");
LCD_ShowString(30,50,200,16,16,"Mutex test");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,90,200,16,16,"2018/5/30");
//创建HIGH任务
OSTaskCreate((OS_TCB * )&High_TaskTCB,
(CPU_CHAR * )"High task",
(OS_TASK_PTR )high_task,
(void * )0,
(OS_PRIO )HIGH_TASK_PRIO,
(CPU_STK * )&HIGH_TASK_STK[0],
(CPU_STK_SIZE)HIGH_STK_SIZE/10,
(CPU_STK_SIZE)HIGH_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
OS_CRITICAL_EXIT(); //退出临界区
OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身
}
//开始任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,设置默认的时间片长度
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建一个互斥信号量
OSMutexCreate((OS_MUTEX* )&TEST_MUTEX,
(CPU_CHAR* )"TEST_MUTEX",
(OS_ERR* )&err);
//创建HIGH任务
OSTaskCreate((OS_TCB * )&High_TaskTCB,
(CPU_CHAR * )"High task",
(OS_TASK_PTR )high_task,
(void * )0,
(OS_PRIO )HIGH_TASK_PRIO,
(CPU_STK * )&HIGH_TASK_STK[0],
(CPU_STK_SIZE)HIGH_STK_SIZE/10,
(CPU_STK_SIZE)HIGH_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
//创建MIDDLE任务
// OSTaskCreate((OS_TCB * )&Middle_TaskTCB,
// (CPU_CHAR * )"Middle task",
// (OS_TASK_PTR )middle_task,
// (void * )0,
// (OS_PRIO )MIDDLE_TASK_PRIO,
// (CPU_STK * )&MIDDLE_TASK_STK[0],
// (CPU_STK_SIZE)MIDDLE_STK_SIZE/10,
// (CPU_STK_SIZE)MIDDLE_STK_SIZE,
// (OS_MSG_QTY )0,
// (OS_TICK )0,
// (void * )0,
// (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
// (OS_ERR * )&err);
//创建LOW任务
// OSTaskCreate((OS_TCB * )&Low_TaskTCB,
// (CPU_CHAR * )"Low task",
// (OS_TASK_PTR )low_task,
// (void * )0,
// (OS_PRIO )LOW_TASK_PRIO,
// (CPU_STK * )&LOW_TASK_STK[0],
// (CPU_STK_SIZE)LOW_STK_SIZE/10,
// (CPU_STK_SIZE)LOW_STK_SIZE,
// (OS_MSG_QTY )0,
// (OS_TICK )0,
// (void * )0,
// (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
// (OS_ERR * )&err);
OS_CRITICAL_EXIT(); //退出临界区
OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身
}
//高优先级任务的任务函数
void high_task(void *p_arg)
{
u8 num;
OS_ERR err;
CPU_SR_ALLOC();
LCD_Init(); //初始化LCD
while(1)
{
LCD_ShowString(30,110,200,16,16,"2018/5/30");
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(5,110,115,314); //画一个矩形
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_PERIODIC,&err); //延时500ms
}
}
//中等优先级任务的任务函数
void middle_task(void *p_arg)
{
u8 num;
OS_ERR err;
CPU_SR_ALLOC();
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(125,110,234,314); //画一个矩形
LCD_DrawLine(125,130,234,130); //画线
POINT_COLOR = BLUE;
LCD_ShowString(126,111,110,16,16,"Middle Task");
OS_CRITICAL_EXIT();
while(1)
{
num++;
printf("middle task Running!\r\n");
LCD_Fill(126,131,233,313,lcd_discolor[13-num%14]); //填充区域
LED0=!LED0;
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}
//低优先级任务的任务函数
void low_task(void *p_arg)
{
static u32 times;
OS_ERR err;
while(1)
{
LCD_ShowString(30,90,200,16,16,"Low Task");
OSMutexPend (&TEST_MUTEX,0,OS_OPT_PEND_BLOCKING,0,&err);//请求互斥信号量
printf("low task Running!\r\n");
for(times=0;times<20000000;times++)
{
OSSched(); //发起任务调度
}
OSMutexPost(&TEST_MUTEX,OS_OPT_POST_NONE,&err);//释放互斥信号量
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}
20155211解雪莹:参与课设题目讨论及完成全过程;辅助调试代码。
《基于Cortex-M4的ucOS-III的应用》课程设计 结题报告
标签:老师 另一个 ram 并且 重点 enabled 统计 文件路径 调试
原文地址:https://www.cnblogs.com/guyanlin/p/9126428.html