'2015/10/18'에 해당되는 글 2건

임베디드 보드에 부착된 각종 주변 장치에 대한 제어 프로그램 작성을 위해서는 먼저 이들 장치에 대한 주소를 알아야 한다. 임베디드 보드에서의 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 항상 겸손하자.

댓글을 달아 주세요

ARM 아키텍처는 임베디드 기기에 많이 사용되는 RISC 프로세서이다. 저전력을 사용하도록 설계하여 ARM CPU는 모바일 시장에서 뚜렷한 강세를 보인다.


ARM 프로세서 명령어 세트 


데이터 처리 명령어 세트


ex) ADD {condition} {S} Rd, Rn, shifter_operand 


덧셈 명령으로써 두 개의 오퍼랜드(Rn, shifter_operand)를 서로 더해 결과를 목적지 레지스터 Rd에 저장한다. 조건(condition) 부분은 플랙에 따른 명령어 실행 조건을 의미한다.


Load/Store 명령어 세트


Branch 명령어 세트


기타 명령어 세트


PXA 시리즈 프로세서


pxa 시리즈 프로세서는 인텔 32비트 Xscale RiSC 코어를 기반으로 하고 여러 주변 장치를 탑재한 임베디드 시스템용 프로세서이다. CPU 부분인 Xscale은 ARM 버전 5구조를 기반으로 하며 비교적 저전력에 고성능을 제공한다. PXA2xx 시리즈와 PXA3xx 시리즈가 있다.


(학교 임베디드 시스템 수업 PXA255 사용함)


PXA 255는 주변 장치 인터페이스를 위해서 시리얼 통신을 위한 UART 포트, MMC 카드 기능, USB 1.1 클라이언트 기능, 적외선 시리얼 통신을 위한 IrDA, 오디오 코텍, 시리얼 통신 기능인 I2C 등을 가지고 있다. UART는 표준 UART, FF UART, 블루투스 UART를 모두 지원한다. 


GPIO


PXA255는 모두 85개의 GPIO 핀 신호를 가지며 각 핀은 입력이나 출력으로 설정될 수 있고 인터럽트 요청 라인이나 UART의 신호들, LCD 디스플레이를 위한 데이터 라인 등 각종 외부 장치와의 연결이나 인터페이스로 사용한다. 대부분의 GPIO는 단순히 디지털 입출력뿐만 아니라 부가적인 기능을 추가로 가진다. GPIO 핀의 각 기능을 설정하고 사용하기 위한 GPIO 레지스터들의 이름과 기능은 다음 표와 같다. 


GPDR(GPIO PIN Direction Register)  - 입출력 방향 설정 레지스터


이 레지스터는 핀 방향, 즉 입출력 방향 설정 레지스터로서 GPIO 핀을 입력 또는 출력으로 설정할 것인지를 결정한다. 0이면 입력으로 설정되어 GPLR을 통해서 GPIO 핀 상태를 읽을 수 있고 1이면 출력으로 설정되어 GPSR이나 GPCR을 사용해 '1'이나 '0'을 출력할 수 있다. 


GAFR(GPIO alternate function register) - Alternate 기능 설정 레지스터


GPIO 부가기능을 설정한다. 


GRER() - 상승 에지 검출 레지스터


이 레지스터의 입력 핀 상태가 LOW에서 HIGH로 되면, GEDR의 해당 비트가 "1"로 된다. 단 GPDR의 해당 비트가 "0"으로 되어 있어 입력 상태여야 하고, GAFR의 해당비트가 "0"으로 되어 있어 부가기능을 사용하지 않는 상태이어야 한다.



GFER(GPIO Falling edge detect register) - 하강 에지 검출 레지스터 


이 레지스터의 입력 핀 상태가 high에서 low로 되면 gedr의 해당 비트가 '1'로 된다. 단 gpdr의 해당 비트가 '0'로 되어 있어 입력 상태이어야 하고, GAFR의 해당 비트가 0으로 되어 있어 부가기능을 사용하지 않는 상태이어야 한다.



GPSR(GPIO Pin output set register) - 출력 '1' 설정 레지스터


이 레지스터에 "1"을 설정하면 해당 핀은 HIGH 상태로 되고 "0"을 설정하면 해당 핀은 변화 없이 이전 상태를 유지한다. 


GPCR(GPIO Pin output clear register) - 출력 '0' 설정 레지스터


이 레지스터에 "1"을 설정하면 해당 핀은 LOW 상태가 되고, "0"을 설정하면 해당 핀은 변화 없이 이전 상태를 유지한다. 


GPLR(GPIO PIN-LEVEL REGISTER) - 입력 레벨 검출 레지스터


이 레지스터는 GPIO의 핀에 인가된 전압 레발 값을 가지므로 현재의 입력핀의 상태를 읽을 수 있다. 전압 레벨이 LOW이면 0으로 HIGH 이면 "1"로 읽힌다. 


GEDR(GPIO edge detect status register) - 입력 에지 검출 레지스터


GPDR해당 비트가 "0"으로 되어 있어 입력 상태이어야 하고, GAFR의 해당 비트가 0으로 되어 있어 부가기능을 사용하지 않는 상태에서 GRER이나 GFER의 해당 비트가 설정되어 있을 경우 상승/하강 에지가 발생하면 해당 비트가 "1"로 되고 이때 인터럽트를 발생시킬 수도 있다. 

블로그 이미지

종환 Revolutionist-JongHwan

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

댓글을 달아 주세요