當前位置:編程學習大全網 - 編程語言 - 編寫壹段ARM程序,實現數據塊復制

編寫壹段ARM程序,實現數據塊復制

妳可以自己寫壹個匯編的程序,把Nand Flash 中的程序搬到SDRAM中。因為S3C2410有Nor Flash和Nand Flash有兩種啟動方式,所以在搬移過程中略有不同。如果用Nand Flash啟動可以使用下面的代碼,至於Nor Flash啟動就相對簡單了,妳可以自己研究壹下。

文件1.head.s

@ 文件 head.s

@ 作用:關閉看門狗、SDRAM 的初始化設置、搬移 Nand Flash 4K 以後

@ 的代碼到 SDRAM 的指定位置、執行 SDRAM 中的代碼

.text

.global _start

_start:

ldr r0, =0x53000000 @ Close Watch Dog Timer

mov r1, #0x0

str r1, [r0]

bl memory_setup @ Initialize memory setting

bl flash_to_sdram @ Copy code to sdram

ldr sp, =0x34000000 @ Set stack pointer

ldr pc, =main @ execute the code in SDRAM

文件2:flash.s

@ 文件 flash.s

@ 作用:設置 Nand Flash 的控制寄存器、讀取 Nand Flash

@ 中的代碼到 SDRAM 的指定位置

.equ NFCONF, 0x4e000000

.equ NFCMD, 0x4e000004

.equ NFADDR, 0x4e000008

.equ NFDATA, 0x4e00000c

.equ NFSTAT, 0x4e000010

.equ NFECC, 0x4e000014

.global flash_to_sdram

flash_to_sdram:

@ Save return addr

mov r10,lr

@ Initialize Nand Flash

mov r0,#NFCONF

ldr r1,=0xf830

str r1,[r0]

@ First reset and enable Nand Flash

ldr r1,[r0]

bic r1, r1, #0x800

str r1,[r0]

ldr r2,=NFCMD

mov r3,#0xff

str r3,[r2]

@ for delay

mov r3, #0

1:

subs r3, r3, #1

bne 1b

@ Wait until Nand Flash bit0 is 1

wait_nfstat:

ldr r2,=NFSTAT

ldr r3,[r2]

tst r3,#0x01

beq wait_nfstat

@ Disable Nand Flash

ldr r0,=NFCONF

ldr r1,[r0]

orr r1,r1,#0x8000

str r1,[r0]

@ Initialzie stack

ldr sp,=4096

@ Set arguments and call

@ function nand_read defined in nand_read.c

ldr r0,=0x30000000

mov r1,#4096

mov r2,#1024

bl nand_read

@ return

mov pc,r10

文件3:interrupt.c

/*

* 文件 interrupt.c

* 作用:設置並響應按鍵中斷

*/

#include "printf.h"

#define GPECON (*(volatile unsigned long *)0x56000040)

#define GPEDAT (*(volatile unsigned long *)0x56000044)

#define GPEUP (*(volatile unsigned long *)0x56000048)

#define GPFCON (*(volatile unsigned long *)0x56000050)

#define GPFDAT (*(volatile unsigned long *)0x56000054)

#define GPFUP (*(volatile unsigned long *)0x56000058)

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

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

#define GPGUP (*(volatile unsigned long *)0x56000068)

#define EINTMASK (*(volatile unsigned long *)0x560000a4)

#define INTMSK (*(volatile unsigned long *)0X4a000008)

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

#define EINTPEND (*(volatile unsigned long *)0x560000a8)

#define INTPND (*(volatile unsigned long *)0X4a000010)

#define SRCPND (*(volatile unsigned long *)0X4a000000)

#define BIT_EINT0 (0x1 << 0)

#define BIT_EINT2 (0x1 << 2)

#define BIT_EINT8_23 (0x1 << 5)

#define SET_KEY_INTERRUPT_REG() ({ \

GPGCON = (GPGCON & (~((3<<12)|(3<<4)))) | ((1<<12)|(1<<4)) ; \

GPGDAT = GPGDAT & (~((1<<6)|(1<<2))); \

GPECON = (GPECON & (~((3<<26)|(3<<22)))) | ((1<<26)|(1<<22)); \

GPEDAT = GPEDAT & (~((1<<13)|(1<<11))); \

GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((2<<22)|(2<<6)) ; \

GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((2<<4)|(2<<0)) ; \

})

__inline void ClearPending(int bit)

{

SRCPND = bit;

INTPND = bit;

}

void init_irq( ) {

GPFCON = ((0x1<<8) | (0x1 << 10) | (0x1 << 12) | (0x1 << 14)); // Set the led D9~D12 output

/*

GPGCON = (GPGCON & (~((3<<12)|(3<<4)))) | ((1<<12)|(1<<4)) ; // GPGCON6,2 set output

// GPGCON6:KSCAN1

// GPGCON2:KSCAN3

GPGDAT = GPGDAT & (~((1<<6)|(1<<2))); // GPGDAT6,2 output 0

GPECON = (GPECON & (~((3<<26)|(3<<22)))) | ((1<<26)|(1<<22)); // GPECON13,11 set output

GPEDAT = GPEDAT & (~((1<<13)|(1<<11))); // GPEDAT13,11 output 0

GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((2<<22)|(2<<6)) ; // GPGCON11,3 set EINT

GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((2<<4)|(2<<0)) ; // GPFDAT2,0 set EINT

*/

// Use the defined micro instead of above code

SET_KEY_INTERRUPT_REG();

GPFUP |= (1<<0) | (1<<2); // Up

GPGUP |= (1<<3) | (1<<11); // Up

EINTPEND |= (1 << 19) | (1 << 11); // Clear eint 11,19

EINTMASK &= (~((1 << 19) | (1 << 11))); // Enable EINT11,19

ClearPending(BIT_EINT0|BIT_EINT2|BIT_EINT8_23); // Enable EINT0,2 and the EINT8_23

INTMSK &= (~0x25);

return;

}

int Key_Scan( void )

{

int i;

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

GPGDAT = (GPGDAT &(~((1<<6)|(1<<2)))) | (1<<6) | (0<<2) ; //GPG6,2 output 0

GPEDAT = (GPEDAT &(~((1<<13)|(1<<11)))) | (1<<13) | (1<<11) ; //GPE13,11 output 0

if( (GPFDAT&(1<< 0)) == 0 ) return 16 ;

else if( (GPFDAT&(1<< 2)) == 0 ) return 15 ;

else if( (GPGDAT&(1<< 3)) == 0 ) return 14 ;

else if( (GPGDAT&(1<<11)) == 0 ) return 13 ;

GPGDAT = (GPGDAT &(~((1<<6)|(1<<2)))) | (0<<6) | (1<<2) ; //GPG6,2 output 0

GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (1<<13) | (1<<11) ; //GPE13,11 output 0

if( (GPFDAT&(1<< 0)) == 0 ) return 11 ;

else if( (GPFDAT&(1<< 2)) == 0 ) return 8 ;

else if( (GPGDAT&(1<< 3)) == 0 ) return 5 ;

else if( (GPGDAT&(1<<11)) == 0 ) return 2 ;

GPGDAT = (GPGDAT & (~((1<<6)|(1<<2)))) | (1<<6) | (1<<2) ; //GPG6,2 output 0

GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (1<<13) | (0<<11) ; //GPE13,11 output 0

if( (GPFDAT&(1<< 0)) == 0 ) return 10 ;

else if( (GPFDAT&(1<< 2)) == 0 ) return 7 ;

else if( (GPGDAT&(1<< 3)) == 0 ) return 4 ;

else if( (GPGDAT&(1<<11)) == 0 ) return 1 ;

GPGDAT = (GPGDAT & (~((1<<6)|(1<<2)))) | (1<<6) | (1<<2) ; //GPG6,2 output 0

GPEDAT = (GPEDAT & (~((1<<13)|(1<<11)))) | (0<<13) | (1<<11) ; //GPE13,11 output 0

if( (GPFDAT&(1<< 0)) == 0 ) return 12 ;

else if( (GPFDAT&(1<< 2)) == 0 ) return 9 ;

else if( (GPGDAT&(1<< 3)) == 0 ) return 6 ;

else if( (GPGDAT&(1<<11)) == 0 ) return 3 ;

else return 0xff ;

}

void EINT_Handle( void ) {

GPGCON = (GPGCON & (~((3<<22)|(3<<6)))) | ((0<<22)|(0<<6)) ; //GPG11,3 set input

GPFCON = (GPFCON & (~((3<<4)|(3<<0)))) | ((0<<4)|(0<<0)) ; //GPF2, 0 set input

if(INTPND==BIT_EINT8_23) {

if(EINTPEND&(1<<11))

EINTPEND |= 1<< 11;

if(EINTPEND&(1<<19))

EINTPEND |= 1<< 19;

ClearPending(BIT_EINT8_23);

}

else if(INTPND==BIT_EINT0) {

ClearPending(BIT_EINT0);

} else if(INTPND==BIT_EINT2) {

ClearPending(BIT_EINT2);

}

int key = Key_Scan() ;

if( key != 0xff ) {

uart_printf( "K%d is pressed!\n", key ) ;

GPFDAT = ~(key << 4);

}

SET_KEY_INTERRUPT_REG();

return;

}

文件4:mem.s

@ 文件 mem.s

@ 作用:SDRAM 的初始化設置

@ 關於初始化的更多細節,請參考我的前壹篇隨筆

.global memory_setup @ 導出 memory_setup, 使其對鏈接器可見

memory_setup:

mov r1, #0x48000000

adrl r2, mem_cfg_val

add r3, r1, #13*4

1:

@ write initial values to registers

ldr r4, [r2], #4

str r4, [r1], #4

cmp r1, r3

bne 1b

mov pc, lr

.align 4

mem_cfg_val:

.long 0x22111110 @ BWSCON

.long 0x00000700 @ BANKCON0

.long 0x00000700 @ BANKCON1

.long 0x00000700 @ BANKCON2

.long 0x00000700 @ BANKCON3

.long 0x00000700 @ BANKCON4

.long 0x00000700 @ BANKCON5

.long 0x00018005 @ BANKCON6

.long 0x00018005 @ BANKCON7 9bit

.long 0x008e07a3 @ REFRESH

.long 0x000000b2 @ BANKSIZE

.long 0x00000030 @ MRSRB6

.long 0x00000030 @ MRSRB7

文件5:nand_read.c

/* 文件 nand_read.c

* 作用:從 Nand Flash 中讀取壹塊數據到 SDRAM 中的指定位置

*/

#define NFCONF (*(volatile unsigned long *)0x4e000000)

#define NFCMD (*(volatile unsigned long *)0x4e000004)

#define NFADDR (*(volatile unsigned long *)0x4e000008)

#define NFDATA (*(volatile unsigned long *)0x4e00000c)

#define NFSTAT (*(volatile unsigned long *)0x4e000010)

#define NFECC (*(volatile unsigned long *)0x4e000014)

#define NAND_SECTOR_SIZE 512

#define NAND_BLOCK_MASK 0x1ff

void wait_idle() {

int i;

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

}

int nand_read(unsigned char *buf, unsigned long start_addr, int size){

int i, j;

/*

* detect the argument

*/

if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

return -1;

}

/* chip Enable */

NFCONF &= ~0x800;

for (i=0; i<10; i++) {

;

}

for (i=start_addr; i < (start_addr + size); i+=NAND_SECTOR_SIZE) {

NFCMD = 0;

/* Write Address */

NFADDR = i & 0xff;

NFADDR = (i >> 9) & 0xff;

NFADDR = (i >> 17) & 0xff;

NFADDR = (i >> 25) & 0xff;

wait_idle();

for(j=0; j < NAND_SECTOR_SIZE; j++) {

*buf++ = (NFDATA & 0xff);

}

}

NFCONF |= 0x800; /* chip disable */

return 0;

}

文件6:sdram.c

/* 文件 sdram.c

* 作用:循環點 FS2410 開發板上的 D9、D10、D11、D12

* 四個發光二極管。

*/

#define GPFCON (*(volatile unsigned long *)0x56000050)

#define GPFDAT (*(volatile unsigned long *)0x56000054)

int main()

{

int i,j;

while(1) {

for (i = 0; i <4; ++i) {

GPFCON = 0x1<<(8+i*2);

GPFDAT = 0x0;

// for delay

for(j=0;j<50000;++j) ;

}

}

}

文件7:nand.lds

SECTIONS {

first 0x00000000 : { head.o mem.o flash.o nand_read.o }

second 0x30000000 : AT(4096) { sdram.o }

}

文件8:Makefile

sdram:head.s flash.s mem.s sdram.c

arm-linux-gcc -c -o head.o head.s

arm-linux-gcc -c -o mem.o mem.s

arm-linux-gcc -c -o flash.o flash.s

arm-linux-gcc -c -o nand_read.o nand_read.c

arm-linux-gcc -c -o sdram.o sdram.c

arm-linux-ld -Tnand.lds head.o mem.o flash.o nand_read.o sdram.o -o sdram_tmp.o

arm-linux-objcopy -O binary -S sdram_tmp.o sdram

clean:

rm -f *.o

rm -f sdram

好了,妳把這些文件拷下去,執行make命令就能生成可執行的二進制代碼sdram,把sdram燒寫到板子上就能運行了。祝妳好運

  • 上一篇:寶駿汽車藍牙音樂媒體斷開是怎麽回事
  • 下一篇:寶馬的 mt 和mp 是什麽意思
  • copyright 2024編程學習大全網