最新嵌入式笔记.docx
《最新嵌入式笔记.docx》由会员分享,可在线阅读,更多相关《最新嵌入式笔记.docx(21页珍藏版)》请在冰豆网上搜索。
最新嵌入式笔记
嵌入式系统软件体系结构:
1、无操作做系统
(1)循环结构(主体是循环)——做很多任务时不好(有延迟),加中断和定时器较好;
(2)前后台结构——中断
2、有操作系统——开发软件难度降低;多个任务并行执行,任务多少与内存(RAM)大小有关;
嵌入式操作系统的分类:
1、商用系统、专用系统、开源系统
2、按响应时间分类——实时操作系统、非实时操作系统
第三章
ARM:
内核、32位、占市场比例75%;
也是公司名,制作内核;
与PC相比——功耗小、价格低、集成度低,但集成了一些外设;
MIPS/W——衡量处理器的标准;
工作模式、代码密度——存储密度。
3、2ARM微处理器体系结构
偏上外设的空间属于I/O空间;
ARM的架构——1个32bitsALU,31个32bits通用寄存器及6个状态寄存器。
3、2、3ARM的寄存器组织(注:
内核寄存器):
未分组寄存器R0~R7;
分组寄存器R8~R14;
程序计数器PC(R15);
R13——堆栈指针SP;
R14——PC的备份,也常写作LR,操作系统切换用;
程序状态寄存器CPSR
3、2、4ARM处理器模式(7种)
(1)用户模式(USR);
(2)快速中断模式(FIQ);(3)外部中断模式(IRQ);
(4)管理模式(SVC);(5)数据访问终止模式(ABT);(6)系统模式(SYS);
(7)未定义指令中止模式(UND);
大部分为用户模式下运行
3、2、5异常
种类;异常向量表——P85;异常优先级;
对异常的响应:
(1)保存下一条指令地址——>LR(R14);
(2)CPSR——>SPSR;
(3)根据异常类型设置CPSR的M[4:
0];
(4)PC跳转至异常向量地址(异常向量表内的);再跳转至异常处理程序;
(5)从异常返回。
ARM指令集——32位;
Thumb指令集——16位,是ARM指令集的子集;
常用指令:
B目标地址;
BL目标地址;R14<——PC-4
BLX目标地址;ARM<——>Thumb
MOVR1,R0;R0->R1
MOVR0,#0;#表示常数——————?
?
?
?
?
?
?
?
?
?
CMPR1,R0;比较;影响CPSR标志位
LDRR0,[R1];MOV不能从存储器读取数据
LDRR0,[R1,R2];相加为内存单元地址——?
?
?
?
?
?
?
?
?
LDRR0,[R1,#8];
LDRR0,[R1,R2,LSL#2]!
;——?
?
?
?
?
?
?
?
?
?
——地址R1+R2*4的数据——》R1,LSL表示左移,LSR表示右移
ADDR0,R2,R3,LSL#1;R0=R2+R3<<1——?
?
?
?
SUBR0,R1,R2;R0=R1-R2
ADC、SBC考虑CBSR中C位——进、借位标志
SWI软中断指令
伪指令——不会生成机器码,起辅助作用
AREAInit,CODE,READONLY
……
ENTER;入口地址
……
END
Thumb指令集:
区别——没有协处理器指令;无访问CPSR、SPSR指令;
无64位乘法指令;访问寄存器受限
3、4ARM处理器编程简介
文件格式:
*.S,*.ASM;*.C,*.CC(C++程序);
一般初始化文件用汇编,主要任务用C语言
汇编语言结构——P102
一个代码段(或多个),链接器确定在存储器中的位置
混合编程:
主要是C语言内嵌套汇编语言
关心:
传递、返回用什么寄存器(特定)
3、5ARM处理器初始化分析
Bootloader:
硬件、软件初始化
1、PC初始化过程
BIOS完成计算机硬件自检——》运行MBR中的代码——》读取运行活动分区引导扇区代码——》从分区中读取内核映像并启动。
2、嵌入式系统初始化
无BIOS,硬件自检由Bootloader完成。
一般Bootloader存放于0x00000000处,即处理器开始执行程序处。
但不同处理器不同,具体可查datasheet。
Bootloader是一段小程序,通过这段小程序初始化最基本的硬件设备,并建立内存空间映射图。
常用Bootloader有:
U—boot和ViVi,其中U—boot开源
第5章嵌入式系统硬件平台与接口设计
5、1
1、S3C2410简介
ARM920T内核、0.18um;
CMOS工艺、外围模块(片上外设);
MMU(内存管理单元)
PWM——控制直流电机中的转速,开关电源,产生方波
S3C2310A微处理器的启动方式
Nandflash——SDRAM——大容量存储器
Norflash——SRAM
——XIP功能:
在片内运行程序,成本高,容量小,掉电不消失
DRAM:
动态随机存储器,存储密度大,需刷新电路;
SRAM:
静态随机存储器,使用方便,容量小,无需刷新电路;
SDRAM:
同步动态随机存储器,存储容量大,需内部刷新电路,需要同步时钟;
启动方式(Nandflash启动)——手机、嵌入式系统
两级引导:
第一级:
系统复位时,若OM[1:
0]为00,则将Nandflash的前4K字节复制到内部SRAM中(CPU自动完成,不需干预);
第二级:
Nandflash前4K一般存放Bootloader,Bootloader初始化SDRAM(外扩内存)及Nandflash控制器,及其他初始化,随后将Bootloader的其它部分复制到SDRAM中,运行SDRAM中的代码(即执行Bootloader),引导操作系统及其他应用程序。
5、2存储器系统设计(很重要)
内存一定是挂在系统总线上的;
高速缓存:
位置——CPU与主存储器(内存之间);
——作用:
提高内存系统性能;
——原理:
cache与主存有相同块号,CPU访问主存时,受限访问cache,有则取,无则访问主存,且主存数据——》cache
内存管理单元(MMU)
作用:
(1)虚拟存储空间到物理存储空间的映射,查表过程;
——解释?
程序所需内存大于物理内存时的情况;
(2)存储器访问权限控制;
(3)设置虚拟存储空间的缓冲特性
5、3串行接口设计(UART)
通过串口观察程序运行状态;
可以接收输入,可以输出好多信息;
用来运行时交流。
1、串行通信的基本概念(UART)SPI、I^2C、CAN
单工、半双工、全双工
USART:
通用同步和异步收发器(有时钟信号);
UART:
通用异步收发器。
异步通信:
(1)接收、发送时钟不同,使用波特率,存在误码;
(2)有纠错机制(奇偶校验——简单、有效、成本低)
(3)传输速率:
波特率——使用UART,晶振选择上注意——11.0592M,或用PLL
与UART有关的寄存器P160
串行接口设计
#definerUTRSTAT0(*(volatileunsigned*)0x50000010)
#definerUTRSTAT1(*(volatileunsigned*)0x50004010)
#definewrUTXH0(ch)(*(volatileunsignedchar*)0x50000020)=(unsignedchar)(ch)
#defineRdURXH0()(*(volatileunsignedchar*)0x50000024)
intmain(void)
{
charc1[1];
while
(1)
{
Uart_SendByten(0,0xa);//换行
Uart_SendByten(0,0xd);//回车
er=Uart_Getch(c1,0,0);
Uart_SendByten(0,c1[0]);
}
}
voidUart_SendByten(intUartnum,U8data)
{
if(Uartnum==0)
{
while(!
(rUTRSTAT0&0x4));//查看倒数三位的状态;判断发送缓冲区是否为空,为1为空,为0为满;
hudelay(10);
wrUTXH0(data);
}
}
charUart_Getch(char*Revdata,intUartnum,inttimeout)
{
if(Uartnum==0)
{
while(!
(rUTRSTAT0&0x1))
*Revdata=RdURXH0();
returnTRUE;
}
}
5、4I/O接口设计
GPIO例:
#defineGPCCON(*(volatileunsigned*)0X56000020)
#defineGPCDAT(*(volatileunsigned*)0X56000024)
#defineGPCUP(*(volatileunsigned*)0X56000028)
Main()
{
GPCCON=0X55555555;
GPCUP=0XFFFF;
GPCDAT=0XA0;
While
(1);
}
I/O接口——独立编址;
统一编址——与存储系统。
5、4、2A/D转换器
基本概念:
S3C2410
时钟:
2.5MHz;8路10位AD;转换速率:
500Ksps
参考电压:
3.3V;精度:
3.3V/2^10≈3.3mV
例:
A/DC
#defineADC_CON_FLAG(0x1<<15)
#defineADCCON_ENABLE_START_BYRED(0x1<<1)
#definePRSCVL(49<<6)
#defineADCCON_ENABLE_START(0x1)
#defineSTDBM(0x0<<2)
#definePRSCEN(0x1<<14)
#definerADCCON(*(volatileunsigned*)0x58000000)
#definerADCDAT0(*(volatileunsigned*)0x5800000C)
voidinit_ADdevice()
{
rADCCON=PRSCVL|ADCCON_ENABLE_START|STDBM|PRSCEN;
}
intGetADresult(intchannel)
{
rADCCON=ADCCON_ENABLE_START_BYREAD|(channel<<3)|PRSCEN|PRSCVL;
hudelay(10);
while(!
(rADCCON&ADCCON_FLAG));
return(0x3FF&rADCDAT0);
}
intmain()
{
floatd;
inti;
while
(1)
{
for(i=0;i<=2;i++)
{
d=GetADresult(i)*3.3/1023;
Uart_Print("a%d=%f\t",i,d);
hudelay(1000);
}
}
}
软件以工程为整体
实验箱自带很多源码,用“模板”文件,看说明;
Startup.c——起始文件,入口程序,只读即可。
AD控制LED亮度
While
(1)
{
K=GetADresult(0);
rGPCDAT=0x00;
Hudelay(110-k/10);
rGPCDAT=0XFF;
Hudelay(k/10+1);
}
寄存器赋值:
读——》修改——》写
PWM控制直流电机(小功率)——寄存器(PWM)
TCNTBn:
决定频率;TCMPBn:
决定占空比;TCNTBn、TCMPBn等;
TCON:
控制寄存器——开始、停止、倒相、更新寄存器
TCFG0:
预分频,死区单元(时间);TCFG1:
MUX分频
程序:
Init_Motoport()
{
rGPBCON=rGPBCON&0X3FFFF0|0XA;//B1、B0对应TOUT1,TOUT0
rTCFG0=(0<<16)|2;
rTCFG1=0;//MUX2分频
rTCNTB0=MOTOR_CONT;//很大的常数
rTCMPB0=MOTOR_MID;//PWM时钟/2000
rTCON=0X2;//updateTCNTB0、TCMPB0
rTCON=0X19;//start;死区使能
}
VoidSetPWM(intvalue)
{
rTCMPB0=MOTOR_MID+value;
}
第4章UC/OS-
操作系统
特点:
开源;
嵌入式操作系统:
提供了一个平台(软件);供软件运行、设备管理、人机接口。
软件调用硬件流程:
操作系统不允许软件直接调用硬件。
UC/OS-
的任务
1、任务的基本概念;2、任务堆栈;3、任务控制块;
4、任务调度;5、任务的创建;6、任务的挂起和恢复;
7、UC/OS-
的初始化和任务的启动;
8、任务的同步与通信
任务的基本概念:
(线程、进程)
任务:
就是一个线程,就是一个用来解决用户问题的C语言函数和与之相关联的一些数据结构而构成的一个实体。
任务的构成:
任务代码(任务执行部分)、任务堆栈(保存工作环境)、任务控制块(TCB)——(保存任务的属性)
两种任务:
用户任务、系统任务
任务状态——P118——图4-3
每一时刻只有一个任务在“运行状态”;
只有“就绪状态”可以进入“运行状态”;
“睡眠状态”的任务没有TCB
用户任务的一般结构——超循环结构(无限循环);
VoidMytask(void*pdata)
{
For(;;)
{
可以被中断的用户代码;
OS_ENTER_CRITICAL();//进入临界段(关中断)
不可以被中断的用户代码;
OS_EXIT_CRITICAL();//退出临界段(开中断)
可以被中断的用户代码;
延时函数(任务切换);//必须是系统自带延时函数(出口)
}
}
任务堆栈
堆栈:
存储器中按数据“后进先出(LIFO)”的原则组织的连续存储空间。
任务堆栈的作用:
任务切换和响应中断时保存CPU寄存器中的内容及存储任务的私有数据。
任务堆栈的创建
OS_CPUH中定义了OS_STK
TypedefunsignedintOS_STK;//16位长度
定义堆栈长度:
#defineTASK_STK_SIZE512
应用程序中:
OS_STKTaskStk[TASK_STK_SIZE];//定义了一个数组作为堆栈
创建任务函数原型:
INT8UOSTaskCreate(void(*task)(void*pd),//指向任务指针
Void*pdata,//给任务传递参数
OS_STK*ptas,//任务堆栈栈顶指针
INT8Uprio);//任务优先级——不能重复;UC/OS-
可以重复
例:
建一个任务,对战长度128字节,优先级20,任务参数MyTaskAgu
#defineMyTaskStkN64
OS_STKMyTaskStk[MyTaskStkN];//16位
Voidmain(void)
{
……
OSTaskCreate(Mytask,&MyTaskAgu,&MyTaskStk[MyTaskStkN-1],20);
——若&MyTaskAgu为(void*)0,表示无参数情况
……
}
注意:
堆栈生长方向问题;
不同处理器不同;若有低地址向高地址生长,则&MyTaskStk[0];
一般OS_CFG.H中定义了OS_STK_GROWTH作为选择开关。
任务堆栈初始化
任务堆栈初始化由操作系统负责,由函数OSTaskStkInit()完成(非用户函数)。
——该函数根据CPU不同而不同,在OS_CPU.H中定义。
最核心的是任务的调度(OSSched());
时钟节拍也是一种中断。
任务控制块及其链表
任务控制块(OS_TCB)用来记录任务的属性(结构体);
堆栈指针、任务当前状况、任务的优先级别等与任务管理有关的属性。
任务控制块把任务代码和任务堆栈关联,相当于任务的身份证。
(1)任务控制块的结构
任务控制块是一个结构类型数据,OS_TCB结构,由OSTaskCreate()函数创建一个用户任务时,函数会对任务控制块中所有成员赋予与该任务相关的数据,并驻留RAM
(2)任务控制块链表
UC/OS-
用两条链表来管理TCB;
一条空TCB链表,所有TCB没有分配给任务;
另一条是任务TCB链表,所有TCB分配给了任务;
空TCB链表由OSInit()创建;
任务链表由OSTaskCreate()创建任务时创建。
注:
1)OSInit()对UC/OS-
初始化时,RAM中创建了一个OS_TCB结构类型数组OSTCBTbl[];
2)OSTaskCreate()或OSTaskCreateExt()创建任务时将空TCB分配给该任务,且加入到任务TCB链表中;
3)删除一个任务,该任务TCB被从任务控制块链表中删除——睡眠状态
任务调度(做好很困难)
CPU中止当前任务,而去运行另一个任务叫任务切换;按某种规则进行的任务切换工作叫做任务调度。
UC/OS-
中,由任务调度器完成。
任务调度器做两项工作:
在任务就绪表中查找具有最高优先级别的就绪任务;完成任务切换。
实现函数:
OSSched()->任务级调度器或OSIntExt()->中断级调度器;注:
非用户函数;
这里主要介绍任务级调度器如何:
(1)查找任务就绪表;
(2)进行任务切换。
——与普通中断不同,SP被改变,导致中断进入、返回是PC不同。
任务就绪表
由INT8U变量OSRdyGrp与INT8U数组OSRdyTbl[]实现
优先级不会超过63:
111111,分成前3位和后3位;
前3位置位OSRdyGrp的某一位,后3位置位OSRdyTbl[n]的某一位;
因此,可将优先级看成6位2进制数,D5D4D3表示OSRdyGrp的具体数据位,低3位D2D1D0表示该数组元素具体数据位。
任务的调度(切换)
两步:
(1)获得待运行任务的TCB指针;
(2)进行断点任务切换;
任务级调度:
(1)OSSched()确认未被上锁,且不是中断服务程序调度器,首先查找最高优先级就绪任务的优先级别,找到它的TCB指针,并且赋值给OSTCBHighRdy;
(2)任务切换宏OS_TASK_SW(),函数OSCtxsw()实现。
能否正确地在CPU各寄存器中恢复断点数据,即CPU的堆栈指针SP是否有正确指向,用OSTCBStkPtr保存SP;
先出了SP之后,中断返回时,PC出栈,此时PC非中断发生时PC具体实现:
由于不具备对PC出栈、入栈指令,所以引发一次中断,中断服务程序OSCtxSw()一般用汇编语言写。
任务的创建
实质就是创建一个任务控制块,并通过任务控制块把任务代码和任务堆栈关联起来。
由函数OSTaskCreate()和OSTaskCreateExt()完成。
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*pts,INT8UPrio)
{
……
检测任务优先级是否合法;
确认优先级未被占用;
初始化任务堆栈;
获得并初始化任务控制块;
任务计数器+1;
任务调度;《—(UC/OS-
处于运行状态)
}
创建任务的一般方法
要求在OSStart()之前至少创建一个任务,习惯上创建一个启动任务,并赋予最高优先级,在调用OSStart()之前,再由它创建其他任务。
任务的挂起和恢复
挂起:
停止任务的运行,使处于等待状态
OSTaskSuspend()挂起自身或空闲任务之外的其他任务;
OSTaskSuspend()刮起的任务只能在其他任务中调用OSTaskResume()使其恢复为就绪状态。
UC/OS-
的初始化和任务的启动
OSInit()对UC/OS-
的所有全局变量和数据结构初始化;同时创建任务OSTaskIdle()(空闲任务);
如果还要使用统计任务,同时创建完成;
数据结构主要是创建包括任务控制块在内的5个空数据缓冲区;
OSStart()启动任务,前提是至少创建了一个用户任务。
用系统自带延时函数OSTimeDly(),可使性能优化,提高CPU利用率。
OS_task.cOS_core.cOS_sem.cOS_time.c
VoidTask1(void*Id)
{
INT16UK=0;
For(;;)
{
K=GetADresult(0);
rGPCDAT=rGPCDAT&(~(1<<5));
OSTimeDly(22-K/50);
rGPCDAT=rGPCDAT|(1<<5);
OSTimeDly(1+K/50);
}
}
任务的同步与通信
一个好的操作系统必须具有完备的同步和通信机制。
事件:
UC/OS-
中使用信号量、消息邮箱和消息队列这些被称作事件的中间环节来实现任务间的通信。
1、信号量(变量)
作用:
“标志位”的作用
(1):
先申请;
(2):
1—》0;(3)、(7):
使用;(4):
后申请,申请不到;
(5):
任务1使用完毕,0—》1;(6):
在申请,可用;
2、消息邮箱
作用:
任务间传递数据
3、消息队列
消息邮箱中的指针换成指针数组;可传递多个消息的数据结构。
4、事件控制块(ECB)
作为功能完善的事件,应对等待的任务有管理功能:
一是要对等待事件的所有任务进行记录并排序;
二是应该允许任务有一定的等待时限。
UC/OS-
使用事件控制块(ECB)的数据结构来描述如信号量、消息邮箱、消息队列这些事件。
(1)ECB数据机构
Typedefstruct
beadorks公司成功地创造了这样一种气氛:
商店和顾客不再是单纯的买卖关系,营业员只是起着参谋的作用,顾客成为商品或者说是作品的作参与者,营业员和顾客互相交流切磋,成为一个共同的创作体{
INT8UOSEventType;//事件类型
INT16UOSEventCnt;//信号量计数器
Void*OSEventPtr;//消息或消息队列指针
INT8UOSEventGrp;//等待事件的任务组
INT8UOSEventTbl[OS_EVENT_TBC_SIZE];
而手工艺制品是一种价格适中,不仅能锻炼同学们的动手能力,同时在制作过程中也能体会一下我国传统工艺的文化。
无论是送给朋友还是亲人都能让人体会到一份浓厚的情谊。
它的价值是不用金钱去估价而是用你一颗真诚而又温暖的心去体会的。
更能让学生家长所接受。
}OS_EVENT;
二、资料网址:
关于DIY手工艺制品的消费调查
OSEventType可取值
OS_EVENT_TYPE_SEM信号量
月生活费人数(频率)百分比OS_EVENT_TYPE_MUTEX互诉型信号量
可见“体验化消费”广受大学生的欢迎、喜欢,这是我们创业项目是否成功的关键,必须引起足够的注意。
OS_EVENT_TYPE_MBOX消息邮箱
OS_EVEN