2011-12-15 4 views
1

ARM 기반 보드에 LCD 디스플레이 드라이버를 쓰려고합니다. LCD 컨트롤러가 외부 메모리 버스에 연결되어 있습니다. 그래서 컨트롤러의 레지스터의 실제 주소를 가상 주소로 변환하려고합니다.ARM 기반 보드의 커널 공간에서 외부 버스에 액세스

내가 할 아래의 코드를 사용하는 :

#define AT91_VA_BASE_CS2 phys_to_virt(0x50000000) 

static inline unsigned char at91_CS2_read(unsigned int reg) 
{ 
    void __iomem *CS2_base = (void __iomem *)AT91_VA_BASE_CS2; 

    return __raw_readb(CS2_base + reg); 
} 

static inline void at91_CS2_write(unsigned int reg, unsigned char value) 
{ 
    void __iomem *CS2_base = (void __iomem *)AT91_VA_BASE_CS2; 

    __raw_writeb(value, CS2_base + reg); 
} 

void write_lcd_port (int mode, unsigned char cmd_dat) 
{ 
    while ((read_lcd_port() & 0x03) != 0x03) { 
     /* wait while LCD is busy!!! */ 
    } /* endwhile */ 


    /* Send Command */ 
    if (mode == 1) 
    { 
     at91_CS2_write(4, cmd_dat); 
    } 
    /* Send Data */ 
    if (mode == 0) 
    { 
     at91_CS2_write(0, cmd_dat); 
    } 
} 

나는 다음과 같은 메시지가 얻을 :이 방법은 내장 주변 장치에 대한 작동

Unable to handle kernel paging request at virtual address 4f000004 
pgd = c39bc000 
[4f000004] *pgd=00000000 
Internal error: Oops: 5 [#1] 
Modules linked in: module_complet dm9000 at91_wdt vfat fat jffs2 nls_iso8859_1 nls_cp437 nls_base usb_storage sd_mod sg scsie 
CPU: 0 
PC is at read_lcd_port+0x1c/0x38 [module_complet] 
LR is at 0x1 
pc : [<bf0a21b8>] lr : [<00000001>] Tainted: P 
sp : c380bf1c ip : 60000093 fp : c380bf2c 
r10: 0003a804 r9 : c380a000 r8 : c001de64 
r7 : 00000000 r6 : fefff000 r5 : 0000009c r4 : 00000001 
r3 : 4f000000 r2 : 00000000 r1 : 00001438 r0 : bf0a25cc 
Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment user 
Control: C000717F Table: 239BC000 DAC: 00000015 
Process insmod (pid: 903, stack limit = 0xc380a198) 
Stack: (0xc380bf1c to 0xc380c000) 
bf00:                00000001 
bf20: c380bf44 c380bf30 bf0a21f4 bf0a21ac 00000000 fefa0000 c380bf54 c380bf48 
bf40: bf0a2288 bf0a21e4 c380bf64 c380bf58 bf0a246c bf0a2280 c380bf84 c380bf68 
bf60: bf0a4058 bf0a2464 40017000 c01c89a0 bf0a2d80 c01c8990 c380bfa4 c380bf88 
bf80: c004cd20 bf0a4010 00000003 00000000 0000000c 00000080 00000000 c380bfa8 
bfa0: c001dcc0 c004cbc8 00000000 0000000c 00900080 40017000 0000162e 00041050 
bfc0: 00000003 00000000 0000000c bea0fde4 bea0fec4 00000002 0003a804 00000000 
bfe0: bea0fd10 bea0fd04 0001b290 400d1d20 60000010 00900080 20002031 20002431 
Backtrace: 
[<bf0a219c>] (read_lcd_port+0x0/0x38 [module_complet]) from [<bf0a21f4>] (write_lcd_port+0x20/0x80 [module_complet]) 
r4 = 00000001 
[<bf0a21d4>] (write_lcd_port+0x0/0x80 [module_complet]) from [<bf0a2288>] (wr_cmd+0x18/0x1c [module_complet]) 
r5 = FEFA0000 r4 = 00000000 
[<bf0a2270>] (wr_cmd+0x0/0x1c [module_complet]) from [<bf0a246c>] (lcd_init+0x18/0x80 [module_complet]) 
[<bf0a2454>] (lcd_init+0x0/0x80 [module_complet]) from [<bf0a4058>] (mon_module_init+0x58/0xcc [module_complet]) 
[<bf0a4000>] (mon_module_init+0x0/0xcc [module_complet]) from [<c004cd20>] (sys_init_module+0x168/0x2c8) 
r6 = C01C8990 r5 = BF0A2D80 r4 = C01C89A0 
[<c004cbb8>] (sys_init_module+0x0/0x2c8) from [<c001dcc0>] (ret_fast_syscall+0x0/0x2c) 
r7 = 00000080 r6 = 0000000C r5 = 00000000 r4 = 00000003 
Code: e59f001c eb3e43c2 e3a0344f e59f0014 (e5d34004) 
Segmentation fault 

주 (예 : 타이머와 같은)를. 따라서 어떤 경우에는 phys_to_virt가 작동합니다. 주소 0x50000000에 페이지가 할당되지 않았다고 생각합니다. 이 특정 주소에 페이지를 어떻게 할당합니까? kmap과 같은 함수를 찾았지만 매우 복잡해 보이며 사용법을 모릅니다.

답변

4

메모리 매핑 주변 장치에 액세스하는 가장 좋은 방법은 커널의 ioremap 및 친구들과 함께하는 것입니다.

먼저, 당신이 당신의 주변 메모리의 특정 영역을 사용하려면 선언 : 당신이 당신의 드라이버를 언로드 할 때

struct resource *res = request_mem_region(0x50000000, region_size, "at91"); 

, 당신은 그 메모리 영역을 확보 할 것입니다.

release_mem_region(0x50000000, region_size); 

이제 사용하기 전에 I/O 영역을 다시 매핑 할 수 있습니다.

void *ptr = ioremap(0x50000000, region_size); 

이러한 레지스터의 캐싱을 방지하려면 대신 ioremap_nocache을 사용하십시오. 또한 해당 부분 만 사용하는 경우 장치의 메모리 공간 하위 영역을 다시 매핑 할 수도 있습니다.

이제 iomapped 영역이 있으므로 해당 메모리에서 I/O를 수행 할 수 있습니다.

iowrite8(value, (char *)ptr + reg); 
unsigned int val = ioread8((char *)ptr + reg); 

메모리 영역을 읽고 쓰면 해당 영역의 매핑을 해제 할 수 있습니다.

iounmap(ptr); 

나는이 도움이되기를 바랍니다. 나는 무료로 온라인으로 읽을 수있는 Linux Device Drivers, 3rd Edition을 읽는 것을 추천한다.

관련 문제