ARM实验1
- 格式:pdf
- 大小:562.58 KB
- 文档页数:9
韦东山最新热门课程推荐:《ARM裸机1期加强版》
在您的单片机学习或工作过程中,是否会遇到过这样的问题?
1. 有单片机开发经验,无Linux操作基础、无硬件知识,如何学习嵌入式?
2. 在学校,学C51太简单没有竞争力怎幺办?一直玩C51裸机跑程序,没做过什幺东西,怎幺学习嵌入式开发?
3. 找不到有完整例程的书,无法系统地学习ARM裸机编程?
4. 如何快速掌握一个陌生的外设功能模块?
电子发烧友学院联合韦东山老师推出最新一期《ARM裸机开发实战》课程,能帮你把以上问题一扫而光!。
第1天-ARM汇编指令MOV/MVN
MOV : 传送(Move)
MOV{条件}{S} , dest = op_1MOV 从另一个寄存器、被移位的寄存器、或一
个立即值装载一个值到目的寄存器。
你可以指定相同的寄存器来实现NOP 指
令的效果,你还可以专门移位一个寄存器:MOVR0, R0; R0 = R0... NOP 指令MOVR0, R0, LSL#3; R0 = R0 * 8 如果R15 是目的寄存器,将修改程序计数器或标志。
这用于返回到调用代码,方法是把连接寄存器的内容传送到R15:
MOV PC, R14 ; 退出到调用者MOVS PC, R14 ; 退出到调用者并恢复标志位MVN : 传送取反的值
(MoveNegative)
MVN{条件}{S} , dest = !op_1MVN 从另一个寄存器、被移位的寄存器、或一
个立即值装载一个值到目的寄存器。
不同之处是在传送之前位被反转了,所以
把一个被取反的值传送到一个寄存器中。
这是逻辑非操作而不是算术操作,就
是二进制的取反,比如二进制是0B11001100,取反就是0B00110011,转换为10 进制就是,这个取反的值加 1 才是它的取负的值:
MVN R0, #4 ; R0 = -5 MVN R0, #0 ; R0 = -1tips:感谢大家的阅读,本文由我司收集整编。
仅供参阅!。
嵌入式系统实验一存储器实验嵌入式系统实验一-存储器实验2022春季嵌入式系统课程实验报告《嵌入式系统》课程实验报告学生姓名:班级:讲师:记分及评价:项目满分:5分一、实验名称记忆实验二、实验目的了解S3C2410X处理器的内部存储空间分配;掌握存储区域配置方法;掌握对存储区进行读写访问的方法。
三、实验内容熟练使用命令脚本文件对arm存储控制器进行正确配置。
使用c语言编程,实现对ram的读写访问。
四、实验原理s3c2410a的存储器控制器提供访问外部存储器所需要的存储器控制信号,具有以下特性:●支持小/大端(通过软件选择)。
●地址空间:每个bank有128mb(总共有8个bank,共1gb)。
●除bank0只能是16/32位宽之外,其他bank都具有可编程的访问位宽(8/16/32位)。
●总共有8个存储器bank(bank0~bank7):一其中6个用于rom,sram等;一剩下2个用于rom,sram,sdram等。
●7个固定的存储器bank(bank0~bank6)起始地址。
●最后一个bank(bank7)的起始地址是可调整的。
●最后两个bank (bank6和bank7)的大小是可编程的。
● 所有内存库的访问周期都是可编程的。
● 可以通过插入外部等待来延长总线访问周期。
● 支持SDRAM的自刷新和断电模式。
《嵌入式系统》课程实验报告2021年春季五、实验结果超级终端上显示一下信息:六、练习编写程序对sram进行字节的读写访问。
#包括\voidmemory_test(void){因蒂;uint16tdata;intmemerror=0;uint16t*pt;2022春季嵌入式系统课程实验报告uart_printf(\0x00e00000,_ram_startaddress+0x00f00000);pt=(uint16t*)(_ram_startaddress+0x00e0000);//记忆书写while((uint32t)pt<(_ram_startaddress+0x00f00000)){*pt=(uint16t)pt;pt++;}//memoryreaduart_uuuprintf(\memorytest(%xh-%xh):rd\\n\uuu内存_uuuu起始地址+0x00e00000,uuu内存_uuu起始地址+0x00f00000);pt=(uint16t*)(_ram_startaddress+0x00e00000);而((uint32t)pt<(_ram_startaddress+0x00f00000)){data=*pt;如果(数据!=(uint16t)pt){memerror=1;uart_uPrintf(\break;}pt++;}if(memerror==0)uart_printf(\}。
arm电源管理(1)--apm.c -- 内核版本比较旧了由于arm系统中没有bios设备, 所以只能为arm系统创建一个虚拟的字符设备与用户空间进行通讯.这就是/arch/arm/kernel/amp.c1. 工作原理:这个apm中实现一个misc设备,实质上也是一个字符设备, misc设备的主设备号是10, 而apm_bios作为一个misc设备, 次设备号是134. 定义为:/** The apm_bios device is one of the misc char devices.* This is its minor number.*/#define APM_MINOR_DEV 134这个apm_bios设备通过ioctl系统调用和用户空间进行通讯, 即当用户进程通过ioctl发来suspend命令时, 它就传给内核, 使系统进入suspend状态.2. 初始化static int __init apm_init(void){int ret;if (apm_disabled) {printk(KERN_NOTICE "apm: disabled on user request.\n");return -ENODEV;}if (PM_IS_ACTIVE()) {printk(KERN_NOTICE "apm: overridden by ACPI.\n");return -EINVAL;}pm_active = 1;//创建一个线程, 用于处理事件队列, 工作函数是kapmd//这个线程好像在arm中没有作用?ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);if (ret < 0) {pm_active = 0;return ret;}//通过proc向用户空间输出apm信息#ifdef CONFIG_PROC_FScreate_proc_info_entry("apm", 0, NULL, apm_get_info); #endif//注册misc设备ret = misc_register(&apm_device);if (ret != 0) {remove_proc_entry("apm", NULL);pm_active = 0;wake_up(&kapmd_wait);wait_for_completion(&kapmd_exit);}return ret;}注册的结构为:static struct file_operations apm_bios_fops = {.owner = THIS_MODULE,.read = apm_read,.poll = apm_poll,.ioctl = apm_ioctl,.open = apm_open,.release = apm_release,};static struct miscdevice apm_device = {.minor = APM_MINOR_DEV,.name = "apm_bios",.fops = &apm_bios_fops};3. 结构函数的实现当一个用户进程打开apm_bios设备时, 它就会调用这个函数static int apm_open(struct inode * inode, struct file * filp){struct apm_user *as;//分配一个apm_user结构, 来表示一个用户进程as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);if (as) {memset(as, 0, sizeof(*as));/** XXX - this is a tiny bit broken, when we consider BSD* process accounting. If the device is opened by root, we* instantly flag that we used superuser privs. Who knows,* we might close the device immediately without doing a* privileged operation -- cevans*///读写等权限设置as->suser = capable(CAP_SYS_ADMIN);as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;//将这个用户加入用户队列down_write(&user_list_lock);list_add(&as->list, &apm_user_list);up_write(&user_list_lock);//这是一个传递私有数据的一个通用方式filp->private_data = as;}return as ? 0 : -ENOMEM;}当用户空间进程去读这个设备时, 这个函数就会被调用.这个函数的主要作用是将事件读出到用户空间static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) {struct apm_user *as = fp->private_data;apm_event_t event;int i = count, ret = 0;if (count < sizeof(apm_event_t))return -EINVAL;//队列空, 且进程非阻塞读, 立刻返回if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) return -EAGAIN;//否则等待到队列非空为止,wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));//将队列中的事件复制给用户空间while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { event = queue_get_event(&as->queue);ret = -EFAULT;if (copy_to_user(buf, &event, sizeof(event)))break;//设置状态if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) as->suspend_state = SUSPEND_READ;buf += sizeof(event);i -= sizeof(event);}if (i < count)ret = count - i;return ret;}//这个poll/select的后端实现, 用于查询有没有数据可读static unsigned int apm_poll(struct file *fp, poll_table * wait){struct apm_user *as = fp->private_data;poll_wait(fp, &apm_waitqueue, wait);return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;}//这个是这个设备的核心函数, 用于内核与用户空间交互/** apm_ioctl - handle APM ioctl** APM_IOC_SUSPEND* This IOCTL is overloaded, and performs two functions. It is used to:* - initiate a suspend* - acknowledge a suspend read from /dev/apm_bios.* Only when everyone who has opened /dev/apm_bios with write permission * has acknowledge does the actual suspend happen.*/static intapm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg){struct apm_user *as = filp->private_data;unsigned long flags;int err = -EINVAL;if (!as->suser || !as->writer)return -EPERM;switch (cmd) {case APM_IOC_SUSPEND:as->suspend_result = -EINTR;if (as->suspend_state == SUSPEND_READ) {/** If we read a suspend command from /dev/apm_bios,* then the corresponding APM_IOC_SUSPEND ioctl is* interpreted as an acknowledge.*/as->suspend_state = SUSPEND_ACKED;suspends_pending--;} else {/** Otherwise it is a request to suspend the system.* Queue an event for all readers, and expect an* acknowledge from all writers who haven't already* acknowledged.*/queue_event(APM_USER_SUSPEND, as);}/** If there are no further acknowledges required, suspend* the system.*/if (suspends_pending == 0)apm_suspend(); //系统进入suspend状态//从suspend中返回/** Wait for the suspend/resume to complete. If there are* pending acknowledges, we wait here for them.** Note that we need to ensure that the PM subsystem does* not kick us out of the wait when it suspends the threads.*/flags = current->flags;current->flags |= PF_NOFREEZE;/** Note: do not allow a thread which is acking the suspend* to escape until the resume is complete.*/if (as->suspend_state == SUSPEND_ACKED)wait_event(apm_suspend_waitqueue,as->suspend_state == SUSPEND_DONE);elsewait_event_interruptible(apm_suspend_waitqueue,as->suspend_state == SUSPEND_DONE);current->flags = flags;err = as->suspend_result;as->suspend_state = SUSPEND_NONE;break;}return err;}4. 事件队列函数static void queue_event(apm_event_t event, struct apm_user *sender) {struct apm_user *as;down_read(&user_list_lock);//将事件加入其他USER,除自己外list_for_each_entry(as, &apm_user_list, list) {if (as != sender && as->reader)queue_event_one_user(as, event);}up_read(&user_list_lock);//唤醒等待读的进程wake_up_interruptible(&apm_waitqueue);}static void queue_event_one_user(struct apm_user *as, apm_event_t event) {if (as->suser && as->writer) {switch (event) {case APM_SYS_SUSPEND:case APM_USER_SUSPEND:/** If this user already has a suspend pending,* don't queue another one.*/if (as->suspend_state != SUSPEND_NONE)return;as->suspend_state = SUSPEND_PENDING;suspends_pending++;break;}}queue_add_event(&as->queue, event);}static void queue_add_event(struct apm_queue *q, apm_event_t event) {q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;if (q->event_head == q->event_tail) { //满了static int notified;if (notified++ == 0)printk(KERN_ERR "apm: an event queue overflowed\n");q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;}q->events[q->event_head] = event; 加入队头}在来看一个出队的函数://在队尾出列static inline apm_event_t queue_get_event(struct apm_queue *q) {q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;return q->events[q->event_tail];}/** APM event queue management.*/static inline int queue_empty(struct apm_queue *q){return q->event_head == q->event_tail;}//队列的结构/** Maximum number of events stored*/#define APM_MAX_EVENTS 16struct apm_queue {unsigned int event_head;unsigned int event_tail;apm_event_t events[APM_MAX_EVENTS];};5. apm_suspend()这里才是整个设备想做的事情--将系统转入suspend状态static void apm_suspend(void){struct apm_user *as;//调用体系无关的接口,将系统转入suspend状态int err = pm_suspend(PM_SUSPEND_MEM);//从suspend返回/** Anyone on the APM queues will think we're still suspended.* Send a message so everyone knows we're now awake again.*///发送一个resume事件queue_event(APM_NORMAL_RESUME, NULL);/** Finally, wake up anyone who is sleeping on the suspend.*/down_read(&user_list_lock);list_for_each_entry(as, &apm_user_list, list) {as->suspend_result = err;as->suspend_state = SUSPEND_DONE; //suspend完成}up_read(&user_list_lock);//唤醒睡眠进程wake_up(&apm_suspend_waitqueue);}。
一、汇编指令实验一:(实验1~3无法调试结果但是基本上是正确的)(1)使用LDR 指令读取0x40003100上的数据,将数据加2 ,若结果小于20则使用STR 指令把结果写回原地址,若结果大于等于20,则把0 写回原地址。
然后再次读取0x40003100上的数据,将数据加2 ,判断结果是否小于20……周而复始循环FunLDR R0 , #0x40003100ADD R0 , #2CMP R0 , #20MOVGE R0 , #0STRLT R0 , #0x40003100B Fun二、汇编指令实验二:(1 )使用MOV和MVN指令访问ARM通用寄存器。
(2 )使用ADD、SUB 、AND、ORR、CMP、TST 等指令完成数据加减运算及逻辑运算。
(1)、(2)这个很简单就按照相应的操作(如:MOV和MVN) 的语法格式就行三、汇编指令实验三:(任选两题作答)(1 )使用ARM汇编指令实现if 条件执行, for 循环结构, while循环结构和while循环结构。
If条件执行:MOV R0 , 0 #R0初始化为0CMP R0 , 0 #比较R0与0的大小MOVEQ R0 , 1 #如果R0等于0 则修改R0为1For循环结构:MOV R5 , 10MOV R1 , #0 #求和MOV R2 , #1 #循环变量FORCMP R5 , R2 #进入for循环先判断BEQ ENDADD R1 , R1 ,R2ADD R2 , R2 ,#1B FORENDDo……while循环结构MOV R5 , 10MOV R1 , #0 #求和MOV R2 , #1 #循环变量DOWHILEADD R1 , R1 ,R2ADD R2 , R2 ,#1CMP R5 , R2 #do_while循环先执行后判断BEQ ENDB DOWHILEENDWhile循环结构MOV R5 , 10MOV R1 , #0 #求和MOV R2 , #1 #循环变量WHILECMP R5 , R2 #进入while循环的时候先判断BEQ ENDADD R1 , R1 ,R2ADD R2 , R2 ,#1B WHILEEND四、c语言程序实验:C 程序使用加法运算来计算1+2+3+...+(99-1)+100的值。
《嵌入式系统设计(实验课)》内容安排《嵌入式系统设计(实验课)》是《嵌入式系统设计》课程的一个重要环节。
通过实验,学生可以对嵌入式系统的设计与开发过程有更深地体会。
实验课共八次,每次2学时,实验内容结合课程内容,介绍一般的实验开发流程和软件硬件开发环境,并辅之以典型的嵌入式程序设计实例,使学生掌握基本的嵌入式软件开发技能。
大量的具有实际应用背景的实验,更将理论与实践结合起来,使实验内容更加生动。
实验报告要求一、实验名称:说明:本次实验的名称二、实验目的:说明:本次实验的主要目的,参考每次的实验指导书三、实验环境:说明:实验用到的硬件软件环境。
四、实验内容与步骤:说明:实现实验目的而进行的实验内容,如果有步骤要求则简要列出步骤五、实验报告总结:说明:对本次实验的总结,1.画出主函数的程序流程图,2.重写主程序.或者:自拟一个新的应用,参照本次实验的主程序,重新设计主程序并给出详尽注释。
3.其他,本次实验得到了什么?收获是什么?有些什么别的想法?六、建议与意见:说明:对于此次实验内容或在实验过程中有任何问题或建议,以及对于改善实验效果有什么建议,均可提出。
在书写实验报告的过程中,主要是帮助自己回顾和总结实验。
重点放在第五部分,前四项可以十分简要地列写,第六项有则提出,无则不写。
实验一嵌入式微处理器系统的开发环境一、实验环境PC机一台软件: ADS 1.2集成开发环境一套二、实验目的1.了解嵌入式系统及其特点;2.熟悉嵌入式系统的开发环境和基本配置并能编写简单的汇编程序三、实验内容1.嵌入式系统的开发环境、基本配置2.使用汇编指令完成简单的加法实验四、实验步骤(1)在D:\新建一个目录,目录名为experiment。
(2)点击 WINDOWS 操作系统的“开始|程序|ARM Developer Suite v1.2 |Code Warrior for ARM Developer Suite”启动Metrowerks Code Warrior,或双击“ADS 1.2”快捷方式启动。
arm跳转指令例子(一)ARM跳转指令例子在ARM架构中,跳转指令是用于改变程序控制流的重要指令之一。
通过使用跳转指令,程序可以在执行过程中无条件或有条件地转移到其他指令的地址。
下面是一些常见的ARM跳转指令例子,并对其进行详细讲解:1. B(无条件跳转指令)B label该指令会使程序跳转到与指定标签相对应的地址处,无条件地执行该地址处的指令。
2. BL(带链接的跳转指令)BL subroutineBL指令用于调用子程序或函数。
它会将当前指令地址保存在链接寄存器(LR)中,并将程序控制流转移到指定子程序地址处。
使用BL指令后,执行完子程序后会返回到调用指令的下一条指令。
3. BEQ(等于时跳转指令)BEQ labelBEQ指令用于在条件等于时跳转到指定标签处。
当标志寄存器中的等于标志为设置时,程序将跳转到指定标签处执行。
4. BNE(不等于时跳转指令)BNE labelBNE指令用于在条件不等于时跳转到指定标签处。
当标志寄存器中的等于标志为清除时,程序将跳转到指定标签处执行。
5. BGT(大于时跳转指令)BGT label该指令用于在条件大于时跳转到指定标签处。
当标志寄存器中的大于标志和零标志都被清除,并且溢出标志被设置时,程序将跳转到指定标签处执行。
6. BLE(小于等于时跳转指令)BLE labelBLE指令用于在条件小于等于时跳转到指定标签处。
当标志寄存器中的大于标志和零标志中的任何一个被设置时,程序将跳转到指定标签处执行。
这些例子展示了常见的ARM跳转指令的用法和目的。
通过合理使用这些指令,程序能够实现不同的控制流程和条件判断,从而实现更为灵活和复杂的功能。
注意:在实际的ARM汇编代码中,标签(label)通常是一个地址或符号的名称,并且在汇编代码中需要定义这些标签所对应的地址。
以上例子中的标签仅用于说明目的和用法,并不涉及具体的地址定义。
希望这些例子能够帮助你更好地理解和使用ARM跳转指令。
ARM技术原理与应用
实验报告
专业电子信息工程班级
学生姓名
学号
指导教师
2017年4月12 日
一、实验目的
(1)掌握ADS集成开发环境的创建;
(2)掌握ADS环境下工程创建;
(3)掌握ADS环境下汇编语言源程序创建、编辑、修改;
(4)掌握ADS环境下汇编语言源程序的汇编操作;
(5)掌握AXD环境下汇编语言程序的调试。
二、实验要求
1、实验必须在在ADS1.2环境下进行。
2、工程名、汇编语言源文件名按照下面规则命名:
工程名:pj+学号最后4位+其它字符
汇编语言源文件名:p+学号最后4位+其它字符+.s
例如:张维智同学学号最后4位是3134
因此,pj3134、pj3134a、pj31341等都是允许的工程名;而 p3134a.s、p3134b.s等都是允许的源文件名。
3、实验报告中需要说明实验中在ADS、AXD环境下进行的实际操作;
4、实验报告中应给出实际的实验操作及计算机的调试观察结果;
5、按照规定格式打印实验报告。
三、实验任务
1、在自己的笔记本电脑上安装ADS1.2ARM集成开发环境。
同时,操作实验室台式机上ADS1.2以便熟悉实验室的ADS1.2集成开发环境。
2、参考课件文档:ARM汇编语言程序设计实验环境与工具的使用-笔记本电脑版-v2.doc,创建pjxxxx工程。
3、创建pxxxx.s汇编语言源程序。
然后严格按照下面格式输入源程序。
AREA Example, CODE, READONLY
Entry
才ode32
START:
Mov R0,#5
MOV R2,#5 ;r2
MOV R0,0
mov R1,#0
LOOP:
CUP R1,R2
BHI ADD_END
ADD R0,R0 R1
ADD R1,R1,#1
B LOOP
ADD_end
B START
End
在实验报告中列出上面自己创建的pxxxx.s汇编语言源程序。
4、将pxxxx.s汇编语言源程序添加到pjxxxx工程中。
记录实验步骤和结果。
5、选Project->Make操作,对pxxxx.s汇编语言源程序进行汇编。
记录错误数,出错行的
行号。
6、修改pxxxx.s汇编语言源程序的语法错误,直到汇编成功为止。
在实验报告中列出最终正确的pxxxx.s汇编语言源程序。
7、单击工具栏中图标,进入AXD调试环境,对pxxxx进行调试。
选择Options→Configur Target…,将Configure配置Processor 为ARM920T。
8、点击Current前面的加号,展开当前模式寄存器组。
选Memory图标打开内存显示窗口,在下图下拉框中输入0x8000,代码从0x8000处存放。
观察实验现象。
9、熟悉工具条。
(1)单步执行10次,观察每次单步执行结果。
(2)在B LOOP语句处设置断点,点GO,执行程序。
观察实验现象。
(3)将光标移到B START语句处,点Run To Cursor,运行到光标处停下。
观察
实验结果。
(4)根据调试结果,说明pxxxx.s汇编语言源程序的功能。
四、实验步骤及结果
(要求根据实验内容,记录操作过程和实验现象、给出实验结果)
1、创建文件工程,工程名:pj3101a
2、创建源文件,命名为p3101.s,并在工程中添加源文件。
3、在源文件中写入程序代码,然后运行make,显示有错误
4、修改错误的程序代码,运行make,直到显示没有错误,然后点击Debug,打开AXD,进行AXD软件调试
5、进入AXD,开始设置AXD的运行调试环境,将Configure配置Processor 为ARM920T
6、代码从0x8000处存放
7、点击单步执行STEP,寄存器r0显示0x5
8、单步执行到11,寄存器r0的值为0x00,r1的值为0x00,r3的值为0x5
9、单步执行STEP到10
10、B LOOP语句处设置断点,执行go,寄存器r0的值为0x1,r1的值为0x2.
11、R0寄存器存放1+2+3+4+5的累加和
程序代码:
AREA EXAMPLE, CODE, READONLY
ENTRY
CODE32
START
MOV R0,#5; 立即数5送寄存器R0
MOV R2,#5; 立即数5送寄存器R1
MOV R0,#0; 立即数5送寄存器R0
MOV R1,#0; 立即数0送寄存器R1
LOOP
CMP R1,R2; 0跟5做比较
BHI ADD_end; 如果0>5,跳转ADD_end
ADD R0,R0,R1; 如果0<5,执行R1的值加R0的值送R0 ADD R1,R1,#1 ;R1的值加1送R1
B LOOP; 跳转到LOOP
ADD_end
B START; 跳转到START
END;结束
程序实现的功能:1+2+3+4+5=15的累加和
五、实验体会
1、运用软件,可以在软件上面看到寄存器存放的值,可以很明显地看到每单步执行一次程序的结果的值,可以方便我们清楚地了解到程序的每一步操作与每一步算法的结果,提高理解程序的能力。
2、借用调试软件,在很大的程度上,我们可以快速地检测程序代码是否出现了错误,从而进行修改加以修正,加快我们写程序代码的速度,以及节省了时间。