| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- i2c
- booth multiplier
- booth multiplier 설계
- 자료구조
- c
- 곱셈기 설계
- FIFO 설계
- booth algorithm
- 비동기 FIFO 구조
- Sync FIFO
- SPI mode
- LinkedList
- ARM
- Cortex-M3
- C언어
- 연산 가속기 설계
- asynchronous fifo
- lec check
- Async FIFO
- keynote
- keynote 도형 회전
- keynote 사용법
- keynote 도형 복사
- LEC
- ACK Polling
- cadence conformal eco
- ISR
- BSS
- Keynote 표
- malloc
- Today
- Total
JINTBEAT Design Life
Linker - (2) 본문
개요 : 현재 Zynq zybo z7-20을 가지고 짬이 날 때, 이런 저런 Test를 하는 중이다. 분명 처음 이 보드를 사용할 때는 아무것도 몰라도 프로그램이 정상적으로 실행되었었다. 한 5년만에 다시 실행해봤더니 실행이 안된다. 그 이유를 디버깅하다 Linker Script 공부를 시작하게 되었다. 그 중 rodata를 DDR로 할당하면 printf가 깨졌던 적이 있다.
.rodata 자체는 읽기만 하면 되니까 DDR에 있어도 원리상 문제는 없다.
> 그런데, DDR이 아직 초기화되지 않은 시점에 .rodata를 읽는 코드가 실행되면 바로 깨질 수 있다.
> printf가 대표적인 희생자이다.
const char *msg = "Hello World";
const int table[4] = {1,2,3,4};
> 이런 건 실행 중에 바뀌지 않기 때문에 굳이 RAM으로 복사할 필요 없이 그냥 Flash / ROM / DDR 어디 읽기 가능한 곳에 있어도 됨.
그런데 왜 printf가 죽을 수 있나 ?
> printf("hello\n")에서 "hello\n" 문자열 자체가 .rodata에 있기 때문
printf("Hello World\n");
컴파일러는 보통 이 문자열을 이렇게 둔다.
.rodata:
"Hello World\n"
그리고 실제 코드는 대략 이런 느낌
printf(0x00123456); // "Hello World\n" 문자열 주소 전달
> 즉, CPU에서는
> 1. .text에서 printf() 호출
> 2. 인자로 넘길 문자열 주소를 읽음
> 3. 그 문자열 내용을 읽어서 UART로 보냄.
그런데, .rodata가 DDR에 있고, DDR init이 안되어 있으면 ?
> CPU가 이 문자열을 읽으려는 순간, read DDR Address가 실패할 것이다.
> 그 결과는 여러 형태로 나올 수 있다.
> 그냥 멈춤 (bus hang)
> data abort / exception
> 이상한 문자 출력
> printf() 안 나온 것처럼 보임
printf가 자주 읽는 것들
printf("count = %d\n", x);
> count = %d\n → .rodata
Startup code는 뭐지 ?
Reset
↓
Startup Code
↓
C Runtime Init
↓
main()
↓
네가 작성한 FW Code
> FW code(main.c, driver.c, app logic)은 startup 이후에 실행된다.
> 보통 reset 직후 CPU가 제일 먼저 실행하는 코드이다.
> 이 코드는 대개 startup.s, crt0.S, vectors.s로 되어 있다.
CPU가 reset되면, 바로 main()으로 jump하지 않기 때문에 따로 필요하다.
> 초기 상태는
> SP(스택 포인터) 설정 안됨.
> RW(.data) 복사 안됨
> ZI(.bss) 초기화 안됨
> 인터럽트 벡터 설정 필요
> 즉, C 코드가 돌 준비가 아직 안된 상태
> 그래서 startup code가 먼저 와서 환경을 만들어줘야한다.
Startup code가 하는 일
1. Stack Pointer 설정
ldr sp, =_estack
> 의미 : 스택 최상단 주소를 SP에 넣음
> 이거 안하면 함수 호출/지역변수/리턴 자체가 불안정함.
2. .data 초기화 (RW 복사)
> Flash의 초기값 → RAM으로 복사
int x = 10;
> 이런건 startup에서 복사해줘야함.
3. .bss 초기화(ZI zero)
> 초기값 없는 전역/정적 변수를 0으로 채운다.
*************************************************************
이 글은 ChatGPT 질의 응답을 바탕으로 작성되었습니다.
*************************************************************
'🖥️ - ARM' 카테고리의 다른 글
| Barrel Shifter란? (0) | 2026.04.15 |
|---|---|
| ELF(Executable and Linkable Format) 이란? (2) | 2026.04.12 |
| Linker - (1) (0) | 2026.04.09 |
| ARM I2C 응용 - EEPROM(ATmel) 동작 분석 (1) | 2025.08.13 |
| ARM I2C(Inter-Integrated Circuit) 동작 원리 (7) | 2025.08.10 |