OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5187|回复: 11

STM32CUBEIDE关于.ld链接文件与内存池管理的问题

[复制链接]

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
发表于 2020-9-25 10:04:13 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 jiangyy 于 2020-9-25 10:19 编辑

最近一直在使用STMCUBEIDE软件编程,在移植正点原子的内存池管理这章节(基于HAL库),发现有几处地方报错,如下:
//内存池(32字节对齐)
__align(32) u8 mem1base[MEM1_MAX_SIZE];                                                                                        //内部SRAM内存池
__align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));                                        //外部SRAM内存池
__align(32) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X10000000)));                                        //内部CCM内存池
//内存管理表
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                                                   //内部SRAM内存池MAP
u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE)));        //外部SRAM内存池MAP
u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000+MEM3_MAX_SIZE)));        //内部CCM内存池MAP


注意报错的地方是  软件无法识别 __attribute__((at(addr))),在网上找了相关文件(比较少),说可以使用 __attribute__((section(“.name”)))来替代,但是问题来了,这个肯定会涉及到启动文件.ld的修改。于是我就更改了STM32F407ZGTX_FLASH.ld文件,只罗列修改地方,如下所示:
/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);        /* end of "RAM" Ram type memory */

_Min_Heap_Size = 0x200 ;        /* required amount of heap  */
_Min_Stack_Size = 0x400 ;        /* required amount of stack */

/* Memories definition */
MEMORY
{
  CCMRAM    (xrw)    : ORIGIN = 0x10000000,   LENGTH = 64K
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 1024K
  SRAM   (rx)    : ORIGIN = 0x68000000,   LENGTH = 1024K
}

/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH

  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH

  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH

  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH

  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections into "RAM" Ram type memory */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */

  } >RAM AT> FLASH

  /* Uninitialized data section into "RAM" Ram type memory */
  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)

    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
  } >CCMRAM AT> FLASH/*新增,第一处修改*/

  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM

  .sram :
  {
    . = ALIGN(4);
    _SRAM_SYMBOLS = .;      /* create a global symbol at data start */
    *(.sram)                           /* .data sections */
    *(.sram*)                          /* .data* sections */

    . = ALIGN(4);
    _ESRAM_SYMBOLS = .;     /* define a global symbol at data end */

  } >SRAM/*新增,第二处修改*/
  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}


上面有两个地方是新增的,修改好.ld文件后,再次去修改malloc.c文件的地方,如下:
//内存池(32字节对齐)
__attribute__ ((aligned (32))) u8 mem1base[MEM1_MAX_SIZE];                                                                                //内部SRAM内存池
__attribute__ ((aligned (32))) u8 mem2base[MEM2_MAX_SIZE] __attribute__((section(".sram.__at_0x68000000")));    //外部SRAM内存池
__attribute__ ((aligned (32))) u8 mem3base[MEM3_MAX_SIZE] __attribute__((section(".ccmram.__at_0x10000000")));         //内部CCM内存池
//内存管理表
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];                                                                                                        //内部SRAM内存池MAP
u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((section(".sram.__at_0x680F0000")));        //外部SRAM内存池MAP
u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((section(".ccmram.__at_0x1000F000")));        //内部CCM内存池MAP


最后,我做了一个测试函数,内容如下:
void Malloc_Test(void)
{
        u8 *p=0;
        u8 *tp=0;
        u8 paddr[18];                                        //存放P Addr:+p地址的ASCII值
        u8 sramx=0;                                                //默认为内部sram

        p=mymalloc(sramx,2048);//内部内存池申请2K字节
        if(p!=NULL)
        {
                tp=p;
                sprintf((char*)paddr,"0X%08X",(u32)tp);
                sprintf((char*)p,"Memory SRAMIN ADDR:");//向p写入一些内容
                printf("%s",p);
                printf("%s\r\n",paddr);
        }
        myfree(sramx,p);//释放内部内存池内存
        p=0;                        //指向空地址
        sramx++;

        p=mymalloc(sramx,2048);//外部内存池申请2K字节
        if(p!=NULL)
        {
                tp=p;
                sprintf((char*)paddr,"0X%08X",(u32)tp);
                sprintf((char*)p,"Memory SRAMEX ADDR:");//向p写入一些内容
                printf("%s",p);
                printf("%s\r\n",paddr);
        }
        myfree(sramx,p);//释放外部内存池内存
        p=0;                        //指向空地址
        sramx++;

        p=mymalloc(sramx,2048);//CCM内存池申请2K字节
        if(p!=NULL)
        {
                tp=p;
                sprintf((char*)paddr,"0X%08X",(u32)tp);
                sprintf((char*)p,"Memory SRAMCCM ADDR:");//向p写入一些内容
                printf("%s",p);
                printf("%s\r\n",paddr);
        }
        myfree(sramx,p);//释放CCM内存池内存
        p=0;                        //指向空地址
}


编译通过,能烧录成功,串口打印数据如下:
Memory SRAMIN ADDR:0X2001AE40
Memory SRAMEX ADDR:0X680EF800
Memory SRAMCCM ADDR:0X1000E800


通过串口,可以看出确实内存申请成功了,但是问题来了,注意!!!!
我发现我生成的.bin文件超级大,1.5G!!!!    .hex文件也超级大,有3.12M。我的天啊!!!看到有个文章,说是修改.ld文件的第二处地方,那就是最后结束的地方>SRAM要加上AT> FLASH,如果不加上的话,bin文件将连续生成,由于我们外部sram的地址在0x68000000,因此,gcc将会把这部分当做flash的地址一部分,也就是说将会生成一个超大的bin文件!!如下:
.sram :
  {
    . = ALIGN(4);
    _SRAM_SYMBOLS = .;      /* create a global symbol at data start */
    *(.sram)                           /* .data sections */
    *(.sram*)                          /* .data* sections */

    . = ALIGN(4);
    _ESRAM_SYMBOLS = .;     /* define a global symbol at data end */

  } >SRAM AT> FLASH/*新增,第二处修改*/


我的妈耶,编译器编译不通过,提示如下:
\STM32CubuIDE\jaymie\STM32F407ZGTX_FLASH.ld:191: warning: memory region `FLASH/' not declared
\jaymie\STM32F407ZGTX_FLASH.ld:191: syntax error

请问有没有贴友们,用过STM32CUBEIDE软件编程,关于这个问题,怎么解决的?折磨了一天,很头疼。

最佳答案

查看完整内容[请看2#楼]

目标文件比较大,是因为目标文件里包含了所添加的段里的变量的初始化值(值为0)(并位于data段),而这些全局变量比较多,所以目标文件里有很多0值。 解决方法有两种: 1 在ld链接脚本内使用 NOLOAD 修饰声明的段,来告诉编译器不要初始化这个段,如: 2 使用自定义命令来生成目标文件,在命令内用-R选项排除指定的段的初始化值添加到data段内,如通过工程配置里的“Build Steps”添加自定义命令: arm-none-eabi-objcopy ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2020-9-25 10:04:14 | 显示全部楼层
目标文件比较大,是因为目标文件里包含了所添加的段里的变量的初始化值(值为0)(并位于data段),而这些全局变量比较多,所以目标文件里有很多0值。
解决方法有两种:
1 在ld链接脚本内使用 NOLOAD 修饰声明的段,来告诉编译器不要初始化这个段,如:
  1. .ccmram (NOLOAD) :
  2. {
  3.    ...
  4. }
复制代码


2 使用自定义命令来生成目标文件,在命令内用-R选项排除指定的段的初始化值添加到data段内,如通过工程配置里的“Build Steps”添加自定义命令:
arm-none-eabi-objcopy -R ".ccmram" -R ".sram" -O binary ${ProjName}.elf ${ProjName}.bin

使用Build Steps添加自定义命令

使用Build Steps添加自定义命令
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-25 10:07:22 | 显示全部楼层
https://www.cnblogs.com/RegressionWorldLine/p/11968467.html

可以参照这个网站,这个说的有些详细,但是还是有问题。
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-25 10:34:50 | 显示全部楼层
还有一个问题是,如果我不使用内存池管理这章节,我单独申请一个内部CCM内存池数据,如下:
u8 ccmram[63*1024] __attribute__((section(".ccmram.__at_0x10000000")));//测试用数组

在一个函数里面给这个ccmram[63*1024] 赋值,  内存使用情况发现CCMRAM占用 98.44%,代码生成的.bin和.hex也正常,是不是内存池管理这章节在STM32CUBEIDE不适用?
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-25 10:50:00 | 显示全部楼层
file:///C:\Users\jiangyuanyuan\AppData\Roaming\Tencent\Users\2223210985\TIM\WinTemp\RichOle\U$6%ZB8Q(CXQF4ZOUJS1FDP.png
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-25 18:54:42 | 显示全部楼层
ufbycd 发表于 2020-9-25 14:06
目标文件比较大,是因为目标文件里包含了所添加的段里的变量的初始化值(值为0)(并位于data段),而这些 ...

兄弟,你太给力了!!!一直觉得STM32CUBEIDE软件很好用,但是垦也很多,需要自己填堵,差点放弃使用这个软件了,但是又不甘心放弃。按照你的方法,我没使用你的命令:

通过工程配置里的“Build Steps”添加自定义命令:arm-none-eabi-objcopy -R ".ccmram" -R ".sram" -O binary ${ProjName}.elf ${ProjName}.bin

编译通过了,.hex和.bin文件缩小到正常了。这解决我后面使用文件系统和内存池管理。我串口打印的信息如下:

sram:1024kb
Memory SRAMIN ADDR:0X2001AE40
Memory SRAMEX ADDR:0X680EF800
Memory SRAMCCM ADDR:0X1000E800
Card Type:SDHC
Card ManufacturerID:3
Card RCA:43690
LogBlockNbr:15523840
LogBlockSize:512
Card Capacity:7580 MB
Card BlockSize:512

SD卡也正常了,后期通过软件自动生成文件系统看看,真的非常感谢您,看来大佬一定对芯片启动文件和汇编精通,也对linux了解颇深。
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-25 18:56:26 | 显示全部楼层
有关STM32CUBEIDE软件使用的人太少了,而且出现问题反馈的人也不多,希望贴友们多多反馈汇总,HAL库是未来的趋势所在。
回复

使用道具 举报

3

主题

312

帖子

0

精华

高级会员

Rank: 4

积分
907
金钱
907
注册时间
2011-10-19
在线时间
196 小时
发表于 2020-9-26 11:21:10 | 显示全部楼层
jiangyy 发表于 2020-9-25 18:56
有关STM32CUBEIDE软件使用的人太少了,而且出现问题反馈的人也不多,希望贴友们多多反馈汇总,HAL库是未来 ...

最成熟的工具链其实是GCC,Keil或IAR主要是易用但定制化不强,而GCC工具链的可控性更强,文档也非常丰富。
想提高能力就应该用GCC那一套。另外,平时有疑难问题就应该多查查官方文档。
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-9-26 11:39:53 | 显示全部楼层
ufbycd 发表于 2020-9-26 11:21
最成熟的工具链其实是GCC,Keil或IAR主要是易用但定制化不强,而GCC工具链的可控性更强,文档也非常丰富 ...

谢谢你
回复

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2020-6-29
在线时间
12 小时
发表于 2020-10-8 01:37:18 | 显示全部楼层
两位大佬的讨论太厉害了

我最近尝试将RT-Thread nano 移植到STM32CubeIDE的工程中,但是也出现了ld链接文件的问题,以至于__attribute__ 相关的一些内容没有被正确链接到程序中,我折腾了两天还没解决
现在用STM32CubeIDE的人还是少,希望以后能够更多人推广GCC开发环境吧
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-10-16 13:38:18 | 显示全部楼层
netube 发表于 2020-10-8 01:37
两位大佬的讨论太厉害了

我最近尝试将RT-Thread nano 移植到STM32CubeIDE的工程中,但是也出现了ld链接 ...

趋势所在,极力推荐HAL库。
回复

使用道具 举报

53

主题

567

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2107
金钱
2107
注册时间
2017-2-11
在线时间
307 小时
 楼主| 发表于 2020-11-20 16:23:50 | 显示全部楼层
https://blog.csdn.net/weixin_397 ... FromBaidu-1.control

修复注释乱码或者中文大小字体不一的问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-15 03:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表