임베디드 보드에 부착된 각종 주변 장치에 대한 제어 프로그램 작성을 위해서는 먼저 이들 장치에 대한 주소를 알아야 한다. 임베디드 보드에서의 LED 장치는 프로세서의 주소버스를 디코딩하여 주소가 결정된다.


LED 장치 주소가 0x0C00 0C00번지라고 가정하여 제어 프로그램을 작성해보자 



led.h소스 



#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define CS3_BASE 0x0c000000
#define LED_OFFSET 0x0C00

unsigned char *CS3_base;
unsigned char *led;

static int fd;

led.h 소스에는 기본 헤더 파일들과 임베디드 보드에서 설정된 LED를 가리키기 위해 프로세서의 chip select 신호의 기본 주소인 0x0C00 0000을 CS3_BASE로 정의하고 있다. 또 이 기본 주소에서 LED 장치 주소와의 차이값인 0x0C00을 LED_OFFSET에 정의하고 있다. CS3_base는 chip select 신호의 기본주소를 가리키는 포인터 변수이고, led는 LED 장치 주소를 가리키는 포인터 변수이다.

led.c 소스

#include "led.h"

int memopen(void)
{
   fd = open("/dev/mem",0_RDWR);
   if(fd<0){
       perror("/dev/mem FAIL!\n");
       exit(1);
  }

return 0;
}

int ledaddr(void)
{
  CS3_base = (unsigned char *)mmap(NULL,1024,PROT_READ|PROT_WRITE,MAP_SHARED,fd,CS3_BASE);
    if((int)CS3_base == -1){
            perror("mmap FAIL! \n");
            return -1;
   }
   led = CS3_base + LED_OFFSET;
   return 0;
}

void memrelease(void)
{
  munmap((unsigned char * )CS3_base,1024);
}

void outled(int sel)
{
 switch(sel){
      case 0:
          {
               printf("LED data = 0xFF\n");
               ledaddr();
               *led = 0xff;
               memrelease();
               break;
          } 
       case 1:
   ........생략.......

       case 2:
  ......
   }
 }

int main(void)
{ 
  int i;
  memopen();

for(i =0; i<10;i++){
  outled(0);
  sleep(1);
  outled(1);
  sleep(1);
  outled(2);
}
  close(fd);
}

위의 led.c 소스에서 fd = open("/dev/mem",0_RDWR); 는 /dev/mem 파일을 열어 파일 기술자를 반환한다. /dev/mem 파일은 O_RDWR 모드로 열리며 이 파일은 메모리 입/출력을 하기 위한 문자 디바이스 파일이다. 

open() 함수에 의해서 반환된 파일 기술자는 변수 fd에 할당되고, 이 값을 아래 mmap() 함수의 파라미터로 사용해 CS3_BASE 주소에 해당하는 현 프로세스 메모리 주소를 구한다.


이 mmap() 함수는 CS3_BASE주소를 가리키는 현 프로세스 주소 공간에서의 주소값을 변수 CS3_base에 리턴한다 

led_addr = CS3_base + LED_OFFSET; 여기서 베이스 주소와 LED 장치와의 오프셋 값인 LED_offset을 베이스 주소에 더하여 변수 led에 LED 장치의 주소를 얻게 된다. 


 *led = oxff; 여기서 실제 LED 장치로 값을 출력한다.. 


* mmap함수


 리눅스/유닉스에서는 프로세스와 프로세스 사이의 보호를 위해 각 프로세스는 서로 별도의 주소 공간을 가지게 된다. 이를 위해서 CPU가 하드웨어적으로 지원하는 MMU(Memory Management Unit)가 필요하며 32비트급 임베디드 시스템용 프로세서는 대부분 MMU를 가지고 있다. 각 프로세스가 별도의 주소 공간을 가지면 한쪽 프로세스에서의 잘못된 동작이 다른 쪽 프로세스에 영향을 미치지 않으므로 프로세스의 보호는 잘 이루어지지만 프로세스와 프로세스 사이에 데이터를 전달하거나 공유할 경우 별도의 대책이 필요하다.


 각 프로세스가 별도의 주소 공간을 가지면 한쪽 프로세스에서의 잘못된 동작이 다른 쪽 프로세스에 영향을 미치지 않으므로 프로세스의 보호는 잘 이루어지지만 프로세스와 프로세스 사이에 데이터를 전달하거나 공유할 경우 별도의 대책이 필요하다. LED 장치의 주소는 물리주소 공간에서 0x0C00 0C00으로 되어 있으나 현 프로세스 주소 공간에서의 주소 0x0C00 0C00는 서로의 주소공간이 다르므로 실제 LED 장치를 가르키는 것이 아니다. 이를 위한 여러 방법 중 하나가 mmap()함수를 사용하는 것이다. mmap() 함수는 현 프로세스의 메모리 공간을 파일이나 공유 메모리 특정영역으로 맵핑시킨다. 파일은 운영체제에서 글로벌 자원이므로 다른 프로세스와 공유가 가능하다. 따라서 파일로 맵핑된 메모리 영역은 프로세스 사이의 데이터 교환에 사용될 수 있다.




블로그 이미지

종환 Revolutionist-JongHwan

github.com/alciakng 항상 겸손하자.