s3c6410裸机程序(2)

发布时间:2024-09-03  

本来以为自己可以很快就把中断程序写好的,但是没想到知道昨天才有了点眉目,虽然还不知道对不对,但是写出来给大家批评指正。


笔者自从上次写了一个轮询式的按键驱动LED灯之后就一直在弄中断这一部分,可是弄来弄去都没什么起色,只好也中断一段时间去配置自己的linux系统,写写应用程序,果然停了几天后突然就成了,真是不知道怎么回事。下面说说笔者的思路。


笔者从《ARM体系结构与编程》这本书中知道了ARM中有七种中断,中断需要中断向量表,而且中断向量表需要放在最低端从地址空间0开始的连续32字节内,为什么七个中断要32字节呢?因为倒数第三个四字节的空间需要空出来。然后是ARM中的中断处理体系,想必阅者都知道x86的中断过程吧,外设通过外设控制器发出中断信号,被中断控制器拦截并进行一定的处理然后发送给CPU,那么ARM肯定也是有中断控制器的,是什么呢?根据s3c6410的用户手册,笔者知道了叫作VIC(全称的中文翻译叫作中断向量控制器)。这个VIC就相当于PC机中的APIC,下面是出事换VIC的代码:


/* 先清除所有中断*/

rVIC0INTENCLEAR = ~(0x0);

rVIC1INTENCLEAR = ~(0x0);

 

 

/* 置中断类型, 全部为IRQ中断*/

rVIC0INTSELECT = 0x0;

rVIC1INTSELECT = 0x0;

 

rVIC0INTENABLE |= 1 << 0;

rVIC0INTENABLE |= 1 << 1;


这个其实很简单,就是让所有中断无效,然后使能按键中断。初始化了VIC之后呢?中断需要三方面协调才可以发生,中断控制器是一个方面,除此之外cpu要能够接受中断,还有就是外设要能够发送中断信号。下面初始化按键:


tmp = rGPNCON;

tmp &= ~0xFFF;

tmp |= 0xAAA;   // 六个按键全部为设置为中断引脚

rGPNCON = tmp; 

rGPNPUD &= ~0xFFF;

 

tmp = rEINT0PEND;

tmp |= 0x1;

tmp |= 0x1 << 1;

rEINT0PEND = tmp;

 

 

tmp = rEINT0MASK;

tmp &= ~(0x3F);

rEINT0MASK = tmp;

 

初始化按键除了要把引脚设置为中断模式外,还有比较重要的就是要清除中断状态寄存器(向对应位写’1‘)和清除中断屏蔽寄存器(对应位清0)。


到了这里似乎就万事俱备,只差中断程序了,但是笔者上次就是在这里遇到了问题,中断向量表要求在地址空间的最低端,但是SDRAM是从0x50000000开始的,程序肯定要下载到这个地址之后的空间,那么笔者自己写的中断向量表怎么办呢?于是笔者想到了使用MMU,把0地址映射到物理地址的0x50200000(程序下载到这个地方),其它部分做相同映射:


start

Interrupt_Vec                         ; 中断向量表

    ldr     PC, ResetAddr

    ldr     PC, UndefAddr

    ldr     PC, SWIAddr

    ldr     PC, PrefetchAddr

    ldr     PC, DataAbortAddr

    DCD     0x0

    ldr     PC, IRQAddr

    ldr     PC, FIQAddr

     

ResetAddr   DCD     ResetInit

UndefAddr   DCD     UndefHandler

SWIAddr     DCD     SWIHandler

PrefetchAddr    DCD     PrefetchHandler

DataAbortAddr   DCD     DataAbortHandler

            DCD     0x0

IRQAddr     DCD     IRQHandler

FIQAddr     DCD     FIQHandler

 

ReservedSpace    SPACE  16384 - 64          ; 页表只能16KB对齐

PageTable       SPACE   16384                 ; 页表,只实现一级映射,1MSection

 

 

; 以下是用不到的中断

UndefHandler

    subs        pc, r14, #4

SWIHandler

    subs        pc, r14, #4

PrefetchHandler

    subs        pc, r14, #4

DataAbortHandler

    subs        pc, r14, #4

FIQHandler

    subs        pc, r14, #4

 

     

EnableMMU

    ; Invalidate entire Cache

    mov     r0, #0

    mcr     p15, 0, r0, c7, c7, 0  

     

    ; Load PageTableBase 

    ldr     r0, =PageTable

    mcr     p15, 0, r0, c2, c0, 0   

     

    ;Field control

    ldr     r0, =0xFFFFFFFF

    mcr     p15, 0, r0, c3, c0, 0

      

     

    ; Enable MMU, Enable I Cache, Disable AP bits

    mrc     p15, 0, r0, c1, c0, 0

    orr     r0, r0, #0x1000

    orr     r0, r0, #0x800000

    orr     r0, r0, #0x1

    mcr     p15, 0, r0, c1, c0, 0

     

     

    mov     pc, r14

    LTORG

     

ResetInit                          ; 复位,设置栈

    LDR     r13, =0x50400000

    bl      _SetPageTable

    bl      EnableMMU

    b       Main

    LTORG

     

IRQHandler                       ; 中断处理

    stmfd   sp!, {r0-r3, r12, r14}

    ldr     r14, =IRQRet

    b       _HandleIRQ

IRQRet

    ldmfd   sp!, {r0-r3, r12, r14}

    subs        pc, r14, #4

     

    LTORG

 至于_SetPageTable这个程序使用c语言实现的:


  


extern int PageTable[];

#define L1_DESCRIPTOR       2

 

int _SetPageTable(void)

{

    int PhyBase;

    int i;

     

    PhyBase = 0x50200000 + L1_DESCRIPTOR;

    PageTable[0] = PhyBase;

     

    for (i = 1; i < 4096; i++)

    {

        PhyBase = 0x0 + L1_DESCRIPTOR + i * 0x00100000;

        PageTable[i] = PhyBase;

    }

    return 0;

}


这样以后,MMU就算是开启了,笔者编译仿真了一下,发现EnableMMU这个程序运行顺利,而且这之后的代码还能正确运行,然后笔者写了中断程序,仍然是按键驱动LED,发现竟然正确运行了。


主函数如下:


void Main(void)

{

 

    InitVIC();  

     

    InitGPIO();

 

    EnableIRQ();

     

    while (1);

}


这就是主流程,可以看出来笔者确实用的中断实现了按键驱动LED。


虽然到这里为止笔者的第一个中断程序算是写出来了,但是上述的程序很容易在中断内部或者InitGPIO函数内死循环,不知道为什么,只好以后解决了,先这样吧!


好文要顶 关注我 收藏该文 微信分享


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>