2014-04-29 2 views
0

지연된 IO 메커니즘을 사용하여 프레임 버퍼 노드의 변경 사항을 추적하는 Linux 커널 드라이버를 구현했습니다.프레임 버퍼 노드를 사용하여 사용자 공간에서 커널 공간으로 쓰기가 지연되었습니다.

static struct fb_deferred_io fb_defio = { 
     .delay   = HZ/2, 
     .deferred_io = fb_dpy_deferred_io, 
}; 

등록 된 프레임 버퍼 노드는/dev/graphics/fb1입니다.

이 노드에 액세스 할 수있는 샘플 애플리케이션 코드는 다음과 같습니다

fbfd = open("/dev/graphics/fb1", O_RDWR); 
if (!fbfd) { 
    printf("error\n"); 
    exit(0); 
} 
screensize = 540*960*4; 
/* Map the device to memory */ 
fbp = (unsigned char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, 
        fbfd, 0); 
if ((int)fbp == -1) { 
    printf("Error: failed to start framebuffer device to memory."); 
} 

int grey = 0x1; 
    for(cnt = 0; cnt < screensize; cnt++) 
      *(fbp + cnt) = grey<<4|grey; 

이 하나의와 전체 FB1 노드를 채울 것입니다.

다른 위치에서 데이터가 일치하지 않는 전체 버퍼를 읽으려고하면 커널 드라이버에서 문제가 발생합니다.

커널 버퍼

같이 매핑된다 :

par->buffer = dma_alloc_coherent(dev, roundup((dpyw*dpyh*BPP/8), PAGE_SIZE),(dma_addr_t *) &DmaPhysBuf, GFP_KERNEL); 
if (!par->buffer) { 
     printk(KERN_WARNING "probe: dma_alloc_coherent failed.\n"); 
     goto err_vfree; 
} 

최종적 버퍼 register_framebuffer 함수를 통해 등록된다.

원본 버퍼를 읽을 때 임의의 위치에서 이전 데이터가 반영되는 대신 데이터가 기록되지 않습니다. 예를 들어

: 버퍼 위치 3964에서

난 11111111 기대했지만, 난 FF00FF00 알았다. 회색의 값과 동일한 응용 프로그램을 실행하는 방법에

내가 22,222,222 예상 된 버퍼 위치 3964에서 22,222,222

변경하지만, 일부 지연있을 것처럼 11111111 것 같습니다

발견 버퍼에 쓴다. 부분적으로 잘못된 데이터로 인해 이미지가 손상되어이 효과에 대한 해결책이 있습니까?

추가 정보가 필요하면 알려주십시오.

참고 : 매핑 할 수있는 버퍼가 캐시 가능한지 여부와 같습니다. 캐시에서 램으로 데이터를 복사하는 게으른 쓰기. 데이터가 제대로 복사되는지 확인해야하지만 여전히 좋은 생각은 아닙니다. :-(

답변

0

결국 나는이 문제를 해결하는 더 좋은 방법을 찾았습니다.mmaped 장치 노드에서 app을 통해 작성된 데이터는 나중에 지연된 쓰기 정책을 통해 나중에 RAM에 기록되는 캐시에 기록됩니다. 데이터가 제대로 플러시되는지 확인하려면 커널에서 flush 함수를 호출해야합니다. 나는 커널이 깨끗한 데이터를 수신 할 수 있도록 데이터를 완전히 플러시하기 위해

dmac_flush_range((void *)pSrc, (void *)pSrc + bufSize); 

을 사용했다.

1

"Deferred io"는 프레임 버퍼 메모리가 디스플레이 장치에 실제로 매핑되지 않고, 대신 일반 메모리 영역이 공유됨을 의미합니다. . 사용자 프로세스와 커널 드라이버 사이에 따라서는 커널이 실제로 그것에 대해 아무것도 할 수 있도록 "동기화"해야합니다 :.

msync(fbp, screensize, MS_SYNC); 

fsync(fbfd)도 작동 할 수 호출을

또한 드라이버 경우 ​​ioctl(fbfd, FBIO_WAITFORVSYNC, 0)를 호출하려고 할 수 있습니다 이 호출은 vsync가 발생할 때까지 응용 프로그램이 대기하게하고 프레임 버퍼 da ta는 확실히 장치로 전송되었습니다.

+0

응용 프로그램 코드에서 msync와 fsync 줄을 모두 추가하려고했습니다. 그러나 데이터가 여전히 올바르지 않습니다. – Anshul

1

화면에 임의의 아티팩트가 표시되는 것과 비슷한 문제가 발생했습니다. 원래 프레임 버퍼 드라이버는 전혀 dma를 사용하지 않았습니다.

msync()를 사용하여 상황을 개선 한 제안 (인공물이 자주 발생하지는 않음)을 시도했지만 문제를 완전히 해결하지 못했습니다.

일부 연구를 한 후 캐시되지 않았기 때문에 dma 메모리를 사용해야한다는 결론에 도달했습니다. 커널 메모리를 사용자 공간에 매핑하기 때문에 mmap에 여전히 문제가 있습니다. 그러나, 나는 커널에이 기능을 처리하는 기능이 이미 있음을 알았다.

그래서, 내 솔루션은 내 프레임 버퍼 드라이버에 있던 mmap에 기능 설정 :

static int my_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) 
{ 
     return dma_mmap_coherent(info->dev, vma, info->screen_base, 
           info->fix.smem_start, info->fix.smem_len); 
} 

static struct fb_ops my_fb_ops = { 
     ... 
     .fb_mmap = my_fb_mmap, 
}; 

그리고 프로브 기능에 : 분명히

struct fb_info *info; 
struct my_fb_par *par; 
dma_addr_t dma_addr; 
char *buf 

info = framebuffer_alloc(sizeof(struct my_fb_par), &my_parent->dev); 
... 
buf = dma_alloc_coherent(info->dev, MY_FB_SIZE, dma_addr, GFP_KERNEL); 
... 
info->screen_base = buf; 
info->fbops = &my_fb_ops; 
info->fix = my_fb_fix; 
info->fix.smem_start = dma_addr; 
info->fix.smem_len = MY_FB_SIZE; 
... 
par = info->par 
... 
par->buffer = buf; 

를, 나는 오류 확인을 떠 났어요 푸는 것, 그러나 잘하면 나는 모든 중요한 부분을 만져 보았습니다.

참고 : 커널 소스의 의견에 따르면 dmac_flush_range()는 개인적인 용도로만 사용됩니다.

관련 문제