Raspberry Pi DRM 출력 예제
config.txt 에 vc4-kms-v3d 체크 확인
sudo nano /boot/firmware/config.txt
sudo apt install libdrm-dev
sudo apt install libinput-dev
// drm_example.c
#include <drm/drm.h>
#include <drm/drm_mode.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <sys/mman.h>
#include <errno.h>
#define DEVICE "/dev/dri/card0"
int main() {
int fd = open(DEVICE, O_RDWR | O_CLOEXEC);
if (fd < 0) {
perror("Failed to open DRM device");
return 1;
}
drmModeRes *resources = drmModeGetResources(fd);
if (!resources) {
perror("drmModeGetResources failed");
close(fd);
return 1;
}
// Pick the first connected connector
drmModeConnector *connector = NULL;
for (int i = 0; i < resources->count_connectors; ++i) {
connector = drmModeGetConnector(fd, resources->connectors[i]);
if (connector->connection == DRM_MODE_CONNECTED) {
break;
}
drmModeFreeConnector(connector);
connector = NULL;
}
if (!connector) {
fprintf(stderr, "No connected connector found\n");
drmModeFreeResources(resources);
close(fd);
return 1;
}
drmModeModeInfo mode = connector->modes[0]; // Use the first mode
int width = mode.hdisplay;
int height = mode.vdisplay;
drmModeEncoder *encoder = drmModeGetEncoder(fd, connector->encoder_id);
uint32_t crtc_id = encoder->crtc_id;
// Create dumb buffer
struct drm_mode_create_dumb creq = {0};
creq.width = width;
creq.height = height;
creq.bpp = 32;
if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq) < 0) {
perror("DRM_IOCTL_MODE_CREATE_DUMB failed");
return 1;
}
uint32_t handle = creq.handle;
uint32_t pitch = creq.pitch;
uint64_t size = creq.size;
// Create framebuffer
uint32_t fb;
if (drmModeAddFB(fd, width, height, 24, 32, pitch, handle, &fb)) {
perror("drmModeAddFB failed");
return 1;
}
// Map buffer
struct drm_mode_map_dumb mreq = {0};
mreq.handle = handle;
if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)) {
perror("DRM_IOCTL_MODE_MAP_DUMB failed");
return 1;
}
uint8_t *map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
if (map == MAP_FAILED) {
perror("mmap failed");
return 1;
}
// Fill with a solid color (e.g., blue)
memset(map, 0, size);
for (int y = 0; y < height; ++y) {
uint32_t *row = (uint32_t *)(map + y * pitch);
for (int x = 0; x < width; ++x) {
row[x] = 0xFF0000FF; // ARGB: Blue
}
}
// Set CRTC (display the framebuffer)
if (drmModeSetCrtc(fd, crtc_id, fb, 0, 0, &connector->connector_id, 1, &mode)) {
perror("drmModeSetCrtc failed");
return 1;
}
printf("Frame displayed. Press Enter to exit...\n");
getchar();
// Clean up
munmap(map, size);
drmModeRmFB(fd, fb);
struct drm_mode_destroy_dumb dreq = {0};
dreq.handle = handle;
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
drmModeFreeEncoder(encoder);
drmModeFreeConnector(connector);
drmModeFreeResources(resources);
close(fd);
return 0;
}
에러발생
/usr/include/xf86drm.h:40:10: fatal error: drm.h: No such file or directory
40 | #include <drm.h>
| ^~~~~~~
1.
pkg-config --cflags libdrm
dpkg -L libdrm-dev | grep drm.h
find /usr/include -name drm.h
drm.h가 있나보라
1-1) 컴파일 할때 -I옵션을 주던가
1-2) Makefile에 추가하기
# 컴파일러
CC := gcc
# 컴파일 옵션
CFLAGS := -Wall -O2 -I/usr/include/libdrm
#CFLAGS := -Wall -O2 -I/usr/include/libdrm
# ㄴ 이게 핵심이다.
# 링커 옵션
LDFLAGS := -ldrm
LDFLAGS_prepend = "-linput "
# 타겟 실행 파일 이름
TARGET := drm_example
# 소스 파일
SRC := drm_example.c
# 기본 빌드 타겟
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC) $(LDFLAGS)
# 정리
clean:
rm -f $(TARGET)
1-3) 환경 변수 사용
export C_INCLUDE_PATH=/usr/include/libdrm:$C_INCLUDE_PATH
gcc -o drm_example drm_example.c -ldrm
*에러 참고링크
https://github.com/agherzan/meta-raspberrypi/issues/987
https://forum.lvgl.io/t/what-drm-and-libinput-library-versions-is-lvgl-expecting/18426/2
https://bugs.gentoo.org/689768
$ pkg-config --cflags libdrm
-I/usr/include/libdrm
메이크 잘 되어졌다.
./drm_example
drmModeSetCrtc failed: Permission denied
실행시 에러 발생
2. 사용자를 video 그룹에 추가하기
DRM 디바이스 파일들은 일반적으로 video 그룹 소유입니다:
ls -l /dev/dri/
crw-rw----+ 1 root video 226, 0 Jun 10 10:00 card0
sudo usermod -aG video $USER
3. 권한 임시 변경 (테스트용)
sudo chmod a+rw /dev/dri/*
보안상 권장되지 않으며, 부팅 시 초기화됩니다.
4. udev rules로 영구 권한 변경 (선택사항)
/etc/udev/rules.d/99-drm.rules에 아래 내용 추가:
KERNEL=="card*", GROUP="video", MODE="0660"
sudo udevadm control --reload-rules
sudo udevadm trigger
X서버 또는 Wayland에서 실행하면 안된다.
✔️ 해당 프로그램은 CRTC 설정을 직접 하므로, Xorg/Wayland가 실행 중이면 실패합니다.
echo $XDG_SESSION_TYPE
결과가 x11, wayland, 또는 wayland+x11이면 GUI가 실행 중이라는 뜻입니다.
콘솔로 전환
sudo systemctl stop lightdm # Ubuntu 계열
sudo systemctl stop display-manager # 일반적으로 이걸로도 가능
라즈베리파이*
sudo systemctl disable lightdm
sudo reboot
✅ 장치가 실제로 CRTC를 지원하는지 확인
sudo apt install libdrm-tests
modetest -c
이 명령으로 CRTC/Connector 정보가 출력되지 않으면, 해당 드라이버가 KMS 모드를 제대로 지원하지 않는 겁니다.
lightdm 을 끄고 ./drm_example 실행하면
HDMI 화면에 파란색화면이 나타난다.
이로써 라즈베리파이에서도 DRM출력이 가능한 것을 알게되었다.
'로봇만들기 > raspberry pi 3' 카테고리의 다른 글
raspberry pi 3 B 카메라 입력 받아 출력하기 (0) | 2025.06.04 |
---|---|
raspberry pi 3 원격 [폴더설정/terminal] 접속 (0) | 2025.06.04 |
raspberry pi 3 B 우분투 올리기 (0) | 2025.06.04 |