由于自己买的开发板的norflash坏了,板子剩下了nandflash了,还想玩开发板,就开始我的裸奔了,开始去了解nandflash启动原理,arm2410是从nandflash前4k空间复制到arm内部4kRAM空间当中运行.知道原理以后我写裸奔程序都不超过4k程序,就可以做跑马灯,rs232驱动,rtc程序是足够了.一开始 我用的软件是ads1.2,只能抄写别人 程序,程序当中有一个init2410.s里面有一大堆的汇编语言,看的我眼花撩乱,我也只能硬着头皮看下去,基本上能看懂了个大概. .s文件主要功能就是程序的开始和对中断向量进行描述,同时想main()函数跳转,跳到c语言当中运行.后来我做跑马灯时候,我把.s文件压缩成3句话,把没有用的语句都删了.一般的初试化函数都在2410lib.c文件当中,里面有串口初试化,端口初始化,等其他初始化.裸奔中我觉的最有成就感的是外部中断的实现和3.5寸lcd显示我的相册.先说一下我外部中断的实现.
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt
上面是中断向量表.
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
普通中断表的指针.
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
;USER mode has not be initialized.
mov pc,lr
;The LR register won't be valid if the current mode is not SVC mode.
中断的栈问题
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
END
中断具体表.
static void __irq KeyISR(void)
{
U8 key ;
rGPGCON = rGPGCON & (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)) ; //GPG11,3 set input
rGPFCON = rGPFCON & (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)) ; //GPF2,0 set input
if(rINTPND==BIT_EINT8_23)
{
ClearPending(BIT_EINT8_23);
if(rEINTPEND&(1<<11))
{
//puts("Interrupt eint11 occur...");
rEINTPEND |= 1<< 11;
}
if(rEINTPEND&(1<<19))
{
//puts("Interrupt eint19 occur...");
rEINTPEND |= 1<< 19;
}
}
else if(rINTPND==BIT_EINT0)
{
//puts("Interrupt eint0 occur...");
ClearPending(BIT_EINT0);
}
else if(rINTPND==BIT_EINT2)
{
//puts("Interrupt eint2 occur...");
ClearPending(BIT_EINT2);
}
//查询按键键值
key = Key_Scan() ;
if( key != 0xff )
printf( "Interrupt occur... K%d is pressed!\n", key ) ;
//Beep( 2000, 3000 ) ;
//重新初始化IO口
rGPGCON = rGPGCON & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)) ; //GPG6,2 set output
rGPGDAT = rGPGDAT & (~((1<<6)|(1<<2))); //GPG6,2 output 0
rGPECON = rGPECON & (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)); //GPE13,11 set output
rGPEDAT = rGPEDAT & (~((1<<13)|(1<<11))); //GPE13,11 output 0
rGPGCON = rGPGCON & (~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)) ; //GPG11,3 set EINT
rGPFCON = rGPFCON & (~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)) ; //GPF2,0 set EINT
}
中断子函数,有四个中断源;实际上是三个中断源,在第三个中断分出了两个中断.中断可能初学者看的迷迷糊糊.好了中断就讲在这里.
现在讲关于lcd显示动态的相册,由于照片的数据结构一定大于4k空间,所以在nandflash纯裸奔是不可能的.这个问题困饶我了很久,后来根据wince和linux启动的原理,我用bootloader(vivi)来启动我lcd裸奔程序,然后固化到nandflash当中即ce区或则是 kernel区.
Lcd_Port_Init();
puts("linshenghuan");
Lcd_Init();
Lcd_EnvidOnOff(1); //turn on vedio
DelayMs();
Lcd_ClearScr(0x00); //fill all screen with some color
DelayMs();
Lcd_ClearScr(0xF1F1);
DelayMs();
Lcd_ClearScr(0x1F1F);
DelayMs();
Lcd_ClearScr(0x00);
Paint_Bmp( 0,0,240,320, xyx_240_320 ) ; //paint a bmp