- 一、变量存储
- 1.内存分区概念
- 2.STM32上分区验证
- 3.在Ubuntu中进行分区验证
- 二、Clion编辑器的学习与实践
- 1.Clion的下载与安装
- 2.安装clion的相关配置环境
- 3.安装OpenOCD环境
- 3.利用clion点亮LED灯
- 三、总结
- 四、参考
1.c语言在内存中分区
栈区(stack)
由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆区(heap)
一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。它与数据结构中的堆不同,分配方式类似于链表。
全局区(静态区)(static)
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量、未初始化的静态变量在相邻的另一块区域。当程序结束后,变量由系统释放 。
文字常量区
存放常量字符串。当程序结束后,常量字符串由系统释放 。
程序代码区
存放函数体的二进制代码。
2.动静态分配内存
| 属性 | 描述 |
|---|---|
| 静态分配内存 | 在程序编译和链接时就确定好的内存 |
| 动态分配内存 | 在程序加载、调入、执行的时候分配 / 回收的内存 |
3.内存分区详解
| 属性 | 描述 |
|---|---|
| .text | 也称为代码段(Code),用来存放程序执行代码,同时也可能会包含一些常量(如一些字符串常量等)。该段内存为静态分配,只读(某些架构可能允许修改)。 这块内存是共享的,当有多个相同进程(Process)存在时,共用同一个 text 段 |
| .data | 也有的地方叫 GVAR (global value),用来存放程序中已经初始化的非零全局变量。静态分配。data又可分为读写(RW)区域和只读(RO)区域。RO 段保存常量所以也被称为 .constdata ;RW 段则是普通非常全局变量,静态变量就在其中 |
| .bss | 存放程序中为初始化的和零值全局变量。静态分配。在程序开始时通常会被清零 |
堆和栈都属于动态分配内存,两者空间大小都是可变的。
| 属性 | 描述 |
|---|---|
| Stack:栈 | 存放 Automatic Variables ,按内存地址由高到低方向生长,其最大值由编译时确定,速度快,但自由性差,最大空间不大 |
| Heap:堆 | 自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存 / 虚拟内存上限决定,速度较慢,但自由性大,可用空间大。 |
在串口通信所建的工程上修改代码
bsp_usart.h 文件:
添加头文件
bsp_usart.c 文件:
添加一个 fputc函数
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USARTx, (uint8_t)ch);
while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
main.c 文件,编写如下代码:
#include "stm32f10x.h"
#include "bsp_usart.h" //添加 bsp_usart.h 头文件
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
printf("hello");
printf("%d",a);
printf("n");
}
int main(void)
{
//定义局部变量
int a=2;
static int inits_local_c=2, uninits_local_c;
int init_local_d = 1;
char *p;
char str[10] = "lyy";
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "qwertyuiop";
//动态分配
int *p1=malloc(4);
int *p2=malloc(4);
USART_Config();//串口初始化
output(a);
//释放
free(p1);
free(p2);
printf("栈区-变量地址n");
printf(" a:%pn", &a);
printf(" init_local_d:%pn", &init_local_d);
printf(" p:%pn", &p);
printf(" str:%pn", str);
printf("n堆区-动态申请地址n");
printf(" %pn", p1);
printf(" %pn", p2);
printf("n全局区-全局变量和静态变量n");
printf("n.bss段n");
printf("全局外部无初值 uninit_global_a:%pn", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%pn", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%pn", &uninits_local_c);
printf("n.data段n");
printf("全局外部有初值 init_global_a:%pn", &init_global_a);
printf("静态外部有初值 inits_global_b:%pn", &inits_global_b);
printf("静态内部有初值 inits_local_c:%pn", &inits_local_c);
printf("n文字常量区n");
printf("文字常量地址 :%pn",var1);
printf("文字常量地址 :%pn",var2);
printf("n代码区n");
printf("程序区地址 :%pn",&main);
printf("函数地址 :%pn",&output);
return 0;
}
编译烧录到板子上,打开野火调试助手
按下reset键得到如下结果:
1.使用命令创建一个hello.c文件
输入以下代码:
#include#include //定义全局变量 int init_global_a = 1; int uninit_global_a; static int inits_global_b = 2; static int uninits_global_b; void output(int a) { printf("hello"); printf("%d",a); printf("n"); } int main( ) { //定义局部变量 int a=2; static int inits_local_c=2, uninits_local_c; int init_local_d = 1; output(a); char *p; char str[10] = "lyy"; //定义常量字符串 char *var1 = "1234567890"; char *var2 = "qwertyuiop"; //动态分配 int *p1=malloc(4); int *p2=malloc(4); //释放 free(p1); free(p2); printf("栈区-变量地址n"); printf(" a:%pn", &a); printf(" init_local_d:%pn", &init_local_d); printf(" p:%pn", &p); printf(" str:%pn", str); printf("n堆区-动态申请地址n"); printf(" %pn", p1); printf(" %pn", p2); printf("n全局区-全局变量和静态变量n"); printf("n.bss段n"); printf("全局外部无初值 uninit_global_a:%pn", &uninit_global_a); printf("静态外部无初值 uninits_global_b:%pn", &uninits_global_b); printf("静态内部无初值 uninits_local_c:%pn", &uninits_local_c); printf("n.data段n"); printf("全局外部有初值 init_global_a:%pn", &init_global_a); printf("静态外部有初值 inits_global_b:%pn", &inits_global_b); printf("静态内部有初值 inits_local_c:%pn", &inits_local_c); printf("n文字常量区n"); printf("文字常量地址 :%pn",var1); printf("文字常量地址 :%pn",var2); printf("n代码区n"); printf("程序区地址 :%pn",&main); printf("函数地址 :%pn",&output); return 0; }
编译执行文件
得到结果
从stm32和Ubuntu都可以看出:从高地址到低地址分区情况
下载传送门.
下载好之后进行安装 以下为安装步骤
等待安装完成。
安装MinGW
下载地址:https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/.
下载后解压完成。
打开clion软件,点击New Project
点击file->setting->Build,Execution, Deployment->Embedded Development选择Tookchains
跟据刚刚下载的mingw64文件的路径将文件调价环境中,最后点击ok
下载解压出来
按照以下步骤添加路径
点击ok就好了
1.打开clion软件,选择新建工程(New Project)
利用其打开STM32CubeMX
改选芯片为STM32F103C8
再进行芯片的相关设置
选择引脚作为输出口(PC13)
生成工程
返回到clion
回到clion软件中找到main.c文件,在main.c文件中找到while(1)语句,在该语句中添加如下代码
while (1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
HAL_Delay(500);
}
进行编译
烧录
结果展示:
Clion 是一个多功能跨平台的 IDE,很有使用价值。在通过Clion进行STM32点亮LED灯的过程中,它一方面调用 STM32CubeMX 直接建立了 HAL 工程,另一方面使用 CMake 编译器完成了代码编译。在这个过程中遇到了很多bug,一遍遍的删除,一遍遍的下载,终于是做了出来。
四、参考基于ubuntu和stm32(keil5)的C程序的内存分配问题.
CLion2021 的详细安装并基于 CLion 实现 stm32F103 点亮 LED.



