한국어
Embedded
 

이 글은 라즈베리파이의 HDMI에 연결된 화면에 텍스트와 그래픽을 표시하기위해 저수준에서 수행해야하는 작업을 정리한 것이다. 라즈베리파이 리눅스 커널에는 이미 구현되어 있으므로 일반적인 경우 이것을 할 필요가없다.

 

프레임버퍼는 기본적으로 소프트웨어가 구성하는 일부 파라미터에 기초하여 화면 좌표에 매핑되는 메모리 블럭이다. 이것을 어떻게 구성하는지에대한 설명을하기 전에 Raspberry Pi가 어떻게 작동하는지 이해해야한다.

 

Raspberry Pi에 사용되는 SoC는 ARM CPU 와 브로드컴 GPU를 탑재한 고성능 프로세서이다. 최초 GPU가 먼저 부팅되고 기본적으로 SD 카드에서 펌웨어 파일을 읽어서 실행한다음 커널 이미지를 메모리에 로드하고 실행한다. 이 과정에서 ARM CPU는 초기화 메시지를 작성하고 메시지의 메모리 주소를 GPU에 전달해야한다. 프로세서 간의 통신은 mailbox 메커니즘을 사용한다.

 

mailbox는 두 프로세서가 모두 접근할 수 있도록 설정된 Peripheral, 하드웨어 레지스터에 불과하다. mailbox의 하드웨어 레지스터 주소는 다음과 같다.

REGISTER

OFFSET

Base

0xB880

Poll

0xB890

Sender

0xB894

Status

0xB898

Configuration

0xB89C

Write

0xB8A0

 

이 레지스터들 중 일부만 사용한다. 

 

우선 mailbox에 쓰기는 다음과 같이 수행할 수 있다.

 

1. 상태 레지스터 (0xB898)를 읽는다.

2. 31번 비트(0x80000000)가 설정되어 있는지 확인한다. (mailbox가 Full인 경우 설정됨)

3. 설정된 경우 1단계로 돌아가고 아니면 다음 단계로 진행한다.

4. 기록 할 데이터는 4비트씩 왼쪽으로 이동해야 한다. 이것은 주소를 28비트로 변환한다.

5. 하위 4비트에는 mailbox 채널 번호가 포함되며, 4 단계의 28비트 주소와 논리 OR연산을 수행하여 이를 28비트 주소와 결합한다.

6. 쓰기 레지스터 (0xB8A0)에 데이터를 쓴다.

 

mailbox에서 읽기는 다음과 같이 한다.

 

1. 상태 (0xB898) 레지스터를 읽는다.

2. 30번 비트 (0x40000000)가 설정되어 있는지 확인한다.(mailbox가 Empty인 경우 설정됨)

3. 설정된 경우 1 단계로 돌아간다.

4. 메일박스 base 레지스터 (0xB880)를 읽는다.

5. 하위 4비트에는 응답 한 mailbox의 채널 번호가 포함된다. 원하는 mailbox와 일치하는지 확인하고 그렇지 않으면 1단계로 돌아간다.

6. 상위 28비트에는 처음 전달한 주소와 동일한 주소가 포함되어야 한다.

mailbox로 주고받는 주소는 4비트씩 왼쪽으로 이동한다. 처음 4비트에는 mailbox 채널 번호가 포함되어 있기 때문이다.

 

메일박스 채널은 10개이다.

 

0. Power management

1. Framebuffer

2. Virtual UART

3. VCHIQ

4. LEDs

5. Buttons

6. Touch screen

7. NA

8. Mailbox-property-interface – ARM to GPU

9. Mailbox-property-interface – GPU to ARM

 

채널 1이 프레임 버퍼 채널로 표시되어 있지만 PRI2부터 채널 8을 사용한다.

 

Configuration

 

프레임 버퍼를 구성하려면 다양한 태그를 쿼리하고 적절한 값으로 설정하면 된다. 아래는 프레임 버퍼와 관련된 태그 목록이다.

REGISTER

ADDRESS

Allocate buffer

0x00040001

Release buffer

0x00048001

Blank screen

0x00040002

Get physical (display) width/height

0x00040003

Test physical (display) width/height

0x00044003

Set physical (display) width/height

0x00048003

Get virtual (buffer) width/height

0x00040004

Test virtual (buffer) width/height

0x00044004

Set virtual (buffer) width/height

0x00048004

Get depth

0x00040005

Test depth

0x00044005

Set depth

0x00048005

Get pixel order

0x00040006

Test pixel order

0x00044006

Set pixel order

0x00048006

Get alpha mode

0x00040007

Test alpha mode

0x00044007

Set alpha mode

0x00048007

Get pitch

0x00040008

Get virtual offset

0x00040009

Test virtual offset

0x00044009

Set virtual offset

0x00048009

Get overscan

0x0004000a

Test overscan

0x0004400a

Set overscan

0x0004800a

Get palette

0x0004000b

Test palette

0x0004400b

Set palette

0x0004800b

 

이 태그들을 사용하여 메세지 버퍼를 설정한다. 이 버퍼의 주소를 위에서 설명한 mailbox 메커니즘을 통해 그래픽 프로세서로 전송해야 한다.

중요한 것은, 메시지를 보내고 응답을 받는 것이 아니라 전달한 버퍼가 GPU에의해 직접 수정된다는 것이다.

메시지를 주고받는 것처럼 보이게 하여 mailbox 비유가 혼란스러울 수 있다. 실제로는 버퍼를 제공하고 원래 요청 값 중 일부가 그래픽 프로세서에 의해 적절한 응답 값으로 수정된다.

 

프레임 버퍼를 구성하는 데 사용할 버퍼는 16바이트에 맞춰야 함을 기억하자. 부호 없는 32비트 정수의 배열로 선언해야 한다. 이 버퍼의 레이아웃은 다음과 같다.

OFFSET

DESCRIPTION

0

Total Buffer size (number of bytes)

1

Request/Response indicator

0x00000000 – Request

0x80000000 – Success Response

0x80000001 – Error Response

2

Tag ID

3

Tag value length (number of bytes)

4

Tag Request/Response indicator

0x00000000 – Request

0x80000000 – Success Response

0x80000001 – Error Response

5

Value data

Value data

n

0 – End tag

 

주의 할 점은 이 버퍼의 주소에 0x40000000 더하여 GPU에 전달해야한다. 주소에 0x400,000 을 더하는 이유는 GPU에서 RAM을 매핑하여 물리적 주소 0x400,000 에서 시작하기 때문이다(L2 캐싱이 활성화된 경우). 비활성화된 경우 실제로는 0xC0000000 에서 시작한다.

GPU가 물리적 메모리에서 0x400,000 + our_address 에 액세스할 때, 실제로는 RAM의 our_address 에 액세스하는 것이다.

 

기본 프레임 버퍼 기능을 구성하는 단계는 다음과 같다. 

 

1. 태그 0x00040003을 사용하여 프레임 버퍼의 실제 너비와 높이를 쿼리한다. 응답은 HDMI 포트에 부착된 모니터의 지원되는 크기와 일치해야 한다.

2. 1단계의 정보를 사용하여 모든 관련 태그를 한 번에 설정하여 일치하는 프레임버퍼 할당을 요청한다. 요청을 하나씩 전송하는 것은 그래픽 프로세서가 모든 파라미터를 무시하게 되므로, 하나의 요청에 통합 태그를 사용하는 것이 중요하다. 설정할 태그는 다음과 같다.

0x00048003 – 물리적 폭과 높이를 설정한다. 이것은 1단계에서 알 수 있다.

0x00048004 – 가상 너비 및 높이를 설정. 일단은 물리적 설정과 동일한 값으로 설정.

0x00048005 – 깊이를 설정한다. 이것은 색상을 나타내기 위해 픽셀 당 몇 비트를 사용해야 하는가를 의미한다. (16과 24 만 시도했다.)

0x00040001 – 실제 버퍼를 메모리에 할당을 요청한다. 

3. 오류를 확인하여 응답을 구문 분석한다.

4. 프레임 버퍼의 한 행에 몇 바이트가 있는지 알려주는 태그 0x00040008을 사용하여 피치를 얻는다.

 

마무리

모든 것이 제대로 진행됐다면 응답으로 실제 프레임버퍼 메모리 주소(포인터)를 받을 것이다.

 

소스코드 및 문서:

linux/drivers/video/fbdev/bcm2708_fb.c

번호 제목 글쓴이 날짜 조회 수
» Raspberry Pi 의 프레임버퍼(Framebuffer)구성 makersweb 2020.05.15 32
42 라즈베리파이2에서 RTOS기반 GPIO제어(LED) file makersweb 2020.04.21 59
41 POSIX를 지원하는 오픈소스 RTOS, RTEMS file makersweb 2020.04.15 29
40 라즈베리파이 부팅 가능한 sd카드 파티션 생성 makersweb 2020.04.15 28
39 플랫폼 디바이스 및 드라이버에 대해서 makersweb 2020.02.01 230
38 디바이스 트리(Device Tree, DT) makersweb 2020.01.12 338
37 RISC-V : 자유롭고 개방 된 RISC 명령어 세트 아키텍처 [2] file makersweb 2020.01.01 81
36 임베디드 비대칭 멀티 프로세싱(asymmetric multiprocessing) 시스템 file makersweb 2019.12.31 76
35 임베디드 시스템에서 베어메탈(Bare metal) 이란? makersweb 2019.12.11 221
34 HelloWorld 커널 모듈과 yocto 레시피 추가 방법 file makersweb 2019.12.09 483
33 ESP32 블루투스 스피커(A2DP Sink) file makersweb 2019.10.29 721
32 ESP-IDF 의 A2DP리뷰 (ESP32) file makersweb 2019.10.28 2486
31 임베디드 리눅스 부팅 절차 file makersweb 2019.10.21 503
30 mainline 커널 및 etnaviv 를 사용하는 Wandboard(Freescale i.MX6Q)에서 eglfs를 사용 makersweb 2019.10.17 224
29 Yocto를 이용한 wandboard BSP 및 Qt5 SDK 빌드 file makersweb 2019.09.29 568
28 STM32 & LibOpenCM3, printf함수사용 file makersweb 2019.08.08 1332
27 STM32(Cortex-M3) LED Blink with PlatformIO file makersweb 2019.08.05 418
26 블루투스(Bluetooth) 기초 file makersweb 2019.08.02 501
25 STM32(Cortex-M3) 개발환경구축 with PlatformIO file makersweb 2019.07.26 764
24 STM32(Cortex-M3) 개발 - Firmware Flashing file makersweb 2019.07.23 515