본문 바로가기
Linux BSP

[Device Driver] 변수의 데이터형과 바이트 순서와 volatile 변수

by TYB 2024. 2. 22.
반응형

변수의 데이터형은 아래의 표와 같다.

 

기존의 long은 부호가 있는 4바이트 정수이므로s32로 바꿔버리겠다. 

 

이전 글의 코드를 재사용하겠다

 

[Linux DeviceDriver] 디바이스 드라이버 코드 수정해서 커널에 포함시키기

디바이스 드라이버에 대한 간단한 이론 지식은 아랫글의 중후반부에 있음 [Linux DeviceDriver] Yocto Project 설정 초기화 및 디바이스 파일 만들어보기 [Linux File System] Yocto Project 2 이전 글 먼저 진행해

program-developers-story.tistory.com

 

 

23 static void gpioLedSet(s32);

 

 52 static void gpioLedSet(s32 val)

 

make 하면 잘 됨.

 

 

왜 이렇게 쓸까?

 

16bit architecture에서 int는 16bit, 32bit architecture에서 int는 32bit 로 바뀐다.

따라서 16bit에서 사용하던 int를 32bit에서 동작시킬려고 한다고 해보자. 괜찮을거다

하지만 따라서 32bit에서 사용하던 int를 16bit에서 동작시킬려고 한다고 해보자. 괜찮을까? 안괜찮을걸

표현할 수 있는 데이터의 범위가 짤려버릴수도 있기 때문에 잘못된 계산, 오동작이 발생할 것이다.

잘 동작하던 코드가 잘 동작하지 않을 것이라는 얘기임.

 

하지만 s32, u32와 같은 데이터 타입은 전혀 문제가 되지 않기 때문에 이런 데이터형을 사용하는거임.

 

C언어에서 흔히 사용하는 구조체는 보통 int형 크기의 배수로 선언되는데, 컨트롤러의 레지스터를 표현하거나 응용프로그램과의 정확한 데이터 교환을 위해 int형의 배수로 정렬되면 곤란한 경우가 발생한다.

char[3]같은 값이 중간에 껴있다면 int형의 배수로 정렬되지 않기 때문인데

이런 경우에는 packed라는 키워드를 사용해서 실제 변수의 크기로 선언하는 것이 좋다.

typedef struct

{

    u16 index;

    u16 data;

    u8   data2;

} __attribute__ ((packed)) testctl_t;

 


바이트 순서

 

사용하고 있는 아키텍처가 빅엔디안인지 리틀엔디안인지에 따라 바이트 순서가 바뀐다. 

 

 

다른플랫폼에이식할경우에는정수바이트순서에 주의해야 한다.

프로세서마다 정수 데이터를 메모리에 표현할 때 가장 작은 바이트를 두는 위치가 다르기 때문이다.

낮은 바이트를 먼저 저장하면 리틀 엔디안 (litle endian) 이라고 하고

반대로 낮은 바이트를 마지막에 저장하면 빅엔디안 (big endian) 이라고 한다. 

 


 

C는 컴파일을 하면 컴파일러가 최적화를 하게 되어 있음.

우리는 우리가 선언한 변수가 스택에 잡혀있을 것이라고 예상하지만, 그건 아무도 모른다.

for 문에 제어용 변수 index를 반복문을 돌 때마다, 속도 빠른 cpu가 상대적으로 속도가 느린 메모리 버스를 통해 느린 메모리에서 값을 읽어와야되는 건데, 이게 스택에 잡혔다면 cpu의 연산 속도가 느려진다는 거임.

 

그래서 컴파일러는 자주 접근하는 변수에 대해 레지스터에 저장을 시켜놓을 수도 있음.

 

그래서 volatile 변수를 써서 컴파일러가 그 변수를 최적화해서 범용레지스터에 저장하지 못하게 한다는거임. 

 

레지스터에 저장된 값을 읽으면 polling을 했는데도 해당되는 변수값을 읽지 못하는 경우가 발생함.

 

 

 

 

결론: volatile은 펌웨어 환경에서 main loop와 interrupt service routine에서 변수를 공유할 때 반드시!!!!!! 사용해줘야한다.

 

 

좋은 컴파일러는 알아서 volatile로 바꿔줄 것이나 일단 gcc는 안해준다는거..

 


 

GFP_KERNEL 

GFP_ATOMIC 우리가 사용할 거, interrupt는 잠들면 안돼~

 


구조체의 변수를 생성과 동시에 초기화 하기 위해서 .num -1, .name= "test"로 코드가 되있는거임.

이거랑 완전히 동일한 작업임.

 

반응형