반응형


복잡하게 디바이스 드라이버까지 작성하지 않고 간단하게 mmap을 사용하여 레지스터에 접근하여 LED를 제어해보려고 합니다.

핀번호 6번 그라운드와 핀번호 12번 GPIO18에 LED를 연결해주었습니다.



BCM2835 데이터 시트에 따르면 LED를 켜고 끄는 데에는 다음 레지스터들을 사용하면 됩니다.

라즈베리파이3에선 BCM2837이지만 동일하게 동작했습니다.


  • GPFSELx – GPIO핀을 Input 또는 Ouput으로 사용할지 결정.

  • GPSETx – GPIO핀을 하이레벨로 만들어줌. Led가 켜진 상태.

  • GPCLRx – GPIO핀을 로우 레벨로 만들어줌. Led가 꺼지는 상태.



GPIO Base Address가 아래처럼 0x 7E20 0000으로 나와 있지만 BCM2835 데이터시트의 1.2.3 ARM physical addresses에 따르면 실제로 접근 시에는 0x 2020 0000부터 시작하는 걸로 생각하면 됩니다.

하지만 이건 라즈베리파이 1 기준입니다. (http://www.raspberrypi.org/forums/viewtopic.php?f=6&t=5982 )




https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=98740  에 따르면 라즈베리파이2에서는 0x3F20 0000으로 바꾸어서 적용시키면 된다고 합니다. 따라서 GPFSEL0의 시작 주소가 0x7E20 0000이 아니라 0x3F20 0000이 되는 것입니다.

라즈베리파이3에서도 테스트해보니 동일하게 동작합니다.


아래에 LED를 제어하는데 사용할 3가지 레지스터의 메모리 주소들을 보여주고 있습니다.




GPIO18번은 GPF_SEL1레지스터에 해당 항목이 있습니다.

24번째 비트부터 26번째 비트까지의 값을 001로 바꾸어주면 GPIO18번는 출력모드가 되게 됩니다.


   //gpio[GPFSEL1/4] = 0b00000001000000000000000000000000;    
   gpio[GPFSEL1/4] |= (1<<24);    



그리고 다음 레지스터들에서 GPIO18번의 위치에 해당되는 비트를 세팅 해주면 LED가 켜지고 꺼지게 할 수 있습니다.



       //gpio[GPSET0/4] = 0b00000000000001000000000000000000;    
       gpio[GPSET0/4] |= (1<<18);   





       //gpio[GPCLR0/4] = 0b00000000000001000000000000000000;   
       gpio[GPCLR0/4] |= (1<<18);




실행시켜보면 LED가 5번 깜빡이게 됩니다.


pi@raspberrypi:~ $ g++ led.c -o led

pi@raspberrypi:~ $ sudo ./led



#include <stdlib.h>    
#include <stdio.h>
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
#include <sys/mman.h>    
       
       
#define GPIO_BASE 0x3F200000    
#define GPFSEL1   0x04
#define GPSET0    0x1C
#define GPCLR0    0x28
       
       
int main()    
{    
   int fd = open( "/dev/mem", O_RDWR|O_SYNC );    
   if ( fd < 0 ){    
       printf( "can't open /dev/mem \n" );    
       exit(-1);    
   }
       
       
   char *gpio_memory_map = (char *)mmap( 0, 4096, PROT_READ|PROT_WRITE,    
       MAP_SHARED, fd, GPIO_BASE );    
       
   if ( gpio_memory_map == MAP_FAILED )    
   {
       printf( " Error : mmap \n" );    
       exit(-1);    
   }
       
           
   volatile unsigned int* gpio = (volatile unsigned int*)gpio_memory_map;    
   //gpio[GPFSEL1/4] = 0b00000001000000000000000000000000;    
   gpio[GPFSEL1/4] |= (1<<24);    
       
   int i;    
   for ( i=0; i<5; i++ )    
   {
       //gpio[GPSET0/4] = 0b00000000000001000000000000000000;    
       gpio[GPSET0/4] |= (1<<18);   
       sleep(1);    
       
       //gpio[GPCLR0/4] = 0b00000000000001000000000000000000;   
       gpio[GPCLR0/4] |= (1<<18);  
       sleep(1);    
   }
       
    munmap( gpio_memory_map, 4096);    
   
   return 0;    
}    



마지막 업데이트 2019. 2. 18


반응형

진행해본 결과물을 기록 및 공유하는 공간입니다.
잘못된 부분이나 개선점을 알려주시면 반영하겠습니다.


소스코드 복사시 하단에 있는 앵커 광고의 왼쪽 위를 클릭하여 닫은 후 해야 합니다.


문제가 생기면 포스트와 바뀐 환경이 있나 먼저 확인해보세요.
질문을 남겨주면 가능한 빨리 답변드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기

댓글을 달아 주세요

TistoryWhaleSkin3.4">