[임베디드 스케치 요약 및 정리] 1. HW Analyse

Embedded June·2022년 12월 10일

임베디드스케치

목록 보기
2/5
post-thumbnail

'임베디드 스케치'의 1번째 요약 및 정리는 임베디드 시스템 속 HW 컴포넌트에 대한 설명이며 원본 교제의 다음 부분을 포함합니다.

  • Chapter 2. HW Analyse

[※] 표시와 함께 존댓말로 적힌 문장은 책에는 없으나 부가설명이 필요한 경우 구글링을 통해 제가 추가 학습한 내용입니다!


1. CPU & Co-porcessor & Cache

  • 회사를 MCU라고 생각하고, 사장실을 Processor라고 생각하면, 사장님이 Core다. 회사에 따라 사장님이 여러 명인 경우가 있다. 사장님 안에는 다양한 장기(레지스터 뱅크, ALU, 곱셈기, Shifter, PSR 등)가 있다.
  • CPU는 Core, Co-processor, MMU(Memory Management Unit), Cache 등으로 구성돼있다. CPU와 각종 peripheral controller들이 모여서 하나의 MCU를 구성한다.
  • CPU가 특정 controller에 신호를 보내면 연결된 peripheral이 동작하는 구조다. 이때 신호의 방향은 신호를 요청한 쪽인 host를 기준으로 부르므로 CPU→Peripheral은 ‘output’, CPU←Peripheral은 ‘input’신호라고 표현한다.
  • ARM 프로세서는 하버드 아키텍처(Harvard Architecture)를 사용하고 있으므로 instruction cache와 data cache가 따로 분리돼있다. 따라서 instruction cache를 읽을 때 동시에 data cache에 접근할 수 있기 때문에 성능면에서 유리하다.
  • ARM 프로세서는 여러 Co-processor를 가지고 있다. 이중 개발자가 가장 많이 다루게 되는 co-processor는 15번이며 CP15라고 부른다. CP15의 대표적인 역할은 다음과 같다.
    1. MMU 활성화/비활성화
    2. Cache 활성화/비활성화
    3. Endian 설정(Little/ Big) 등등

  • CP15 내부에는 CR, TTBR, DACR 같은 15개 내외의 레지스터가 있다.
  • 이중 1번 레지스터인 CR(Control Register)레지스터에는 I, C, M-bit가 있다. 이 bit를 설정해서 I-Cache, D-Cache, MMU를 활성화 또는 비활성화 할 수 있다.
  • Cache를 사용하기 위해서는 반드시 가상주소를 사용할 수 있어야 하므로 MMU를 먼저 활성화 해야한다.
  • CPU가 원하는 가상주소(Virtual Address, VA)를 MMU에 전달하면, MMU는 Page table을 참조해 대응하는 물리주소(Physical Address, PA)를 반환해 SDRAM에 접근해 read/write 한다.

  • ARM Core가 원하는 주소는 MMU에 의해 가상주소로 바뀌어 I-Cache와 D-Cache를 참조한다.
  • 만일 찾는 주소가 cache의 entry에 있다면 ‘hit’이므로 core는 바로 원하는 값을 얻을 수 있다.
  • ‘Miss’라면, 메모리에 접근해서 원하는 값을 찾아와 cache에 새로운 entry로 삽입한다.
  • ARM Core는 D-Cache에 저장할 때 두 가지 ‘쓰기 정책(Write Policy)’ 중 하나를 사용한다.
    1. Write Through: Cache의 내용과 SDRAM의 내용은 항상 일치해 일관성(Consistency)을 유지한다. Cache값이 변경되면, 변경사항은 SDRAM에도 적용된다.
    2. Write Back: 약간의 일관성을 포기하고 우선 cache값만 변경한다. 변경된 cache 내용은 ‘Write Back PA TAG RAM’이라는 버퍼에 저장된다. 버퍼가 가득찰 때 SDRAM에 write한다.
  • [※] Cache thrashing과 associative cache 그리고 policy(write, replacement, allocation)에 대한 내용이 아주 살짝 언급됩니다. 이 부분은 운영체제(OS)에 대한 부분을 복습해서 개인적으로 학습하도록 합니다.

2. Flash memory

2.1. NOR Flash

  • NOR 플래시 메모리는 주로 프로그램을 구동시키는 실행 바이너리를 내장하고 있다.
  • CPU는 NOR 플래시에 든 바이너리를 바로 실행할 수 있다. CPU와 address bus, data bus가 연결돼 원하는 주소를 지정해서 데이터를 바로바로 접근할 수 있기 때문이다.

[※] 원문에는 어떤 NOR Flash 회로도와 데이터시트를 봤는지 언급이 없습니다. 따라서 원문을 보면 내용이 잘 이해가 안 갑니다. 따로 원문 내용에 일치하는 회로도와 데이터시트를 포함했습니다.

NOR Flash 동작 ① : Erase (지우기)

TMP92CF29A 회로도

512KB 5V NOR Flash - ATMEL AT49F040A 中

  • 데이터시트에는 지우기 동작을 위해 CPU가 NOR Flash에 전달해야 할 일련의 주소와 데이터값들이 명시돼있다.
  • 6-cycle에 걸쳐서 명시된 주소에 데이터를 전송하면 지우기 동작이 수행된다.
  • 이때 회로도를 보면 MCU의 데이터핀이 1칸씩 밀려서 A1핀이 NOR 플래시의 A0핀에 연결된 것을 확인할 수 있다.
  • NOR 플래시 입장에서 555주소라고 인식하려면 MCU는 어떻게 주소를 줘야 할까?
    • 0x555 = 0101 0101 0101이다. 이 주소를 왼쪽으로 1번 shift 하면 1010 1010 1010이다.
    • 1010 1010 1010 = 0xAAA이다. 따라서 MCU가 0xAAA를 가리키면 NOR flash는 0x555라고 이해한다.
    • 한 번 더 왼쪽으로 1번 shift 해보자. 0101 0101 0100 = 0x554다.
    • 따라서 MCU가 0x554를 가리키면 NOR flash는 0xAAA라고 이해한다.
  • [※] 그러므로, 데이터시트와 회로도를 반드시 참고해서 현재 어떤 플래시를 사용하고 있는지, Core와 어떻게 연결돼있는지 먼저 확인해야 합니다.
Data.Set 0xAAA %w 0xAA // 1st cycle
Data.Set 0x554 %w 0x55 // 2nd cycle
Data.Set 0xAAA %w 0x80 // 3rd cycle
Data.Set 0xAAA %w 0xAA // 4th cycle
Data.Set 0x554 %w 0x55 // 5th cycle
Data.Set 0xAAA %w 0x10 // 6th cycle
  • HW 디버거로 위와 같이 6-cycle에 걸쳐 특정 주소로 데이터를 보내면 ‘Chip Erase’ 동작이 수행된다.
  • 이후 NOR 플래시 메모리를 덤프 해보면 모든 값이 0xFFFF로 보여, 정상적으로 동작이 완료됐음을 알 수 있다.
  • 만일 erase 동작을 했는데도 덤프 해보니 값이 지워지지 않는다면, NOR 플래시 내부적으로 개발자의 실수를 방지하기 위한 ‘Lock’이 걸려있을 가능성이 있다. 데이터시트를 참고해 ‘Unlock’ 기능이 있는지 확인하고 unlock command를 보낸 뒤 다시 erase 해보자.

NOR Flash 동작 ② : Write (쓰기)

  • Erase에서 다뤘던 설명과 마찬가지로 이번에는 4-cycle에 걸쳐서 특정 주소에 특정 데이터값을 전달함으로써 NOR 플래시의 원하는 주소에 write할 수 있다.
  • 1~3-cycle은 write을 하기 위한 준비단계고, 마지막 4th cycle에 원하는 주소와 데이터값을 특정할 수 있다.

  • 주의할 점은 NOR이든 NAND든 플래시 메모리는 Write 전에 반드시 Erase를 해야 한다는 점이다.
    • [※] Write 동작은 bit를 1에서 0으로 변경하는 기능밖에 하지 못하기 때문입니다. 이해에 도움이 되기 위해 플래시 메모리의 구조와 동작원리를 간단히 설명하겠습니다. 플래시 메모리의 1개 memory cell의 정보는 ‘floating gate’라는 곳에 전자가 full인지(= 0) empty인지(= 1)로 판단합니다. Write(또는 Program)은 ‘control gate’에 높은 전압을 인가해 tunneling(터널링) 현상을 발생시켜 ‘floating gate’에 전자를 채워넣어 0으로 바꾸는 기능만 합니다. 따라서 이미 0인 곳에 1을 write 해봤자 소용이 없습니다. 결과적으로 write 전에 erase를 해서 모든 bit를 1로 초기화해야만 올바르게 모든 bit를 write 할 수 있습니다. (NAND 플래시라면 block 단위로 erase한 뒤 page 단위로 write 하는거고, NOR 플래시라면 chip 또는 sector 단위로 erase한 뒤 bit 단위로 write 합니다 ㅎㅎㅎ)
void program_byte(void) {
	addr16a = (unsigned short*) (*parameter + 0xAAA);
	addr16b = (unsigned short*) (*parameter + 0x554);
	*addr16a = 0xAA; // 1st cycle
	*addr16b = 0x55; // 2nd cycle
	*addr16a = 0xA0; // 3rd cycle
	*addr16Target = 0x1234 // 4th cycle = program
}
  • C프로그램으로 만들면 위와 같다. 이후 HW 디버거로 덤프해보면 *addr16Target으로 지정한 주소에 0x1234가 write 된 것을 확인할 수 있다.

NOR Flash 동작 ③ : Read (읽기)

  • 읽기 동작은 별다른 선행작업 없이 특정 주소에 대해 요청하기만 하면 바로 데이터를 받아볼 수 있다.

2.2. NAND Flash

  • NOR 플래시와 달리 NAND 플래시는 내부에 저장된 메인 바이너리를 CPU가 바로 동작시킬 수 없다.
    • NAND는 NOR과 달리 address/ data line이 CPU와 연결돼있지 않으며 핀도 따로 없기 때문이다.
    • 그만큼 소형화가 가능하기 때문에 NAND 플래시는 대용량의 데이터 저장용으로 많이 사용되고 있다.
  • CPU가 메인 바이너리를 실행하기 위해서는 반드시 NAND 플래시에 있는 바이너리를 SDRAM으로 복사해야 한다. 이 작업을 ‘부트로더’가 수행한다.
    • 보통 NAND 플래시를 지원하는 ARM 프로세서가 탑재된 MCU는 CPU 내부에 internal RAM(iRAM)을 가지고 있는데 여기에 부트로더가 저장된다.
  • 부팅과정을 정리하면 다음과 같다.
    1. 임베디드 시스템에 전원이 인가된다.
    2. CPU는 현재 탑재된 스토리지가 어떤 플래시 메모리인지 판단한다. (NOR ? NAND ?)
    3. NAND 플래시 메모리라면, NAND controller가 iRAM으로 부트로더를 복사해 넣는다.
    4. CPU는 iRAM에 저장된 부트로더를 실행한다.
      부트로더는 NAND 플래시에 저장된 메인 바이너리를 SDRAM으로 복사한다.
    5. CPU는 SDRAM에 저장된 메인 바이너리를 실행해 부팅한다.

NAND Flash Pin-map

삼성 K9F5608D0D 32MB NAND Flash memory 데이터시트 中

삼성 K9F5608D0D 32MB NAND Flash memory 데이터시트 中

  • ALE (Address Latch Enable): NAND의 몇 번째 페이지인지 알려주기 위해서 필요하다.
    • [※] ALE는 address 역할을 할 bit들이 모두 준비가 됐는지 확인한 뒤 보내는 트리거 역할을 합니다.
    • [※] I/O핀들 모두가 동시에 전압이 인가되지 않고 정말 아주 짧은 순간이지만 어떤 핀은 먼저 전압이 인가되고 어떤 핀은 나중에 인가됩니다.
    • [※] ALE가 없다면, 그 짧은 순간 사이에 먼저 주소를 보내버려 올바른 페이지를 지정하지 못하는 오류가 발생할 수 있습니다. 따라서 address를 보낼 준비가 모두 됐는지 확인하고 발사하는 트리거 역할을 합니다.
  • CLE (Command Latch Enable): 지우기, 쓰기, 읽기와 같은 명령어를 보내기 위해 필요하다.
    • [※] 존재 이유는 ALE에서의 추가설명과 동일합니다. 트리거 역할을 합니다.
  • [※] CE, RE, WE: Enable 핀입니다. 각각 chip이 동작하는지, Read가 가능한지, Write가 가능한지 여부를 알려줍니다.

NAND flash 구조와 특징

  • NAND 플래시는 내부적으로 Device > Plane > Block > Page 단위로 구성된다.
    • [※] 위 그림을 보면, 1 Page는 512Byte(0.5KB)에 배드블럭 여부 또는 에러감지를 위한 ECC용도로 16Byte를 추가한 528Byte입니다. 1 Block은 32개 page로 구성되니 약 16KB입니다. 그런 block이 2,048개가 모인게 이 NAND 플래시 메모리(=device)이므로 이 메모리는 32MB NAND 플래시 메모리네요.
  • NAND 플래시에선 read, write은 page 단위로, erase는 block단위로 이뤄진다.
    • [※] Erase만 block 단위로 이뤄지는 데는 2가지 이유가 있습니다.
    • [※] 1. 반도체 공정 상 하나의 block은 같은 substrate(기판)를 공유하기 때문입니다. Erase는 control gate에 강한 역전압을 걸어 floating gate에 갇혀있던 전자를 substrate로 내보냄으로써 이뤄집니다. 즉, 같은 substrate에는 동일한 전압이 인가된다는 뜻이지요. 따라서 동일 substrate를 공유하는 block의 내부 전자들이 모두 빠져나와 데이터가 지워집니다.
    • [※] 2. 설령 page 단위로 한 row에 전압을 인가할 수 있다고 하더라도 ‘이론적으로만’ 가능하고 실제로는 불가능합니다. 인가되는 전압이 다른 row에도 영향을 미쳐 substrate를 ground 보다 높은 전위를 가지게 만듭니다. 따라서 erase 하기 위해서는 더 높은 역전압을 걸어줘야 하고 이는 주변 row에 더 많은 영향을 주는 악순환에 빠지게 되며 소자를 손상시키는 원인이 됩니다.

NAND flash 동작 (Erase, write, read)

  • NAND 플래시의 동작은 ‘Command Setup + Address + Command End’로 구성된다.
    • Erase는 0x60 + addr + 0xD0,
      write(program)은 0x80 + addr + 0x10,
      read는 0x00(0x01) or 0x50 + addr로 구성된다.
    • 주소는 먼저 열을 지정한 뒤에 행을 지정해 특정 page를 선택할 수 있다.
  • [※] 상세한 동작 순서는 데이터시트의 타이밍도를 참고하면 됩니다. (원문에는 HW 디버거와 간략한 C 소스도 소개하는데, 실제 소스코드에서 일부를 가져오신듯 해 코드만 봐서는 뭐가 뭔지 파악하기 어려워 생략하겠습니다.)

3. SDRAM

  • 역할: 프로그램이 실행되는 동안 필요한 데이터를 플래시메모리에서 복사 후 저장해서 CPU가 빠르게 접근할 수 있도록 돕는다.
  • 특징: 전원이 꺼지면 저장된 데이터가 모두 사라지는 휘발성 메모리다.
    • [※] 단일 DRAM memory cell에는 캐패시터가 있습니다. 이 캐패시터에 전자가 있는지 없는지 여부로 데이터의 유무를 결정합니다. 외부 전원이 인가되지 않으면 캐패시터는 누전(방전)되므로 데이터가 사라지게 됩니다.
  • 어떤 임베디드 시스템이든 SDRAM의 시작 주소와 크기를 알기 위해 반드시 address map을 우선 파악해야 한다.
  • Memory address map을 보니 SDRAM의 시작 주소가 0x3000_0000임을 알 수 있고 마지막 주소는 0x3800_0000 이므로 SDRAM의 크기는 0x0800_0000이다. 즉 8×16^6 = 8×2^24 = 128×2^20 = 128MB임을 알 수 있다.
  • 우리같은 사람은 이렇게 address map을 읽고 SDRAM의 시작주소와 크기를 파악할 수 있지만, CPU는 따로 알려주지 않는 이상 모른다. 따라서 CPU에게 SDRAM의 시작주소, 크기, 타이밍 등 기본사항을 따로 알려줘야만 한다. 이 작업을 ‘메모리 컨트롤러 설정’이라고 부르며 SDRAM을 사용하기 전에 반드시 수행해야 한다.
  • 메모리 컨트롤러 설정은 ‘startup.s’ 어셈블리 파일에서 한다. 이에 대한 설명은 다음 챕터에서 자세하게 다룬다.
  • [※] 데이터 라인을 DQ라고 부르는 이유: 우리는 메모리를 배울 때 가장 먼저 플립플롭(Flip-Flop)을 배웁니다. 플립플롭은 input을 ‘D’, output을 ‘Q’라고 부르는데, 현대 메모리의 데이터 라인은 양방향이므로 DQ라고 부릅니다.

4. JTAG과 Serial Port

  • 최근 MCU는 워낙 작아 내부에 ball 형태로 숨겨져 있기 때문에 개발자가 디버깅하기 어렵다.
  • 이때 JTAG은 개발자가 시스템 외부에서 신호와 각종 데이터값을 측정할 수 있도록 돕는 디버깅 및 플래시 다운로더 역할을 하는 장치다.
    1. 디버깅용
      • 디버깅은 printf()를 찍어보면서 시리얼포트로 출력되는 메시지를 확인해보는 SW디버깅과 직접 코어에 핀을 연결해서 원하는 때 halt 및 running을 제어하고 각종 신호와 데이터를 직접 확인해보는 HW디버깅으로 분류된다.
      • SW디버깅은 디버깅을 위한 별도의 비용이 들지 않고 간단하다는 장점과 printf() 함수를 사용해야 하고 매번 컴파일을 하고 플래시 다운로드를 해줘야 한다는 단점이 있다.
      • HW디버깅은 편리하고 개발 기간을 단축한다는 장점과 비용이 들며 따로 HW 디버거 사용법을 배워야 한다는 단점이 있다.
    2. 플래시 다운로더용
      • C 소스파일을 컴파일하면 바이너리가 만들어진다.
      • 이 바이너리를 플래시 메모리에 다운로드 하기 위해서는 JTAG 포트를 사용해야 한다.
  • JTAG 포트는 ‘TDI’(입력신호), ‘TDO’(출력신호), ‘TMS’(모드선택), ‘TCK’(클럭), ‘TRST’(리셋) 5가지를 기본으로 가지고 있고 HW 디버깅까지 지원하면 ‘Vref’, ‘GND’, ‘nSRST’ 3개 포트를 추가로 가진다.
  • 시리얼 포트(Serial Port)는 Serial, UART, COM 등 다양한 이름으로 불리는데 주로 디버깅용이나 바이너리 전송용으로 많이 활용된다.
  • 시리얼 포트는 RX(Receive), TX(Transport), GND 핀을 가지고 있고 시리얼 통신을 제어하는 IC가 포함된다.
  • 시리얼 포트를 수행하기 위해서는 MCU 내부에 있는 ‘Serial Control Register’를 설정하면 된다.
  • 만일 개발하고 있는 MCU에 시리얼 포트가 없다면 어떻게 해야 할까? Co-processor를 사용하면 된다.
    • 15번 Co-processor인 C15의 14번 레지스터인 P14는 시리얼 메시지를 출력하는 기능을 수행한다. 이때 일반적인 방법으로는 내부 데이터를 확인할 수 없기 때문에 HW 디버거가 필요하다.
    • 평소 RX, TX로 시리얼 통신하듯 P14에 RX, TX 신호를 넣어준다.
    • 이때 내부적으로 Co-processor 관련 표준 명령어인 MCR, MRC로 P14에 값이 오고간다.

profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글