can裝置驅動

2021-07-25 23:59:21 字數 3419 閱讀 1963

**

拿到乙個裝置驅動,首先要看的是裝置初始化函式。

static int __init mcp251x_init(void)  

return spi_register_driver(&mcp251x_driver);  

}  class_create()用於自動建立裝置節點,我們可以暫時不看,有興趣的可以看看linux原始碼。alloc_chrdev_region()自動為driver_name分配裝置號。在這裡,我們真正關心的是spi_register_driver()函式和mcp251x_driver結構體的內容。

我們先看spi_register_driver()的內容。

/** 

* spi_register_driver - register a spi driver 

* @sdrv: the driver to register 

* context: can sleep 

*/  

int spi_register_driver(struct spi_driver *sdrv)  

spi_register_driver()完成了驅動在匯流排的掛載以及spi驅動函式probe, remove, shutdown的賦值。那mcp251x_driver是什麼樣的結構體,裡面又儲存了什麼內容呢?

static struct spi_driver mcp251x_driver = ,  

.probe = mcp251x_probe,  

.remove = __devexit_p(mcp251x_remove),  

#ifdef config_pm   

.suspend = mcp251x_suspend,  

.resume = mcp251x_resume,  

#endif   

}; 

mcp251x_driver是結構體spi_driver的例項,在mcp251x_driver裡面完成了mcp251x驅動函式probe, remove, suspend, resume的賦值。

在進入mcp251x的驅動函式之前,我們還是先看看mcp251x的結構吧!

struct mcp251x  

;  其中的很多結構體,我們暫時不管。下面開始進入正題。

static int __devinit mcp251x_probe(struct spi_device *spi)  

/* 將mcp251x的裝置資訊儲存到spi的裝置結構體中 */  

dev_set_drvdata(&spi->dev, chip);  

/* mcp251x結構體初始化 */  

chip->txbin = chip->txbout = 0;  

chip->rxbin = chip->rxbout = 0;  

chip->count = 0;  

chip->spi = spi;  

init_mutex(&chip->lock);  

init_mutex(&chip->txblock);  

init_mutex(&chip->rxblock);  

init_waitqueue_head(&chip->wq);  

#if (linux_version_code >= kernel_version(2,6,20))   

init_work(&chip->irq_work, mcp251x_irq_handler);  

#else   

init_work(&chip->irq_work, mcp251x_irq_handler, spi);  

#endif   

/* 為spi的buf分配空間 */  

chip->spi_transfer_buf = kmalloc(spi_transfer_buf_len, gfp_kernel);  

if (!chip->spi_transfer_buf)  

/* 輸入模式,不使用內部上拉電阻 */  

at91_set_gpio_input(spi->irq, 0);  

/* 繫結輸入函式mcp251x_irq,傳遞引數spi */  

/* mcp251x_irq函式我們等下再看,先放一放 */  

ret = request_irq(spi->irq, mcp251x_irq, irqf_sample_random, driver_name, spi);  

if (ret < 0)  

if (can_minor > can_dev_max)  

goto error_register;  

if (can_major)  

else  

if (ret < 0)  

/* 字元裝置的初始化以及新增到核心 */  

cdev_init(&chip->cdev, &mcp251x_fops);  

chip->cdev.owner = this_module;  

ret = cdev_add(&chip->cdev, devid, 1);  

if (ret < 0)  

dev_info(&spi->dev, "device register at dev(%d:%d)\n", major(devid), minor(devid));  

/* 自動建立裝置檔案 */  

chip->class_dev = device_create(can_class, null,  

mkdev(major(devid), can_minor), &spi->dev, "can%d", can_minor);  

if (is_err(chip->class_dev))  

/* mcp251x初始化設定 */  

mcp251x_hw_init(spi);  

mcp251x_set_bit_rate(spi, 125000);  /* a reasonable default */  

mcp251x_hw_sleep(spi);  

return 0;  

error_class_reg:  

cdev_del(&chip->cdev);  

error_devadd:  

unregister_chrdev_region(devid, 0);  

error_register:  

free_irq(spi->irq, spi);  

error_irq:  

kfree(chip->spi_transfer_buf);  

error_buf:  

kfree(chip);  

error_alloc:  

return ret;  



裝置驅動例項 字元裝置驅動

在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...

驅動 linux裝置驅動 字元裝置驅動開發

preface 前面對linux裝置驅動的相應知識點進行了總結,現在進入實踐階段!linux 裝置驅動入門篇 linux 裝置驅動掃盲篇 fedora下的字元裝置驅動開發 開發乙個基本的字元裝置驅動 在linux核心驅動中,字元裝置是最基本的裝置驅動。字元裝置包括了裝置最基本的操作,如開啟裝置 關閉...

Linux裝置驅動之《字元裝置驅動》

linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是乙個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open close read write 等。下面是乙個字元裝置驅動程式的簡單實現test.c 模組分析 1.初始化裝置驅動的結構體 struct fil...