核心中與驅動相關的記憶體操作之十一(IO記憶體)
阿新 • • 發佈:2019-02-19
裝置通常會提供一組暫存器用於控制裝置、讀定裝置和獲取裝置狀態,即控制暫存器、資料暫存器和狀態暫存器.這些暫存器可能位於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);
例如S3C2440的LCD驅動裡面,對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. }