1. 메모리 저장 & 실행 과정
`main.c` 소스 파일 Compile → `main.o` 오브젝트 바이너리 코드 파일 변환 → Linker가 `main.elf` 실행 코드로 변환
- Flash Memory : 실행 코드 저장
- RAM : 데이터 저장
.elf 실행 코드가 flash Memory에 저장되는데 어떻게 저장?
→ 메모리는 각 section으로 나뉘어져 있음
.map 파일
`.map` 파일에서 각 section을 어디에 저장시킬지 저장되어 있음. (네비게이션 역할)
(.text : 사용자 정의 함수 등)
LinkerScript 파일
/*
******************************************************************************
**
** @file : LinkerScript.ld
**
** @author : Auto-generated by STM32CubeIDE
**
** @brief : Linker script for STM32F411RETx Device from STM32F4 series
** 512KBytes FLASH
** 128KBytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
******************************************************************************
** @attention
**
** Copyright (c) 2024 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
******************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into "FLASH" Rom type memory */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
{
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} >FLASH
.ARM (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
{
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >FLASH
.preinit_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array (READONLY) : /* The "READONLY" keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section into "RAM" Ram type memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
LinkerScript에서 코드 및 데이터를 메모리에 저장시킴
(Datasheet의 메모리 주소에 코드 및 데이터 저장)
isr_vector를 Flash Memory의 0x0800 0000 주소에 저장하고
다음 주소부터 .text(사용자 정의 함수 등)를 Flash Memory에 저장
(.text : map 파일에서 정의)
`.text` section : 실행 코드 → Flash 영역
`.data` section : 전역 변수(초기화 되어 있는) → RAM 영역
`.bss` section : 전역 변수(초기화 되어 있지 않는, 0으로 자동 초기화) → RAM 영역
Linker가 각 section을 메모리에 저장시키고
어디에 저장할지는 .map 파일에 저장되어 있다. (네비게이션 역할)
Startup 코드
전원을 인가하면 메모리의 0x0000 0000(BOOT 영역)부터 시작
⇒ Start up 코드 저장되어 있음 (위 사진에서 ENTRY)
SP(Stack Pointer) : RAM 영역의 가장 마지막 주소를 SP로 가르킴
- Flash Memory : 실행 코드 저장
- Start up code
- main code
- …
- RAM : 데이터 저장
- .data : 전역 변수(초기화 되어 있는)
- .bss : 전역 변수(초기화 되어 있지 않는, 0으로 자동 초기화)
- Stack : 지역변수, 매개변수
- Heap : 프로그래머 동적 할당
Stack & Heap
1. Stack 영역
⦁ 지역변수 등 함수가 호출될 때 영역이 할당되며 함수 호출이 완료되면 다시 사라진다.
⦁ 잠깐 사용하고 삭제하는 데이터 저장(지역변수, 매개변수)
⦁ 해당 객체가 정의된 함수 호출이 완료되면 소멸
⦁ LIFO(Last-In-First-Out) 방식 Stack 영역의 크기가 RAM 크기를 초과하면 Stack Overflow 발생
⦁ Heap 영역보다 빠름
2. Heap 영역
⦁ 동적 메모리 할당(포인터, `malloc`, `calloc`, `realloc` 및 `free`)
→ Heap 크기는 고정되지 않으며 메모리가 할당되거나 할당 해제됨에 따라
동적으로 늘어나거나 줄어들 수 있음
⦁ 프로그래머가 할당하지 않으면 데이터 영역을 제외한 RAM 구역이 Stack 영역으로 사용됨
⦁ Stack 영역보다 느림 (동적 할당 및 할당 해제 메커니즘이 필요해서)
2. Driver(Button, LED)
main.c
/* USER CODE BEGIN 2 */
Button_t Button_1, Button_2, Button_3;
button_init(&Button_1, GPIOC, GPIO_PIN_10);
button_init(&Button_2, GPIOC, GPIO_PIN_11);
button_init(&Button_3, GPIOC, GPIO_PIN_12);
LED_t LED_1, LED_2, LED_3;
LED_init(&LED_1, GPIOC, GPIO_PIN_8);
LED_init(&LED_2, GPIOC, GPIO_PIN_6);
LED_init(&LED_3, GPIOC, GPIO_PIN_5);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(button_getState(&Button_1) == ACT_RELEASED)
{
LED_toggle(&LED_1);
}
if(button_getState(&Button_2) == ACT_RELEASED)
{
LED_toggle(&LED_2);
}
if(button_getState(&Button_3) == ACT_RELEASED)
{
LED_toggle(&LED_3);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
Button Driver
// 헤더 파일
/*
* Button.h
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#ifndef DRIVER_BUTTON_BUTTON_H_
#define DRIVER_BUTTON_BUTTON_H_
#include "stm32f4xx_hal.h"
typedef enum {PUSHED, RELEASED, NO_ACT, ACT_PUSHED, ACT_RELEASED} button_state_t;
typedef struct{
GPIO_TypeDef* GPIOx;
uint16_t GPIO_Pin;
int prevState;
}Button_t;
void button_init(Button_t *Button, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
button_state_t button_getState(Button_t *Button);
#endif /* DRIVER_BUTTON_BUTTON_H_ */
// 소스 파일
/*
* Button.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "Button.h"
void button_init(Button_t *Button, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
Button->GPIOx = GPIOx;
Button->GPIO_Pin = GPIO_Pin;
Button->prevState = RELEASED;
}
button_state_t button_getState(Button_t *Button)
{
// static int prevState = RELEASED;
int curState = HAL_GPIO_ReadPin(Button->GPIOx, Button->GPIO_Pin); // Read pin State
if((Button->prevState == RELEASED) && (curState == PUSHED))
{
HAL_Delay(50);
Button->prevState = PUSHED; // PUSH == 0
return ACT_PUSHED; // return 3
}
else if((Button->prevState == PUSHED) && (curState == RELEASED))
{
HAL_Delay(50);
Button->prevState = RELEASED;
return ACT_RELEASED;
}
return NO_ACT;
}
LED Driver
// 헤더 파일
/*
* LED.h
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#ifndef DRIVER_LED_LED_H_
#define DRIVER_LED_LED_H_
#include "stm32f4xx_hal.h"
typedef struct{
GPIO_TypeDef *GPIOx;
uint16_t GPIO_Pin;
}LED_t;
void LED_init(LED_t *LED, GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
void LED_ON(LED_t *LED);
void LED_OFF(LED_t *LED);
void LED_toggle(LED_t *LED);
#endif /* DRIVER_LED_LED_H_ */
// 소스 파일
/*
* LED.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "LED.h"
void LED_init(LED_t *LED, GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
LED->GPIOx = GPIOx;
LED->GPIO_Pin = GPIO_Pin;
}
void LED_ON(LED_t *LED)
{
HAL_GPIO_WritePin(LED->GPIOx, LED->GPIO_Pin, SET);
}
void LED_OFF(LED_t *LED)
{
HAL_GPIO_WritePin(LED->GPIOx, LED->GPIO_Pin, RESET);
}
void LED_toggle(LED_t *LED)
{
HAL_GPIO_TogglePin(LED->GPIOx, LED->GPIO_Pin);
}
main.c
while (1)
{
APMain();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
APMain
// 헤더 파일
/*
* AP_Main.h
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#ifndef AP_AP_MAIN_H_
#define AP_AP_MAIN_H_
#include "stm32f4xx_hal.h"
#include "../Driver/Button/Button.h"
#include "../Driver/LED/LED.h"
void sys_init();
int APMain();
#endif /* AP_AP_MAIN_H_ */
// 소스 파일
/*
* AP_Main.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "AP_Main.h"
Button_t Button_1, Button_2, Button_3;
LED_t LED_1, LED_2, LED_3;
void sys_init()
{
button_init(&Button_1, GPIOC, GPIO_PIN_10);
button_init(&Button_2, GPIOC, GPIO_PIN_11);
button_init(&Button_3, GPIOC, GPIO_PIN_12);
LED_init(&LED_1, GPIOC, GPIO_PIN_8);
LED_init(&LED_2, GPIOC, GPIO_PIN_6);
LED_init(&LED_3, GPIOC, GPIO_PIN_5);
}
int APMain()
{
sys_init();
while (1)
{
if (button_getState(&Button_1) == ACT_RELEASED)
{
LED_toggle(&LED_1);
}
if (button_getState(&Button_2) == ACT_RELEASED)
{
LED_toggle(&LED_2);
}
if (button_getState(&Button_3) == ACT_RELEASED)
{
LED_toggle(&LED_3);
}
}
}
- 전체 코드
→ main.c 실행 코드가 application main 코드를 호출하여 시스템 초기화 & 어플리케이션 실행
⇒ main : Caller / APMain : Callee
Made By Minseok KIM
'ARM > 2_Study' 카테고리의 다른 글
[ARM] STM32_FreeRTOS, Shared Memory (0) | 2024.04.30 |
---|---|
[ARM] STM32_Serial Communication(UART), Queue (0) | 2024.04.29 |
[ARM] STM32_PWM, Driver(Motor) (0) | 2024.04.29 |
[ARM] STM32_Driver(CLCD I2C, Ultrasonic) (0) | 2024.04.26 |
[ARM] STM32_Low level Programming (0) | 2024.04.24 |
Let's Be Happy!
도움이 되었으면 좋겠어요 :)