임베디드 공부하면서 하드웨어, 부트로더, 커널 이미지, 디바이스 드라이버 구현 등 정리

 

 

임베디드 정리.pdf
0.73MB

 

나빌로스를 한답시고 보면서

정작 어셈블리 공부를 제대로 안하고 이상한걸 보고 있었다가 다시 돌아왔다.

 

 

너무 깊이 배울 필요는 없어서 자료 찾다보니

kldp의 자료가 적당할거같고 

mov는 어떻게 쓰고, jmp는 어떻게 쓰고 하는 자질구래한 내용들 많은 강좌보다는

섹션이 뭐고 다 포함하고 

이 내용을 따라했다.

https://wiki.kldp.org/HOWTO/html/Assembly-HOWTO/x848.html

 

소개

마침내 때가 왔다. 여러분이 아직도 이 문서를 읽고 있으며, 여전히 어셈블리로 무언가를 만들겠다는 광기어린(!) 생각을 가지고 있다면 (여기까지 읽은 사람이라면, 정말 어셈블리 팬임에 틀림

wiki.kldp.org

 

 

 

 

 

프로그램 레이아웃

- .text 섹션 : 작성한 코드

- .data 섹션 : 초기화된 데이터 

- .bss 섹션 : 초기화 되지 않은 데이터

 

 

NASM 코드 helloworld

 

section		.data						; 섹션 .data 선언

msg		db		"hello, world!", 0xa		; 출력할 문자열
len		equ		$ - msg				; 문자열 길이

section		.text						;여기부터 .text 섹션

	global _start						;ELF링커나 로더에게 프로그램 엔트리포인터알려줌.보통 _start

_start:
    mov		edx, len					; 시스템콜의 세번째 인수, 출력할 메시지 길이 가져옴
    mov		ecx, msg					; 시스템콜의 두번째 인수, 출력할 메시지 포인터 가져옴
    mov		ebx, 1						; 시스템콜의 첫번째 인수, 파일 디스크립터 전달.
    mov		eax, 4						; eax 레지스터에 시스템 콜번호 전달. 4번은 sys_write
    int		0x80						;커널 호출

; 출력 완료 후 exit 호출
    mov		ebx, 0						; exit 코드로 0을 준다.
    mov 	eax, 1						;시스템 콜 1번(sys_exit)
    int		0x80						;커널 호출

 

 

실행 결과

 

 

 

 

kldp 내용만 봐도 뭔지 대강알긴 하겠지만 설명이 좀 부족해보인다

 

여기보다는 이쪽 튜토리얼이 예제나 설명이 자세하다.

https://asmtutor.com/

 

 

NASM Assembly Language Tutorials - asmtutor.com

~$ nasm -f elf helloworld-input.asm ~$ ld -m elf_i386 helloworld-input.o -o helloworld-input ~$ ./helloworld-input Please enter your name: Daniel Givney Hello, Daniel Givney

asmtutor.com

 

 

lesson 1 예제를 보면

 

직접 어셈블리어로 하드웨어를 제어하고 싶을때 EAX 레지스터에다가 함수번호(오퍼레이션 코드)를 넣고,

나머지 레지스터에다가 필요한 값을 넣은 다음에, int 명령으로 소프트웨어 인터럽트를 주면 지정한 함수가 호출된다.

 

sys_exit()는 EAX=1을

sys_write()는 EAX=4 그리고 EBX, ECX, EDX에 필요한 값을 넣어주면 된다.

 

; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
 
SECTION .data
msg     db      'Hello World!', 0Ah     ; assign msg variable with your message string
 
SECTION .text
global  _start
 
_start:
 
    mov     edx, 13     ; number of bytes to write - one for each letter plus 0Ah (line feed character)
    mov     ecx, msg    ; move the memory address of our message string into ecx
    mov     ebx, 1      ; write to the STDOUT file
    mov     eax, 4      ; invoke SYS_WRITE (kernel opcode 4)
    int     80h

 

위에서 설명한대로

SECTION .data

데이터 섹션 그러니까 초기화 되는 변수 부분을 나타내는데

msg라는 변수에다가  'hello world'를 담는건 알겠지만 왼쪽에 db와 우측에는 ,0ah가 존재한다.

 

 

이게 뭐소리인가 찾아보니

db는 바이트 데이터 형을 의미한다하고,

다른데도 찾아보니 msg에 바이트 단위 배열로 넣기 위한 자료형 선언한다는 의미라한다.

ref : https://velog.io/@kyoung99u/%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC-%EC%96%B8%EC%96%B4

 

[Assembly] 어셈블리 기초

변수 어셈블리 프로그램에서 변수를 어떻게 사용할까? 어셈블리 프로그램에서는 타 프로그램과 같이 변수를 정의하여 사용하는데, 변수는 변수명과 데이터형, 초기값을 가진다. 0806 어셈블리언

velog.io

 

 

그러면 ,0ah는

쿼라에 질문올라온게 있긴한데

답변한 사람 말로는

0xA는 라인피드

0xD는 캐리지 리턴이라고 설명하고 있다.

그러면 0xAh는 뒤에 h가 붙어있는데 이건 뭔소린가 싶긴한데 설명이없다.

 

https://www.quora.com/What-is-the-meaning-of-0ah-0dh-in-assembly-language-for-displaying-any-message

 

What is the meaning of 0ah, 0dh in assembly language for displaying any message?

Answer (1 of 4): As everyone else answered, 0xA linefeed (\n), 0xD carriage return(\r), but have you wondered why is this two different notion in assembly? why did the carriage return and line feed was different back then ?? in high level languages when we

www.quora.com

 

 

여길 보니 0ah가 아스키 코드로 라인피드가 맞다고 하는걸 보니 답변자가 빠트린가 보다

https://www.sluiceartfair.com/2018/contributing/what-is-0ah-in-assembly/

 

What is 0AH in assembly? – Sluiceartfair.com

What is 0AH in assembly? 0Ah is the hexadecimal constant for the Line Feed character in ASCII, often abbreviated LF. 24h is the hexadecimal constant for the ‘$’ character in ASCII. What is carriage return in assembly language? Carriage Return Character

www.sluiceartfair.com

 

int 80h는 소프트웨어 인터럽트를 발생시키는 어셈블리 코드라고한다.

https://second.wiki/wiki/int_80h

 

Int 80h

Int 80h

second.wiki

 

 

일단 어셈블리와 링커를 돌린후 실행하보면 생각한데로 출력은 잘되는데 세그먼테이션 폴트가 뜬다.

이 문제는 다음 레슨에서 설명하는데

~$ nasm -f elf helloworld.asm
~$ ld -m elf_i386 helloworld.o -o helloworld
~$ ./helloworld
Hello World!
Segmentation fault

 

 

 

 

레슨 2 : 프로그램을 제대로 종료시키자

레슨 1에서는 어셈블리어로 sys_write 시스템 콜을 써서 출력을 시켰는데 이번 레슨에서는 sys_exit에 대해서 보자

설명이 쭉 있는데, 결국에는 모든 프로그램은 메모리를 공유하고 있다보니 global _start에서부터 순차적으로 실행해주는데 어디서 끝낼지 커널한태 알려주지 않으면 구현하지 않은 다음 주소에 있는것도 실행하게 되고 이게 세그먼테이션 폴트의 원인이 된다고 한다.

 

sys_exit를 쓰기 위해선

EBX에 0을 전달하도록 0을

EAX에 sys_exit를 호출하는 1을 넣으면 되서 코드는 이렇게 된다고 말한다.

; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
 
SECTION .data
msg     db      'Hello World!', 0Ah
 
SECTION .text
global  _start
 
_start:
 
    mov     edx, 13
    mov     ecx, msg
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    mov     ebx, 0      ; return 0 status on exit - 'No Errors'
    mov     eax, 1      ; invoke SYS_EXIT (kernel opcode 1)
    int     80h

 

정상적으로 프로그램을 종료시켜서인지 세그먼테이션 폴트가 뜨지 않고 잘 끝낫다!

 

 

나빌로스 하면서 링커스크립트를 좀 봐야할거같아서 찾아보니까 이 자료가 적당해보인다.

 

http://korea.gnu.org/manual/release/ld/ld-mahajjh/ld_3.html

 

Using LD, the GNU linker - Linker Scripts

Every link is controlled by a linker script. This script is written in the linker command language. 모든 링크 과정은 링커 스크립트가 조정한다. 이 스크립트는 링커 명령 언어로 쓰여진다. The main purpose of the linker script

korea.gnu.org

 

 

링커

- 여러 오브젝트 파일을 합쳐서 실행 파일로 만들며, 각 오브젝트 파일은 섹션들을 갖고 있음.

 

 

SECTION 명령어 개요

- 링커 스크립트의 유일한 명령어로 코드, 초기화된 데이터, 초기화되지 않은 데이터가 있으면 .text, .data, .bss 섹션이 됨

 

 

 

링커 스크립트 예시

- 코드가 0x10000에 로드되고, 데이터는 0x800 0000에서 시작하는 경우'

- 첫째 줄에선 위치 카운터 '.'의 값을 0x1 0000로 설정.(처음에는 0이며, 설정안할시 현재 값)

- 둘째 줄에선 출력섹션으로 .text 정의하면서, ':' 뒤에 있는 *(.text)는 모든 입력 파일의 .text 섹션을 나타냄.

  + 출력 섹션 '.text'를 정의 할 때, 위치 카운터가 '0x1 0000'이므로 출력(실행) 파일의 .text 섹션 주소를 '0x1 0000'이 됨.

- 셋째 줄에선 위치 카운터 값을 '0x800 0000'로 설정

- 나머지 줄에선 .data, .bss 섹션 정의.

  + 출력 섹션 .data의 주소는 0x800 0000으로 설정

  + .bss의 주소는 .data 섹션의 바로 뒤에 위치

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.data) }
}

 

 

 

 

SECTIONS 명령어

- 입력 섹션의 내용을 어떻게 출력 섹션에 매핑할지. 출력 섹션의 메모리 상 위치를 어떻게 할지 정의

- sections-command whdfb : entry 명령어, 심볼 입력, 출력 섹션 설명

SECTIONS
{
  sections-command
  sections-command
  ...
}

 

 

출력 섹션 형태

section [address] [(type)] : [AT(lma)]
{
  output-section-command
  output-section-command
  ...
}

 

 

 

 

ARM 아키텍처

- 아키텍처 = 명령어 체계 자체(명령어들을 instruction set 혹은 어셈블리어라 함)

- 아키텍처 기반으로 CPU 코어 설계

- 하나의 아키텍처로 여러 가지 코어 설계 가능

- ARM Cortex 시리즈 : A, R, M

* ARMv1 -> ARMv2 : MUL 추가

* ARMv2 -> ARMv3 : 프로세스 캐시 추가

 

ARM CPU

- STM32F103 : ARMv7-M 아키텍처 구조, ARM Cortex-M3 코어 사용

- Exynos4412 : ARMv7-A 아키텍처 구조, ARM Cortex-A9 코어 사용

 

 

 

ARM 코어 레지스터

- 동작 모드 : User, FIQ, SVC, Abort, IRQ, undefined

- 일정 조건에 따라 자동으로 바뀜

- User -> IRQ -> User : 펌웨어로 제어

- System : CPU가 특수 상황시 전환

- User : R0 ~ R15의 16개 + CPSR 레지스터 사용

- SVC(supervisor), Abort, IRQ, Undefined : R13, R14, SPSR 레지스터 사용

- 총 37개 레지스터 사용 = 17 + 8 + 3 + 3 + 3 + 3

- 동작 모드 별 레지스터

 

 

ARM 명령어 체계

- ARM 모드 : 32비트 체계

- Thumb 모드 : 16비트 명령어 체계, 일부 레지스터만 사용, 컴파일 시 Thumb 전용 컴파일러나 옵션으로 선택

 

ARM 코어 레지스터

- R15 : 프로그램 카운터

- R14 : 링크 레지스터, 서브루틴 함수서 돌아갈 주소

- R13 : 스택 포인터

- CPSR current program status register 

- SPSR saved program status register : cpsr 레지스터 값을 모드마다 백업용으로 저장하기 위해 사용.

 

 

 

명령어 집합 종류

- 분기 명령 : 함수, if then else 구조

- 데이터 처리 명령 : 프로세서 내부 데이터 이동, 산술, 논리, 비교 명령어

- 상태 레지스터 접근 명령 : CPSR, SPSR 제어 명령어

- Single register load and store instruction : 프로세서 메모리 간 단일 데이터 전송명령

- 다중 레지스터 로드 앤 스토어 레지스터 : 프로세서 메모리 간 다중 데이터 전송 명령

- 코프로세서 명령 : coprocossor(ARM core에서 처리못하거나 확장기능 구현시 사용하는 별도 프로세서) 제어 명령

 

ARM 명령어 집합 포멧

- 명령어 종류 별로 다른 형식

 

 

Thumb 명령어 집합

- 16비트 명령어 체계

- 보통 ARM 코드에 비해 30% 메모리 절약

- BX, BLX 명령으로 ARM 과 Thumb 상태 변환

C 코드 최적화의 필요성

- 임베디드 CPU 한계 : 저전력, 저가로 성능 제한

 -> 제한된 자원으로 좋은 성능을 내기위해 필요

+ CPU 구조, 어셈블러, 컴파일러에 대한 이해 필요

 

일반적인 최적화 방법

- 나눗셈, 나머지 연산을 피함

- 반복을 최적화

- 메모리 보다 빠른 레지스터 사용

- 함수 호출 방식을 최적화

 

AVR core 구조

- 폰노이만 : 데이터, 프로그램 메모리를 하나의 버스로 사용

- 하버드 : 데이터, 프로그램 메모리를 분리 -> 동시에 명령어와 데이터를 읽고쓰기 가능

 -> AVR core는 하버드 아키텍처를 따름

 

CPU 연산 과정

- fetch :  메모리서 명령어 가져옴

- decode : 명령어에 있는 레지스터 해석

- execute : 실행

 

AVR core

- single level pipelining 사용

- 한 명령어가 실행되는 동안 다음 명령어가 pre fetch됨

 -> 매 클럭 사이클마다 명령어가 실행

- 32개의 8비트 범용 레지스터를 가지고 있음. 이를 잘 활용해서 최적화

- R0 ~ R25 : 데이터 레지스터로 사용

- R26 ~ R31 : 주소 레지스터로 사용

 

 

 

AVR 컴파일러

- AVR studio : gcc 사용. avr-gcc

- code vision : 상용 컴파일러 사용

 

 

AVR GCC 최적화 옵션

- 옵션에 따라 코드 크기, 성능 최적화 레벨 지정 가능

  ex) -O0, -O1, -O2, -O3, -Os

    => avr-GCC -O3 main.c

  *-O0 는 최적화 x, -O3은 가장 높은 성능, -Os는 코드 사이즈 가장 줄임

 

 

 

데이터에 따른 최적화

- 타입에 따른 최적화 : 가능한 크기가 작은 타입 사용

- 범위에 따른 최적화 : 같은 크기더라도 전역보다 지역변수가 유리.

* atmega128에선 전역변수는 SRAM(16비트 어드레스모드)에 할당.

   -> 변수 크기가 8비트 크기여도 16비트 크기 어드레스로 할당하여 공간 낭비

 

static을 이용한 최적화

- 전역 변수에 static 사용시 선언된 파일 내에서만으로 범위 제한.

- 지역 변수의 경우 static 사용 안하는것이 좋다.

 

어셈블리어를 사용한 최적화

- 적당히 사용하면 좋으나 코드 이식성을 떨어지게함.

- 인라인 어셈블리 : C코드 일부를 어셈블리어로 사용

ex : #define sei() __asm__ __volatile__("sei"::)

- __asm__ : 인라인 어셈블리를 의미하는 지시어

- __volatile__ : 최적화에 의해 없어지는걸 방지

- sei : SREG 레지스터의 I flag(전역 인터럽트 플레그)를 셋

  일반 인라인 어셈블리
C코드 #include <avr/io.h>
void enable_usart_rx(void)
{
  UCSR0B |= 0x80;
};

int main()
{
  enable_usart_rx();
  while(1){
  }
}
#include <avr/io.h>
#define enable_usart_rx() \
  __asm__ __volatile__(\
  "lds r24, 0x00C1" "\n\t" \
  "ori r24, 0x80" "\n\t" \
  "sts 0x00C1, r24" \
  ::)
int main()
{
  enable_usart_rx();
  while(1){
  }
}
AVR 코드 메모리 사용량 296bytes 226bytes
최적화 옵션 -Os -Os

 

Cycle Counter

- 어셈블리 명령어가 실행된 회수

- 실행이 끝난 후 값 = 총 실행된 명령어 회수

 

임베디드 시스템 개발

- PC랑 달리 용도가 정해지고, 가격, 전력을 고려해서 HW와 SW를 제한해야 함.

- 호스트 PC에서 타겟 디바이스에 맞게 컴파일 후 올려서 동작 시킨다

- Host PC에서 하는 일 : 개발 툴(교차 컴파일러, 디버거 등), 시뮬레이션을 위한 타겟 장치 시뮬레이터 등

- 부트로더 개발 : 타겟 장치에 전원 인가시 부팅 롬에서 가장 먼저 실행. HW 초기화, 커널 로딩, JTAG 인터페이스로 설치

- 커널과 파일 시스템 : 호스트 PC의 개발 환경에서 만듬, 이미지 형태로 부트롬이나 다른 곳에 저장. 

- 임베디드 응용프로그램 : 커널과 파일 시스템위에서 동작.

 

 

 

부트로더

- HW 초기화, OS 커널 메모리로 로드하는 펌웨어

- LILO Linux LOader : 특정 파일시스템에 의존 x, 최대 16개 이미지 시동시 선택 가능, MBR이나 파티션 부트섹터에 위치

- GRUB GNU GRUB : GNU의 부트로더, 동적으로 커널 인자 조정 가능, 다양한 실행 파일 지원, 명령줄 인터페이스 제공

- BLOB BootLoader OBject : 선택 부팅 가능, MBR에서 동작하는 다른 부트로더와는 달리 플레시 메모리 0블록에서 동작

- U-BootUniversal Bootloader : PPC와 ARM 기반의 임베디드 부트로더, ARM, x86, MIPS 등 CPU 지원, 오픈소스

- NTLDR NT Loader : 윈도우 NT 시동 부트로더, 하드디스크 이외의 USB 플래시 드라이브 등 휴대용 장치서도 실행 가능

 

 

 

U-Boot Universal Bootloader

- 다양한 시스템에서 사용가능한 부트로더로 시리얼, 네트워크, USB, Flash 등 지원

- 다양한 아키텍처와 디바이스를 지원하므로 타겟 보드에 맞게 포팅 필요

- 동작 흐름 : Start.s 시작

   * Start.s : CPU 초기화(인터럽트 마스크, 클럭 설정), DRAM 초기화, 플래시 메모리 코드를 DRAM으로 다른 초기화작업

 

https://julrams.tistory.com/category/System%20Programming/Tips?page=4

 

U-boot 구성

- /api : API 코드, 예제

- /arch : 아키텍처 별 code, lib, 시작코드 start.S

- /common : 아키텍처에 독립적인 파일과 명령어

- /drivers : 외부 장치 드라이버들

- /fs : uboot의 파일 시스템 관련

- /include : 헤더  파일

- /net : network 관련

- build.sh : 빌드 스크립트

- Makefile : 빌드 설정 Makefile

ref : https://kergoo.wordpress.com/2017/04/09/u-boot-porting-guide/

 

 

주변장치 

1. UART와 USART

2. GPIO

3. JTAG, SWD

4. I2C(TWI)

5. PWM

6. SPI

7. Flash Memory

8. Ehternet

9. USB

10. CAN

 

 

7. Flash Memory

- 데이터 읽고 쓰는 비휘발성 메모리,종류 : Nand/Nor Flash Memory

- Nand Flash Memory : 싸서 대용량으로 많이 쓴다

- eMMC Embedded Multi Media Controller : Nand Flash Memory + 메모리 컨트롤러 + 멀티미디어 카드 + BGA 캡슐화

  => 데이터 전송 속도와 처리 량 개선하여 모바일 장치에서 많이 쓴다

 

8. Ethernet

- 이더넷.. OSI 7계층 데이터링크 인가, 물리계층인가 쯤에 있던거같은데 찾아보니 물리 계층이더라.

- MAC 주소로 호스트 간 데이터 주고받는 네트워크 약속, 유선은 이더넷, 무선은 802.11(와이파이)

* 물리 계층 : 신호와 배선 규칙(이더넷, RS-232C, 802.11),  데이터 링크 계층 : 프로토콜 형식 정의(MAC)

* 인터넷과 이더넷 ? : 인터넷은 네트워크(교통), 이더넷은 네트워크를 이루는 컴퓨터들의 통신 수단 중 하나(도로)란다.

ref: https://namu.wiki/w/%EC%9D%B4%EB%8D%94%EB%84%B7

 

이더넷 장치 블록 다이어그램

 

9. USB Universal Serial Bus

- 배경 : 인텔, 마소, IBM 등 주변장치와 PC 간 인터페이스 통일, 쉽고 빠르며 작은 인터페이싱을 위해 개발

- 특징 : 버스 자체 전원 공급(+5v, 500mA), 소형 커넥터, PnP 지원 등

ref : https://blog.daum.net/insopack77/23

 

 

- 용어 정리 ref : https://m.cafe.daum.net/banghakme/9XyX/167

   - USB 호스트 : USB 호스트 컨트롤러, USB 시스템 소프트웨어, 클라이언트로 구성하여 USB 디바이스 접근 제어.

   - USB 디바이스 : USB 인터페이스, USB 논리 디바이스, Function 으로 구성.

- USB 데이터 전송 구조

   - Client SW : OS와 USB 디바이스에 따라 제공되는 SW

   - USB System SW : OS에서 USB를 지원하는 SW

   - USB 호스트 컨트롤러 : 호스트 측 버스 인터페이스로 USB 디바이스를 호스트와 결합시켜주는 모든 SW/HW 

 

-  USB에 대한 추가적인 자세한 동작 원리는 아래 링크

ref : https://m.blog.naver.com/prnbada7/221215493534


USB 데이터 전송 구조

물리적인 버스구조

 

 

 

10. CAN Controller Area Network

- 배경 : 차량 내 ECU Electronics Control Unit 간 통신에 1:1 방식인 UART가 적합하지 않아 다중 통신용으로 개발.

- 용도 : 차량 내부 계측 제어 장비들간 직렬 통신할 수 있도록 개발된 네트워크.

- 특징 : 멀티 마스터 통신, 선 2개면 충분(CAN_high, CAN_Low), 잡음에 강함, 고속 원거리 통신 등

- CAN FRAME : SOF 시작비트, ID, Control 데이터길이, Data 데이터, CRC 오류 검출, ACK 오류없이 ok, EOF 끝비트

 

 

 

주변장치 

1. UART와 USART

2. GPIO

3. JTAG, SWD

4. I2C(TWI)

5. PWM

6. SPI

7. Flash Memory

8. Ehternet

9. USB

10. CAN

11. 무선 장치

 

 

 

1. UART Universal Asynchronous Receiver/Transmitter

- 범용으로 병렬 데이터를 직렬화 하여 비동기적으로 송수신하는 규격(인터페이스) (* 병렬 통신 : 버스)

- USB2Serial 디버그, 블루투스, Rs-232/422 등 용도로 사용

- RS-232, RS-422와 같이 사용됨(*UART는 직렬 통신 규칙, RS-232는 하드웨어 규칙)

ref : https://treeroad.tistory.com/entry/RS232%EC%99%80-UART

- 위 링크보다는 이게 더 정확한 설명인거 같다.

ref : https://ko.serial-cable.com/info/difference-of-uart-serial-and-rs232-serial-30244548.html

- USART의 경우 동기 직렬 통신도 지원

- 시작비트, 데이터 비트(5 ~ 8비트), 패리티비트(필수 x), 종료 비트로 구성

 

 

** TTL 레벨과 RS-232C 레벨

- TTL 레벨은 0v, 5v로 0,1 표현 <-> RS-232C 레벨은 +-5V 양, 음전압으로 표현하여 노이즈에 강인

ref : https://treeroad.tistory.com/entry/%EC%99%9C-TTL-%ED%86%B5%EC%8B%A0%EC%9D%B8%EA%B0%80

 

 

2. GPIO General Perpose Input Output 

- 범용으로 사용 가능한 입출력 포트

- 디스플레이, 센서, LCD, USB Host, CAN 등 통신 인터페이스로도 사용

- 아래의 링크는 UART GPIO로 시리얼 통신 예시

ref : https://codedosa.com/470

 

 

 

3. 디버그 인터페이스

- JTAG Joint Test Action Group : 플레시 메모리에 소스코드를 다운로드/업로드하는 경우, 디버깅 용도로 사용

  * TDI 테스트 데이터 입력, TDO 테스트 데이터 출력, TCK 테스트 클럭, TMS 테스트 모드, TRST 테스트리셋

- SWD Serial Wired Debug : 직렬 통신이다보니 클럭 SWCLK와 데이터 SWDIO 핀 2개 사용

 

 

 

 

4. I2C Inter Integrated Circuit(TWI Two Wire Interface라고도 함)

- 마이크로 프로세서와 저속 주변장치 간 통신을 위한 규격

- 양방향 선 2개 SCL Serial Clock과 SDA Serial Data 이용. 마스터-슬레이브 구성으로 동작

-> 하드웨어적으로 간단, 수 많은(최대 127개) 노드(슬레이브) 연결, UART와 달리 클럭을 사용해서 속도 안정해도됨

5. PWM 

- 한 주기당 펄스의 폭, 듀티비를 조절하여 만들어 낸 신호

- DC 모터 제어 뿐만 아니라 LED 밝기, 밸브, 유압, 기계 장치 등 많은 분야에서 사용

6. SPI Serial Peripheral Interface

- 모토로라에서 개발한 전이중 동기 통신 규격

- I2C 방식과 비슷하게 마스터-슬레이브 방식 다만 전이중 통신

- SCLK : 시리얼 클럭

- MOSI : 마스터 출력 슬레이브 입력

- MISO : 마스터 인풋, 슬레이브 아웃풋

- SS : 슬레이브 셀렉트

SPI 인터페이스와 데이터 포멧

 

 

 

 

5. 프로세서 아키텍처로 분류

- 프로세서 제조사 or IP 회사로 분류

- x86 : 인텔의 32비트 아키텍처 PC에서 많이 쓰임. 레지스터가 8개로 부족

- amd64 : amd에서 만든 x86을 확장한 64비트 아키텍처. 레지스터를 16개로 늘어남. 가상 메모리, 물리메모리 크게늘어남

- arm : 초기 저전력 soc를 만들다가 고성능 저전력 프로세서 설계   ex) cortex-A(응용어플)/R(rtos 최적)/M(mcu 최적)

   + ARM 설계를 따르는 프로세서 : 퀄컴 스냅드래곤, NVIDA 테그라, 삼성 엑시노스

- mips : 스탠포드에서 RISC로 개발. 비디오 콘솔, 멀티미디어 같이 높은 연산 처리가 필요한 곳에 사용.

 

 

ARM RISC

- 초기 ARM7/9/11 같은 저전력 프로세서 위주였으나 스마트폰 대중화후 고성능 Cortex 아키텍처 시리즈

- RISC 특징 : load-store 구조, 고정 길이 32비트 명령어, 주소 명령어 구조(1개 명령어는 2개 소스 주소 + 1개 목적지)

* 로드-저장 구조 : CISC에서 memory to memory(메모리서 레지스터로 가져와 메모리로 저장) 연산을 하는것과 달리 레지스터에 로드 저장, 메모리 사용 x

- ARM RISC

  - 32비트 프로세서여도 16비트 명령어 사용가능(Thumb 모드) -> 코드 크기 축소

  - 조건부 명령어 구조 : 모든 명령어에 조건부 추가 가능

  - 최적화된 레지스터 갯수: 일반 RISC CPU가 많은 레지스터를 사용해 공간 낭비, ARM RISC는 필요한 레지스터만 사용

 

 

어플리케이션 프로세서 AP

-  모바일 기기에 사용되는 프로세서로 PC에 사용되는것과는 다름. 스마트폰이 나오면서 OS, 게임, 멀티미디어가 중요해져 어플리케이션에 특화하는 쪽으로 설계되 AP라 부름.

- ex : 퀄컴 스냅 드래곤, 삼성 엑시노스, 엔디비아 테그라

퀄컴 스냅드래곤

 

 

ARM Cortex

- 초기 저전력 위주 ARM7/9/11 설계에서 용도별로 구분한 시리즈

- ARM Cortex-A : Non-RTOS와 어플리케이션에 특화된 프로세서

- ARM Cortex-R : RTOS와 실시간 시스템에 특화됨

- ARM Cortex-M : 저가, 저전력에 특화된 MCU

 

 

 

 

ARM 아키텍처

- 다시 정리하면 초기에는 저전력 프로세서 위주였으나 용도 별로 특화된 coretex 시리즈가 나옴

- ARM RISC : 32비트 프로세서에서도 16비트 명령어 지원(thumb 모드), 조건부 명령어, 최적 레지스터 수

시리즈 아키텍처 버전 코어 기능
ARM1 ARMv1 ARM1 캐시 x
ARM2 ARMv2a ARM2 곱샘 명령 추가, 4MIPS, 8Mhz
ARM3 ARMv2a ARM2a ARM 프로세서서 최초로 캐시 사용 4k, 7MIPS, 12MHz
ARM6 ARMv3 ARM60 최초 32비트 메모리 지원, 10 MIPS, 12MHz
ARM7 ARMv3 ARM700 8k 캐시, 40MHz
ARM7500FE Soc, FPA와 EDO 메모리 커트롤러 추가(FE), 56MHz
ARM8 ARMv4 ARM810 5단계 파이프라인, 고정된 예측 분기, 84MIPS, 72MHz
ARM9TDMI ARMv4 ARM9TDMI 5단계 파이프라인
ARM9E ARMv5TE ARM946E-S 향상된 DSP, 가변 메모리 밀착형 MPU
ARM11 ARMv6 ARM1136J-S SIMD(단일 명령어 다중 데이터), 8단계 파이프라인 532-665MHz

 

 

 

ARM Cortex-A 아키텍처

- 스마트폰에 적합한 고성능 아키텍처, 이 아키텍처 + 메모리 + 제어기를 한칩 SoC에 만들어 사용

시리즈 아키텍처버전 코어 기능
Cortex-A ARMv7-A Cortex-A5 저전력 초소형 프로세서, 8단계 싱글 파이프라인
    Cortex-A7 멀티코어, 1.2GHz (ex : 엑시노스 5410)
    Cortex-A9 저전력 최적 멀티코어 프로세서(많이씀) (ex:엔비디아 테그라2)
    Cortex-A15 Armv7-A 중 가장 고성능
    Cortex-A17 Big litttle 지원
  Armv8-A Cortex-A32 32비트 기반 가장 작은 공간, MCU 소형 임베디드 시스템 중 고성능
    Cortex-A35 64비트 Armv8-A
    Cortex-A65AE 차량용 멀티스레드 Cortex-A CPU
    Cortex-76AE 자율주행차 같은 안전 어플리케이션용
    Cortex-A77 5G 솔루션, 고성능

 

 

ARM Cortex-A9 프로세서

- ARMv7 + 다중 슈퍼스케일러, 비순차 추론 8단계 파이프라인을 이용한 고성능 프로세서

- 슈퍼 스케일러 파이프라인 : 최대 성능, 저전력

- Neon 엔진 : 미디어, 신호 처리 가속화 엔진

- 부동 소수점 처리장치 : 이전 ARM FPU 성능 2배 개선

- Thumb-2 : 기존 코드 성능을 유지하며 메모리양 최대 30% 절감

- Trust Zone : 보안 어플리케이션 안전 실행 보장

- L2 캐쉬 컨트롤러 : 2MB 캐쉬 메모리까지 저 지연, 고 대역 액세스 제공

 

임베디드 시스템 개발 프로세스

- 분석 -> 설계 -> 개발 -> 테스트 -> 양산 -> 유지 보수

 

 

1. 분석

- 수요/기술 조사, 요구사항 평가, 사양, 비용, 디자인 등 정리

- output : 제품 기획서, 요구 명세서, 디자인 설계서

 

2. 설계

- 하드웨어 회로/기구/소프트웨어 설계

- output : 회로도, 기구설계도면, 소프트웨어 흐름 차트, UI 설계서

회로도 기구설계도
UI 설계서 소프트웨어 흐름도

 

 

3. 개발

- 하드웨어 PCB(printed circuit board), PBA(printed board assembly)  개발 후 SW 개발 디버깅 진행

- output : PCB, PBA, BOM, 아트웍 데이터, 소스코드

 

4. 테스트

- 기능, 신뢰성, 성능등을 시험

- ex : 유닛 테스트, HW 테스트,  통합 테스트, 필드 테스트, 환경 테스트

 

5. 양산 : 시제품 양산 - 부품 구입, PCB/SMT/기구 제작 및 포장

6. 유지보수 : 업데이트, AS

 

 

 

 

임베디드 프로세서 분류 방식

1. 명령어(시스템 구조)에 의한 분류

2. 버스 크기에 의한 분류

3. CPU 연산 장치 개수 분류

4. 아키텍처 분류

5. 용도에 따라 분류

 

 

1. 명령어(시스템 구조로 분류)

- CISC Complex Instruction Set Computer : 명령어가 길고 복잡하고 실행 사이클도 다양한 컴퓨터. 적은 명령어 사용

   ex) Interl x86(78년 인텔 8086에 사용된 아키텍처와 후속작), AMD64(x86의 64bit 확장 명령어셋 amd가 99년 발표)

- RISC Reduced ISC : CISC의 단점 개선. 명령어가 짧고, 간단, 빠름. 그렇다고 성능이 좋은건 아니며 명령어 많이 필요.

   ex) ARM, AArch64(arm의 64비트 확장 명령어셋) , RISC-V(버클리서 만든 무료 오픈소스 RISC ISA)

 

2. 데이터 버스 크기에 따른 프로세서

- 버스 크기가 클수록 많이 처리해서 좋지만, 용도나 비용, 전원 소모 등에 따라 적은 비트의 프로세서도 여전히 많이씀

- 4비트 : Intel 4004 71년 인텔에서 출시한 4비트 CPU 최초의 마이크로 프로세서

- 8비트 : PC에 사용된 Intel 8080(74년 출시), 모토로라 6800 등이 있고, MCU 용으로 8051(인텔), AVR(아트멜), PIC (마이크로칩)이 가전, 센서 등에 지금도 많이 씀.

- 16비트 : 8비트 보다 고성능, intel 8086이 78년 최초 제작(이후 186, 286 등). 32비트에 밀려 잘안씀.

- 32비트 : 가장 오래 사용됨 intel 80386, 80486, MIPS, ARM 등에서도 많이 출시

- 64비트 :  32비트 마이크로 프로세서의 확장. IA-64(intel과 hp가 개발), x86-64(amd64), armv8-A(arm의 64비트 ISA, 예시로 퀄컴 스냅드래곤, 삼성 엑시노스 등)

4비트 마이크로 프로세서 : 인텔 4004 8비트 마이크로 컨트롤러 : 아트멜사의 Atmega128
16비트 마이크로 프로세서 : 인텔 8086 32비트 마이크로 프로세서 : 인텔 80386

 

 

3. 코어 수로 분류

- 처음에는 ALU(산술연산장치/정수) 하나 뿐이었으나 필요에 따라 FPU(부동 소수점 연산)가 추가 되거나 여러개로 구성

 * 부동 소수점 : 소수점이 둥둥 떠다닌다. 지수에 따라서 소수점이 이동되서인듯 싶다.

- 클록 속도를 높이는 대신 코어를 높여 성능 향상. 싱글 코어, 듀얼 코어, 쿼드코어, 헥사 코어 등

 

 

 

4.용도에 따라 분류

- CPU(MPU) : pc or 워크스테이션에 사용됨. 제어기(명령어 해석 및 실행), 레지스터, ALU 등 구성

- MCU : cpu보다 저성능이지만 마이크로 프로세서에 메모리, 주변 장치 제어기, 입출력 인터페이스 내장. 

- DSP(digital signal processor) : 디지털 신호 처리를 위해 행렬 연산에 최적화됨. ex) 오디오, 영상 처리

* 컴퓨터가 실수 저장하는 방식  고정 소수점, 부동 소수점 : 10비트로 고정소수점은 1024개 수 표현 가능. 부동 소수점 방식에서 그 중 2비트를 자리수로 쓴다면 2^8(0~254) x 10^3(0, 10, 100, 1000) -> 25만개 표현 가능. 고정 소수점보다 세밀

- GPU(graphics processing unit) : 그래픽, 음성 신호를 다루기 위해 병렬처리에 특화되어 캐시 메모리가 작은 대신 수 많은 ALU가 덜 정밀하더라도 동시에 처리해 고속화됨. 

- FPU(floating point unit) : cpu 내에 부동 소수점 연산에 최적화된 논리회로

 

 

 

 

 

+ Recent posts