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

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

[复制链接]
qianfan 发布时间:2015-11-1 20:27
本帖最后由 QianFan 于 2015-11-1 20:37 编辑
6 O, E% K0 `( @) k$ U4 U6 {
$ h! }) V/ G5 @0 T    Ubuntu下开发STM32已经接近尾声。如果不出意外的话,这篇将会是最后一篇了。突然有点心痛,毕竟,在也没有机会这么明目张胆的传图片,刷金币了。( w& H+ R+ \' ?2 C3 w, y

" t: w, Q5 y, [  F2 _0 {Newlib申请内存的机制
8 f7 _' E4 M0 Z    这次介绍的是Newlib下的malloc。不同与keil mdk下的malloc。两者的实现机制是不同的。keil mdk是在汇编文件中改一个数值,用来设置堆的大小。今后的所有malloc申请的内存都在这个堆中。堆的大小是在编译的时候确定的,预先放入bss段中。而Newlib使用的是sbrk的机制。只要sbrk的申请的地址还没到当前sp的位置,就能一直申请。(代码图片是我在原先的基础上添加了点调试信息)
. \# P4 w( A, t' x, R+ ]2 s8 V: e 2015-11-01 17:55:56屏幕截图.png + ~* r# }  O) ~3 C( [
end是bss段的结束地址。因为使用了extern char end asm("end")这样的语法,在编译的时候只能使用-std=gnu99,而不能使用-std=c99。stack_ptr是当前sp的值。只要上一次结束的地址加上这一次申请字节数的和不超过sp,sbrk就能成功。malloc也能成功。
& V9 G; f* ~1 E4 b4 _sbrk相当于内存的经销商,malloc只是一个小贩。当有人向malloc请求内存的时候,如果malloc手中有剩余的内存并且足够这次分配,那就直接把手中剩余的内存分配出去。使用完内存之后,只要记得使用free还给malloc就行。如果申请的时候,malloc手中没有足够的内存,那么malloc会向sbrk要一块内存,自己再转手出售给其他的需要者。
' ~: x; j. O, w" h. K# Q4 @; o. ^* o6 L4 B3 C# d4 N# a! H* W& A
内存分配测试
1 M  V4 X; u1 }8 `
2015-11-01 18:06:20屏幕截图.png ' q( ^! `% W6 H
主函数中一直尝试无限制的分配内存,只分配不释放。将代码下载至SRAM中运行。(make sram,sudo make burns)5 A- h$ W# Z9 s& F+ y
在内存分配之前,malloc分配的起始地址是536871400(0x2000_01E8),具体为什么是这个数值,在稍后会解释。进入main之前申请了436,1032字节(实际是428和1024字节,剩余8字节用于存储分配信息)。估计1K内存是用来给printf当缓冲区了。至于另外428字节不知道用作什么用了。
) C0 L5 l+ P' [4 U& o* @9 E 2015-11-01 18:07:32屏幕截图.png
7 y5 j0 n2 i. ~6 L. d0 ~" X/ Y$ p. U$ R' ]+ o. F) ~
在170次内存之后,申请了17000个字节的空闲内存,共消耗17000+170*8=18360字节的内存。5 l" M3 \" Z+ z" V3 l
2015-11-01 18:07:52屏幕截图.png
9 d  s' b3 a. I! P到内存耗尽的时候,堆指针在0x2000_4F5C(536891120+108) 处。这个值差不多接近栈顶(0x2000_5000)了。8 h0 c* _2 U8 A- U1 M2 C- L3 M

' P6 ?( m$ u2 Q给栈保留一定的内存
5 G/ F/ o& z+ W" L: B6 e9 o
如果一直使用malloc分配内存的话,最终可能会导致栈的内存与堆的内存冲突。为了安全考虑,暂时考虑为栈保留一定的空间。在syscalls.c文件中添加一个可配置的宏,用于确定可保留的大小。这个数值可以在syscalls.c文件中更改,也可以在编译的时候使用-D来更改。这里保留了2K的空间给栈。
* l. D4 }7 S, G 2015-11-01 18:27:30屏幕截图.png 2015-11-01 18:29:10屏幕截图.png
8 p& E8 ?+ U$ Z1 x+ Q
4 {1 y7 [& h7 ]  }7 ~9 z1 P, D3 C
" G. I3 U9 `% t/ n6 `" T" G" X内存布局* O8 V2 S& L) R+ d. `* r
可能你会疑问为什么malloc内存分配是从0x2000_01E8开始的,为什么链接文件中定义了_Min_Stack_Size,这里却还要为栈保存空间。虽然在SRAM中运行程序一节https://www.stmcu.org.cn/module/forum/thread-603793-1-1.html中也简单的提到了一些,这里打算详细的说一下。
- g- T5 b) `, c, @: J在链接的时候,我添加了参数-Wl,-Map=flash_sram.map,用来记录代码或者数据的布局。打开文件可以看到这样的信息:2 I% _  d! }* \; {
2015-11-01 18:38:25屏幕截图.png " a9 Q* c) V# Y5 a$ e
从Map文件上看,bss段(未赋值的变量)是从0x2000_00a4开始的。(从0x2000_0000开始到0x2000_00a4之间的数据是用来存放已赋值的变量。)在bss段的结束地址(end)之后,有根据_Min_Heap_Size,_Min_Stack_Size保留的内存区。这两片内存去并没有什么作用,只是用来保证bss段不至于过大而已。) p7 y) i9 Q5 l9 L1 y) o
从sbrk的输出上也能够看出来,malloc进行内存分配的时候是从bss段的结束,也就是end地址处开始的。显然malloc的内存分配能够覆盖_Min_Heap_Size和_Min_Stack_Size。: D  R3 r6 g: H4 m. Z
相关的代码在malloc_v2.zip中。7 ^& h' y- F9 D$ V

6 c7 b' _" u* l
, J2 ]2 C- P, Z  J% ?5 W/ `. w# r相关Newlib系统调用的更多信息请参考:
' u, i9 i# X* R9 h: m3 @! C5 X% Z

% ?: ~# n3 f, Q9 V! w
- M$ L& i0 M! U3 x" l, M# q

malloc_v1.zip

下载

410.52 KB, 下载次数: 52

malloc_v2.zip

下载

410.56 KB, 下载次数: 65

收藏 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
0 o2 G/ h" \/ n: [2 N恭喜连载完结,感谢qianfan无私的分享!
# S* r( ^3 [& P9 J0 s& t
橙哥,一块交流啊
qianfan 回答时间:2015-11-2 09:35:20
ataudio 发表于 2015-11-2 08:59) n$ L# i2 l" b. N: o, f% B
恭喜楼主大功告成。我用server版,还没有安装好驱动。要换desktop版了。 ...

# p9 m) l- f7 O( r9 T我用的是desktop版本。你说的驱动是stlink吗?
ataudio 回答时间:2015-11-2 14:41:24
QianFan 发表于 2015-11-2 09:35  c' \0 l- K1 V
我用的是desktop版本。你说的驱动是stlink吗?
1 V+ U2 Q& ]' }$ m; m1 X
是的。你发给我的stlink驱动包,和我下载的完全一样。在server下运行报一样的错误。看你的截图应该是在desktop的配色下编写的,所以我抽空换成desktop试试。。
qianfan 回答时间:2015-11-2 14:59:04
ataudio 发表于 2015-11-2 14:41) F# O2 S* ~  K* |: Y
是的。你发给我的stlink驱动包,和我下载的完全一样。在server下运行报一样的错误。看你的截图应该是在des ...
$ Y# g' C$ h" i8 _8 W
可能是这个原因。不知道你的libusb安装了没有
ataudio 回答时间:2015-11-3 10:46:14
怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时会提示错误,装了libusb之后再来一次,配置OK、编译也OK,就是sudo make install看到了:0 m' g9 I4 L* e$ ]; l- w' z
make[2]: Nothing to be done for 'install-data-am'.% O" E! h9 S7 a' ^, \! t5 ^

9 ?4 r2 B$ r; j* ]% v不知道安装是否成功了。先继续往下配置看看。
qianfan 回答时间:2015-11-3 13:32:06
ataudio 发表于 2015-11-3 10:46& {4 ?8 ?# r# p) ~9 ?( k# s
怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时 ...

0 V/ Y; N. z3 ~4 F事实st-flash看看有反映吗
qianfan 回答时间:2015-11-3 13:32:36
ataudio 发表于 2015-11-3 10:46& |7 m1 e0 z% d6 x, i
怀疑是gcc版本的原因。需要gcc  5.0以上。桌面版是5.2,编译通过了。第一次libusb1.0没安装,在configure时 ...

! X5 o' j4 d$ J$ n6 s' w0 V应该不是吧。我的是4。8。4
ataudio 回答时间:2015-11-4 11:24:06
本帖最后由 ataudio 于 2015-11-4 13:06 编辑
0 e: W* Z( I1 o, r8 R" D1 |* S
QianFan 发表于 2015-11-3 13:32( s0 d0 U9 E3 [3 c! l6 w
事实st-flash看看有反映吗
这个是不是表明stlink已经装上了?
3 L: y) }% |3 l* Y0 yaoems@ubuntu:~$ st-flash         
4 c) s7 Q' V( _( ]invalid command line7 u( Y$ q$ F: T/ d) ^
stlinkv1 command line: ./st-flash [--debug] [--reset] {read|write} /dev/sgX path addr <size>7 y9 A, i3 L* l
stlinkv1 command line: ./st-flash [--debug] /dev/sgX erase
! L, f/ j# Q1 sstlinkv2 command line: ./st-flash [--debug] [--reset] {read|write} path addr <size>
" q( n, A' p# K. O  p1 O+ Mstlinkv2 command line: ./st-flash [--debug] erase
2 I) F& g5 m, i9 J% q& n) U                       use hex format for addr and <size>
2 \; [: C- q1 z% l6 haoems@ubuntu:~$ 9 P/ J: Z% l) }8 L
% U% `9 d! U/ |! \. F
qianfan 回答时间:2015-11-4 13:49:30
ataudio 发表于 2015-11-4 11:248 U  p/ r0 W  j( Q# z; b3 k
这个是不是表明stlink已经装上了?
; `, ?  ~* l0 V) j: @) saoems@ubuntu:~$ st-flash         ! O8 O* C  ?$ F/ }) C8 g8 |2 ]" V
invalid command line
7 `9 O0 N1 ^5 J* g# c/ q
对的,这就说明安装成功了。

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版