关常志ARM答辩报告.docx
《关常志ARM答辩报告.docx》由会员分享,可在线阅读,更多相关《关常志ARM答辩报告.docx(22页珍藏版)》请在冰豆网上搜索。
关常志ARM答辩报告
软件学院
课程设计报告书
课程名称ARM汇编程序设计
设计题目基于ARM9的嵌入式MP3设计与开发
专业班级嵌入式软件08—1班
学号0820010106
姓名关常志
指导教师姜彦吉
2010年12月
1设计时间
此次课程设计从2010年11月20日开始,12月29日基本结束。
2设计目的
本设计采用ARM微处理器,作为整个音频播放系统的控制和管理单元,设计的出发点就是强化ARM汇编的基本技能,加深对嵌入式系统的理解,积累嵌入式系统开发的经验;此外对嵌入式linux有初步的认识,对UCOS有初步了解。
3设计任务
通过USB与pc机通信进行下载音频文件。
能够播放MP3格式文件。
具有键盘输入,LCD显示和存储,播放控制功能。
关于硬件和软件:
硬件:
数据存储,和任务实施。
软件:
OS模块,USB通信模块,音频解码模块,人机交互模块。
详细描述为:
bootloader引导程序,操作系统软件,USB固件及文件系统模块,FLASH存储模块,数字音频解码模块,人机交互模块。
4设计内容
4.1系统工作流程描述
4.1.1语言描述
系统上电后,BOOTLOADER首先进行系统内核,文件系统加载,在操作系统运行成功后启动多任务的调度。
键盘是唯一的输入设备,负责各任务间的通信,不同的按键产生不同的消息。
系统进行任务的调度,响应用户的操作意图。
当用户进入主菜单模式时就进行音频的各种操作,如:
播放,暂停,循环。
当power键按下时,传递系统开机信息,系统进行任务调度,调用LCD任务,进入主菜单模式,长按POWER就调用LCD关机任务,CPU时钟关,当开机后有一分钟没有任何操作时,调用LCD,关闭背景灯。
当系统有USB连接主机时,调用USB任务,与主机通信。
4.1.2工作流程图
4.2系统结构框图
4.3硬件部分结构及工作原理图
4.4系统开发平台
本系统采用ADS1.2进行系统程序的编写,编译,和初步调试。
4.5部分程序代码
4.5.1系统启动代码
定义系统模式堆栈的大小
SVC_STACK_LEGTHEQU32
NoIntEQU0x80
USR32ModeEQU0x10
SVC32ModeEQU0x13
SYS32ModeEQU0x1f
IRQ32ModeEQU0x12
FIQ32ModeEQU0x11
T_bit用于检测进入异常前cpu是否处于THUMB状态
T_bitEQU0x20
CODE32
PRESERVE8
AREA|subr|,CODE,READONLY
IMPORTOSTCBCur;指向当前任务TCB的指针
IMPORTOSTCBHighRdy;指向将要运行的任务TCB的指针
IMPORTOSPrioCur;当前任务的优先级
IMPORTOSPrioHighRdy;将要运行的任务的优先级
IMPORTOSTaskSwHook;任务切换的钩子函数
IMPORTOSRunning;uC/OS-II运行标志
IMPORTOsEnterSum;关中断计数器(关中断信号量)
IMPORTSWI_Exception;软中断异常处理程序
EXPORT__OSStartHighRdy
EXPORTOSIntCtxSw;中断退出时的入口,参见startup.s中的IRQ_Handler
EXPORTSoftwareInterrupt;软中断入口
软件中断
SoftwareInterrupt
LDRSP,StackSvc;重新设置堆栈指针
STMFDSP!
{R0-R3,R12,LR}
MOVR1,SP;R1指向参数存储位置
MRSR3,SPSR
TSTR3,#T_bit;中断前是否是Thumb状态
LDRNEHR0,[LR,#-2];是:
取得Thumb状态SWI号
BICNER0,R0,#0xff00
LDREQR0,[LR,#-4];否:
取得arm状态SWI号
BICEQR0,R0,#0xFF000000
;r0=SWI号,R1指向参数存储位置
CMPR0,#1
LDRLOPC,=OSIntCtxSw
LDREQPC,=__OSStartHighRdy;SWI0x01为第一次任务切换
BLSWI_Exception
LDMFDSP!
{R0-R3,R12,PC}^
StackSvcDCD(SvcStackSpace+SVC_STACK_LEGTH*4-4)
SIntCtxSw
;下面为保存任务环境
LDRR2,[SP,#20];获取PC
LDRR12,[SP,#16];获取R12
MRSR0,CPSR
MSRCPSR_c,#(NoInt|SYS32Mode)
MOVR1,LR
STMFDSP!
{R1-R2};保存LR,PC
STMFDSP!
{R4-R12};保存R4-R12
MSRCPSR_c,R0
LDMFDSP!
{R4-R7};获取R0-R3
ADDSP,SP,#8;出栈R12,PC
MSRCPSR_c,#(NoInt|SYS32Mode)
STMFDSP!
{R4-R7};保存R0-R3
LDRR1,=OsEnterSum;获取OsEnterSum
LDRR2,[R1]
STMFDSP!
{R2,R3};保存CPSR,OsEnterSum
;保存当前任务堆栈指针到当前任务的TCB
LDRR1,=OSTCBCur
LDRR1,[R1]
STRSP,[R1]
BLOSTaskSwHook;调用钩子函数
;OSPrioCur<=OSPrioHighRdy
LDRR4,=OSPrioCur
LDRR5,=OSPrioHighRdy
LDRBR6,[R5]
STRBR6,[R4]
;OSTCBCur<=OSTCBHighRdy
LDRR6,=OSTCBHighRdy
LDRR6,[R6]
LDRR4,=OSTCBCur
STRR6,[R4]
OSIntCtxSw_1
;获取新任务堆栈指针
LDRR4,[R6]
ADDSP,R4,#68;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
LDRLR,[SP,#-8]
MSRCPSR_c,#(NoInt|SVC32Mode);进入管理模式
MOVSP,R4;设置堆栈指针
LDMFDSP!
{R4,R5};CPSR,OsEnterSum
;恢复新任务的OsEnterSum
LDRR3,=OsEnterSum
STRR4,[R3]
MSRSPSR_cxsf,R5;恢复CPSR
LDMFDSP!
{R0-R12,LR,PC}^;运行新任务
__OSStartHighRdy
MSRCPSR_c,#(NoInt|SYS32Mode)
;告诉uC/OS-II自身已经运行
LDRR4,=OSRunning
MOVR5,#1
STRBR5,[R4]
BLOSTaskSwHook;调用钩子函数
LDRR6,=OSTCBHighRdy
LDRR6,[R6]
BOSIntCtxSw_1
AREASWIStacks,DATA,NOINIT,ALIGN=2
SvcStackSpaceSPACESVC_STACK_LEGTH*4;管理模式堆栈空间
END
4.5.2系统主函数(main.c)部分代码
#defineCLEAR_INT_MARK(){EXTINT=0x02;VICVectAddr=0x00;}
#include"..\ARM\config.h"
#include"..\LED\LED.h"
#include"..\ARM\LPC214x.h"
#include"..\VS1003\vs1003.h"
#include"..\CH375\CH375.h"
#include"..\CH375\CH375HFM.h"
#include"..\LGDP4216\LGDP4216.h"
#defineTaskStartStkLength512
#defineTaskStkLength128//定义用户任务堆栈长度
#defineTaskStartPrio1
#defineVS1003SemFlag1
#defineCH375SemFlag2
#defineLGDP4216SemFlag4
OS_STKTaskStartStk[TaskStartStkLength];//定义用户任务打印统计信息任务的堆栈
OS_STKTerminalTaskStk[TaskStkLength];
OS_STKCH375TaskStk[TaskStkLength];//定义用户任务U盘读取任务的堆栈
OS_STKVS1003TaskStk[TaskStkLength];//定义用户任务音乐播放任务的堆栈
OS_STKDisplayTaskStk[TaskStkLength];//定义用户任务显示任务的堆栈
staticvoidAppTerminalRx(INT8Udata);
INT8UAppTerminalRxMboxData;
INT8UPlayCtrlData;
OS_EVENT*AppTerminalRxMbox;
OS_FLAG_GRP*SemFlag;
uint8err;
uint8Spe[14];
uint8SpeFlag;
voidTaskStart(void*pdata);
voidTerminalTask(void*pdata);
voidCH375Task(void*pdata);//U盘读取任务
voidVS1003Task(void*pdata);//音乐播放任务
voidDisplayTask(void*pdata);//显示任务
staticvoidAppTerminalRx(INT8Udata)
{
AppTerminalRxMboxData=data;
OSMboxPost(AppTerminalRxMbox,&AppTerminalRxMboxData);
}
/*检查操作状态,如果错误则显示错误代码并停机*/
voidmStopIfError(unsignedchariError)
{
if(iError==ERR_SUCCESS)return;/*操作成功*/
//printf("Error:
0x%02X\r\n",iError);/*显示错误*/
while
(1){
LED_OUT_ACT();/*LED闪烁*/
OSTimeDly(OS_TICKS_PER_SEC/10);
LED_OUT_INACT();
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
#ifLIB_CFG_INT_EN==1
voidinit_eint1(){
PINSEL0=(PINSEL0&(~(0x03<<6)))|(0x03<<6);//选择EINT1
VICVectAddr1=(unsignedlong)CH375Interrupt;//设置中断处理方法地址
VICVectCntl1=0x20|0x0F;//设置使用1号中断向量寄存器
VICIntEnable=0x01<<0x0F;//开启1号中断
}
#endif
intmain(void)
{
#ifOS_VERSION>276
#ifOS_TASK_NAME_SIZE>0
INT8Uerr;
#endif
#endif
SCS=0x03;
TargetInit();//初始化硬件
OSInit();//初始化uC/OS-II
OSTaskCreateExt(TaskStart,
(void*)0,
&TaskStartStk[TaskStartStkLength-1],
TaskStartPrio,
TaskStartPrio,
&TaskStartStk[0],
TaskStartStkLength,
(void*)0,
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR);
#ifOS_VERSION>276
#ifOS_TASK_NAME_SIZE>14
OSTaskNameSet(TaskStartPrio,(INT8U*)"StartTask",&err);
#else
#ifOS_TASK_NAME_SIZE>7
OSTaskNameSet(TaskStartPrio,(INT8U*)"Start",&err);
#endif
#endif
#endif//创建起动任务
OSStart();
return0;//开始多任务
}
voidTaskStart(void*pdata)
{
#ifOS_CRITICAL_METHOD==3//AllocatestorageforCPUstatusregister
OS_CPU_SRcpu_sr;
#endif
#ifOS_VERSION>276
#ifOS_TASK_NAME_SIZE>0
INT8Uerr;
#endif
#endif
#ifOS_TASK_STAT_EN>0
OSStatInit();/*DetermineCPUcapacity*/
#endif
#ifOS_VIEW_MODULE>0
OSView_Init();
OSView_TerminalRxSetCallback(AppTerminalRx);
OSView_RxIntEn();/*EnableRxInterrupts*/
#endif
SemFlag=OSFlagCreate(VS1003SemFlag|LGDP4216SemFlag,&err);
AppTerminalRxMbox=OSMboxCreate((void*)0);
OSTaskCreateExt(CH375Task,
(void*)0,
&CH375TaskStk[TaskStkLength-1],
&CH375TaskStk[0],
TaskStkLength,
(void*)0,
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR);
OSTaskCreateExt(VS1003Task,
(void*)0,
&VS1003TaskStk[TaskStkLength-1],
5,
5,
&VS1003TaskStk[0],
TaskStkLength,
(void*)0,
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR);
OSTaskCreateExt(TerminalTask,
(void*)0,
&TerminalTaskStk[TaskStkLength-1],
6,
6,
&TerminalTaskStk[0],
TaskStkLength,
(void*)0,
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR);
OSTaskCreateExt(DisplayTask,
(void*)0,
&DisplayTaskStk[TaskStkLength-1],
7,
7,
&DisplayTaskStk[0],
TaskStkLength,
(void*)0,
OS_TASK_OPT_STK_CHK+OS_TASK_OPT_STK_CLR);
#ifOS_VERSION>276
#ifOS_TASK_NAME_SIZE>14
OSTaskNameSet(4,(INT8U*)"CH375Task",&err);
OSTaskNameSet(5,(INT8U*)"VS1003Task",&err);
OSTaskNameSet(6,(INT8U*)"TerminalTask",&err);
OSTaskNameSet(7,(INT8U*)"DisplayTask",&err);
#endif
#endif
while
(1){
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
voidTerminalTask(void*pdata)
{
#ifOS_CRITICAL_METHOD==3/*AllocatestorageforCPUstatusregister*/
OS_CPU_SRcpu_sr;
#endif
chars[100];
INT8U*key;
INT8Uerr;
pdata=pdata;/*Preventcompilerwarning*/
while(TRUE){
key=(INT8U*)OSMboxPend(AppTerminalRxMbox,0,&err);
switch(*key){
case'1':
sprintf(s,"\nCPUUsage=%3u%%\n",OSCPUUsage);
OSView_TxStr(s,1);
break;
case'2':
sprintf(s,"\n#Tasks=%3u\n",OSTaskCtr);
OSView_TxStr(s,1);
break;
case'n':
PlayCtrlData|=0x01;
OSView_TxStr("\nNextsong.\n",1);
break;
default:
OSView_TxStr("\n\nMicrium,Inc.",1);
OSView_TxStr("\n1:
CPUUsage(%)",1);
OSView_TxStr("\n2:
#Tasks",1);
OSView_TxStr("\n?
:
Help(Thismenu)\n",1);
break;
}
}
}
//音乐播放任务
voidVS1003Task(void*pdata)
{
uint8byteIndex,data;
uint32blockIndex;
pdata=pdata;
InitPortVS1003();
//printf("VS1003testbegin.\r\n");
//VsSineTest();
//printf("VS1003testfinish.\r\n");
SpeFlag=0;
Mp3SoftReset();
LoadPatch();
while
(1)
{
OSFlagPend(SemFlag,(OS_FLAGS)(CH375SemFlag),OS_FLAG_WAIT_SET_ALL,0,&err);
OSFlagPost(SemFlag,(OS_FLAGS)(CH375SemFlag),OS_FLAG_CLR,&err);
for(blockIndex=0;blockIndex<(FILE_DATA_BUF_LEN/VS1003_BLOCK_SIZE);blockIndex++){
DREQWait();
SPIStart();
Mp3SelectData();
//SPIBatchSend((uint8*)&FILE_DATA_BUF,(blockIndex<<5/*2^5=VS1003_BLOCK_SIZE*/),32);
for(byteIndex=0;byteIndexif(SPIRW(&data,FILE_DATA_BUF[(blockIndex<<5/*2^5=VS1003_BLOCK_SIZE*/)+byteIndex])==FALSE){
//printf("SPIRWerror!
.\r\n");
}
}
Mp3DeselectData();
if(SPIEnd()==FALSE){
//printf("SPIEnderror!
.\r\n");
}
if(SpeFlag==0){
//RequesttoreadSpectrumAnalyzerregister
Mp3WriteRegister(SCI_WRAMADDR,0x18,0x04);
//ReadSpectrumAnalyzerregisters
for(byteIndex=0;byteIndex<14;byteIndex++){
Spe[byteIndex]=Mp3ReadRegister(SCI_WRAM)&63;
}
SpeFlag=0xFF;
}
}
OSFlagPost(SemFlag,(OS_FLAGS)VS1003SemFlag,OS_FLAG_SET,&err);
}
}
/*LED清屏程序*/
voidOLedClear(unsignedc