정리 다하고 나서 아는 분한테 물어보다가 ioremap을 사용하는 방법이 있다는 걸 알게되서 시간나는대로 ioremap도 사용해봐야 겠네요..
참고 : http://sysprogs.com/VisualKernel/tutorials/raspberry/leddriver/
1. LED연결
라즈베리 파이에서는 Broadcom BCM2835 SOC칩을 사용하고 있다. 이 칩에는 ARM1176JZFS 700Mhz프로세서, Videocore 4 GPU, 256메가 메모리를 포함하고 있다. 우선 보드에서 LED를 연결해서 사용할 GPIO의 번호를 정한 후, 데이터 시트에서 설정하기 위한 레지스터들을 찾으면 된다.
GPIO 18번에 LED를 연결하여 1초 주기로 LED를 깜빡이게 하는 예제 코드를 작성해보려 한다. 라즈베리파이에서 해당되는 핀은 아래에 보이듯이 12번핀이다. 여기에 LED를 연결하고 그라운드를 연결해주면 된다.
2. 레지스터 세팅
LED를 켜고 끄는 데에는 다음 레지스터들을 사용하면 된다.
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부터 시작하는 걸로 보면 된다.
(http://www.raspberrypi.org/forums/viewtopic.php?f=6&t=5982 )
위 표를 참고해서 같은 배열로 구조체를 선언한다.
하드웨어의 레지스터에 접근하기 위하여 __io_address 매크로 함수를 이용하여 주소를 가져와 구조체 포인터 변수에 매핑한다. 엔트리 포인트인 LedBlinkModule_init함수에 추가되는 코드임.
GPIO18번은 GPF_SEL1레지스터에 해당 항목이 있다.
구조체 멤버에 대한 접근을 통해 이제 하드웨어 접근이 가능하다. GPFSEL1 레지스터에 아래값을 입력하면 FSEL18이 001로 설정되어 GPIO18번 핀은 Output 모드가 된다. 엔트리 포인트인 LedBlinkModule_init함수에 추가되는 코드임.
GPIO 18번은 다음 레지스터들을 세팅 해주면 LED가 켜지고 꺼지게 할 수 있다.
LED가 깜빡이게 하기 위해서는 GPSET과 GPCLR을 일정시간을 두고 번갈아가며 세팅해주면 된다. 인덱스가 0부터 시작하므로 GPIO핀 18번은 19번째 비트가 된다. 타이머 콜백함수인 BlinkTimerHandler에 추가되는 코드임.
3. 리눅스 커널에서 제공하는 타이머 사용
타이머를 초기화하고 시작한다. 엔트리 포인트인 LedBlinkModule_init함수에 추가되는 코드임.
정해진 시간마다 호출이 되는 콜백 함수이다.
4. sysfs 디바이스 객체를 생성
sysfs는 유저영역과 커널과의 통신을 위해서 사용되는 파일시스템의 한 종류이다.
다음 매크로를 사용하여 유저 스페이스에서 선언한 LED가 깜빡이는 주기값을 가져온다. 가져오는 함수는 set_period_callback함수이다. 디바이스 파일인 period파일이 sys디렉토리 아래에 생성된다.( 정확한 위치는 아래에서 설명 )
DEVICE_ATTR(_name, _mode, _show, _store)
_name : sysfs의 파일 이름, 즉 디바이스 이름 _mode : 파일의 권한, chmod에서 사용하는 것과 동일함 _show : show 함수를 등록한다. 커널에서 유저스페이스로 값을 넘겨주는 함수 포인터. _store : store 함수를 등록한다. 유저스페이스에서 커널로 값을 넘겨주는 함수 포인터. |
콜백함수에서 가져온 값을 s_BlinkPeriod 변수에 저장한다.
sys 디렉토리에 디바이스를 추가하기 위해서는 다음 함수들을 호출해야 한다.
엔트리 포인트인 LedBlinkModule_init함수에 위에 있는 코드들이 추가되면 모듈이 적재된 후 다음과 같은 파일 및 디렉토리가 생성된다.
5. 테스트
디폴트 동작은 1초를 주기로 LED가 켜졌다가 꺼졌다하는 것이다. period에 다음 명령을 사용해서 주기를 바꿀 수 있다.
아래처럼 하면 깜빡이는 속도가 좀더 빨라져서 100ms LED가 켜졌다가 100ms 꺼지는 것을 반복한다.
pi@webnautes-pi ~ $ echo "100" > /sys/devices/virtual/LedBlink/LedBlink/period
더 길게 해서 오랫동안 LED가 켜지게 할 수 도 있다.
pi@webnautes-pi ~ $ echo "5000" > /sys/devices/virtual/LedBlink/LedBlink/period
'Raspberry Pi > Raspberry Pi 활용' 카테고리의 다른 글
raspberry pi 2에서 bcm2835 데이터 시트를 사용할 수 있다는데... (0) | 2015.09.15 |
---|---|
리눅스 문자 디바이스 드라이버 예제 (0) | 2015.02.22 |
Raspberry pi에 Git를 위한 Web 인터페이스 설치하기 ( GitWeb) (0) | 2015.02.08 |
라즈베리파이를 개인 클라우드로 바꾸기 (1) | 2015.02.05 |
Raspberry pi를 git 서버로 사용하기 (4) | 2015.02.04 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!