发新帖我要提问
12
返回列表
打印
[LPC]

LPC1788外挂SDRAM问题

[复制链接]
楼主: qzroger
手机看帖
扫描二维码
随时随地手机跟帖
21
qzroger|  楼主 | 2014-3-26 16:51 | 只看该作者 回帖奖励 |倒序浏览
huangxz 发表于 2014-3-26 14:50
从原理上讲是可以的,只是我觉的没必要这样做,bootload跟app各司其职就可以了。 ...

我还不是很明白这里bootloader和APP的分散文件怎么写,可以举个例子么,非常感谢

使用特权

评论回复
22
huangxz| | 2014-3-26 18:05 | 只看该作者
qzroger 发表于 2014-3-26 16:49
int main()
{
SDRAMInit();
        if(        0x10000000 == (*(uint32_t *)(APPLICATION_ADDRESS) & 0xffff0000))
          {
            /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
            if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x1FFE0000 ) == 0x10000000)
            {
                        cm3_int_close();
                        led_off();
                      /* Jump to user application */
                      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
                      Jump_To_Application = (pFunction) JumpAddress;
                      /* Initialize user application's Stack Pointer */
                      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
                      Jump_To_Application();
            }
          }


上面是跳转的代码

你的main里面应该少了load的代码,不过这些都比较简单了,memcpy就可以了。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0xa0000000 0x00080000  {    ; load region size_region
  ER_IROM1 0xa0000000 0x00080000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0xa0080000 0x00010000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

使用特权

评论回复
23
qzroger|  楼主 | 2014-3-27 09:11 | 只看该作者
huangxz 发表于 2014-3-26 18:05
上面是跳转的代码

你的main里面应该少了load的代码,不过这些都比较简单了,memcpy就可以了。

我网上看到有人说把HEAP映射到片外地址,STACK映射在片内地址就可以同时使用片内片外内存了是不,但我按照网上搜来的办法,来设置HEAP和STACK地址,我的分散加载文件如下:

LR_IROM1 0x00000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }

  RW_IRAM1 0x10000000  0x00010000  {
   .ANY (+RW +ZI)
  }
  
  ARM_LIB_HEAP  0xa0000000 EMPTY  0x00001000 {}
  ARM_LIB_STACK   0x10004000   EMPTY  -0x00004000  {}
}
会显示一下错误提示,.\Flash\Emc_NandFlashDemo.axf: Error: L6221E: Execution region RW_IRAM1 with Execution range [0x10000000,0x10003988) overlaps with Execution region ARM_LIB_STACK with Execution range [0x10000000,0x10004000).能说下要在分散加载文件中,如何指定HEAP和STACK地址吗,谢谢

使用特权

评论回复
24
huangxz| | 2014-3-27 10:20 | 只看该作者
qzroger 发表于 2014-3-27 09:11
我网上看到有人说把HEAP映射到片外地址,STACK映射在片内地址就可以同时使用片内片外内存了是不,但我按 ...

cortex-m3的stack和heap是在startup.s文件里面配置的,这个跟arm7不一样

使用特权

评论回复
25
lr2131| | 2014-3-28 13:30 | 只看该作者
qzroger 发表于 2014-3-26 10:20
其实我还不是很明白,问下bootloader能和应用程序放在一个工程文件中实现吗,就是在初始化SDRAM的时候内 ...

我见过有把APP单独一个工程生成的bin文件,放到boot中的数组里,固定好地址,然后把最后生成的烧写文件烧写到芯片中,或者反过来,把boot的bin放到APP的工程中,作为数组。

其实这本质上还是两个分立的工程,这样做,只是想得到一个烧写文件,而不是两个烧写文件,烧两次。

其实自己也可以写个程序,把两个bin文件合并,烧一次就行。

把一个工程生成的烧写文件放到另一个工程中,作为固定地址的数据,严格来说不能算是一个工程,
因为在一个工程中没法看到两个程序的代码。那种在一个工程看到两份代码的,我也没见过。

使用特权

评论回复
26
lr2131| | 2014-3-28 13:35 | 只看该作者
qzroger 发表于 2014-3-26 16:49
int main()
{
SDRAMInit();

boot的伪代码主体差不都是对的,首先初始化SDRAM,然后跳转到APP中。

使用特权

评论回复
27
lr2131| | 2014-3-28 13:39 | 只看该作者
qzroger 发表于 2014-3-27 09:11
我网上看到有人说把HEAP映射到片外地址,STACK映射在片内地址就可以同时使用片内片外内存了是不,但我按 ...

  ARM_LIB_HEAP  0xa0000000 EMPTY  0x00001000 {}
  ARM_LIB_STACK   0x10004000   EMPTY  -0x00004000  {}

这两行不用搞出来吧,你是从哪看到的。
HEAP和STACK在启动代码中可以设置好,地址好像会在分散加载脚本的RAM中某个区域(当然是在RAM中,我都觉得自己在说废话)

使用特权

评论回复
28
qzroger|  楼主 | 2014-3-28 15:59 | 只看该作者
lr2131 发表于 2014-3-28 13:39
ARM_LIB_HEAP  0xa0000000 EMPTY  0x00001000 {}
  ARM_LIB_STACK   0x10004000   EMPTY  -0x00004000  ...

下载就是不知道在分散加载文件中怎么设置HEAP和STACK的地址,要是知道就分享下,非常感谢。

使用特权

评论回复
29
lr2131| | 2014-3-28 17:09 | 只看该作者
qzroger 发表于 2014-3-28 15:59
下载就是不知道在分散加载文件中怎么设置HEAP和STACK的地址,要是知道就分享下,非常感谢。 ...

我看看在STM32F407上我自己编写的工程,给你参考下

使用特权

评论回复
30
lr2131| | 2014-3-28 17:27 | 只看该作者
STM32F407分散加载脚本:
; 这里分号是类似于C语言中的“//” ,做行注释用的,汇编语言中也是用分号做行注释
LR_IROM1 0x08000000 0x00100000  {    ; load region size_region ;  ; RO RW ZI的加载域 ,起始地址是0x08000000 ,大小不超过0x00100000  
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address ;如果你不需要把代码段(RO)加载到RAM中运行,那代码段(RO)的运行域和加载域一样,参数和上一行一样写。
   startup.o (START, +First)  ;RESET         START ; startup.o说明了启动文件是startup.s,你按你自己工程中的文件名字修改吧。START到后面再说。+First照着写,好像是用来表明这个是整个程序的入口。
;   *(InRoot$$Sections); // root域,这个我也不清楚,有时去掉也没事。
   .ANY (+RO)// 照着写吧,让RO都放一起,RO一般不用分散几处。
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data ;RW和ZI的运行域,当然一定要放到RAM中,可以是片内RAM,也可以是片外RAM。你要是地址指定在外挂的SDRAM的地址上,自然就是用的片外RAM,编译器其实是不知道的,它也不需要知;道,你知道就行。 0x20000000 是RW的起始地址,0x00020000  是最大长度。如果是boot的话,这里你写LPC1788的片内RAM的首地址吧 ,我看了LPC1788的Memmap,看得有点晕,有main RAM,还有几个SRAM,不明白。然后注意长度不要;超过了
        startup.o (STACK);startup.o和上面一样。STACK后面解释。
   .ANY (+RW,+ZI)// 全部的RW,全部的ZI,照着写吧。
  }

解释下START 和STACK。这个是要看启动文件中的汇编代码的,其实也不用看懂多少,会修改就行。
贴出我自己修改的启动文件
        IMPORT        SystemInit
        IMPORT        __main

        EXPORT         Reset


STACK_SIZE                EQU                0x00000400
        AREA STACK,NOINIT,READWRITE,ALIGN=3
STACK_MEM        SPACE        STACK_SIZE
init_SP

        AREA START,DATA,READONLY

__vectors
                        DCD         init_SP
                        DCD                Reset
                      DCD     NMI_Handler                ; NMI Handler

        PRESERVE8
        THUMB
        AREA |.text|,CODE,READONLY

Reset
        ;FPU settings
;        LDR     R0, =0xE000ED88           ; Enable CP10,CP11
;        LDR     R1,[R0]
;        ORR     R1,R1,#(0xF << 20)
;        STR     R1,[R0]

        BL        SystemInit
        BL        __main

NMI_Handler
                B .

        END



汇编的一些术语我都忘了,START和STACK分别对应汇编程序中的两个段,你自己的启动文件中这两个段可能是其他名字,你对着改改吧。

START,是数据段,对应的是中断向量表。
STACK,也算是数据段吧,对应的是栈。

使用特权

评论回复
31
lr2131| | 2014-3-28 17:31 | 只看该作者
我给的好像还有点问题,回头我再改改。把STACK和静态区重叠了,另外再加一个段试试。

使用特权

评论回复
32
lr2131| | 2014-3-31 10:49 | 只看该作者
在LPC1788的工程上改的,添加了Heap和Stack,编译倒是没报错,但不能保证实际运行效果。
LR_IROM1 0x00000000 0x000003000  {    ; load region size_region 0x3000是boot程序的大小,按


;己实际大小改参数
  ER_IROM1 0x00000000 0x00003000  {  ; load address = execution address
   startup_LPC177x_8x.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x10000000   {  ; RW data ;boot程序的中断向量表在flash的首地址中,可以不用重映射

到SRAM中。
   .ANY (+RW +ZI)
  }

      HEAP +0 UNINIT
    {
        startup_LPC177x_8x.o (HEAP)
    }

    STACKS 0x10010000 UNINIT
    {
        startup_LPC177x_8x.o (STACK)
    }
}
这个是给boot的分散加载文件,

APP的分散加载文件:

; *************************************************************

LR_IROM1 0x00003000 0x00080000  {    ; load region size_region
  ER_IROM1 0x00003000 0x00080000  {  ; load address = execution address
   startup_LPC177x_8x.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
;从0x10000000开始的SRAM作为中断向量表重映射用,脚本中可以不写这个区域的分配,但boot代码需
;要在跳转前拷贝APP中断向量表到SRAM中,并设置好中断向量表偏移量寄存器。
  RW_RAM 0xA0000000   {  ; RW data ;SDRAM的起始地址
   .ANY (+RW +ZI)
  }

      HEAP +0 UNINIT
    {
        startup_LPC177x_8x.o (HEAP)
    }

    STACKS 0xA0080000 UNINIT ;SDRAM的结束地址,因为系统栈是满递减堆栈方式的。
    {
        startup_LPC177x_8x.o (STACK)
    }
}


使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
qzroger + 2
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则