你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

Ubuntu下开发STM32---10.使用malloc

[复制链接]
qianfan 发布时间:2015-11-1 20:27
本帖最后由 QianFan 于 2015-11-1 20:37 编辑
6 T5 D0 W% M! L* n; t8 V% o5 e- U! x! H6 s& e
    Ubuntu下开发STM32已经接近尾声。如果不出意外的话,这篇将会是最后一篇了。突然有点心痛,毕竟,在也没有机会这么明目张胆的传图片,刷金币了。
) s/ w; p! v- ?/ O  N- j
) i% y7 t1 J4 s, b0 x( M% FNewlib申请内存的机制! B; y# ~/ o6 V, x9 {' O" j5 c
    这次介绍的是Newlib下的malloc。不同与keil mdk下的malloc。两者的实现机制是不同的。keil mdk是在汇编文件中改一个数值,用来设置堆的大小。今后的所有malloc申请的内存都在这个堆中。堆的大小是在编译的时候确定的,预先放入bss段中。而Newlib使用的是sbrk的机制。只要sbrk的申请的地址还没到当前sp的位置,就能一直申请。(代码图片是我在原先的基础上添加了点调试信息)
7 x5 ^; n4 ]1 a  g8 P* _# [ 2015-11-01 17:55:56屏幕截图.png & q. m) R0 i' H2 Q$ H
end是bss段的结束地址。因为使用了extern char end asm("end")这样的语法,在编译的时候只能使用-std=gnu99,而不能使用-std=c99。stack_ptr是当前sp的值。只要上一次结束的地址加上这一次申请字节数的和不超过sp,sbrk就能成功。malloc也能成功。
7 y9 W2 c/ p' H6 Z* o; qsbrk相当于内存的经销商,malloc只是一个小贩。当有人向malloc请求内存的时候,如果malloc手中有剩余的内存并且足够这次分配,那就直接把手中剩余的内存分配出去。使用完内存之后,只要记得使用free还给malloc就行。如果申请的时候,malloc手中没有足够的内存,那么malloc会向sbrk要一块内存,自己再转手出售给其他的需要者。
4 ^( M; n  o& m% B5 {, i& f
/ R; W( \4 P# s$ v* k' g% A内存分配测试
. K0 R6 J+ O( e: G9 |9 b( ~
2015-11-01 18:06:20屏幕截图.png ( H" `0 T' x0 O: u" _5 M" d  ]
主函数中一直尝试无限制的分配内存,只分配不释放。将代码下载至SRAM中运行。(make sram,sudo make burns)1 ^! J: k2 @3 ]+ D1 R0 T
在内存分配之前,malloc分配的起始地址是536871400(0x2000_01E8),具体为什么是这个数值,在稍后会解释。进入main之前申请了436,1032字节(实际是428和1024字节,剩余8字节用于存储分配信息)。估计1K内存是用来给printf当缓冲区了。至于另外428字节不知道用作什么用了。) Q5 b) A' b5 `3 s
2015-11-01 18:07:32屏幕截图.png
" z  s$ {8 v: s+ T  e4 c5 A) Q
8 Y. A) V( h/ b在170次内存之后,申请了17000个字节的空闲内存,共消耗17000+170*8=18360字节的内存。
! `$ @; {/ T/ k: N% R 2015-11-01 18:07:52屏幕截图.png / j- l& g$ q" w* H
到内存耗尽的时候,堆指针在0x2000_4F5C(536891120+108) 处。这个值差不多接近栈顶(0x2000_5000)了。2 T. b  M, T% p

. f4 a* F2 M- [* d8 V3 a给栈保留一定的内存

; m1 M( j8 ^4 C" i如果一直使用malloc分配内存的话,最终可能会导致栈的内存与堆的内存冲突。为了安全考虑,暂时考虑为栈保留一定的空间。在syscalls.c文件中添加一个可配置的宏,用于确定可保留的大小。这个数值可以在syscalls.c文件中更改,也可以在编译的时候使用-D来更改。这里保留了2K的空间给栈。
+ s& C8 J& |- t# F0 ]& o/ ~ 2015-11-01 18:27:30屏幕截图.png 2015-11-01 18:29:10屏幕截图.png % P% O: P* K! {" M9 s
- L6 W/ A5 n# j2 g- s3 i( |2 g1 y; \/ @

' P. O; A" F, o' R7 V3 n  j" A内存布局# |9 Y# Y- G" s/ P( g  d
可能你会疑问为什么malloc内存分配是从0x2000_01E8开始的,为什么链接文件中定义了_Min_Stack_Size,这里却还要为栈保存空间。虽然在SRAM中运行程序一节https://www.stmcu.org.cn/module/forum/thread-603793-1-1.html中也简单的提到了一些,这里打算详细的说一下。: y2 g+ \  g  N+ ^; o2 o
在链接的时候,我添加了参数-Wl,-Map=flash_sram.map,用来记录代码或者数据的布局。打开文件可以看到这样的信息:6 ]! M% U" j  f4 M
2015-11-01 18:38:25屏幕截图.png
( n6 H# N% ^# N6 f( ^" J* A: W( e+ p从Map文件上看,bss段(未赋值的变量)是从0x2000_00a4开始的。(从0x2000_0000开始到0x2000_00a4之间的数据是用来存放已赋值的变量。)在bss段的结束地址(end)之后,有根据_Min_Heap_Size,_Min_Stack_Size保留的内存区。这两片内存去并没有什么作用,只是用来保证bss段不至于过大而已。0 U8 q/ \# C( P+ j/ ^
从sbrk的输出上也能够看出来,malloc进行内存分配的时候是从bss段的结束,也就是end地址处开始的。显然malloc的内存分配能够覆盖_Min_Heap_Size和_Min_Stack_Size。
4 g( K! T5 W, v) k1 p" h相关的代码在malloc_v2.zip中。/ |4 L( ~) d& ]5 A7 x, }

, `4 h/ k- {0 _& O3 X: q9 b2 D5 y, ?# h0 S0 x; Z
相关Newlib系统调用的更多信息请参考:
( g/ |7 D: |6 Y9 B+ ]" O
5 G8 T" }' _* x" x; o( L' z( F
6 y' m& O$ K2 K# t: [7 ~4 _

malloc_v1.zip

下载

410.52 KB, 下载次数: 53

malloc_v2.zip

下载

410.56 KB, 下载次数: 66

赞 收藏 4 评论12 发布时间:2015-11-1 20:27

举报

12个回答
埃斯提爱慕 回答时间:2015-11-1 22:42:01
提示: 作者被禁止或删除 内容自动屏蔽
creep 回答时间:2015-11-1 23:00:56
恭喜连载完结,感谢qianfan无私的分享!
ataudio 回答时间:2015-11-2 08:59:33
恭喜楼主大功告成。我用server版,还没有安装好驱动。要换desktop版了。
qianfan 回答时间:2015-11-2 09:34:53
creep 发表于 2015-11-1 23:00
# H: ?% {& r0 x+ H恭喜连载完结,感谢qianfan无私的分享!

/ o# ~: ]; W& X  A6 M1 X2 C5 n橙哥,一块交流啊
qianfan 回答时间:2015-11-2 09:35:20
ataudio 发表于 2015-11-2 08:59! F4 n5 C" h5 }; S9 G6 h: o6 j
恭喜楼主大功告成。我用server版,还没有安装好驱动。要换desktop版了。 ...

. Z: F, w: \8 _8 _( k) R* s  C, M2 D我用的是desktop版本。你说的驱动是stlink吗?
ataudio 回答时间:2015-11-2 14:41:24
QianFan 发表于 2015-11-2 09:355 |, A- _6 F1 K, Y! f
我用的是desktop版本。你说的驱动是stlink吗?

6 Y" G& Y8 F  ?6 b. j+ F9 ]* i' @是的。你发给我的stlink驱动包,和我下载的完全一样。在server下运行报一样的错误。看你的截图应该是在desktop的配色下编写的,所以我抽空换成desktop试试。。
qianfan 回答时间:2015-11-2 14:59:04
ataudio 发表于 2015-11-2 14:41$ Z" K0 c5 v- R$ O* P
是的。你发给我的stlink驱动包,和我下载的完全一样。在server下运行报一样的错误。看你的截图应该是在des ...

* ]7 g$ J6 v4 j0 L* T: [2 U; W7 N可能是这个原因。不知道你的libusb安装了没有
ataudio 回答时间:2015-11-3 10:46:14
怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时会提示错误,装了libusb之后再来一次,配置OK、编译也OK,就是sudo make install看到了:' Y$ u& V1 }$ P! m; q
make[2]: Nothing to be done for 'install-data-am'.3 Z* x. ^- h- x5 M7 j- }; g' u! f( {

- g. N8 K/ c+ r: o# a. o2 ~不知道安装是否成功了。先继续往下配置看看。
qianfan 回答时间:2015-11-3 13:32:06
ataudio 发表于 2015-11-3 10:462 b' j" i$ Z4 t# V
怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时 ...
: Z" J7 L  V1 f% j  W
事实st-flash看看有反映吗
qianfan 回答时间:2015-11-3 13:32:36
ataudio 发表于 2015-11-3 10:46
9 ^( c, d. E  g' G  M" U2 L0 p怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时 ...

# p0 e2 X% V+ z. Y1 m& h6 i应该不是吧。我的是4。8。4
ataudio 回答时间:2015-11-4 11:24:06
本帖最后由 ataudio 于 2015-11-4 13:06 编辑
8 J8 t5 U/ d+ k4 k! z' j2 ~2 z
QianFan 发表于 2015-11-3 13:32) D6 p" T& Z" c. F
事实st-flash看看有反映吗
这个是不是表明stlink已经装上了?
  k. U8 `) P7 U6 J; D: j* r$ x. uaoems@ubuntu:~$ st-flash         
1 _2 j, `1 @9 jinvalid command line$ ^* P; a2 T; h5 b
stlinkv1 command line: ./st-flash [--debug] [--reset] {read|write} /dev/sgX path addr <size>
4 e  H, ]5 o' E' z# ~2 k" J8 W5 l9 Dstlinkv1 command line: ./st-flash [--debug] /dev/sgX erase: }9 ?0 y0 K# O
stlinkv2 command line: ./st-flash [--debug] [--reset] {read|write} path addr <size>9 |+ ^' T# k. {( T( ^
stlinkv2 command line: ./st-flash [--debug] erase
; S, S2 i2 R8 R! R                       use hex format for addr and <size>6 p+ P! v: U: |" p3 N# s
aoems@ubuntu:~$ ( J. ]1 X5 y  M% k' f. L
: @# M' {4 [" M% q* ]9 _: l
qianfan 回答时间:2015-11-4 13:49:30
ataudio 发表于 2015-11-4 11:24
- Z! `& _1 G/ A* O这个是不是表明stlink已经装上了?
- y- E, T; N# g7 E# Paoems@ubuntu:~$ st-flash         
6 }# |7 i: B. x6 {% k# I# Hinvalid command line

* b/ O" {; @3 M8 Q0 T  F对的,这就说明安装成功了。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版