历史上的今天
返回首页

历史上的今天

今天是:2024年10月14日(星期一)

正在发生

2018年10月14日 | Tiny4412异常处理

2018-10-14 来源:eefocus

#include "regs.h"

void enable_mmu(unsigned long ttb);

void init_ttb(unsigned long *ttb_base);

void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa);

void memset(char *buf, char ch, int size);

void memcpy(char *dst, char *src, int size);

void do_swi(unsigned long regs[]);

void (*printf)(char *, ...) = 0x43e11434;

void main(void)

{    

    unsigned long  vector_base = 0xffff0000;

    unsigned long  tt_base = 0x73000000;

    unsigned long *pdo_swi = 0x75000000;

    extern unsigned long vectors_start, vectors_end;

    memset(tt_base, 0x00, 16 * 1024);

    mmap(tt_base, vector_base, 0x70000000);    

    enable_mmu(tt_base);

    memcpy(vector_base, vectors_start, 0x100);

    *pdo_swi = do_swi;

    

    __asm__ __volatile__ (

        "mov r0, r0\n"            

        "swi 0x7777\n"

        "mov r1, r1\n"

    );

}

void do_swi(unsigned long regs[])

{

    unsigned long *instr = regs[13] - 4;

    printf("swi:  0x%x\n", *instr & 0xffffff);

}

void enable_mmu(unsigned long ttb)

{    

    unsigned long c1_flags;

    init_ttb(ttb);

    c1_flags = 1 | (1 << 3) | ( 1 << 11) | ( 1 << 13) |  (1 << 28);

    __asm__ __volatile__ (

        "mvn r0, #0 \n"            

        "mcr p15, 0, r0, c3, c0, 0\n"

        "mcr p15, 0, %1, c2, c0, 0\n" //configure ttb

        "mrc p15, 0, r0, c1, c0, 0\n"

        "orr %0, r0, %0\n"

        "mcr p15, 0, %0, c1, c0, 0\n" //enable mmu

        :

        : "r" (c1_flags), "r" (ttb)

        : "r0"

    );

}

void init_ttb(unsigned long *ttb_base)

{

    unsigned long va, pa;

    for (va = 0x00000000; va < 0x10000000; va += 0x100000) { //Others

        pa = va;

        ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;    

    }

    for (va = 0x10000000; va < 0x14000000; va += 0x100000) { //SFR

        pa = va;

        ttb_base[ va >> 20] = (pa & 0xfff00000) |  2;    

    }

    for (va = 0x40000000; va < 0x80000000; va += 0x100000) { //DRAM

        pa = va;

        ttb_base[ va >> 20] = (pa & 0xfff00000) | 2;    

    }

    

}

void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa)

{

    ttb_base[ va >> 20] = (pa & 0xfff00000) |  2;    

}

void memset(char *buf, char ch, int size)

{

    int i;

    for (i = 0; i < size; i ++)

        buf[i] = ch;

}

void memcpy(char *dst, char *src, int size)

{

    int i;

    for (i = 0; i < size; i ++) 

        dst[i] = src[i];    

}

__asm__ (

"vectors:\n"

    "b reset\n"

    "b und\n"

    "b swi\n"

    "b pre_abt\n"

    "b dat_abt\n"

    ".word 0\n"

    "b irq\n"

    "b fiq\n"

"reset:\n"

"und:\n"

    "mov sp, #0x74000000\n"

    "stmfd sp!, {r0-r12, lr}\n"

    "mov r0, sp\n"

    "mov r3, #0x74000000\n"

    "ldr r3, [r3]\n"

    "blx r3\n"

    "mov sp, #0x74000000\n"

    "ldmea sp, {r0-r12, pc}^\n"

"swi:\n"

    "stmfd sp!, {r0-r12, lr}\n"

    

    "mov r0, sp\n"

    "mov r3, #0x75000000\n"

    "ldr r3, [r3]\n"

    "blx r3\n"

    "ldmfd sp, {r0-r12, pc}^\n"

"pre_abt:\n"

"dat_abt:\n"

"fiq:\n"

"irq:\n"

    "mov sp, #0x75000000\n"

    "sub lr, lr, #4    \n"

    "stmfd sp!, {r0-r12, lr}\n"

    

    "mov r0, sp\n"

    "mov r3, #0x75000000\n"

    "ldr r3, [r3]\n"

    "blx r3\n"

    "mov sp, #0x75000000\n"

    "ldmea sp, {r0-r12, pc}^\n"

"EOV:\n"

"vectors_start:\n"

    ".word vectors\n"

"vectors_end:\n"

    ".word EOV\n"

);

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

Makefile文件:

default:

    arm-linux-gcc -c test.c  -o test.o

    arm-linux-ld  -Ttext=0x70003000  test.o  -o test

    arm-linux-objcopy  -O binary  test  test.bin

clean:

    rm -f test.o  test  test.bin   *~ 

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

烧写测试参考:“Tiny4412从SD卡启动u-boot用linux的DNW烧写裸板程序”


说明:

    ①系统上电复位后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处执行:

"swi:\n"

   "stmfd sp!, {r0-r12, lr}\n"

//保护现场,把usr模式下的相关寄存器入栈,

//存放顺序是先存放lr、r12....r0,最终sp指向r0的地址

"mov r0, sp\n"                   //把上一步中指向usr模式下r0地址的sp传给r0寄存器

"mov r3, #0x75000000\n" 

"ldr r3, [r3]\n"

"blx r3\n"                          //调用中断处理函数do_swi,参数放在r0中

//regs[0] == r0

//regs[1] == r1

//.....

//regs[12] == r12

//regs[13] == lr

void do_swi(unsigned long regs[]) //regs指向usr模式下r0地址

{

    //按照入栈顺序regs[13]为usr模式下lr值,即发生swi异常时下一条指令的地址

    //regs[13] - 4 = lr - 4 ; 即上一条指令的地址也就是swi异常的地址

    unsigned long *instr = regs[13] - 4;

    

    //根据ARM指令是32位的,swi指令也是32位且其后面跟的value值占该指令的低24位得到value值

    printf("swi:  0x%x\n", *instr & 0xffffff);

}


推荐阅读

史海拾趣

Gang Song Electronics Co Ltd公司的发展小趣事

作为物联网领域的领军企业之一,Telit(包含GainSpan的技术)不仅致力于技术创新和市场拓展,还积极参与行业标准的制定和生态建设的推动。通过与其他企业和组织的合作与交流,Telit推动了物联网技术的标准化和规范化发展。同时,它还积极构建物联网生态系统,与上下游企业建立紧密的合作关系,共同推动物联网产业的繁荣和发展。这些努力不仅提升了Telit在行业内的地位和影响力,也为整个物联网产业的发展做出了重要贡献。

DACHANG公司的发展小趣事

DACHANG公司的起点可追溯到一次重要的技术突破。当时,公司创始人带领团队经过数月的艰苦研发,成功开发出了一款具有革命性意义的新型电子元件。这款元件不仅性能卓越,而且成本较低,极大地满足了市场对于高性价比电子产品的需求。凭借这一技术突破,DACHANG公司迅速在市场上获得了认可,为公司后续的发展奠定了坚实的基础。

Blue Creation公司的发展小趣事

作为一家有社会责任感的企业,Blue Creation公司始终关注环保和可持续发展。公司积极采用环保材料和节能技术,努力降低生产过程中的环境影响。同时,公司还积极参与公益事业,捐资助学、扶贫济困,回馈社会。这些举措不仅提升了Blue Creation的企业形象,也为其赢得了社会各界的广泛赞誉。

以上五个故事分别从不同角度展现了Blue Creation公司在电子行业发展的历程和成就。虽然这些故事是虚构的,但它们所蕴含的企业发展理念和经验对于现实中的企业来说仍具有一定的借鉴意义。

冠图电子(GTL-POWER)公司的发展小趣事

在市场竞争日益激烈的背景下,Blue Creation公司意识到单打独斗难以立足。于是,公司积极寻求与其他企业建立合作关系。通过与一家知名芯片制造商的深度合作,Blue Creation成功将其电源管理技术集成到对方的芯片产品中,双方共同开拓市场,实现了互利共赢。这一举措不仅提升了Blue Creation的知名度,也为其带来了稳定的收入来源。

Daburn公司的发展小趣事

在Daburn公司的发展历程中,质量控制一直是重中之重。公司建立了严格的质量管理体系,从原材料采购到生产流程再到成品检验,每一个环节都严格把控。此外,Daburn还注重持续改进,通过引入先进的生产设备和工艺,不断提高产品的质量和性能。这种对质量的执着追求让Daburn赢得了客户的信任和好评。

Elprotronic Inc.公司的发展小趣事

随着电子行业的不断发展,客户对电子元器件的需求也在不断变化。Elprotronic Inc.紧跟市场趋势,不断推出具有创新性的产品和技术。其中,一项名为“高速数据传输技术”的创新成果引起了业界的广泛关注。这项技术可以大幅提高数据传输速度,同时保证数据的稳定性和安全性。这一突破性的技术创新为Elprotronic Inc.赢得了更多客户的信赖和支持,也进一步巩固了公司在行业中的地位。

问答坊 | AI 解惑

Stellaris单片机相关安装软件下载

[ 本帖最后由 chenzhufly 于 2010-3-15 18:35 编辑 ]…

查看全部问答>

菜鸟问题:隐式声明函数 copy_to_user。大家帮忙啊

#include #include #include        /* everything... */ #define DEVICE_NAME                \"demo\" #define demo_MAJOR 249 #define demo_MINOR 0 #define MAX_BUF_LEN ...…

查看全部问答>

基于wm5的RFID读写驱动中间件开发

我最近参与了老师的一个实验室项目,其中有一项内容是在windows mobile5的平台上开发sirit公司产的RFID读写器的驱动,我开发的环境是c# .net cf2.0,使用vs2008,读写卡是sdio插口。如今我向各位大侠请教的是如何开发类似的驱动,模拟器能否模拟还 ...…

查看全部问答>

求教wince下设置窗口刷新区域大小的API函数

本人在开发一个WINCE下的流媒体播放软件,在加入GUI后,出现一个比较头疼的问题,在播放流媒体,视频窗口是可变的,在播放界面退回主界面时,需要重画整个窗口,显示主界面贴图。但我发现winCE在窗口重画时,判断的更新区域不是全屏,而是视频窗大 ...…

查看全部问答>

asp.net 嵌入就业前景?

asp.net 嵌入就业前景?…

查看全部问答>

倾囊求助 s3c44B0x 板子问题

前一段时间买了个s3c44B0的板子,用了没几次就不行了,上电后串口没有任何打印信息 附带的资料说是正常情况上电后 应该 d1 d2 d3依次闪烁,我的板子是它们一齐全亮了,重烧系统也不行。 com1 下面就是那三个灯 …

查看全部问答>

新手51串口接收的问题!!!!!

51串口每秒接收一组上位机数据,要求是如果这组数据是想要的就控制一个开关通断!想请教的是串口中断接收数据怎么才能很好的控制一个开关通断,开关平均500MS闭合一次!在接收中断函数里面写延时行不通!请教各位。。!…

查看全部问答>

飞思卡尔SCI教程

SCI即UART这是我们的一个教程,当初是为nss08kit_r1开发板写的它应该使用与所有s08单片机,也适用于coldfire v1 mcu转载请注明出处…

查看全部问答>

求助:signaltap II抓取波形问题

遇到这个问题:用signaltap来抓取波形分析,采样时钟用的200m,能抓到100m的时钟,但不能抓到通过100m时钟处理得信号数据波形,这是怎么回事呢? 还有,加入signaltap后,编译综合后出现一些警告,不知道怎么处理这类问题呢?望知道的朋友给点建议 ...…

查看全部问答>

液晶UI设计

最近想把以前的做的项目的液晶显示做的好看一些,使用的控制芯片为F28027,原先使用的液晶为NOKIA5110.同样也考虑使用SPI总线的TFT来做,希望做过UI界面设计的仪器讨论一下。 上传的为我要显示的内容,有温湿度,海拔高度,GPS数据,UTC时间,计步 ...…

查看全部问答>