请教DSP6713如何使程序在外部SDRAM上运行

请教DSP6713如何使程序在外部SDRAM上运行,第1张

可以现在内部运行,然后用一段小程序把代码拷贝到外部去,再跳转到外部运行。

之所以不能直接在sdram中执行程序是因为sdram必须先进行初始化 *** 作。

如果你的程序很小,可直接放在片内ram中,然后用读写指令拷到初始化完成的sdram中即可。

如果你的程序很大,可建一个二进制的文件存放第二级的代码,把第一级的引导代码在ram中运行之后,先初始化sdram,再去读取那个二进制文件,并把数据写到sdram中,完成后跳转到sdram中运行。

MT48LC2M32的时钟是由DSP给的,给多给少都可以,在硬件允许的范围内,一般是越快越好。你可自行查阅DSP与sdram的时钟频率的上限,以确定给多少。

要想代码在SRAM中运行。有几个步骤需要做。

1、中断向量表需要修改,这样才能把中断向量表重新映射一遍。

#ifdef VECT_TAB_SRAM

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0)

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0)

#endif

2、分散加载要设置,就是设置你的代码段和数据段在ram的运行地址,就是arm手册中的运行域。

3、你的代码相当于boot 和app模式,boot在flash中执行,然后把app从nor flash搬到sram所在地址。

你的运行域地址就是代码搬移到sram所在的地址

你可以自己写一个汇编的程序,把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, #0x0a

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 = 0i <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 = 0i <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=0i<10i++) {

}

for (i=start_addri <(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=0j <NAND_SECTOR_SIZEj++) {

*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 = 0i <4++i) {

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

GPFDAT = 0x0

// for delay

for(j=0j<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烧写到板子上就能运行了。祝你好运


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7817426.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存