嵌入式课程作业记录——ARM复习提纲(下)

Posted Mount256

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式课程作业记录——ARM复习提纲(下)相关的知识,希望对你有一定的参考价值。

教材:《ARM 9嵌入式系统设计与开发应用》(熊茂华,杨震伦编著)(清华大学出版社)

考试题型:选择题40分(20题),填空题10分(5题),简答题20分(4题),读程序20分(4题),写程序10分(1题)。

留个存档作记录,因为复习提纲太长,因此分开了两篇来发。

16. 总线宽度和等待寄存器BWSCON、Bank控制寄存器BANKCONn的初始化程序,中断向量表、堆栈的初始化(考注释)?

用来设置总线宽和等待状态。例如,只要通过配置相应寄存器的值,可以使CPU时钟频率改变。

总线宽度和等待控制寄存器BWSCON和BANKCON控制寄存器的初始化程序:

// config.h
/* 总线宽度控制定义(0表示8位,1表示16位,2表示32位) */
#define  	DW8			(0x0)
#define  	DW16		(0x1)
#define  	DW32		(0x2)
#define  	WAIT		(0x1<<2)
#define  	UBLB		(0x1<<3)

/* Bank时序控制(位域)定义 */
#define     MT			15			/* 存储类型选择,仅对Bank6和Bank7有效 (2bit) */
#define     Trcd		 2			/* RAS到CAS延迟,仅对SDRAM有效 (2bit) */
#define     SCAN		 0			/* 列地址位数,仅对SDRAM有效 (2bit) */

#define     Tacs		13			/* 在nGCSn有效之前,地址信号的建立时间 (2bit) */
#define     Tcos		11			/* 在nOE有效之前,片选的建立时间 (2bit) */
#define     Tacc		 8			/* 访问周期 (3bit) */
#define     Tcoh		 6			/* nOE结束之后,片选信号的保持时间 (2bit) */
#define     Tcah		 4			/* nGCSn结束之后,地址信号的保持时间 (2bit) */
#define     Tacp		 2			/* Page模式的访问周期 (2bit) */
#define     PMC			 0			/* Page模式配置 (2bit) */

/**** 外部总线配置,用户可根据实际需要修改 ****/
#define  	B7_BWCON	(DW16|WAIT|UBLB) 
#define  	B6_BWCON	(DW32|UBLB) 	/* SDRAM所用的Bank,不要修改 */ 
#define  	B5_BWCON	(DW16|WAIT|UBLB)  
#define  	B4_BWCON	(DW16|WAIT|UBLB)  
#define  	B3_BWCON	(DW16|WAIT|UBLB)  
#define  	B2_BWCON	(DW16|WAIT|UBLB)  
#define  	B1_BWCON	(DW16|WAIT|UBLB)

#define  	B7_BANKCON	((0<<MT)|(1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B6_BANKCON	((3<<MT)|(1<<Trcd)|(1<<SCAN))		/* SDRAM所用的Bank,不要修改 */
#define  	B5_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B4_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B3_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B2_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B1_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))
#define  	B0_BANKCON	((1<<Tacs)|(1<<Tcos)|(7<<Tacc)|(1<<Tcoh)|(1<<Tcah)|(1<<Tacp)|(0<<PMC))



// s3c2410.h
// BWSCON寄存器基地址定义
#define  BWSCON_ADDR	0x48000000
// Memory control 
#define rBWSCON    (*(volatile unsigned *)0x48000000) //Bus width & wait status
#define rBANKCON0  (*(volatile unsigned *)0x48000004) //Boot ROM control
#define rBANKCON1  (*(volatile unsigned *)0x48000008) //BANK1 control
#define rBANKCON2  (*(volatile unsigned *)0x4800000c) //BANK2 cControl
#define rBANKCON3  (*(volatile unsigned *)0x48000010) //BANK3 control
#define rBANKCON4  (*(volatile unsigned *)0x48000014) //BANK4 control
#define rBANKCON5  (*(volatile unsigned *)0x48000018) //BANK5 control
#define rBANKCON6  (*(volatile unsigned *)0x4800001c) //BANK6 control
#define rBANKCON7  (*(volatile unsigned *)0x48000020) //BANK7 control
#define rREFRESH   (*(volatile unsigned *)0x48000024) //DRAM/SDRAM refresh
#define rBANKSIZE  (*(volatile unsigned *)0x48000028) //Flexible Bank Size
#define rMRSRB6    (*(volatile unsigned *)0x4800002c) //Mode register set for SDRAM
#define rMRSRB7    (*(volatile unsigned *)0x48000030) //Mode register set for SDRAM


// target.c
// 总线配置数据表 (用户可以在config.h文件中配置总线)	
const uint32  __BUS_INIT[] =
	
	(B7_BWCON<<28)|(B6_BWCON<<24)|(B5_BWCON<<20)|(B4_BWCON<<16)|(B3_BWCON<<12)|(B2_BWCON<<8)|(B1_BWCON<<4),	// BWSCON寄存器
	B0_BANKCON,			// BANKCON0寄存器
	B1_BANKCON,			// BANKCON1寄存器 	
	B2_BANKCON, 		// BANKCON2寄存器
	B3_BANKCON, 		// BANKCON3寄存器
	B4_BANKCON, 		// BANKCON4寄存器
	B5_BANKCON, 		// BANKCON5寄存器
	B6_BANKCON, 		// BANKCON6寄存器 (SDRAM)
	B7_BANKCON, 		// BANKCON7寄存器 (SRAM)
	(1<<23)|(0<<22)|(0<<20)|(3<<18)|(1113),		// REFRESH寄存器(SDRAM) 例如:period=15.6us, HCLK=60Mhz, (2048+1-15.6*60)
	(1<<7)|(1<<5)|(1<<4)|(2<<0),				// BANKSIZE寄存器,128MB
	(3<<4),										// MRSRB6寄存器
	(3<<4)										// MRSRB7寄存器	
;


// target.c
/*********************************************************************************************************
** Function name: TargetBusInit
** Descriptions: 针对目标板的总线系统初始化,包括Bank的宽度、SDRAM控制器等等。
**               不要在此函数中加入任何用户代码。
** Input: 无
** Output: 无
********************************************************************************************************/
void  TargetBusInit(void)
   
#ifdef	__Release	
    int  i;
    volatile uint32  *cp1;
    							    		
	// 总线设置,初始化SDRAM控制器
	cp1 = (void *)BWSCON_ADDR;
	for(i=0; i<13; i++)
	
		*cp1++ = __BUS_INIT[i];		
	
#endif    

中断向量表初始化:

;定义堆栈的大小
USR_STACK_LEGTH     EQU         64
SVC_STACK_LEGTH     EQU         0
FIQ_STACK_LEGTH     EQU         16
IRQ_STACK_LEGTH     EQU         64
ABT_STACK_LEGTH     EQU         0
UND_STACK_LEGTH     EQU         0

			AREA	Example5,CODE,READONLY	; 声明代码段Example5
			ENTRY				; 标识程序入口
			CODE32				; 声明32位ARM指令
START		MOV		R0,#0
			MOV		R1,#1
			MOV		R2,#2
			MOV		R3,#3
			MOV		R4,#4
			MOV		R5,#5
			MOV		R6,#6
			MOV		R7,#7
			MOV		R8,#8
			MOV		R9,#9
			MOV		R10,#10
			MOV		R11,#11
			MOV		R12,#12
			
			BL		InitStack	; 初始化各模式下的堆栈指针
			
			; 打开IRQ中断 (将CPSR寄存器的I位清零)
			MRS		R0,CPSR			; R0 <= CPSR
			BIC		R0,R0,#0x80 
			MSR		CPSR_cxsf,R0	; CPSR <= R0
						
			; 切换到用户模式
        	MSR     CPSR_c, #0xd0
        	MRS		R0,CPSR
        	
        	; 切换到管理模式
        	MSR     CPSR_c, #0xdf
        	MRS		R0,CPSR		

HALT		B		HALT

; 名称:InitStack
; 功能:堆栈初始化,即初始化各模式下的堆栈指针。
; 入口参数:无
; 出口参数:无
; 说明:在特权模式下调用此子程序,比如复位后的管理模式
InitStack    
        	MOV     R0, LR		; R0 <= LR,因为各种模式下R0是相同的

;设置管理模式堆栈
        	MSR     CPSR_c, #0xd3
        	LDR     SP, StackSvc
;设置中断模式堆栈
        	MSR     CPSR_c, #0xd2
        	LDR     SP, StackIrq
;设置快速中断模式堆栈
        	MSR     CPSR_c, #0xd1
        	LDR     SP, StackFiq
;设置中止模式堆栈
        	MSR     CPSR_c, #0xd7
      		LDR     SP, StackAbt
;设置未定义模式堆栈
        	MSR     CPSR_c, #0xdb
        	LDR     SP, StackUnd
;设置系统模式堆栈
        	MSR     CPSR_c, #0xdf
        	LDR     SP, StackUsr

        	MOV     PC, R0

StackUsr   	DCD     UsrStackSpace + (USR_STACK_LEGTH - 1)*4
StackSvc    DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)*4
StackIrq    DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)*4
StackFiq    DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)*4
StackAbt    DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)*4
StackUnd    DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)*4


; 分配堆栈空间 
        	AREA    MyStacks, DATA, NOINIT, ALIGN=2
UsrStackSpace     	SPACE  	USR_STACK_LEGTH * 4 	; 用户(系统)模式堆栈空间
SvcStackSpace      	SPACE  	SVC_STACK_LEGTH * 4  	; 管理模式堆栈空间
IrqStackSpace      	SPACE  	IRQ_STACK_LEGTH * 4  	; 中断模式堆栈空间
FiqStackSpace      	SPACE  	FIQ_STACK_LEGTH * 4  	; 快速中断模式堆栈空间
AbtStackSpace      	SPACE  	ABT_STACK_LEGTH * 4  	; 中止义模式堆栈空间
UndtStackSpace     	SPACE  	UND_STACK_LEGTH * 4  	; 未定义模式堆栈			
			
			
			END	

堆栈初始化:

/*********************************************************************************************************
** 函数名称: OSTaskStkInit
** 功能描述: 任务堆栈初始化代码,本函数调用失败会使系统崩溃
** 输 入: task  : 任务开始执行的地址
**         pdata :传递给任务的参数
**         ptos  :任务的堆栈开始位置
**         opt   :附加参数,当前版本对于本函数无用,具体意义参见OSTaskCreateExt()的opt参数
** 输 出: 栈顶指针位置
** 全局变量:
** 调用模块: 
********************************************************************************************************/

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)

    OS_STK *stk;

    opt    = opt;                           /* 'opt'  没有使用。作用是避免编译器警告    */
    stk    = ptos;                          /* 获取堆栈指针 */

                                            /* 建立任务环境,ADS1.2使用满递减堆栈       */
    *stk = (OS_STK) task;                   /*  pc  */
    *--stk = (OS_STK) task;                 /*  lr  */

    *--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,第一个参数使用R0传递   */
    *--stk = (USER_USING_MODE|0x00);	    /*  spsr,允许 IRQ, FIQ 中断   */
    *--stk = 0;                             /*  关中断计数器OsEnterSum;    */

    return (stk);

17. S3C2410电源控制模式有正常、慢速、空闲和电源关断4种模式

  • 【正常模式】电源管理模块为CPU和S3C2410中的外围设备提供时钟。在这个模式由于所有外围设备都处于开启状态,因此功耗达到最大。
  • 【慢速模式(无PLL模式)】不使用PLL,而是用外部时钟(XTIPLL/EXTCLK)直接作为FCLK时钟(CPU内核时钟)。在这种模式下,功耗仅取决于外部时频率,与PLL无关。
  • 【空闲模式】电源管理模块只断开FCLK,但仍为所有其他外围设备提供时钟。该模式降低了CPU的功耗,任何中断请求可以从空闲模式唤醒CPU。
  • 【掉电模式】电源管理模块断开内部电源。除了唤醒逻辑外,CPU和内部逻辑都不会产生功耗。激活掉电模式需要两个独立的电源,一个电源为唤醒逻辑供电,另一个电源为包括CPU在内的其他内部逻辑供电,并且可以开关控制。在该模式下,第二个电源将关闭。

18. 汇编语言和C混合编程通常有哪几种方式?

常见的有3种方式:

  • 在C代码中嵌入汇编指令
void string_copy(char *dst,const char *str)

  char ch;
  __asm
  
    loop
      LDRB  ch,[str],#1
      STRB  ch,[dst],#1
      CMP    ch,#0
      BNE loop 
  


int main()

  char *a="hello world!"
  char b[64];
  string_copy(a,b);
  return 0;

  • C调用汇编:

(1)汇编export

(2)C语言定义 extern function

(3)C语言调用汇编

myArm.s
  AREA  myARM,CODE ,READONLY
  export my_strcopy
my_strcopy
      loop
        LDRB R4,[R0],#1
        CMP  R4,#0
        BEQ OVER
        STRB R4,[R1],#1
        B loop
      OVER
           end

myMain.c

extern void my_strcopy(char *dtr,char*str);
int main()

  char *a="hello world!"
  char b[64];
  my_strcopy(a,b);
  return 0;

  • 汇编调用C语言:

(1)C语言实现函数

(2)汇编import函数名

(3)BL 函数名

myArm.s
  AREA  myARM,CODE ,READONLY
  IMPORT c_fun
  ENTRY
start
  mov R0,#1
  mov R1,#2
  mov R2,#3
  BL  c_fun
  end

myMain.c
int c_fun(int a,int b,int c)//从汇编中调到这里,此时a=1,b=2,c=3

  return a+b+c;//从这里再返回去,此时R0=6;

19. ARM汇编语言与C语言混合编程的子程序之间的调用必须遵循一定的调用规则,这些规则统称为ATPCS

ATPCS即ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)的简称。
PCS规定了应用程序的函数可以如何分开地写,分开地编译,最后将它们连接在一起,所以它实际上定义了一套有关过程(函数)调用者与被调用者之间的协议。

PCS强制实现如下约定:调用函数如何传递参数(即压栈方法,以何种方式存放参数),被调用函数如何获取参数,以何种方式传递函数返回值。

部分规则:

  • r0-r3一般用来传递函数的参数,r4-r7则用来放置局部变量。而r12-r15则可以有特别的用途。
  • 小于32位的参数值会被自动扩展为32位。
  • 64位的参数被当成两个32位数。
  • 对于浮点数.如果芯片本身硬件上支持浮点运算,则浮点参数会放在浮点寄存器里传递。如果硬件上不支持浮点数运算,则转化为整型放通用寄存器传递。
  • 其它类型通通转为32位整型数传递。
  • 对于参数可变的程序调用,前四个参数放在r0~r3中传递,如果多于四个参则按相反的顺序进栈保存,所谓相反的顺序是指靠前参数后进栈。
  • 对于固定参数的调用,如果有可以做浮点运算的硬件部件, 各个浮点参数按顺序处理;为每个浮点参数分配FP寄存器;分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器。第一个整数参数通过寄存器R0~R3来传递,其他参数通过数据栈传递。

20. ucos内核调度特点(P98)

uC/OS内核调度主要有以下特点:

  • 只支持基于优先级的抢占式调度算法,不支持时间片轮训。
  • 64个优先级,只能创建64个任务,用户只能创建56个任务。有一个优先级最低的空闲任务,在没有用户任务时运行。
  • 每个任务优先级都不相同。0优先级最高,63优先级最低。
  • 不支持优先级逆转。
  • READY队列通过内存映射表实现快速查询,效率非常高。
  • 支持时钟节拍。
  • 支持信号量、消息队列、事件控制块、事件标志组、消息邮箱任务通信机制。
  • 支持中断嵌套,嵌套层数可达255层,中断使用当前任务的堆栈保存上下文。
  • 每个任务都有自己的堆栈,堆栈大小有用户自行决定。
  • 支持动态修改任务优先级。
  • 任务TCB为静态数组,建立任务只是从中获得一个TCB,不用动态分配,释放内存。
  • 任务堆栈为用户静态或动态创建,在任务创建外完成,任务创建本身不进行动态内存分配。
  • 任务的总个数(OS_MAX_TASKS)由用户决定。

21. ucos TCB的内容(P100)

(都是些什么乱七八糟的)

主要参数的功能如下:

  • *OSTCBStkPtr是指向当前任务栈顶的指针。
  • *OSTCBExtPtr是任务扩展模块使用。
  • *OSTCBStkBottom是指向任务堆栈栈底的指针。
  • OSTCBStkSize是存有栈中可容纳的指针元数目。
  • OSTCBOpt把“选择项”传给函数OSTashCreateExt()。只有当用户将OS_CFG.H文件中的OS_TASK_CREATE_EXT设为1时,这个变量才有效。
  • OSTCBId用于存储任务的识别码(ID)。
  • OSTCBNextOSTCBPrev用于任务控制OS_TCBs的双向链表的前后连接,该链表在时钟节拍函数OSTimerTick()
  • OSTCBEventPtr是指向事件控制块的指针。
  • OSTCBMsg是指向传给任务消息的指针。
  • OSTCBDly当需要把任务延时若干个时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事件的发生。
  • OSTCBStat是任务的状态字。
  • OSTCBPrio是任务优先级,高优先级任务的OSTCBPrio值最小。
  • OSTCBDelReq是一个布尔量,用于表示该任务是否需要删除。
  • OSTCBX OSTCBY OSTCBBitX OSTCBBitY用于加速任务进入就绪态的过程或进入等待事件发声状态的过程。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。

22. ucos就绪表、写表(登记)、删表算法(P100) 查询最高优先级算法(P101)(填空)

(1)就绪表

任务就绪表记录了系统中所有处于就绪状态的任务,从代码上来看它就是一个类型为INT8U的数组OSRdyTbl[]。。系统中的任务为32个时,OSRdyTbl[]就有4个成员。每个成员占据8位,所以OSRdyTbl[]的每一个数据元素对应8个任务,这8个任务称为一个任务组。在就绪表中,以任务优先二进制位,当该位为1时表示对应的任务处于就绪状态,反之为非就绪状态。

考虑到查找效率,uCOS-II定义了一个INT8U的变量OSRdyGrp,该变量的每一位都对应OSRdyTbl[]的一个任务组(即数据的一个成员)。若某任务任务所对应的位置置为1,否则为0。

举例:OSRdyGrp=00001011,那么就意味着OSRdyTbl[0]、OSRdyTbl[1]、OSRdyTbl[3]中有就绪的任务。由图可知,uCOS-II最多可以管理8 * 8 = 64个任务。

任务就绪表是以任务的优先级从低到高排序的,那么想要根据任务的优先级来找到该任务所处于就绪表中位置就轻而易举了:

由于系统至多支持64个任务,所以优先级至多也就到63,即二进制的00111111,只占据低6位,每一个OSRdyTbl[]元素只是占据8,所以只需要用3个二进制位即可表示这8位中的哪一位为1,同理,高3位用于表示至多8个OSRdyTbl[]元素的哪一个元素。即:优先级的高3位二进制位(D5、D4、D3)指明,即:优先级的高3位二进制位(D5、D4、D3)指明OSRdyTbl[]的数组下标n,低3位(D2、D1、D0)指明OSRdyTbl[n]的哪一位数据位。另外,确定OSRdyTbl[]的下标n,也说明OSRdyGrp的第几位置位。

举例:某任务的优先级prio=24,问该任务落在就绪表中的哪一位?

24的二进制位为00011000,D5、D4、D3位011,即OSRdyTbl[]的下标为3,D2、D1、D0为0,即优先级prio=24的任务在OSRdyTbl[3]的第0位。OSRdyGrp的第3位置位。

每个任务的就绪态标志都放入到就绪表中,就绪表中有两个变量OSRdyGrpOSRdyTbl[]

OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组是否有进入就绪态的任务。

任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置为1。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO

为确定下次该哪个优先级的任务运行了,内核调度器总是将最低优先级的任务在就绪表中相应字节的相应位置1,即OS_LOWEST_PRIO = 1

(2)写表、删表

使任务进入就绪表(通过OSMapTbl[]来在就绪表相应的行和列置1):

OSRdyGrp           |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

任务优先级的低三位用于确定任务在总就绪表OSRdyTbl[]中的所在位,接下去的三位用于确定是在OSRdyTbl[]数组的第几个元素。OSMapTbl[]用于限制OSRdyTbl[]数组元素下标为0-7。

从就绪表中删除一个任务(通过OSMapTbl[]来在就绪表相应的行和列置0):

if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
   OSRdyGrp &= ~OSMapTbl[prio >> 3];

将就绪任务表数组OSRdyTbl[]中相应元素的相应位清0。而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时才将相应位清0,即OSRdyTbl[prio >> 3]所有位为0时,OSRdyGrp的相应位才清零。

(3)从就绪表中查找优先级最高的任务

使用的是哈希算法。

所以要找出优先级最高的任务,分两步:

第一步,确定任务组(OSRdyTbl[]的下标)Y:找出OSRedyGrp中为1的最低位Y;

第二步,确定任务组中的位X:找出任务组中OSRdyTbl[x]中为1的最低位X。

综上,找出目标任务的核心算法在于确定某数值为1的最低位,uCOS-II的具体实现是,借助OSUnMapTbl[]数组:

例如0x06(00000110),为1的最低位是Bit[1],

以上是关于嵌入式课程作业记录——ARM复习提纲(下)的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式课程作业记录——ARM复习提纲(上)

嵌入式课程作业记录

计算机组成原理复习提纲

JMU软件大数据技术复习提纲

JMU软件大数据技术复习提纲

计算机网络复习提纲