新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM-Linux驅(qū)動--ADC驅(qū)動(中斷方式)

        ARM-Linux驅(qū)動--ADC驅(qū)動(中斷方式)

        作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
        硬件平臺:FL2440

        內(nèi)核版本:2.6.28

        本文引用地址:http://www.104case.com/article/201611/318862.htm

        主機(jī)平臺:Ubuntu 11.04

        內(nèi)核版本:2.6.39

        原創(chuàng)作品,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/yming0221/archive/2011/06/26/6568937.aspx

        這個驅(qū)動寫了好久,因?yàn)樵瓉淼腖inux內(nèi)核編譯的時候?qū)?strong>觸摸屏驅(qū)動編譯進(jìn)內(nèi)核了,而觸摸屏驅(qū)動里的ADC中斷在注冊的時候類型選擇的是

        IRQF_SAMPLE_RANDOM,不是共享類型,所以,自己寫的ADC驅(qū)動在每次open的時候,總提示ADC中斷注冊失敗。

        解決方案:

        重新配置內(nèi)核,選擇觸摸屏驅(qū)動以模塊的形式編譯,而不是直接編譯進(jìn)內(nèi)核,這樣Linux在啟動的時候不會自動加載觸摸屏驅(qū)動,當(dāng)然,IRQ_ADC中斷號不會被占用。這樣可以測試自己寫的ADC驅(qū)動了。

        以下是驅(qū)動源代碼:

        1. #include
        2. #include
        3. #include
        4. #include/*創(chuàng)建設(shè)備節(jié)點(diǎn)*/
        5. #include
        6. #include/*定義DECLARE_WAIT_QUEUE_HEAD*/
        7. #include/*定義了irqreturn_t等*/
        8. #includeinterrupt.h>/*request_irqdisable_irqenable_irq*/
        9. #include
        10. #include
        11. #include/*其中包含了#include"mach/irqs.h"*/
        12. #includeadc.h>
        13. #include
        14. #defineADC_MAJOR102
        15. #defineADC_NAME"my_adc"
        16. #defineSUCCESS0
        17. staticintadc_open(structinode*,structfile*);
        18. staticintadc_release(structinode*,structfile*);
        19. staticint__initadc_init(void);
        20. staticint__exitadc_exit(void);
        21. staticssize_tadc_read(structfile*,char*,size_t,loff_t*);
        22. volatileunsignedlongadc_con;
        23. unsignedlongadc_dat0;
        24. intflag;//等待任務(wù)完成標(biāo)志
        25. unsignedlongbuf;//存放轉(zhuǎn)換完成的數(shù)據(jù)
        26. //聲明等待隊(duì)列
        27. DECLARE_WAIT_QUEUE_HEAD(adc_wait);
        28. structclk*adc_clk;
        29. staticirqreturn_tadc_interrupt(intirq,void*dev_id)//中斷處理程序
        30. {
        31. if(flag==0)
        32. {
        33. buf=(readw(adc_dat0)&0x3ff);//讀取轉(zhuǎn)換完成的數(shù)據(jù)
        34. flag=1;
        35. wake_up_interruptible(&adc_wait);//喚醒等待其上的進(jìn)程
        36. printk("Readvalueis%ld/n",buf);
        37. }
        38. returnIRQ_HANDLED;
        39. }
        40. structfile_operationsadc_ops=
        41. {
        42. .owner=THIS_MODULE,
        43. .read=adc_read,
        44. .open=adc_open,
        45. .release=adc_release,
        46. };
        47. staticint__initadc_init(void)
        48. {
        49. intret;
        50. adc_clk=clk_get(NULL,"adc");//獲取時鐘
        51. clk_enable(adc_clk);//使能時鐘
        52. ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops);//注冊設(shè)備
        53. if(ret<0)
        54. {
        55. printk("registerdevicefail/n");
        56. returnret;
        57. }
        58. adc_con=(unsignedlong)ioremap(0x58000000,4);
        59. adc_dat0=(volatileunsignedlong)ioremap(0x58000000+S3C2410_ADCDAT0,4);
        60. if(!(adc_con&adc_dat0))
        61. {
        62. printk("Failedtoioremap/n");
        63. gotohandle;
        64. }
        65. printk("Initialized.../n");
        66. returnSUCCESS;
        67. handle:
        68. unregister_chrdev(ADC_MAJOR,ADC_NAME);
        69. return-1;
        70. }
        71. staticintadc_open(structinode*inode,structfile*file)//打開設(shè)備函數(shù)
        72. {
        73. //注冊中斷
        74. intret;
        75. //disable_irq(IRQ_ADC);
        76. //enable_irq(IRQ_ADC);
        77. ret=request_irq(IRQ_ADC,adc_interrupt,IRQF_SHARED,ADC_NAME,1);//注冊中斷IRQ_ADC在mach/irqs.h中定義
        78. if(ret<0)
        79. {
        80. printk("IRQ%dcannotrequest/n",IRQ_ADC);
        81. returnret;
        82. }
        83. returnSUCCESS;
        84. }
        85. staticintadc_release(structinode*inode,structfile*file)//關(guān)閉設(shè)備函數(shù)
        86. {
        87. free_irq(IRQ_ADC,1);//釋放中斷
        88. returnSUCCESS;
        89. }
        90. staticssize_tadc_read(structfile*file,
        91. char*buffer,
        92. size_tlength,
        93. loff_t*offset)//設(shè)備讀取函數(shù)
        94. {
        95. writew((1<<14)|(0x31<<6),adc_con);//設(shè)置ADCCON
        96. writew((readw(adc_con)|0x1),adc_con);//啟動AD轉(zhuǎn)換
        97. wait_event_interruptible(adc_wait,flag);
        98. flag=0;
        99. }
        100. staticint__exitadc_exit(void)//驅(qū)動卸載函數(shù)
        101. {
        102. iounmap(adc_con);
        103. iounmap(adc_dat0);
        104. unregister_chrdev(ADC_MAJOR,ADC_NAME);
        105. clk_disable(adc_clk);
        106. clk_put(adc_clk);
        107. printk("Theadcisunintialized/n");
        108. returnSUCCESS;
        109. }
        110. module_init(adc_init);
        111. module_exit(adc_exit);
        112. MODULE_LICENSE("GPL");

        Makefile文件:

        1. obj-m:=adc.o
        2. KERNELDIR?=/arm/linux-2.6.28.7-2440
        3. PWD:=$(shellpwd)
        4. default:
        5. $(MAKE)-C$(KERNELDIR)M=$(PWD)modules
        6. clean:
        7. rm-f*.o*.ko*.order*.symversread
        8. read:
        9. arm-linux-gcc-oreadread_adc.c

        以下是測試代碼:

        1. #include
        2. #include
        3. #include
        4. #defineADC_DEVICE"/dev/my_adc"
        5. intmain()
        6. {
        7. intret;
        8. unsignedintdata;
        9. ret=open(ADC_DEVICE,0);
        10. if(ret<0)
        11. {
        12. printf("Openadcfail/n");
        13. returnret;
        14. }
        15. for(;;)
        16. {
        17. //printf("cnt=%d/n",cnt);
        18. read(ret,&data,sizeof(data));
        19. //printf("Thevalueis%d/n",data);
        20. }
        21. close(ret);
        22. return0;
        23. }

        首先新建設(shè)備:

        mknod /dev/my_adc c 102 32

        然后插入驅(qū)動 insmod adc.ko

        運(yùn)行測試程序./read

        結(jié)果如下:

        可以看出,調(diào)節(jié)ad轉(zhuǎn)換器上的旋鈕,看到AD轉(zhuǎn)換值的變化,說明驅(qū)動工作正常。



        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 宜兴市| 五台县| 大石桥市| 昭觉县| 景德镇市| 武鸣县| 颍上县| 拉萨市| 务川| 蒙阴县| 台江县| 乳源| 广昌县| 界首市| 定南县| 建阳市| 民县| 苏尼特右旗| 华坪县| 抚顺市| 云林县| 南川市| 蓝山县| 苍南县| 兴安盟| 临武县| 鸡西市| 永德县| 静海县| 曲靖市| 蒙山县| 丰台区| 广东省| 屯门区| 徐汇区| 延寿县| 武城县| 海阳市| 湘乡市| 高要市| 莱阳市|