
以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。(1)其面向特定系统应用。(2)其涉及计算机、微电子技术、电子技术、通信、和软件等行业。(3)其硬件和软件都必须具备高度可定制性。(4)其生命周期相当长。(5)其不具备本地系统开发能力,需要专门的工具和环境。
2.写出ARM的三个特殊功能寄存器
1SP(R13): R13在ARM指令中常用作堆栈指针
2LR(R14): R14保存子程序的返回地址(MOV PC,LR)
3PC(R15):R15指向正在”取指”的指令
4CPSR: CPSR可在任何运行模式下被访问,它包括条件标志位、中断禁止位、当前处理器模式标志位,以及其他一些相关的控制和状态位。
5SPSR: 异常发生时,SPSR用于保存CPSR的当前值,从异常退出时则可由SPSR来恢复CPSR。
3.进入/退出异常状态的流程
进入异常:
1在适当的LR中保存下一条指令的地址
2将CPSR复制到适当的SPSR中;
3将CPSR模式位强制设置为与异常类型相对应的值;
4强制PC从相关的异常向量处取指。
退出异常:
1将LR中的值减去偏移量后存入PC,偏移量根据异常的类型而有所不同;
2将SPSR的值复制回CPSR;
3清零在入口置位的中断禁止标志。
4.列出ARM的工作模式
1用户(user)正常程序运行的工作模式
2系统(sys)用于支持操作系统的任务等
3管理(svc)供操作系统使用的一种保护模式
4中止(abt)用于虚拟内存或存储器保护
5未定义(und)支持软件仿真的硬件协处理器
6中断(irq)中断请求处理
7快速中断(fiq)快速中断请求处理
5.描述CPSR的各个bit位
14个条件代码标志(负(N)、零(Z)、进位(C)和溢出(V) );
22个中断禁止位,分别控制一种类型的中断;
35个对当前处理器模式进行编码的位(M[4:0]);
10000用户;10001快速中断;10010中断;10011管理;10111中止,11011未定义;11111系统
41个用于指示当前执行指令(ARM还是Thumb)
6.什么是立即数
通常把在立即寻址方式指令中给出的数称为立即数
7.B,BL,BX之间的区别
跳转、带链接跳转、跳转并切换状态
1B指令跳转到指定的地址去执行程序;
2BL指令先将下一条指令的地址复制到R14(LR)链接寄存器中,然后跳转到指定地址,运行程序
3BX指令跳转到Rm指定的地址去执行程序。若Rm的bit0位为1,则跳转时自动将CPSR中的标志T置位,若bit0位为0,则跳转时自动将CPSR中的标志T复位
8.ARM内核一共37个寄存器,分组寄存器与未分组寄存器分别有那些,分别描述
9.NOP延时程序
DELAY1
NOP
NOP
NOP
SUBS R1,R1,#1
BNE DELAY1
10.FIQ比IRQ快速的原因,描述如何禁止FIQ,IRQ中断
1FIQ优先级比IRQ高,不会被中断
2FIQ有自己的专属寄存器(R8~R12),不用对通用寄存器入栈保护,可以加快速度
设置CPSR中I位F位为1;
11.MOV与LDR的区别,LDR中伪指令与加载指令的区别
MOV和LDR的区别,数据从内存到CPU之间的移动只能通过LDR/STR指令来完成,MOV只能在寄存器之间移动数据,或者把立即数移动到寄存器中。
LDR的原来的意义是将内存的某个值加载到寄存器里面;LDR伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中,所以,LDR伪指令和MOV是比较相似的
12.嵌入式系统的组成部分?各部分功能
(1)硬件层;搭建硬件环境
(2)操作系统层(包括引导程序,内核和文件系统);细分
引导程序:引导加载内核和文件系统
内核:初始化硬件设备和完成内存空间的映射,并挂载根文件系统
文件系统:启动第一个应用程序init,初始化控制台等设备后等待用户调用应用程序。
(3)应用层
根据需求完成所需的功能。
13.ARM处理器的指令集有几种,寻址方式有几种
指令集:
ARM存储器访问指令
ARM数据处理指令
乘法指令
ARM分支指令
ARM杂项指令
寻址方式:
1、立即寻址 操作数在指令中直接给出
ADD R0,R0,#1 ;R0←R0+1
ADD R0,R0,#0x3f ;R0←R0+0x3f
2、寄存器寻址 操作数在寄存器
ADD R0,R1,R2 ;R0←R1+R2
3、寄存器间接寻址 操作数的地址在寄存器
ADD R0,R1,[R2] ;R0←R1+[R2]
LDR R0,[R1] ;R0←[R1]
STR R0,[R1] ;[R1]←R0
4、基址变址寻址 操作数地址 = 基址寄存器 + 指令中给出的地址偏移
LDR R0,[R1,#4] ;R0←[R1+4]
LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4
LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4
LDR R0,[R1,R2] ;R0←[R1+R2]
5、多寄存器寻址 类似寄存器寻址,此处是多个寄存器而已
LDMIA R0,{R1,R2,R3,R4} ;R1←[R0]
;R2←[R0+4]
;R3←[R0+8]
;R4←[R0+12]
6、相对寻址 目标地址 = pc 当前值 + 指令给出的标号偏移地址
BL NEXT ;跳转到子程序NEXT 处执行
......
NEXT
......
MOV PC,LR ;从子程序返回
7、堆栈寻址
ARM 微处理器支持这四种类型的堆栈工作方式。
- 满递增堆栈:堆栈指针指向最后压入的数据,且由低地址向高地址生成。
- 满递减堆栈:堆栈指针指向最后压入的数据,且由高地址向低地址生成。
- 空递增堆栈:堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。
- 空递减堆栈:堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。
8、寄存器移位寻址
MOV R0,R2,LSL #3 ;R0=R2*8
14.嵌入式处理器有哪四类?
MCU,MPU,DSP,SOC
15.存储器映射控制寄存器(MEMMAP)
00:BOOT装载程序模式,中断向量从BOOT BLOCK重新映射
01:用户Flash模式,中间向量不重新映射,它位于Flash中
10:用户RAM模式,中断向量从静态RAM重新映射
11:用户外部存储器模式,中断向量从外部存储器重新映射(LPC22XX系列)
16.功率控制寄存器
PCON:PCON=0X01(CPU进入空闲模式),PCON=0X02(CPU进入掉电模式)
PCONP:允许将所选的外设功能关闭以实现节电的目的
17.PLL寄存器
PLLCON:包含使能和连接PLL的控制位
PLLCFG:配置PLL倍频器和分频器的值
PLLSTAT:关于PLL的工作状态和正在使用的控制位参数
PLLFEED:保证PLL正在使用的参数不被意外修改
18.VIC控制寄存器
VICIntSelect:将32个中断请求的每个中断分配额为FIQ或IRQ
VICIntEnable:控制32个中断请求(包括软件中断)的使能
VICIntEnClr:允许软件将中断使能寄存器中的一个或多个位清零
VIC参数设置寄存器
VICVectAddr:发生一个IRQ中断时,IRQ服务程序可读出该寄存器并跳转到读出的地址
VICDefVectAddr:保存了非向量IRQ的中断服务程序ISR地址
VICVectAddr0~15:保存了16个向量IRQslot的中断服务程序地址
VICVectCnt10~15:控制16个向量IRQ通道中的一个。
VIC状态寄存器
VICIRQStatus:得到所有使能并分配为IRQ中断请求的状态
VICFIQStatus:得到所有使能并分配为FIQ中断请求的状态
VICRawIntr:得到所有32个中断请求和软件中断的状态
VICProtection:管理整个芯片的所有中断(bit0置1,VIC寄存器只能在模式下访问)
19.GPIO寄存器
IOxPIN:GPIO引脚值寄存器
IOxDIR:GPIO方向寄存器
IOxSET:GPIO输出置位寄存器
IOxCLR:GPIO输出清零寄存器
20.外部中断寄存器
EXTINT:外部中断标志寄存器
EXTWAKE:外部中断唤醒寄存器
EXTMODE:外部中断模式寄存器(0电平触发,1边沿触发)
EXTPOLAR:外部中断极性寄存器(0低电平或下降沿,1高电平或上升沿)
EXTMODE=(1<<2)|(1<<3);EINT0,1电平触发,EINT3,4边沿触发
EXTPOLAR=(1<<2)|(1<<3);EINT0,1低电平/下降沿,EINT3,4高电平/上升沿
21.ARM处理器的字,半字,字节分别是32位,16位,8位
22.ARM处理器内部共有37个用户可访问的寄存器,分别为31个通用32位寄存器和6个状态寄存器。
ARM处理器共有7种不同的处理器模式,每种模式都有一组相应的寄存器组,最多可以18个活动的寄存器。
23.两种存储字节的模式
大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将低位存放在高地址。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。
24.中止异常
中止表示当前存储器的访问不能完成,是由外部的ABORT输入信号引起的异常,分为两类:
(1) 预取指中止:由程序存储器引起的中止异常;
(2) 数据中止:由数据存储器引起的中止异常;
25.ARM系统控制模块包括:
晶体振荡器:通过外接晶振或时钟源为系统提供时钟信号
复位:复位使ARM内核与外设部件进入一个确定的初始状态
存储器映射控制:控制异常向量表的重新映射方式
锁相环(PLL):将晶体振荡器输入的时钟信号倍频到一个合适的时钟频率
VPB分频器:将内核时钟与外设时钟分开的部件
功率控制:使处理器空闲或者掉电,还能关闭指定的功能部件,以降低芯片功耗
唤醒定时器:系统上电或掉电唤醒后,保证晶体整荡器能输出稳定的时钟信号
26.用户模式和系统模式不能由异常进入, 除用户模式外,其它模式均为模式,除用户模式与系统模式,其他模式均为异常模式.
27.ARM7TDMI中, T:支持16为压缩指令集Thumb; D: 支持片上Debug; M:内嵌硬件乘法器 Multiplier,; I: 嵌入式ICE,支持片上断点和调试。
28.存储器地址映射就是给寄存器分配地址;
地址映射: 为了保证CPU执行指令时可正确访问存储单元,将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址的过程称为地址映射.
29.常用的嵌入式系统
uC/OS II,uClinux,WinCE,PalmOS,VxWorks,Symbian,Android
30.RS232帧格式包括:起始位,停止位,奇偶校验位,数据段
31.
32.
33.
34.
35.
程序段:
MOV r0, #15
MOV r1, #9
start
;补充代码
stop
B stop
END
程序:
MOV r0,#15
MOV r1,#9
Start:
CMP r0,r1
SUBLT r1,r1,r0
SUBGT r0,r0,r1
BNE start
Stop:
B stop
END
36.计算PLL设置值:假设有一个基于LPC2114的系统,所使用的晶振为11.0592MHZ石英晶振。请计算出最大的系统时钟(ccls)频率为多少MHZ?此时PLL的M值和P值各为多少?请列出计算公式,并编写设置PLL的程序段。
解:Fosc= 11.0592=Fcclk/M 系统LPC2114的最大系统时钟频率为60Hz所以 M = Fcclk/Fosc约等于5最大的cclk频率Fcclk=M□Fosc=5*11.0592=55.296 MHz因为Fcco范围为156~320MHz 故P=Fcco /(Fcclk*2)=1.4 ~ 2. 因为p的值只能去2 、4、8 故 P=2 PLLCON = 1; PLLCFG = plldat; PLLFEED = 0xaa; PLLFEED = 0x55;While((PLLSTAT&(1<<10))==0); PLLCON = 3; PLLFEED = 0xaa; PLLFEED = 0x55; M — 1 = 5; P = 2; PLLCFG =5|(2<<5) return (TRUE);
37.D
一个典型的初始化
uart0_init(mode, 115200); // 初始化UART,此时DLAB = 0
U0FCR = 0x81; // 开启UART FIFO模式 触发点8字符
U0IER = 0x01; // 使能RBR中断,禁止THRE Rx线状态中断(DLAB=0时)
VICIntSelect = 0; // 选择所有中断为IRQ中断
VICVectCntl0 = 0x20 | 0x06; // slot0 对应中断源为UART
VICVectAddr0 = (uint32)uart_int; // slot0 中断服务程序
VICIntEnable = 1 << 0x06; // 使能UART中断源
IRQEnable(); // 开启目标板IRQ中断
一个典型的中断处理例程
void __irq uart_int()
...{
uint8 i;
uart0_send_str("Interrupt! ");
38.UART0初始化 通讯波特率115200,8位数据位,1位停止位,无奇偶校验
#include "config.h"
char *recver_buffer;
char rcv_new;
/**********************************************************
* 名称: UART0_Init()
* 功能: UART0初始化(通讯波特率115200,8位数据位,
1位停止位,无奇偶校验)
* 入口参数: bps 串口波特率
* 出口参数: 无
**********************************************************/
void UART0_Init(uint32 bps)
{
uint16 Fdiv;
PINSEL0 = 0x00000005; //设置串口引脚
U0LCR = 0x83; //置为除数锁存位,进行配置
Fdiv = (Fpclk >> 4) / bps; // 设置波特率
U0DLM = Fdiv >> 8;
U0DLL = Fdiv & 0xff;
U0LCR = 0x03; //清除除数锁存位,并设置工作模式模式
U0FCR = 0x81; // 使能FIFO,并设置触发点为8字节
U0IER = 0x01; // 允许RBR中断,即接收中断
}
/*********************************************************
* 名 称: IRQ_UART0
* 功 能: 串口UART0中断接收8个字节的数据
* 入口参数: 无
* 出口参数: 无
**********************************************************/
void __irq IRQ_UART0(void)
{ uint8 i;
if( 0x04 == (U0IIR&0x0F) )
{
rcv_new = 1; // 设置接收到新的数据标志,并清除中断标志位
for(i=0; i<8; i++)
{
recver_buffer[i] = U0RBR; // 读取FIFO的数据
}
VICVectAddr = 0;
} //清除中断
}
/**********************************************************
* 名称: Interrupt_Init
* 功能: 初始化串口中断,给串口中断选择为向量中断,
* 分配向量通道号1给串口
* 入口参数: 无
* 出口参数: 无
**********************************************************/
void Interrupt_Init (void)
{
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl0 = 0x26; // UART0中断通道分配到IRQ slot 0,即优先级最高
VICVectAddr0 = (int)IRQ_UART0; // 设置UART0向量地址
VICIntEnable = 0x00000040; // 使能UART0中断
}
/**********************************************************
* 名 称: UART0_SendByte
* 功 能: 向串口发送字节数据,并等待发送完毕。
* 入口参数: data 要发送的数据
* 出口参数: 无
**********************************************************/
void UART0_SendByte(char data)
{
U0THR = data;
while(0 == (U0LSR & 0x40));
}
/**********************************************************
* 名称: UART0_SendBuf()
* 功能: 通过串口发送一帧数据
* 入口参数: *buffer 存放一帧数据
* 出口参数: 无
**********************************************************/
void UART0_SendBuf(char *buffer)
{
char *pbuffer;
uint8 i;
for(pbuffer = buffer,i = 0;i < 8; i++)
UART0_SendByte(*(pbuffer++));
}
/**********************************************************
* 名称: main()函数
* 功能: 上位机接收的数据开头两个字符为0x10,0x11,
* 则原样输出,否次输出0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
* 入口参数: *buffer 存放一帧数据
* 出口参数: 无
**********************************************************/
int main (void)
{
char *send_buffer =”abcdef”; //定义发送帧缓冲区
UART0_Init(115200);
Interrupt_Init();
while(1)
{
if(1 == rcv_new) // 是否已经接收到8 Bytes的数据
{
rcv_new = 0; // 清除标志
if(0x10 ==recver_buffer[0] && 0x11 == recver_buffer[1])
{
UART0_SendBuf(send_buffer);
}
else
{
UART0_SendBuf(recver_buffer);
}
}
}
return 0;
}
39.UART驱动程序(查询)
/* xmain.c */
#define TXD0READY (1<<2) //发送数据状态OK
#define RXD0READY (1) //接收数据状态OK
/* UART串口初始化 */
void uart_init( )
{
GPHCON |= 0xa0; //GPH2,GPH3 used as TXD0,RXD0
GPHUP = 0x0; //GPH2,GPH3内部上拉
ULCON0 = 0x03; //8N1
UCON0 = 0x05; //查询方式为轮询或中断;时钟选择为PCLK
UFCON0 = 0x00; //不使用FIFO
UMCON0 = 0x00; //不使用流控
UBRDIV0 = 12; //波特率为57600,PCLK=12Mhz
}
/* UART串口单个字符打印函数 */
extern void putc(unsigned char c)
{
while( ! (UTRSTAT0 & TXD0READY) );
UTXH0 = c;
}
/* UART串口接受单个字符函数 */
extern unsigned char getc(void)
{
while( ! (UTRSTAT0 & RXD0READY) );
return URXH0;
}
/* UART串口字符串打印函数 */
extern int printk(const char* str)
{
int i = 0;
while( str[i] ){
putc( (unsigned char) str[i++] );
}
return i;
}
__inline void delay(int msec)
{
int i, j;
for(i = 1000; i > 0; i--)
for(j = msec*10; j > 0; j--)
/* do nothing */;
}
/* xmain 通过UART串口打印字符串 */
int xmain()
{
uart_init();
while(1) {
delay(10);
printk("Uart串口打印试验/r/n");
}
return 0;
}
40.为了使目标系统能正常工作,必须配置相关的寄存器,如I/O口寄存器、串口控制寄存器和串口源/目的寄存器等。S3C44B0X有2个串口,这里以串口0为例,进行相关寄存器的配置。
/*I/O口配置,定义各相关引脚功能和上拉电阻状态 */
rPCONC |=0xf0000000;
rPUPC |=0xc000;
rPCONE=(rPCONE &0x3ffeb)|0x28;
rPUPE |=0x6;
rPCONF=(rPCONF &0x3ff)+0x124800;
rPUPF |=0x1e0;
/* 定义串口0工作寄存器组 */
rULCON0=0x3; //正常模式,无奇偶校验,1位停止位,8位数据位
rUCON0=0x245; //Rx为边沿触发,Tx为电平触发,禁
//止超时中断,产生接收错误中断,普通传送、
//发送与接收为中断或轮询模式
rUFCON0=(2<<6)|(1<<4)|(6)|1; //FIFO启动需先复位
rUBRDIV0=(mclk/(baud*16)); //mclk为60000000,baud为115200
2.2 FIFO串口发送模块
串口数据发送帧格式是可编程的,它包含1个开始位,5~8个数据位,1个可选的奇偶位和1~2个停止位,这些都可以通过线控制寄存器(UCONn)来设置。发送器也能够产生发送中止条件。中止条件迫使串口输出保持在逻辑0状态,这种状态保持超过1个传输帧的时间长度。通常在1帧传输数据完整地传输完之后,再通过这个全0状态将中止信号发送给对方。中止信号发送之后,传送数据将持续地放入到输出FIFO中。要发送的数据被存放在定义的字符串指针uart0TxStr 中,串口发送模块通过读该字符串中的字符进行数据发送,核心源代码如下:
void __irq Uart0_TxFifoInt(void)
{
/* 判断FIFO发送缓冲区是否为满或字符串结束 */
while( !(rUFSTAT0 & 0x200) && (*uart0TxStr !='\\0'))
{
rUTXH0=*uart0TxStr++;
for(i=0;i<700;i++); //延迟,防止FIFO误写
}
rI_ISPC=BIT_UTXD0;
if(*uart0TxStr == '\\0')
{
rINTMSK |= BIT_UTXD0;
rI_ISPC=BIT_UTXD0;
}
}
2.3 FIFO串口接收模块
接收的数据帧格式与发送一样都是可编程的。它包括了1个起始位,5~8个数据位,1个可选的奇偶校验位和1~2个停止位,这些都可以通过线控制寄存器(UCONn)来设置。接收器还可以检测到溢出错误、奇偶校验错误、帧错误和中止状况,每种情况下都会将1个错误标志置位。
(1)溢出错误表示新的数据已经覆盖了旧的数据,因为旧的数据没有及时被读入。
(2)奇偶校验错误表示接收器检测到了意料之外的奇偶校验结果。
(3)帧错误表示接收到的数据没有有效的停止位。
(4)中止状况表示RxDn的输入被保持为0状态超过了1个帧传输的时间[3]。
(5)在FIFO模式下接收FIFO不为空,但接收器已经在3个字时间内没有接收到任何数据,就认为发生了接收超时状况。
接收模块将数据从接收移位寄存器中读出后,首先被存储到接收缓存数组keyBuf[ ]中。变量keyBufWrPt和keyBufRdPt指向缓存数组中当前写数据和读数据,当接收模块往缓存数组中写入1个字节后,keyBufWrPt加1;当Uart_IntGetKey从缓存数组中读出1个字节后,keyBufRdPt加1。两变量最大值为KEY_LEN,超过最大值时置零。接收模块的核心代码如下[4]:
/* 接收模块将移位寄存器中的数据读出到接收缓存数组中 */
void __irq Uart0_RxFifoInt(void)
{
rI_ISPC=BIT_URXD0;
if(rUFSTAT0==0)
Uart_Printf("time out\\n");
while( (rUFSTAT0&0xf) >0 ) //循环直到FIFO
//发送缓冲区为空
{
keyBuf[keyBufWrPt++]=rURXH0; //读取接收缓冲区数据存入缓存数组
if(keyBufWrPt==KEY_BUFLEN)
keyBufWrPt=0;
}
}
/* 定义1个函数从接收缓存数组中读取数据 */
char Uart_IntGetkey(void)
{
if(keyBufRdPt==KEY_BUFLEN)
keyBufRdPt=0;
while(keyBufWrPt==keyBufRdPt);//等待直到FIFO被触发
return keyBuf[keyBufRdPt++];
}
2.4 FIFO容错模块
除了接收FIFO寄存器之外,UART还具有1个状态FIFO。状态FIFO表示了在FIFO寄存器中,哪一个数据被毫无错误地接收。假设UART的FIFO连续接收到A、B、C、D、E字符,并且在接收B字符时发生了帧错误(即该字符没有停止位),在接收D字符时发生了奇偶校验错。虽然UART错误发生了,但不会产生错误中断,因为含有错误的字符还没有被CPU读取。当字符被读出时错误中断才会发生,而且只有在读出URXHn和UERSTATn寄存器后,FIFO错误状态寄存器才会被清除[5]。容错模块核心代码如下[6]。
void __irq Uart0_RxFifoErrorInt(void)
{
rI_ISPC=BIT_UERR01;
Uart_Printf("UERSTAT0=0x%x\\n",rUERSTAT0& 0xf);
while( (rUFSTAT0&0xf) >0 )
{
keyBuf[keyBufWrPt++]=rURXH0;
if(keyBufWrPt==KEY_BUFLEN);
keyBufWrPt=0;
}
}
char buf[16]// 全局变量用做数据收发int start,i;#define first 0;#define second 8;#define UART0_num 6;void UARt0Ini(){ **********//page 295;//下面是添加UOIER=0x07//UART0收发使能,RX使能;U0FCR=0x81//很遗憾ARm7不支持16字节触发点,这里设为8个字节?start=first;数组计数初始化为0i=0;}void __irg uart_exception(void){switch(U0IIR & 0x0f){case 0x04: int i;for( i=0; i++;i<8)buf[start++]=U0RBR;//接受8个字节;start=second;//准备第二次接受数据; break;case 0x0c:break;//这里不提供cti 处理;case 0x02;//THRE发送处理if(i<16)U0THR=bur[i++];break;default:break;}}void isrini(){ VICIntSelect=0x16;//uart通道选择VICIntEnable=VICIntEnable||(1<
