포스트

임베디드 스터디 - 메모리 초기화

임베디드 스터디 - 메모리 초기화

칩 셀렉트 로직 (CS)

  • CPU 내장 RAM 외에도 추가 외장 SDRAM을 사용할 경우, MMIO를 통해 메모리 주소 설정
  • CS가 메모리 주소 범위를 바탕으로 디코더 동작, 메모리 선택
1
2
3
4
5
6
CPU 주소버스 상위 비트 → 디코더 → CS0 (NOR Flash)
                                 → CS1 (SDRAM)
                                 → CS2 (주변장치)

0x0000_0000 ~ 0x00FF_FFFF → CS0 활성 → NOR Flash
0x2000_0000 ~ 0x20FF_FFFF → CS1 활성 → SDRAM

메모리 컨트롤러

  • 각 메모리마다 동작 타이밍이 다르기에, 별도의 관리가 필요
  • 메모리 컨트롤러는 스타트업 코드 실행 시 클럭 설정(PLL) 이후 실행
    • 각 메모리의 타이밍 파라미터 설정 필요
  • CPU는 읽기/쓰기 요청만, 이후 타이밍 처리는 메모리 컨트롤러가 처리함
1
2
3
4
5
6
CPU → "0x2000_0000 읽어줘"
         ↓
   메모리 컨트롤러
   (RAS → 대기 → CAS → 대기 → 데이터 캡처)
         ↓
   CPU ← 데이터 반환

링커스크립트 (.ld)

  • 빌드 과정에서 컴파일된 파일의 메모리 주소를 배정하는 코드
    • MEMORY : 어떤 메모리가 어떤 주소에 얼마나 있는지 선언
    • SECTIONS : 각 섹션(.text, .data, .bss)을 어느 메모리에 배치할 지 지정
  • 만약 링커스크립트의 주소와 실제 메모리의 주소가 안맞다면, HardFault 예외, 최악은 알 수 없는 동작을 수행하는 경우도 발생한다.
    • 보드 스펙시트나 MCU 스펙시트를 바탕으로 링커스크립트를 생성해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
MEMORY {
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 512K
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

SECTIONS {
    .text : {
        *(.text*)       /* 모든 오브젝트의 .text 섹션 */
    } > FLASH           /* Flash에 배치 */

    .data : {
        *(.data*)
    } > RAM AT > FLASH  /* RAM에 올라가지만, 초기값은 Flash에 저장 */

    .bss : {
        *(.bss*)
    } > RAM             /* RAM에만 배치, Flash 공간 불필요 */
}

링커스크립트 기본 문법

  • MEMORY : 메모리 선언
  • 속성은 총 세 가지
    • r = 읽기
    • w = 쓰기
    • x = 실행 가능
1
2
3
4
MEMORY {
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 512K
    RAM   (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
  • SECTIONS : 각 섹션의 메모리 지정
    • * : 와일드카드 문법.
      • 섹션 앞 * : 모든 .o(오브젝트 파일)을 지정
      • 섹션 뒤 * : 모든 서브섹션
    • > : 실행 위치
    • AT > : 초기값 위치
1
2
3
4
5
SECTIONS {
    .data : {
        *(.data*)
    } > RAM AT > FLASH
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.