datasheet

OK6410裸机之异常处理

2018-10-11来源: eefocus 关键字:OK6410  裸机  异常处理

start.S源码:

.globl _start

_start:

    // 0 地址 

    b reset                                          // 复位时,cpu跳到0地址  其实复位之后,CPU就处于管理模式(svc)

    ldr pc, =undefined_instruction  //cpu遇到不能识别的指令时 ,地址4,该指令到内存处读取un..的链接地址

    ldr pc, _vector_swi             // 当执行swi指令时, 进入swi模 式 ,地址8,该指令直接读取_vector_swi当前地址

    b halt     @ldr    pc, _prefetch_abort  // 预取中止异常 

    b halt     @ldr    pc, _data_abort        // 数据访问异常 

    b halt     @ldr    pc, _not_used           // 没用到 

    ldr    pc, _irq                                        // 0x18 中断异常 

    b halt     @ldr    pc, _fiq                      // 快中断异常 

_irq :

    .word vector_irq

_vector_swi:

    .word vector_swi

        

vector_swi:

    // 1. 保存现场 

    ldr sp, =0x56000000      //sp是svc模式自己的r13,要从新设置

    stmdb sp!, {r0-r12, lr}     // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =swi_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^   // ^表示把spsr恢复到cpsr 

    

swi_str:

    .word 0x00697773           // swi 

    

undefined_instruction:

    // 1. 保存现场 

    ldr sp, =0x55000000

    stmdb sp!, {r0-r12, lr}

    // 2. 处理异常 

    mrs r0, cpsr

    ldr r1, =und_str

    bl print_cpsr

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^    // ^表示把spsr恢复到cpsr 

und_str:

    .word 0x00646e75            // und 

usr_str:

    .word 0x00727375             // usr 

vector_irq:

    // 1. 保存现场 

    ldr sp, =0x54000000

    sub lr, lr, #4

    stmdb sp!, {r0-r12, lr}        // lr就是swi的下一条指令地址 

    // 2. 处理异常 

    // 2.1 分辨是哪个中断 

    // 2.2 调用它的处理函数 

    // 3. 恢复现场 

    ldmia sp!, {r0-r12, pc}^     // ^表示把spsr恢复到cpsr 

reset:

// 硬件相关的设置 

    // Peri port setup 

    ldr r0, =0x70000000

    orr r0, r0, #0x13

    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

    

// 关看门狗 

    // 往WTCON(0x7E004000)写0 

    ldr r0, =0x7E004000

    mov r1, #0

    str r1, [r0]

    

    // 设置栈 

    ldr sp, =8*1024

    // 设置时钟 

    bl clock_init

    bl ddr_init

    bl init_uart

// 把程序的代码段、数据段复制到它的链接地址去     

    adr r0, _start            // 获得_start指令当前所在的地址 : 0

    ldr r1, =_start           // _start的链接地址 0x51000000 

    

    ldr r2, =bss_start     // bss段的起始链接地址 

    

    sub r2, r2, r1

    

    cmp r0,r1

    beq clean_bss

    

    bl copy2ddr

    cmp r0, #0

    bne halt

        

// 清BSS 

    // 把BSS段对应的内存清零 

clean_bss:

    ldr r0, =bss_start

    ldr r1, =bss_end

    mov r3, #0

    cmp r0, r1

    ldreq pc, =on_ddr

clean_loop:

    str r3, [r0], #4

    cmp r0, r1    

    bne clean_loop        

    ldr pc, =on_ddr     //跳到DDR中运行

on_ddr:    

    mrs r0, cpsr           //把状态寄存器的值读到r0中

    bic    r0,r0,#0x1f   //清掉后5位

    orr    r0,r0,#0x10   //把第四位置1

    msr    cpsr,r0         // 进入user mode ,把r0的值赋给程序状态寄存器

    ldr sp, =0x57000000 //用户模式下的sp

    ldr r1, =usr_str

    bl print_cpsr

    

    swi 0

    // cpu进入svc模式

    // 把之前的cpsr保存到spsr_svc 

    // 切换到r13_svc, r14_svc

    // 把swi的下一条指令(bl hello)的地址存到r14(lr)_svc

    // 跳到地址8

              

    bl hello

undef:  //执行完hello函数以后会执行该条未定义指令,从而进入未定义指令中断

    .word 0xff000000 

    // cpu进入Undefined模式

    // 把之前的cpsr保存到spsr_und 

    // 切换到r13_und, r14_und

    // 把下一条指令存的地址到r14(lr)_und

    // 跳到地址4

swi_ret:

    bl main

halt:

    b halt

====================================================================

说明:

    ①上面代码上电复位后CPU就处于管理模式(svc),执行0地址处的b reset跳转到reset:处继续运行,把相关硬件初始化以后会清掉cpsr后5位并把第四位置1,进入user mode设置栈后运行于用户态(usr),即处理器启动时首先进入管理员模式(svc),此后进入除用户模式之外的其他模式,主要完成各模式的堆栈设置,最后进入用户模式,运行用户程序;当发生swi软中断以后cpu进入svc模式。


    ②swi软中断主要用于usr模式(应用程序通常运行于usr模式)切换到svc模式下。在arm的7种模式当中(已经不止7种了)usr模式是唯一一个非特权模式,其他都是特权模式,比如fiq、und等都是特权模式,他们之间的切换直接更改cpsr寄存器的低5位的模式位或者真的发生fiq、und等异常的时候就可以达到切换的目的;而usr模式不是特权模式没有办法更改cpsr寄存器的低5位进行切换,想切换到特权模式只能调用swi指令,swi指令会帮助它进入到svc模式。

    ③如果原来是svc模式,发生未定义指令异常后进入und(Undefined)模式,这时候要重新设置sp栈指针;如果执行swi指令的时候已经处于svc模式,那么发生swi的软中断之后仍然还是svc模式,这个时候就不用再去设置sp栈指针了(在tiny4412异常实验中因为运行的uboot,已经处于svc模式,故要注意sp指针)。

    ④只有处理swi和und异常的时候lr指向下一条指令,其他的异常发生的时候lr都是指向下两条指令;ARM上的每条指令长度都是32位即4个字节;swi指令也是32位且其后面跟的value值占该指令的低24位,所以在程序里可以得到swi指令的value值,具体如下:

unsigned long *pdo_swi = 0x75000000;

*pdo_swi = do_swi;   //先把中断处理函数do_swi地址放在0x75000000

在发生swi异常的时候程序会自动跳到异常向量入口:"b swi\n"

接着跳转到swi处执

[1] [2]

关键字:OK6410  裸机  异常处理

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2018/ic-news101141669.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:ARM工作模式和大端小端存储模式
下一篇:OK6410裸机之NAND Flash操作更新固件

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

OK6410开发板uboot烧写

uboot的移植完成以后,满以为很快能烧写到板子上并安装linux,结果uboot烧写了三天才终于成功,这其中碰到了不少的问题,在此做个总结。首先,飞凌的OK6410开发板并不支持JLink烧写uboot,只能通过SD卡来烧写,这一点我事先并不知道,他们网店介绍里并未说明,而且销售人员也没有做出任何提示,结果我花了整整一天时间尝试所有通过JLink烧写uboot的可能方法,结合网上个别人反映,最终意识到通过JLink完成uboot烧写是不可能成功的了,后来在销售人员那里确认了这一点,对飞凌表示不满。当时买板的时候没有买SD卡,因为感觉没什么用,就想给老板省点钱,现在没SD卡不行了,但在寻找JLink烧写uboot方法的过程中我发现
发表于 2018-10-12

OK6410裸机汇编:1th_led

;   rm *.o led.elf led.bin led.dis=====================================================================下载测试,下载方法可以参考“烧写OK6410裸板方法汇总”章节介绍:    用SecureCRT下载led.bin:    tftp 0x50008000 led.bin    go 0x50008000即可看到程序运行效果。
发表于 2018-10-12

OK6410裸机学习第二天:2th_leds

start.S文件:.globl _start_start:1、硬件相关的设置:把外设的基地址告诉CPU 0 ~ 0x6fff ffff为内存的地址空间,0x7000 0000 ~ 0x7fff ffff为外设寄存器的地址空间       ldr r0, =0x70000000    orr r0, r0, #0x13    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-
发表于 2018-10-12

OK6410裸机学习第三天:3th_leds_c

start.S文件:.globl _start_start:1、硬件相关的设置:把外设的基地址告诉CPU 0 ~ 0x6fff ffff为内存的地址空间,0x7000 0000 ~ 0x7fff ffff为外设寄存器的地址空间    //Peri port setup     ldr r0, =0x70000000    orr r0, r0, #0x13    mcr p15,0,r0,c15,c2,4     &
发表于 2018-10-12

OK6410裸机学习第四天:4th_leds_params

start.S文件:.globl _start_start:1、硬件相关的设置:把外设的基地址告诉CPU  0 ~ 0x6fff ffff为内存的地址空间,0x7000 0000 ~ 0x7fff ffff为外设寄存器的地址空间       ldr r0, =0x70000000    orr r0, r0, #0x13    mcr p15,0,r0,c15,c2,4       @ 256M(0x700
发表于 2018-10-12

OK6410光盘里的uboot不能用TFTP下载文件?

无论用ping命令还是tftp命令,都显示CS8900 Ethernet chip not found?!看了uboot1.1.6/include/configs/smdk6410.h,里面确实是配置为网卡使用CS8900,什么时候发布个配置为DM9000的uboot源码啊?或者发个补丁也行此问题已解决 方法很简单,给用飞凌S3C6410的朋友一个参考。  a.用\u-boot-1.1.6-TQ6410\drivers\目录下的dm9000x.c和dm9000x.h替换OK6410的u-boot里的同名文件  b.用\u-boot-1.1.6-TQ6410\include\configs\tq6410.h里配置网卡的几行代码替换
发表于 2018-10-12

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved
pt type="text/javascript" src="//v3.jiathis.com/code/jia.js?uid=2113614" charset="utf-8">