打印
[应用相关]

STM32 大小端模式 与 堆栈

[复制链接]
1731|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Listate|  楼主 | 2016-11-15 22:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
栈增长和大端/小端问题是和CPU相关的两个问题.

1,首先来看:栈(STACK)的问题.

函数的局部变量,都是存放在"栈"里面,栈的英文是:STACK.STACK的大小,我们可以在stm32的启动文件里面设置,以战舰stm32开发板为例,在startup_stm32f10x_hd.s里面,开头就有:

Stack_Size      EQU     0x00000800

表示栈大小是0X800,也就是2048字节.这样,CPU处理任务的时候,函数局部变量做多可占用的大小就是:2048字节,注意:是所有在处理的函数,包括函数嵌套,递归,等等,都是从这个"栈"里面,来分配的.
所以,如果一个函数的局部变量过多,比如在函数里面定义一个u8 buf[512],这一下就占了1/4的栈大小了,再在其他函数里面来搞两下,程序崩溃是很容易的事情,这时候,一般你会进入到hardfault....
这是初学者非常容易犯的一个错误.切记不要在函数里面放N多局部变量,尤其有大数组的时候!
再说说栈的增长方向,我们可以用如下代码测试:

//保存栈增长方向
//0,向下增长;1,向上增长.
static u8 stack_dir;

//查找栈增长方向,结果保存在stack_dir里面.
void find_stack_direction(void)
{
    static u8 *addr=NULL; //用于存放第一个dummy的地址。
    u8 dummy;               //用于获取栈地址
    if(addr==NULL)    //第一次进入
    {                          
        addr=&dummy;     //保存dummy的地址
        find_stack_direction ();  //递归
    }else                //第二次进入
{  
        if(&dummy>addr)stack_dir=1; //第二次dummy的地址大于第一次dummy,那么说明栈增长方向是向上的.
        else stack_dir=0;           //第二次dummy的地址小于第一次dummy,那么说明栈增长方向是向下的.  
}
}

这个代码不是我写的,网上抄来的,思路很巧妙,利用递归,判断两次分配给dummy的地址,来比较栈是向下生长,还是向上生长.
如果你在STM32测试这个函数,你会发现,STM32的栈,是向下生长的.事实上,一般CPU的栈增长方向,都是向下的.
再说说,大小端的问题.
大端模式:低位字节存在高地址上,高位字节存在低地址上
小端模式:高位字节存在高地址上,低位字节存在低地址上

STM32属于小端模式,简单的说,比如u32 temp=0X12345678;
假设temp地址在0X2000 0010.
那么在内存里面,存放就变成了:
地址              |            HEX         |
0X2000 0010  |  78   56   43  12  |

CPU到底是大端还是小端,可以通过如下代码测试:
//CPU大小端
//0,小端模式;1,大端模式.
static u8 cpu_endian;

//获取CPU大小端模式,结果保存在cpu_endian里面
void find_cpu_endian(void)
{
int x=1;
if(*(char*)&x==1)cpu_endian=0; //小端模式
else cpu_endian=1;    //大端模式  
}
以上测试,在STM32上,你会得到cpu_endian=0,也就是小端模式.
沙发
feiqi1| | 2016-11-15 22:36 | 只看该作者
以附件工程为例,在前面第一个图,程序总共占用内存:20+2348字节,这么多内存,到底是怎么得来的呢?

使用特权

评论回复
板凳
androidbus| | 2016-11-15 22:38 | 只看该作者
我们可以双击Project侧边栏的:Targt1,会弹出test.map,在这个里面,我们就可以清楚的知道这些内存到底是怎么来的了吧

使用特权

评论回复
地板
litengg| | 2016-11-15 22:46 | 只看该作者
STM32属于小端模式,简单的说,比如u32 temp=0X12345678;
假设temp地址在0X2000 0010.
那么在内存里面,存放就变成了:
地址              |            HEX         |
0X2000 0010  |  78   56   43  12   

使用特权

评论回复
5
qiangweii| | 2016-11-15 22:47 | 只看该作者
STM32的内存分配,应该分为两种情况。
1,使用了系统的malloc。
2,未使用系统的malloc。

使用特权

评论回复
6
shashaa| | 2016-11-15 22:54 | 只看该作者
一般对于我们开发板例程,实际上,没有所谓堆区的概念,而仅仅是:静态存储区+栈区。

使用特权

评论回复
7
bbapple| | 2016-11-15 22:55 | 只看该作者
无论哪种情况,所有的全局变量,包括静态变量之类的,全部存储在静态存储区。

使用特权

评论回复
8
Listate|  楼主 | 2016-11-15 23:02 | 只看该作者
feiqi1 发表于 2016-11-15 22:36
以附件工程为例,在前面第一个图,程序总共占用内存:20+2348字节,这么多内存,到底是怎么得来的呢? ...

堆heap和栈stack都是计算机内存,只是属性不同而已,stack由编译器自动分配和回收,heap由程序员手动分配和回收,通过malloc和free函数。

使用特权

评论回复
9
gyh974| | 2016-11-16 08:53 | 只看该作者

使用特权

评论回复
10
wxmxmicro| | 2016-11-16 10:30 | 只看该作者
学习了

使用特权

评论回复
11
soulmist| | 2016-11-16 18:07 | 只看该作者
heh

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

161

主题

1233

帖子

1

粉丝