韦东山Linux嵌入式课程社区
直播中

吕聪

7年用户 166经验值
私信 关注

为什么教程示例nand中的程序修改在nor中运行后启动不了?

各位大侠        遇到的问题是这样的,开发板配套的裸机程序全部是在nand中运行的
       究其原因,是由于sp指针指向4000这个地址。
       如果是nor启动 这个地址是nor内部的编址,所以不能在nor中运行
       后来我把sp的指向地址 改为0x40000000+1000(后面加1000的目的是 我不太确定地址的生长方向)
      编译后通过jlink下载到nor启动 关电2s。后来发现还是启动不了
      由于晚上 睡觉时间 我就关电睡觉去了
     第二天起来 在开机 居然可以用了
     我觉得好奇怪
     代码如下:
@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************      

.text
.global _start
_start:
            ldr     r0, =0x53000000     @ WATCHDOG寄存器地址
            mov     r1, #0x0                     
            str   r1, [r0]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启

            ldr     sp, =0x1000 0000
            ldr     sp, =0x2000 0000
            ldr     sp, =0x3000 0000
            ldr     sp, =0x4000 0000   @这里用了4步  是担心寻址范围 所以分成4步

                                        @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop
//==============================================================

//C代码
#define GPFCON      (*(volatile unsigned long *)0x56000050)
#define GPFDAT      (*(volatile unsigned long *)0x56000054)

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

/*
* LED1,LED2,LED4对应GPF4、GPF5、GPF6
*/
#define        GPF4_out        (1<<(4*2))
#define        GPF5_out        (1<<(5*2))
#define        GPF6_out        (1<<(6*2))

#define        GPF4_msk        (3<<(4*2))
#define        GPF5_msk        (3<<(5*2))
#define        GPF6_msk        (3<<(6*2))

/*
* S2,S3,S4对应GPF0、GPF2、GPG3
*/
#define GPF0_in     (0<<(0*2))
#define GPF2_in     (0<<(2*2))
#define GPG3_in     (0<<(3*2))

#define GPF0_msk    (3<<(0*2))
#define GPF2_msk    (3<<(2*2))
#define GPG3_msk    (3<<(3*2))

int main()
{
        unsigned long dwDat;
        // LED1,LED2,LED4对应的3根引脚设为输出
        GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
        GPFCON |= GPF4_out | GPF5_out | GPF6_out;

        // S2,S3对应的2根引脚设为输入
        GPFCON &= ~(GPF0_msk | GPF2_msk);
        GPFCON |= GPF0_in | GPF2_in;

        // S4对应的引脚设为输入
        GPGCON &= ~GPG3_msk;
        GPGCON |= GPG3_in;

        while(1){
            //若Kn为0(表示按下),则令LEDn为0(表示点亮)
            dwDat = GPFDAT;             // 读取GPF管脚电平状态

            if (dwDat & (1<<0))        // S2没有按下
                GPFDAT |= (1<<4);       // LED1熄灭
            else   
                GPFDAT &= ~(1<<4);      // LED1点亮

            if (dwDat & (1<<2))         // S3没有按下
                GPFDAT |= (1<<5);       // LED2熄灭
            else   
                GPFDAT &= ~(1<<5);      // LED2点亮

            dwDat = GPGDAT;             // 读取GPG管脚电平状态

            if (dwDat & (1<<3))         // S4没有按下
                GPFDAT |= (1<<6);       // LED3熄灭
            else   
                GPFDAT &= ~(1<<6);      // LED3点亮
    }

    return 0;
}

回帖(1)

李正阳

2019-8-20 10:43:39
1. 这些操作没必要:
ldr     sp, =0x1000 0000
            ldr     sp, =0x2000 0000
            ldr     sp, =0x3000 0000
            ldr     sp, =0x4000 0000   @这里用了4步  是担心寻址范围 所以分成4步

因为:ldr sp, =val   这个val是存放在代码里,不涉及什么录址范围

2.设栈:
ldr sp, =(0x40000000 + 4096)

栈是向下增长
举报

更多回帖

发帖
×
20
完善资料,
赚取积分