當前位置: 華文星空 > 體育

Linux 內核驅動

2022-11-12體育

1. ADC內核驅動實作框架
ADC 內核驅動的實作是基於 ARM ADC BSP 驅動 與 Linux 內核驅動的框架進行銜接,主要分為以下幾個部份構成:
在底層采用的 Linux 內核裝置模型,基於 platform 平台匯流排
在 VFS 層使用的是 Linux 內核字元裝置驅動框架,用於實作 VFS 層 相應的驅動存取介面
2. ADC 內核驅動 platfrom 匯流排實作
2.1 platfrom 匯流排的註冊
基於 platfrom 匯流排部份,主要用於銜接 BSP 驅動 與上層的 字元裝置驅動的存取介面.
platfrom 匯流排實作包含驅動描述與裝置描述,其中裝置描述在 Linux 內核裝置樹中描述. 需要在 exynos4412-fs4412.dts 中添加如下描述
adc@126c0000{
compatible = "Samsung,exynos4412-adc"; reg = <0x126c0000 0x20>;
adc-io-channer = <3>;
clocks = <&clock 326>;
clock-names = "adc"; interrupt-parent = <&combiner>;
interrupts = <10 3>;
= "okay"; status
};platfrom 驅動描述結構定義如下:


在上述結構中, of_match_table 成員的描述如下:
#if defined(CONFIG_OF)
static const struct of_device_id exynos_adc_dt_ids[] = {
{ .compatible = "Samsung,exynos4412-adc" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, exynos_adc_dt_ids);
#endif
在 platfrom 平台匯流排註冊與解除安裝 ADC 驅動,具體程式碼如下:
int adc_device_init(void)
{
//註冊 platfrom driver
return platform_driver_register(&exynosadc_driver);
}
void adc_device_exit(void)
{
//解除安裝 platfrom driver
return platform_driver_unregister(&exynosadc_driver);
}2.1 probe 函式的實作
在 probe 實作以下功能:
分配 adc 裝置描述結構體的空間獲取 platfrom 驅動私有數據
申請中斷資源
獲取IO記憶體資源
申請IO資源的使用
寄存器地址的對映獲取 ADC 的通道註冊 ADC 字元裝置初始化等待佇列
在 remove 函式中主要實作相關資源的釋放
2.2.1 adc 裝置描述與記憶體分配
在 Linux 內核中描述 ADC 使用下面的結構,這是我們自己定義的:
struct adc_device
{
void *reg;//寄存器對映地址int major_num;//主裝置號int irq_num;//中斷號
int adc_data;//adc 裝置數據
int io_channer;//io 通 道
struct clk *adc_clk;//adc 時鐘資源
struct resource *res;//adc io 資 源
struct class *cls;//adc 裝置類
struct device *dev;//adc 裝置物件
struct cdev cdev;//adc 字元裝置物件
wait_queue_head_t read_event_wait;//等待佇列頭
};
在分配 adc 結構體時,使用的是 kzalloc 函式,具體實作如下:


2.2.2 設定 platform 平台私有數據
獲取 platform 私有數據,需要呼叫 platform_set_drvdata 數據
static inline void platform_set_drvdata(struct platform_device
*pdev,void *data)
@param pdev : platform 平台匯流排裝置描述結構
@param data : 需要儲存的
這裏主要是將對應的 struct adc_device 物件的地址儲存在 struct device 結構體中的
driver_data 成員中,方便其他函式存取,主要是針對有過平台裝置時,不同的平台裝置有不同
的結構來描述,在匹配成功之後要進行區分
2.2.3 獲取中斷資源
這裏獲取中斷資源主要是獲取中斷號,透過 platform_get_irq 函式來實作
padc->irq_num = platform_get_irq(pdev, 0);
if(padc->irq_num < 0){
printk("Fail to platform_get_irq\n");
ret = padc->irq_num;
goto err_platform_get_irq;
}
2.2.4 獲取 IO 記憶體資源
這裏獲取的資源為 ADC 寄存器的資源,具體程式碼如下:


在裝置樹已經有相應的描述
2.2.5 IO資源的占用
在 Linux 內核中,相應的寄存器資源需要申請才能使用,一旦申請成功之後,則不允許別人來存取這段空間.
一般在對映寄存器地址空間之前,就需要申請,這裏需要呼叫 ****
#define request_mem_region(start,n,name)
@param start : 申請資源開始的地址
@param n : 申請資源的長度
@param name : 申請的資源的裝置的名字
具體實作如下:
if(!request_mem_region(padc->res->start,io_resource_size,pdev->name))
{
printk("Fail to request_mem_region\n"); ret = -EBUSY;
goto err_request_mem_region;
當需要解除相應的 IO 資源時,則需要呼叫 release_resource 函式
int release_resource(struct resource *old)
參數:
@param resource : 指定 adc 資源結構物件的指標
2.2.6 獲取 adc 的數據通道
adc 的數據通道是在裝置樹中進行描述,在這裏只是獲取,具體需要呼叫:
of_property_read_u32(pdev->dev.of_node, "adc-io-channer", &padc->io_cha
nner);
由於文章字數有限,更多基於Linux adc 驅動實作文章請添加QQ:(1912904432)索要完整版文章


include <stdio.h>
int main() {
printf("hello world!\n");
return 0;
}