1. 程式人生 > >核心中與驅動相關的記憶體操作之十一(IO記憶體)

核心中與驅動相關的記憶體操作之十一(IO記憶體)

    裝置通常會提供一組暫存器用於控制裝置、讀定裝置和獲取裝置狀態,即控制暫存器、資料暫存器和狀態暫存器.這些暫存器可能位於I/O空間,也可能位於記憶體空間.當位於I/O空間時,通常被稱為I/O,位於記憶體空間時,對應的記憶體空間被稱為I/O記憶體.在嵌入式LINUX,我們接觸最多的就是I/O記憶體:

#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)

     向核心申請n個記憶體地址,這些地址從first開始,name引數為裝置的名稱.如果分配成功返回值為非

NULL,如果返回NULL,則意味著申請I/O記憶體失敗.
其相反的動作函式為:

int release_resource(struct resource *old)

   這對函式一般用來判斷I/O記憶體是否已經被佔用了.它一般配合platform_get_resource()函式來使用.platform_get_resource()用來獲取平臺裝置端的I/O記憶體地址空間,並以其返回值為引數.如下:

struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num) 

     以S3C2440的RTC為例,簡單說明:

1.	static int __devinit s3c_rtc_probe(struct platform_device *pdev)  
2.	{  
3.	    ... ...;  
4.	        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
5.	    if (res == NULL) {  
6.	        dev_err(&pdev->dev, "failed to get memory region resource\n");  
7.	        return -ENOENT;  
8.	    }  
9.	  
10.	    s3c_rtc_mem = request_mem_region(res->start,res->end-res->start+1,pdev->name);  
11.	    ... ...;  
12.	}  

    [注:]I/O記憶體一般只用來判斷我們目標操作記憶體是否被佔用,但是這並不是必須的.

        在對I/O記憶體的存取核心提供了專門的API:

1.	unsigned readb(address);  
2.	unsigned readw(address);  
3.	unsigned readl(address);   
4.	  
5.	void writeb(unsigned value, address);  
6.	void writew(unsigned value, address);  
7.	void writel(unsigned value, address);   
    

   例如S3C2440LCD驅動裡面,LCD主控端暫存器的配置:

1.	static int __init s3c24xxfb_probe(struct platform_device *pdev,enum s3c_drv_type drv_type)  
2.	{  
3.	    ... ...;  
4.	    lcdcon1 = readl(info->io + S3C2410_LCDCON1);  
5.	    writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);  
6.	    ... ...;  
7.	}