임베디드 개발(before)/IoT 임베디드 SW 개발자 양성과정

[31일차] ARM 프로세서 이해 및 활용 (부트코드 작성, 소프트웨어 최적화, LED 실습)

주운녕 2020. 8. 24. 18:06

1. 임베디드 개발자가 처음 보드를 만질 때 알아야 할 것.

1) 메모리 맵.

2) 회로도

 

2. 다룰 줄 알아야 하는 장비

1) 테스터기 (삑삑이. 쇼트 난 곳 찾을 때 많이 써봤다.)

2) 오실로 스코프 (PWM 값 찍어 파형 볼 때 사용해봤다.)


1. 부트 코드 작성

1) 프로세서의 Reset과 Start-up 코드.

▷ Start-up코드(=Init.o, crt0.o)를 이해하면 좋음 점. 

: 하드웨어 세팅, 실행환경, 아키텍처에 대한 이해, 드라이버 작성 등을 할 때 유용하다.

 

▷ 하드웨어 초기화 작업을 한다.

: RAM, Clock, Stack 주소 설정하는 것과 같은 것.

- 시스템의 클럭

- 메모리 컨트롤러

- 입출력 포트의 구성

- MMU 등

- 인터럽트와 스택 초기화

▷ 리셋 핸들러의 마지막에서는 main() 함수와 같은 C로 구성된 함수를 호출.

▷ 이 부분을 startup코드 또는 부트 코드라고 부른다.

 

2) Startup 코드

▷ startup코드를 작성하기 위해서는

- 어셈블리어를 알아야 한다.

- 시스템 하드웨어 구조 및 기능에 대한 전반적인 사항을 알아야 한다.

▷ 필수사항

- Exception Vector Table의 설정

- Reset 핸들러의 구성

- 시스템 초기화

 

3) Entry Point 선언

▷ 모든 프로그램은 시작되는 부분을 정의해야 한다.

- 어셈블러로 구성되며 모든 프로그램에는 반드시 필요.

- 일반적인 crt0.S(C-RunTime 0의 약자)(OS 가 올려져 있는 경우), Init.S, Startup.S 등의 이름 사용

▷ Entry Point 선언

▷ 프로그램 대략 실행 방향

- NANF에 있는 프로그램이 mDDR(RAM)에 복사, SoC 내부의 iSRAM(0x4000:0000 위치), iROM(0x0000:0000 위치)에 이동

 

2. 소프트웨어 최적화

- 깊게 들어가지 않고 대략적인 것들만 살펴보았다.

- 컴파일러의 최적화를 생각하며 코딩하면 오 이 친구 좀 할 줄 아는가 보네, 란 소리를 들을 수 있다.

 

▷ 컴파일러의 최적화 레벨

- -O0, -O1, -O2 등이 있다. 각각의 최적화 정도가 다르다.

 

▷ 컴파일러의 최적화 기능

- 무관한 코드는 무조건 제거

- 스택의 사용이 많으면 시스템 성능 감소.

- Loop 문 최적화 : for 문 작성 시 i++ 보다 i-- 방향이 어셈블리어로 더 간결하다.

:: i++은 add와 cmp, ble 명령어, i--은 subs와 bne 명령어 두 개 (subs에 뺄셈과 상태 레지스터 판단 둘 다 가능)

- Inline 함수를 사용하면 성능 향상. 단점 : 코드 사이즈 증가.

 

▷ 고급 프로그래밍 기법

- Inline Assenbler : C 소스 내에서 Assembler를 사용하는 방법.

- ASM과 C/C++ Mixed 프로그래밍

 

3. LED 실습.

- main.c

void Main(void)
{
	
#if 1
	/* Testing LED with GPIO */
	int i, j;
	
	Led_Port_Init();
	for(i=0;i<16;i++) {
		Led_Display(i);
		for(j=0;j<0x1ffff;j++);
	}

 

- lib.c

void Led_Port_Init()
{	
	/* 
	 * LED On : Active Low 
	 * Initialize GPGDAT[7:4] : high
	 * Setup GPGCON[15:8] : 01-> GPG7~4 Output mode
	 * GPGUP pull up function disable
	 * 
	 */
	 /* EXERCISE TODO: complete the code below */  
     
	rGPGDAT |=  0x00F0;		/* set GPGDAT[7:4] high for initial condition */ //하이로 만들어줌 
	rGPGCON &= ~(0xff<<8);	/* clr */ //초기화 
	rGPGCON |=  0x00005500;	/* set GPG[7:4] output mode */ //4~7 아웃풋 모드로 해줌
	rGPGUDP &=  (0xaa<<8);	/* pull up disabled */

	//rGPGUDP &=  ~(0xffff<<8);	/* pull up disabled */ // 0000 0000 : 0000 0000 : 00 00 00 00 : 11 11  00 00 
}

void Led_Display(int data)
{
	/* 
 	 * LED On : Active high 
     * LED Off: Active low
	 * GPGDAT[7:4]
	 */
	
	rGPGDAT |= (0xf<<4);

	/* EXERCISE TODO: complete the code below */	
	
	if(data & 0x01)  rGPGDAT &= ~(0x1<<7);  /* turn ON LED1 */
	if(data & 0x02)  rGPGDAT &= ~(0x1<<6);	/* turn ON LED2 */
	if(data & 0x04)  rGPGDAT &= ~(0x1<<5);	/* turn ON LED3 */
	if(data & 0x08)  rGPGDAT &= ~(0x1<<4);  /* turn ON LED4 */
}

▷ LED가 켜진다.


* 개인적인 학습 목적으로 작성한 글이기에 내용에 잘못된 정보가 있을 수 있습니다.