Review of variable storage and learning and practice of Clion editor
- 1. Experimental requirements
- Second, variable storage review
- 3. Introduction, installation and configuration of Clion
- 4. Experiment
- V. Summary
- 6. References
1. Experimental requirements
1. Write a C program, revisit the concepts of global variables, local variables, heaps, stacks, etc., and program and verify in Ubuntu (x86) system and STM32 (Keil) respectively (STM32 printf information through the serial port to the host computer serial port assistant) . Summarize the allocation addresses of variables such as heap, stack, global, and local variables in C programs under Ubuntu and stm32, and conduct comparative analysis.
2. Install Clion2021, and use a new embedded software development kit (replacing Keil) to complete the stm32F103 LED lighting program.
Second, variable storage review
1. Memory allocation
(1) Brief description of memory attributes
静态分配内存:在程序编译和链接时就确定好的内存
动态分配内存:在程序加载、调入、执行的时候分配/回收的内存
(2) Brief description of memory partition
Stack area (stack): automatically allocated and released by the compiler to store function parameters and local variables (auto type). It operates like a stack in a data structure.
Heap area (heap): The program dynamically allocates and releases space. Generally, it is allocated and released by the programmer. If the programmer does not release it, it may be recycled by the OS at the end of the program. (Different from the heap in the data structure, the allocation method is similar to a linked list)
Global/static area (static): The storage of global variables and static variables is put together, and initialized global variables and static variables are in the same area, uninitialized Global variables and uninitialized static variables are in another adjacent area. (When the program ends, the variable is released by the system)
Literal constant area: store constant strings (when the program ends, the constant strings are released by the system)
Program code area: store the binary code of the function body
Note:
a normal program is stored in memory It is usually divided into three parts: program segment, data segment and stack.
Program segment: The machine code of the program, read-only data, usually read-only, and writing to it is illegal.
Data segment: Static data in the program.
Stack: A contiguous block in memory. Dynamic data is stored through the stack. The stack pointer register (SP) points to the top of the stack. The bottom of the stack is a fixed address, which is characterized by last-in-first-out, that is, the data put in later is taken out first. It supports PUSH, POP operations. PUSH is to put data on the top of the stack, and POP is to take out the data on the top of the stack.
(3) Partition comparison
Note:
① As the number of function call layers increases, the function stack frame extends to the low address of the memory block by block.
② As the number of function call layers in the process decreases (that is, the return of each function call), the stack frame will be abandoned piece by piece and retracted to the high address of the memory.
③ The size of the stack frame of each function varies with the nature of the function, and is determined by the number of local variables of the function.
④ The process's dynamic application for memory occurs in the Heap (heap). As the amount of memory dynamically allocated to the process by the system increases, the Heap (heap) may extend to high or low addresses, which depends on different CPUs. Realization, but generally speaking, it grows towards the high address of the memory.
⑤ When the growth of the uninitialized data area (BSS) or Stack (stack area) exhausts the free memory allocated by the system to the process, the process will be blocked and re-scheduled by the operating system with a larger memory module .
(4) STM32 data storage location
The contents of the code area and constant area are compiled and stored in ROM; the stack, heap, and global area (.bss segment, .data segment) are stored in RAM.
2. Programming for verification
(1) Free authentication
[1] The code is as follows
#include <stdio.h>
#include <stdlib.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( )
{
//定义局部变量
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 = "123456";
char *var2 = "yushu";
//动态分配
int *p1=malloc(4);
int *p2=malloc(4);
//释放
free(p1);
free(p2);
printf("栈区-变量地址\n");
printf(" a:%p\n", &a);
printf(" init_local_d:%p\n", &init_local_d);
printf(" p:%p\n", &p);
printf(" str:%p\n", str);
printf("\n堆区-动态申请地址\n");
printf(" %p\n", p1);
printf(" %p\n", p2);
printf("\n全局区-全局变量和静态变量\n");
printf("\n.bss段\n");
printf("全局外部无初值 uninit_global_a:%p\n", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%p\n", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%p\n", &uninits_local_c);
printf("\n.data段\n");
printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
printf("静态外部有初值 inits_global_b:%p\n", &inits_global_b);
printf("静态内部有初值 inits_local_c:%p\n", &inits_local_c);
printf("\n文字常量区\n");
printf("文字常量地址 :%p\n",var1);
printf("文字常量地址 :%p\n",var2);
printf("\n代码区\n");
printf("程序区地址 :%p\n",&main);
printf("函数地址 :%p\n",&output);
return 0;
}
【2】Terminal creation and viewing
(2) STM32 verification
[1] Code generation
Since the process of automatically generating code has been done many times, I will not repeat it here. The generated code compression package is given as follows:
Link: https://pan.baidu.com/s/1jJHzOzG4AjrXWWC4wJ8xBA
Extraction code: 1521
[2] Code writing
The bsp_usart.h file
adds the header file:
#include <stdio.h>
#include <stdlib.h>
main.c file
#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 = "123456";
char *var2 = "yushu";
//动态分配
int *p1=malloc(4);
int *p2=malloc(4);
USART_Config();//串口初始化
output(a);
//释放
free(p1);
free(p2);
printf("栈区-变量地址\n");
printf(" a:%p\n", &a);
printf(" init_local_d:%p\n", &init_local_d);
printf(" p:%p\n", &p);
printf(" str:%p\n", str);
printf("\n堆区-动态申请地址\n");
printf(" %p\n", p1);
printf(" %p\n", p2);
printf("\n全局区-全局变量和静态变量\n");
printf("\n.bss段\n");
printf("全局外部无初值 uninit_global_a:%p\n", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%p\n", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%p\n", &uninits_local_c);
printf("\n.data段\n");
printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
printf("静态外部有初值 inits_global_b:%p\n", &inits_global_b);
printf("静态内部有初值 inits_local_c:%p\n", &inits_local_c);
printf("\n文字常量区\n");
printf("文字常量地址 :%p\n",var1);
printf("文字常量地址 :%p\n",var2);
printf("\n代码区\n");
printf("程序区地址 :%p\n",&main);
printf("函数地址 :%p\n",&output);
return 0;
}
The bsp_usart.c file
overrides the fputc function:
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USARTx, (uint8_t)ch);
while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
After compiling main.c
, you can see the size of the Code, RO-data, RW-data, and ZI-data sections.
Note
Code: store program code
RO - data: store const constants and
instructions =Code + RO-Data + RW-Data RAM=RW-data+ZI-data
【3】Program output
Use mcuisp software to start programming.
After opening the serial port with SSCOM, press RESET on the chip to display the output result:
when using the XCOM serial port debugging assistant, it will output horizontally, and it is not recommended to use it here
(3) Analysis and comparison
The address value of Ubuntu in the stack area and the heap area increases from top to bottom, the address value of STM32 in the stack area decreases from top to bottom, and the address value in the heap area increases from top to bottom. From the perspective of each area, the address of the stack area is at a high address, and the address of the code area is at a low address.
3. Introduction, installation and configuration of Clion
1. Introduction to Clion
Clion is a cross-platform IDE designed for developing C and C++. It is designed on top of IntelliJ and includes many smart features to increase developer productivity. CLion helps developers use smart editors to improve code quality, automate code refactoring, and deeply integrate the CMake compilation system to improve developer productivity.
2. Install CLion2021
(1) Download
clion official website:
CLion: A Cross-Platform IDE for C and C++ by JetBrains
can be downloaded through Baidu network disk (here I borrowed someone else’s URL)
network disk: https://pan.baidu.com/s/1-uhNBBdWsPfgxBqaDqigqA
extraction Code: qwer
(2) Installation Tutorial
Double-click the exe file and click Next
to modify the installation location.
You can check it, add “bin” folder to the PATH, and you don’t need to add environment variables
later. Next, go to next
finish
and open clion for a short-term trial.
Click log in to … create an account
here I use QQ mailbox to register
and click submit. After successful registration, log out and log in again.
Click start trial
3. Install arm-none-eabi-gcc
(1) Download
Official website address: GNU Toolchain | GNU Arm Embedded Toolchain Downloads – Arm Developer
选择gcc-arm-none-eabi-10.3-2021.10-win32.exe
(2) Installation Tutorial
Select Simplified Chinese
and follow the installation wizard to continue.
Notepad and cmd will pop up automatically
4. Install openocd
(1) Download and decompress
Official website: Download OpenOCD for Windows
download is the latest 11.18, this is a compressed package, just unzip it
5. Install MinGW
(1) Download and decompress
Net disk download: https://pan.baidu.com/s/1Q9lzsIWJJ4_MPThVYDnENg
Extraction code:
After downloading qwer, just unzip the file just like openocd
6. Add to the system environment variable
arm-none-eabi-gcc 路径下bin文件夹
Openocd路径下bin文件夹
mingw64路径下bin文件夹
How to add system environment variables:
Settings –> System –> About –> Advanced System Settings –> Environment Variables
Then check whether the installation is successful
Enter arm-none-eabi-gcc -v on the command line, if there is output, it means success.
7. Clion configuration
(1) Create a project
click create
(2) Configure toolchains
Select File-Settings-Build-Toolchains, add MinGW, the path information will be automatically matched on the right, and select debugger arm-none-eabi-gdb.exe in the bin folder under the arm-none-eabi-gcc path
(3) Configure Embedded Development
Select File-Settings-Build-Embedded Development, convert the OpenOCD file directory on the right to the location you downloaded, and finally click Test and find that the prompt color is dark green, which means the configuration is successful (by the way, CubeMX is also configured)
OK
4. Experiment
1. Project creation
Create a new project with CLion
Select STM32CubeMX, fill in the path to save the project, and click Create
2. Generate project
After entering cubemx, the system defaults to f030F4Px, and we need to use f103c8t6, click back to select the chip location. Then select the chip
, configure RCC , configure
SYS
, configure pins
, and set the PC13 pin as GPIO_Output to light up the LED.
Configure the serial port USART1
to name the project file and set
the Project Name to fill in again (because the process of changing the chip is actually a new ioc file created by the Cube), it is recommended to fill in the previous project name and file directory, so that you can put the previously unwanted one. ioc file is overwritten.
Then in Toolchain/IDE, select SW4STM32
Finally, click on the upper right corner, select Yes, generate the project, and click open projects
3. Configure the clion project
Back to CLion, you can see the following interface appears, select the stm32f103c8_biue_pill.cfg file, and use
4. Code change and burning operation
Add code
Open the main.c file and add the code to make the PC13 pin LED blink in the while loop
while (1)
{
/* USER CODE END WHILE */
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);
/* USER CODE BEGIN 3 */
}
compile
burn
5. Results
V. Summary
This experiment only requires you to understand the code. You don’t need to write it yourself. You can use the code. It may be troublesome to install and configure the clion software. You need to register an account. Others need to pay attention to the operation carefully and carefully. In short, refer to the boss code and blog to complete the experiment.
6. References
https://blog.csdn.net/qq_43279579/article/details/110308101
https://blog.csdn.net/liwei16611/article/details/88545248
https://my.oschina.net/mizhinian/blog/4472814
https://blog.csdn.net/u011784994/article/details/53157614
https://blog.csdn.net/m0_58892312/article/details/121866325
https://blog.csdn.net/qq_60678931/article/details/121866156