본문 바로가기
관심거리/IT(컴퓨터/인터넷)

Embedded System에 사용되는 메모리 MAP 방식에 관한 연구

by 상실이남집사 2013. 12. 13.

1. 서론


최근 임베디드 시스템에 대한 열기와 유비쿼터스에 대하여 많은 미디어를 통하여 실감할 수 있다. 임베디드 시스템에서 사용하는 메모리 접근 제어 방식에 대하여 기술한다.

실제 임베디드 시스템을 이용한 개발 모델을 수행하는 과정에서 꼭 이해하여야 하는 중요한 이론중의 하나라고 볼 수 있다.

흔히 임베디드 시스템은 메모리를 I/O Device와 연결을 함에 있어 메모리를 매핑(Memory mapping)시켜 사용한다.

이러한 메모리 매핑 방법에서는 표준 C Library에서 제공하는 mmap 함수를 이용하는 방법과 직접 메모리 세그먼트와 오프셋을 포인터로 연결하는 방식을 사용한다.

따라서 다음과 같이 두 가지의 방식을 사용한다.


- 임메디드 시스템의 메모리 접근 방법


        1. mmap 함수를 이용하는 방법

        2. 메모리 직접제어 방식



2. 본론


임베디드 시스템에 사용하는 메모리 접근 방식에 대하여 하나씩 살펴보고 이것을 C 언어 코드와 함께 살펴보기로 한다.


2.1 mmap을 이용한 제어


mmap 함수를 이용하는 방법은 우선 mmap함수의 몸체를 살펴 볼 필요가 있다.

다음은 mmap함수의 선언부분이다.



#include

void * mmap(void *start, size_t length, int prot ,

          int flags, int fd, off_t offset);


int munmap(void *start, size_t length);



mmap함수는 start부터 length까지의 메모리 영역을 열린 파일 fd에 대응한다.

대응할 때 파일의 위치를 지정할 수 있는데 이것은 offset을 통해서 이루어진다.

prot는 파일에 대응되는 메모리 영역의 보호특성을 결정하기 위해서 사용된다.

메모리영역과 파일이 서로 대응되기 때문에 파일에 대한 어떠한 작업이 메모리영역에

직접적인 영향을 미칠 수 있기 때문이다.

prot는 다음과 같은 플레그(flag)를 제공한다.



PROT_EXEC 페이지(page)는 실행될 수 있다.

PROT_READ 페이지는 읽혀질 수 있다.

PROT_WRITE 페이지는 쓸 수 있다.

PROT_NONE 페이지를 접근할 수 없다.



mmap를 사용할 때 반드시 MAP_PRIVATE와 MAP_SHARED둘중 하나를 사용해야 한다.



#include

#define IO_BASE_ADDR 0x30000000

#define U32 unsigned int

#define U16 unsigned short

#define IO_SIZE  0xff


U32 *base_addr;

U16    data;

int      fd;

fd = open( "/dev/mem", O_RDWR|O_SYNC );

if( fd < 0 )

{

perror( "/dev/mem open error" );

exit(1);

}


// map alloc

base_addr =

     mmap (0, PROT_READ|PROT_WRITE, MAP_SHARED, fd, IO_BASE_ADDR );


// put the data

*base_addr=0x1234;

// get the data

data = *base;

/* other code here */

munmap( baseaddr, IO_SIZE ); // map release

close( fd );



2.2 volatile 키워드를 사용하는 방식


메모리의 특정 영역을 특정 장치와 연결하여 사용하는 방법입니다.

임베디드 시스템에서 가장 흔한 예가 제어 레지스터와의 메모리 매핑이 되겠다.

그 이외에도 많은 장치(플래시, LCD, 터치 스크린)들을 이러한 식으로 사용될 수 있다.

만약 임베디드 시스템에서 특정 제어 레지스터에 값을 설정한다고 가정한다면

이 방법으로 사용할 수 있다. 물론 값을 얻어 오기 위해서도 사용할 수 있다.

이런 경우의 예제를 살펴보면 다음과 같다.



volatile U16 *addr=0x00;


// put data

*addr =0xf0;

*(addr+0x555) =0xaa;

*(addr+0x2aa) =0x55;

*(addr+0x555) =0x90;


// get data

data1=*addr;

data2 =*(addr + 0x01);



위의 예제에서 특정 장치와 memory map된 주소에 데이터를 쓰는 경우에는 다음과 같은 간단한 매크로를 사용 할 수 있다.



#define AMD_CMD(addr, data) *( (volatile U16 *) addr) = (U16)(data);


/* some code :: put data into memory */

AMD_CMD(0x3000000, 0x1234);



컴파일러는 volatile 키워드가 선언된 변수에 대해서는 무조건 메모리에 접근하여 됩니다.

이러한 memory-mapped I/O 이외에도, 쓰레드 등으로 프로그램을 만들어서 공유변수를 한쪽에서 읽고, 한쪽에서 쓰는 경우도 해당될 수 있으며,

시스템 시간과 같이 특정 위치의 변수 값이 자신과는 독립적으로 계속 변하는 경우에도

사용할 수 있다.



3. 결론


두 방식에 대하여 메모리를 직접 제어하는 방법에 대하여 알아보았다. 파일 I/O와 함께

mmap 함수를 사용하는 경우와 volatile 키워드를 사용한 메모리 직접 제어 방식에 대하여 각각 예를 통하여 살펴보았다.

임베디드 시스템을 이해하고 프로그래밍 함에 있어 꼭 필요한 것은 사실이다.

따라서 이러한 제어 방식에 대하여 충분히 이해를 하고

임베디드 시스템 프로그래밍을 작성하여야 한다.

이것은 앞으로 ARM 코어 칩을 사용하는 CPU와 기타 장치의 적적한 제어 과정에 사용될

아주 기본적인 지식이다.

향후 이러한 방식을 직접 적용하여 LCD, 플래시 메모리, Uart(시리얼 통신)을 제어하는데

도움이 될 것이다.

댓글