历史上的今天
返回首页

历史上的今天

今天是:2024年10月11日(星期五)

正在发生

2018年10月11日 | OK6410裸机之中断处理过程

2018-10-11 来源:eefocus

start.S文件:

.globl _start

_start:

    // 0 地址 

    b reset                                                // 复位时,cpu跳到0地址 

    ldr pc, =undefined_instruction         // cpu遇到不能识别的指令时 

    ldr pc, _vector_swi                              // 当执行swi指令时, 进入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

    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           

    //为什么这里的lr要减4? 因为在每条指令执行之前判断有无中断,这条指令并未执行,

    //而此时的lr指向了下一条指令,故返回时lr要减4指向那条没有运行的指令

    //只有处理swi和und异常的时候lr指向下一条指令,其他的异常发生的时候lr都是指向下两条指令

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

    // 2. 处理异常 

    bl do_irq

    

    // 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                 // sp_svc 

    // 设置时钟 

    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

on_ddr:    

    bl irq_init

    mrs r0, cpsr

    bic    r0,r0,#0x9f         // 清cpsr的I位,M4~M0 

    orr    r0,r0,#0x10

    msr    cpsr,r0              // 进入user mode 

    ldr sp, =0x57000000  // sp_sys/usr 

    ldr r1, =usr_str

    bl print_cpsr

    

    swi 0

    // cpu进入svc模式

    // 把之前的cpsr保存到spsr_svc 

    // 切换到r13_svc, r14_svc

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

    // 跳到地址8

              

    bl hello

undef:

    .word 0xff000000

    // cpu进入Undefined模式

    // 把之前的cpsr保存到spsr_und 

    // 切换到r13_und, r14_und

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

    // 跳到地址4

swi_ret:

    bl main

halt:

    b halt    

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

irq.c源码:

#define GPNCON     (*((volatile unsigned long *)0x7F008830))

#define GPNDAT     (*((volatile unsigned long *)0x7F008834))

#define EINT0CON0  (*((volatile unsigned long *)0x7F008900))

#define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

#define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

#define PRIORITY    (*((volatile unsigned long *)0x7F008280))

#define SERVICE     (*((volatile unsigned long *)0x7F008284))

#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))

#define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))

#define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))

#define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))

#define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))

#define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))

#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))

#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))

#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))

#define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

#define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))

void irq_init(void)

{

    // 配置GPIO引脚为中断引脚 

    // GPN0~5 设为中断引脚 

    GPNCON &= ~(0xfff);

    GPNCON |= 0xaaa;

    // 设置中断触发方式为: 双边沿触发 

    EINT0CON0 &= ~(0xfff);

    EINT0CON0 |= 0x777;

    // 使能中断 

    EINT0MASK &= ~(0x3f);

    // 在中断控制器里使能这些中断 

    VIC0INTENABLE |= (0x3);          // bit0: eint0~3, bit1: eint4~11  

    // 设置优先级 

}

void do_irq(void)

{

    int i = 0;

    

    printf("do_irq\n\r");

    printf("SERVICE     = 0x%x\n\r", SERVICE);

    printf("SERVICEPEND = 0x%x\n\r", SERVICEPEND);

    printf("EINT0PEND   = 0x%x\n\r", EINT0PEND);  //发生了哪一个外部中断

    

    // 2.1 简单的分辨一下是哪个中断 

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

    {

        if (EINT0PEND & (1<

        {

            if (GPNDAT & (1<

            {

                printf("K%d released\n\r", i+1);

            }

            else

            {

                printf("K%d pressed\n\r", i+1);

            }

        }

    }

    // 2.2 调用它的处理函数     

    // 2.3 清中断     

    EINT0PEND   = 0x3f;  // 清中断 

    VIC0ADDRESS = 0;

}


推荐阅读

史海拾趣

中环(Central)公司的发展小趣事

2019年,中环公司发布了210mm尺寸G12超大硅片“夸父”系列产品。这一创新产品凭借其高效、高质的特点,迅速获得了市场的认可。G12超大硅片的推出不仅引领了光伏材料的发展方向,也进一步巩固了中环在光伏领域的领先地位。

GarrettCom公司的发展小趣事

并购:2011年,全球领先的信号传输解决方案提供商Belden成功收购了GarrettCom。这一并购标志着GarrettCom正式成为Belden大家庭的一员,也为其带来了更广阔的发展空间和资源支持。

融合:加入Belden后,GarrettCom继续发挥其在工业通信领域的专长,并与Belden的其他业务线形成协同效应。双方共同为客户提供更全面的信号传输和通信解决方案,进一步提升了市场竞争力。

Herth+Buss Fahrzeugteile GmbH & Co KG公司的发展小趣事
相对于其他安防设备,成本较低,适合大规模应用。
Brite-Led Optoelectronics Inc公司的发展小趣事

面对电子行业的快速变化和不断升级的技术需求,Brite-Led始终保持敏锐的洞察力和创新精神。公司不断投入研发资源,推出新产品和新技术,以满足市场的变化和客户的需求。同时,公司还注重人才培养和引进,建立了一支高素质的研发团队和管理团队。这些措施使得Brite-Led在激烈的市场竞争中始终保持领先地位,实现了持续发展。

以上是关于Brite-Led Optoelectronics Inc公司发展的5个虚构故事,虽然这些故事是基于虚构的,但它们可能反映了Brite-Led Optoelectronics Inc公司在实际发展中可能遇到的一些情况和挑战。

全志(Allwinner)公司的发展小趣事

随着平板市场的逐渐饱和,全志科技开始寻求新的增长点。公司在保持原有产品线优势的同时,积极拓展多品类产品线,实施了营销端BU化,并提出了未来大方向的MANS战略。这一转型不仅增强了公司的市场竞争力,也为公司的长期发展打开了新的局面。

AMICC [AMIC TECHNOLOGY]公司的发展小趣事

AMICC的创立之初,面临着资金短缺、市场竞争激烈等多重困难。创始人凭借对半导体技术的深刻理解和敏锐的市场洞察力,带领团队夜以继日地研发新产品,积极寻找合作伙伴。经过不懈的努力,AMICC逐渐在行业中崭露头角,其产品质量和性能得到了市场的认可。

问答坊 | AI 解惑

验证码10次有9次不正确?

验证码10次有9次不正确?:\'( …

查看全部问答>

stm32的UC/OS ii问题,请指教

小弟找了个STM32的板跑UC/OSII,环境用的IAR5.2 仿真的时候上来就跳到了地址80024F4,但是FLASH设置的是从800,000开始 而且前面不只是向量表,还有一些是UC/OS的东西, 请指教 还有为什么上来系统就自己跳到low-level_int的,在哪设置啊 二:low_lev ...…

查看全部问答>

wince下调用dll

在wince下怎么调用dll? 我有vc下的一个.dll,.lib,.h文件,在wince的程序里编译通过。 同时在模拟器里已经加了dll文件。但是运行的时候总是显示没有找到某个元件。 请问dll的调用和.lib一致吗?…

查看全部问答>

AB PLC-5/60 25针转9针走dse协议

AB PLC-5/60 25针转9针走dse协议,请教各位高手怎么实现?…

查看全部问答>

手机资料一键备份器

手机资料一键备份器生活在现代社会中的人们已经对高科技产品形成了很强的依附。假如你某天丧失了手机,或许就意味着很多接洽方式再也无法找回。尽管现在的大部分别机都可以与电脑相连并进行备份,但是过程过于繁琐。而为了方便人们对数据进行备份, ...…

查看全部问答>

lm3s8962上的RT-Thread连载——Finsh shell的基本使用

RT-Thread Shell实验1 Finsh的基本使用 实验目的: ²        了解RT-Thread的命令行工具Finsh Shell组件 ²        掌握Finsh Shell的基本使用方法; ²& ...…

查看全部问答>

求助:串口数据在超级终端的反馈

从PC键盘上往板子的COM0送字符,并将COM0收到字符再传回超级终端显示,但现在超级终端没显示输入的字符,只显示原来printf的字符?麻烦大家看看哪错了,谢谢 板子是万利的199元的那块板子 程序大致如下:   int main(void)  ...…

查看全部问答>

【转帖】深入解析STM32_USB-FS-Device_Lib库(V3.1.0)

深入解析STM32_USB-FS-Device_Lib库(V3.1.0) 基于STM32 的USB程序开发笔记,写的挺不错,与大家分享 开发笔记1.rar (1.94 MB) 下载次数:454 2010-8-27 09:48 开发笔记2.rar ...…

查看全部问答>

请教高手关于430单片机Timer_A定时器中断问题

代码: void Systerm_Init() { WDTCTL=WDTHOLD+WDTPW; //关看门狗 BCSCTL1&=~XT2OFF; // XT2 TURN ON BCSCTL2=SELM1+DIVM1+DIVM0+SELS; //TX2 为主时钟,8分频,TX2 AS SMAIN } void TimerA_init() { TACTL=TAS ...…

查看全部问答>

详细的舵机资料大全

本帖最后由 paulhyde 于 2014-9-15 03:22 编辑    …

查看全部问答>