新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 根據(jù)韋東山修改的mini2440中斷的裸機代碼

根據(jù)韋東山修改的mini2440中斷的裸機代碼

作者: 時間:2016-11-21 來源:網(wǎng)絡(luò) 收藏
這是根據(jù)韋東山的關(guān)于中斷的代碼改成在mini2440板子上可以運行的代碼。
以下是5個文件的所有內(nèi)容:
@是注釋符??!

head.S文件內(nèi)容:


@**************************************************************************
@ File:head.S
@ 功能:初始化,設(shè)置中斷模式、系統(tǒng)模式的棧,設(shè)置好中斷處理函數(shù)
@**************************************************************************

.extern main
.text
.global _start
_start:
@**************************************************************************
@ 中斷向量,本程序中,除Reset和HandleIRQ外,其他異常都沒有使用
@**************************************************************************
@0x00地址處的指令為"b Reset",在系統(tǒng)復(fù)位后,這條指令將跳去執(zhí)行標號"Reset"開始的代碼
b Reset

@0x04:未定義指令終止模式的向量地址
HandleUndef:
b HandleUndef

@0x08:管理模式的向量地址,通過SWI指令進入此模式
HandleSWI:
b HandleSWI

@0x0c:指令預(yù)取終止導(dǎo)致的異常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort

@0x10:數(shù)據(jù)訪問終止導(dǎo)致的異常的向量地址
HandleDataAbort:
b HandleDataAbort

@0x14:保留
HandleNotUsed:
b HandleNotUsed

@0x18:中斷模式的向量地址
b HandleIRQ

@0x1c:快中斷模式的向量地址
HandleFIQ:
b HandleFIQ

Reset:
ldr sp,=4096
@設(shè)置棧指針,以下都是C函數(shù),調(diào)用前需要設(shè)好棧。棧是用 @來保存C函數(shù)的變量和返回地址
bl disable_watch_dog @關(guān)閉WATCHDOG,否則CPU會不斷重啟

msr cpsr_c,#0xd2 @進入中斷模式
ldr sp,=3072 @設(shè)置中斷模式的棧指針,這里的sp寄存器是sp_irq

msr cpsr_c,#0xdf @進入系統(tǒng)模式
ldr sp,=4096 @設(shè)置系統(tǒng)模式的棧指針,這里的sp寄存器是sp_sys
@其實復(fù)位之后,CPU就處于系統(tǒng)模式
@前面的"ldr sp,=4096"完成同樣的功能,此句可省略

bl init_led @初始化LED的GPIO管腳,在init.c中
bl init_irq @調(diào)用中斷初始化函數(shù),在init.c中
msr cpsr_c,#0x5f @設(shè)置I-bit=0,開IRQ中斷

ldr lr,=halt_loop @設(shè)置返回地址
ldr pc,=main @調(diào)用main函數(shù),main函數(shù)是個不做任何事的無限循環(huán)。當按下按鍵時,這個循環(huán)被打斷,CPU進入
@中斷模式,執(zhí)行“b HandleIRQ”的指令
halt_loop:
b halt_loop

HandleIRQ: @HandleIRQ開始的代碼用于處理中斷
sub lr,lr,#4 @計算中斷處理完畢后的返回地址
stmdb sp!,{r0-r12,lr} @保存使用到的寄存器
@注意,此時的sp是中斷模式的sp
@初始值是上面設(shè)置的3072

ldr lr,=int_return @設(shè)置調(diào)用ISR即EINT_Handle函數(shù)后的返回地址
ldr pc,=EINT_Handle @調(diào)用中斷服務(wù)函數(shù),在interrupt.c中

int_return:
ldmia sp!,{r0-r12,pc}^ @中斷返回,^表示將spsr的值復(fù)制到cpsr


init.c文件內(nèi)容:








#define EINTMASK (*(volatile unsigned long*)0x560000a4)//外部中斷屏蔽寄存器
#define INTMSK (*(volatile unsigned long*)0x4a000008)


#define GPBCON (*(volatile unsigned long*)0x56000010)
#define GPBDAT (*(volatile unsigned long*)0x56000014)

#define GPB5_out (1<<(5*2))
#define GPB6_out (1<<(6*2))
#define GPB7_out (1<<(7*2))
#define GPB8_out (1<<(8*2))


#define GPGCON (*(volatile unsigned long*)0x56000060)
#define GPGDAT (*(volatile unsigned long*)0x56000064)

#define GPG0_eint (2<<(0*2)) //K1,EINT8
#define GPG3_eint (2<<(3*2)) //K2,EINT11
#define GPG5_eint (2<<(5*2)) //K3,EINT13
#define GPG6_eint (2<<(6*2)) //K4,EINT14



#define WTCON (*(volatile unsigned long*)0x53000000)

void disable_watch_dog(void)
{
WTCON=0;
}

void init_led(void)
{
GPBCON=GPB5_out|GPB6_out|GPB7_out|GPB8_out;
GPBDAT|=(0x0f<<5); //所有LED熄滅,如果沒有這一句,LED燈默認是全亮的
}



void init_irq()
{
GPGCON=GPG0_eint|GPG3_eint|GPG5_eint|GPG6_eint;

//對于EINT8,EINT11,EINT13,EINT14,需要在EINTMASK寄存器使能它們
EINTMASK&=(~(1<<8))&(~(1<<11))&(~(1<<13))&(~(1<<14));
//這4個外部中斷的優(yōu)先級是相同的,EINT8_23都接仲裁器的REQ1引腳
//所以不用像韋東山程序里那樣再設(shè)置優(yōu)先級了

//EINT8,EINT11,EINT13,EINT14使能
INTMSK&=(~(1<<5));
}



interrupt.c文件內(nèi)容:


#define GPBDAT (*(volatile unsigned long*)0x56000014)
#define INTOFFSET (*(volatile unsigned long*)0x4A000014)
#define EINTPEND (*(volatile unsigned long*)0x560000a8)
#define SRCPND (*(volatile unsigned long*)0x4a000000)
#define INTPND (*(volatile unsigned long*)0x4a000010)

void EINT_Handle()
{
unsigned long oft=INTOFFSET;
unsigned long val;


GPBDAT|=(0x0f<<5); //所有LED熄滅,如果沒有這一句,那么會出現(xiàn)一個結(jié)果,就是將程序下到板子里運行時,
//4個LED燈都是滅的,因為在init.c函數(shù)里設(shè)置它為全滅。然后你按下K1,LED1亮了,
//再按下K2,LED2亮了,但是LED1卻沒熄滅,知道你按到K4,4個LED全亮,再按就沒變化了
//加上這一句就不一樣了,每按一個鍵,只亮相應(yīng)的燈,這也說明中斷的執(zhí)行情況
val=EINTPEND; //EINT寄存器,它的位x為1時,表示EINT已經(jīng)發(fā)生(x為4——23)。
if(val&(1<<8)) //K1被按下,LED1被點亮
GPBDAT&=~(1<<5);

if(val&(1<<11)) //K2被按下,LED2被點亮
GPBDAT&=~(1<<6);

if(val&(1<<13)) //K3被按下,LED3被點亮
GPBDAT&=~(1<<7);

if(val&(1<<14)) //K4被按下,LED4被點亮
GPBDAT&=~(1<<8);
//清除中斷
if(oft==5)
EINTPEND=(1<<8)|(1<<11)|(1<<13)|(1<<14); //清除EINTPEND寄存器,往某位寫入1即可清楚此位
SRCPND=1< //清除SRCPND寄存器,往某位寫入1即可清楚此位
INTPND=1< //清除INTPND寄存器,往某位寫入1即可清楚此位
//注意:清除順序很重要:先是EINTPEND,然后是SRCPND,最后是INTPND
}



main.c文件內(nèi)容:



int main()
{
while(1);
return 0;
}

Makfile文件內(nèi)容:

objs:=head.o init.o interrupt.o main.o

int.bin:$(objs)
arm-linux-ld -Ttext 0x00000000 -o int_elf $^
arm-linux-objcopy -O binary -S int_elf $@
arm-linux-objdump -D -m arm int_elf > int.dis

%.o:%.c
arm-linux-gcc -Wall -O2 -c -o $@ $<

%.o:%.S
arm-linux-gcc -Wall -O2 -c -o $@ $<

clean:
rm -f int.bin int_elf int.dis *.o


關(guān)鍵詞: mini2440中斷裸機代

評論


技術(shù)專區(qū)

關(guān)閉