FW 심화 과정/[2] STM32심화실습

0721 외부변수참조 / .h / CPU구조 / reg와argument / 슈도명령어 ~234

천숭이 2022. 7. 22. 00:20

< main.c >

extern int DoAdd(int, int);   // -> 생략가능
extern float DoAddFloat(float, float);

int main()
{
	printf("%d \r\n", DoAdd(3,4));
	printf("%f \r\n", DoAddFloat(0.5, 1.5));
}

< extern.c >

int DoAdd (int a, int b)
{
	return (a+b);
}

float DoAddFloat(float a, float b)
{
	return(a+b);
}

- main문에서, int형 함수인 extern DoAdd 선언 구문은 생략이 가능하나, float DoAddFloat  실수형 함수 선언 구문은 생략 불가

- 그 이유는, 메모리상 정수형 저장과 실수형 저장 형식이 완전 다르기에 실수형 함수의 경우는 명확히 명시해야 한다

 

 

# static

* 외부 파일에 노출시키지 않도록 하는 함수는 static 키워드를 사용

 

 

# 코드 유지 관리 고려한 외부 변수 접근 방법

    -> 헤더파일 작성

(작성중)

 

 

 


# CPU 내부 구조

- stm32 cpu는 현업에서 많이 사용된다

- bus와 연결된 것은 모두 IP

- Core내부 진짜레지스터, IP내부 특수 목적 레지스터

cpu -> processor -> Core

- ROM에 SFR 제어 코드가 적재되어 있음

- 코드는 ROM에, 실행은 Processor에서

 

 

- RAM에서 연산이 발생하면 Core에 Load 명령어를 통해 레지스터에 저장, 연산결과 또한 레지스터에 저장.

- Store 명령어를 통해 연산결과를 복구

 

- ROM에서 PC가 명령어를 전달(Instruction Fetch)

- PC가 4씩 증가하면서 명령어 패치, 명령어 수행됨

 

 

# 레지스터

R13 -> SP (스택포인터)
R14 -> LR (링크 레지스터)
R15 -> PC (프로그램 카운터)

어셈블리어 사용 시 주의! )

R0~R3, R12       : 이 레지스터들은 PUSH, POP 할 필요가 없다 (스택이 필요하지 않다)

나머지 레지스터 : 무조건 PUSH, POP을 사용해야 한다

 

 

# 매개변수

- 매개변수 네 개 까지는 레지스터에 작성이 가능하나, 다섯 개부터는 스택에 저장됨.

- int func (a, b, c, d, e) 함수의 매개변수가 이러면,

R0 <- a

R1 <- b

R2 <- c

R3 <- d

stack <- e

이렇게 저장됨.

 

- printf(" %#010x  \r\n", a); 

printf도 함수이므로 첫번째 매개변수 " %#010x  \r\n"의 주소는 R0에 저장.

두번째 매개변수 a는 R1에 저장.

 

- 연산 결과를 반환하는 함수의 경우, 무조건 결과를 R0에 저장하고 그 값을 return

 

 

 

# 어셈블리어 슈도 명령어 (가짜코드)

- 상수 자체가 32bit가 되면 안됨. opcode 비트자리가 필요하기 때문.

MOV R0, #0X12345678  ; ERROR

위 코드는 에러로 발생. 이 때 슈도 명령어를 사용하면 컴파일러가 알아서 실행해준다

MOV R0, =0X12345678   ; 정상 작동
; 가짜 코드를 작성하면 컴파일러가 추가로 작성하는 코드들
LDR R0, [ PC, #offset ]   ; 초과 되는 사이즈를 계산해 로드
MOV R0, #0x100            ; 해당 주소를 넘겨줌

 

정수의 범위가 너무 크게 되면, 안전한 곳에 저장하고 해당 위치들을 알린다.

" 레지스터만 스택에 저장 가능! "