내장 환경 변수의 목적
CFG_ENV_IS_IN_FLASH 또는 CFG_ENV_IS_IN_NAND가 정의된 경우에만 ENV_IS_EMBEDDED 기능이 활성화됩니다. 본 실험에서는 NOR 플래시를 기준으로 설명합니다. U-Boot 바이너리(100KB+)와 환경 변수 저장에 필요한 섹터 크기 간 차이에서 발생하는 문제를 해결합니다. 일반적으로 플래시 전반부에는 8KB 섹터가 존재하나 후반부는 64KB 섹터로 구성됩니다. ENV_IS_EMBEDDED 미사용 시 환경 변수 영역이 코드 영역 뒤에 배치되어 64KB를 강제로 점유하게 되며, 이는 플래시와 RAM 공간 낭비로 이어집니다.
내장 환경 변수 기능 적용 시 환경 변수 영역을 코드 섹션 내(예: 8KB 섹터)에 임베딩하여 공간 효율성을 높입니다. 또한 재배치 시 환경 변수가 코드와 함께 RAM에 자동 복사되어 초기화 과정에서 별도의 메모리 할당 및 복사 작업이 불필요해집니다.
구현 메커니즘 분석
1. 조건부 매크로 정의
#if defined(CONFIG_ENV_IN_FLASH)
#if (CONFIG_ENV_ADDR >= CONFIG_MONITOR_BASE) && \
(CONFIG_ENV_ADDR + CONFIG_ENV_SIZE <= \
CONFIG_MONITOR_BASE + CONFIG_MONITOR_LEN)
#define ENV_IS_EMBEDDED 1
#endif
#endif
2. 환경 변수 구조체 강제 배치
#if defined(ENV_IS_EMBEDDED)
#define __SECTION_TEXT __attribute__((section(".text")))
typedef struct {
uint32_t crc;
uint8_t flags;
char data[CONFIG_ENV_SIZE];
} env_block;
env_block environment __SECTION_TEXT = {
ENV_CRC,
#ifdef CONFIG_REDUNDANT_ENV
1,
#endif
{
#ifdef CONFIG_BOOTARGS
"bootargs=" CONFIG_BOOTARGS "\0"
#endif
"\0"
}
};
#endif
3. 환경 변수 포인터 초기화
#ifdef ENV_IS_EMBEDDED
extern uint8_t environment[];
env_block *env_ptr = (env_block *)&environment[0];
#else
env_block *env_ptr = (env_block *)CONFIG_ENV_ADDR;
#endif
4. 환경 변수 유효성 검증
int env_init() {
if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
global_data->env_addr = (uint32_t)&env_ptr->data;
global_data->env_valid = 1;
return 0;
}
global_data->env_addr = (uint32_t)default_env;
global_data->env_valid = 0;
return 0;
}
실험 및 결과
1. 플래시 메모리 설정
#define CONFIG_ENV_IN_FLASH 1
#define CONFIG_ENV_SIZE 0x2000
#define CONFIG_ENV_ADDR 0x00004000
#define CONFIG_MONITOR_BASE CONFIG_ENV_ADDR
#define CONFIG_MONITOR_LEN 0x200000
2. 링커 스크립트 수정
.text : {
cpu/arm920t/start.o(.text)
. = ENV_OFFSET;
common/environment.o(.text)
*(.text)
}
3. 환경 변수 크기 변수 제거
/* common/environment.c 수정 */
// unsigned long env_size __SECTION_TEXT = sizeof(env_block); 주석 처리
실험 결과
- 초기 실행: 환경 변수가 0x33F84000 주소에 성공적으로 로드
- 환경 변수 저장: 두 번째 섹터(0x4000)에 정상 저장
- 재시작: 저장된 환경 변수 CRC 검증 성공 및 정상 부팅
미해결 의문점
- 데이터 세그먼트 변수를 텍스트 세그먼트에 배치하는 메커니즘
- 컴파일 타임 환경 변수 CRC 생성 과정
- 특정 주소(0x33F84000)에 변수를 배치하는 링커 동작 원리