<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > S3C2440驅動(dòng)簡(jiǎn)析——串口驅動(dòng)

S3C2440驅動(dòng)簡(jiǎn)析——串口驅動(dòng)

作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò ) 收藏
對于驅動(dòng)的學(xué)習停歇了幾乎一周的時(shí)間,期間忙于補習Linux應用編程和搜索驅動(dòng)、內核相關(guān)書(shū)籍,以便之后更進(jìn)一步地學(xué)習。在之前友善提供的驅動(dòng)例程里面,涉及的知識面非常有限,需要研究更多的驅動(dòng)源碼,了解更多的驅動(dòng)知識,是當務(wù)之急。研究別人代碼的同時(shí),當然不忘自己也要動(dòng)手練習。以下貼出串口驅動(dòng)程序,并在程序里附上簡(jiǎn)要注釋。
[c-sharp]view plaincopy
  1. // linux/drivers/serial/s3c2440.c
  2. *
  3. *DriverforSamsungS3C2440andS3C2442SoConboardUARTs.
  4. *
  5. *BenDooks,Copyright(c)2003-2005,2008SimtecElectronics
  6. *http://armlinux.simtec.co.uk/
  7. *
  8. *Thisprogramisfreesoftware;youcanredistributeitand/ormodify
  9. *itunderthetermsoftheGNUGeneralPublicLicenseversion2as
  10. *publishedbytheFreeSoftwareFoundation.
  11. //
  12. #include"linux/module.h"
  13. #include"linux/ioport.h"
  14. #include"linux/io.h"
  15. #include"linux/platform_device.h"
  16. #include"linux/init.h"
  17. #include"linux/serial_core.h"
  18. #include"linux/serial.h"
  19. #include"asm/irq.h"
  20. #include"mach/hardware.h"
  21. #include"plat/regs-serial.h"
  22. #include"mach/regs-gpio.h"
  23. #include"samsung.h"
  24. staticints3c2440_serial_setsource(structuart_port*port,
  25. structs3c24xx_uart_clksrc*clk)
  26. {//本函數選定串口端口和時(shí)鐘源
  27. unsignedlongucon=rd_regl(port,S3C2410_UCON);//讀取寄存器UCON
  28. // todo-properfclk<>nonfclkswitch.//
  29. ucon&=~S3C2440_UCON_CLKMASK;//#defineS3C2440_UCON_CLKMASK(3<<10)
  30. if(strcmp(clk->name,"uclk")==0)//選擇時(shí)鐘源
  31. ucon|=S3C2440_UCON_UCLK;
  32. elseif(strcmp(clk->name,"pclk")==0)
  33. ucon|=S3C2440_UCON_PCLK;
  34. elseif(strcmp(clk->name,"fclk")==0)
  35. ucon|=S3C2440_UCON_FCLK;
  36. else{
  37. printk(KERN_ERR"unknownclocksource%s/n",clk->name);
  38. return-EINVAL;
  39. }
  40. wr_regl(port,S3C2410_UCON,ucon);//把設置過(guò)的ucon寫(xiě)回串口控制寄存器
  41. return0;
  42. }
  43. staticints3c2440_serial_getsource(structuart_port*port,
  44. structs3c24xx_uart_clksrc*clk)
  45. {//設置時(shí)鐘源和對應預分頻值
  46. unsignedlongucon=rd_regl(port,S3C2410_UCON);
  47. unsignedlongucon0,ucon1,ucon2;
  48. switch(ucon&S3C2440_UCON_CLKMASK){
  49. caseS3C2440_UCON_UCLK:
  50. clk->divisor=1;
  51. clk->name="uclk";
  52. break;
  53. caseS3C2440_UCON_PCLK:
  54. caseS3C2440_UCON_PCLK2:
  55. clk->divisor=1;
  56. clk->name="pclk";
  57. break;
  58. caseS3C2440_UCON_FCLK:
  59. //thefunofcalculatingtheuartdivisorson
  60. *thes3c2440//
  61. ucon0=__raw_readl(S3C24XX_VA_UART0+S3C2410_UCON);
  62. ucon1=__raw_readl(S3C24XX_VA_UART1+S3C2410_UCON);
  63. ucon2=__raw_readl(S3C24XX_VA_UART2+S3C2410_UCON);
  64. printk("ucons:lx,lx,lx/n",ucon0,ucon1,ucon2);
  65. ucon0&=S3C2440_UCON0_DIVMASK;
  66. ucon1&=S3C2440_UCON1_DIVMASK;
  67. ucon2&=S3C2440_UCON2_DIVMASK;
  68. if(ucon0!=0){
  69. clk->divisor=ucon0>>S3C2440_UCON_DIVSHIFT;
  70. clk->divisor+=6;
  71. }elseif(ucon1!=0){
  72. clk->divisor=ucon1>>S3C2440_UCON_DIVSHIFT;
  73. clk->divisor+=21;
  74. }elseif(ucon2!=0){
  75. clk->divisor=ucon2>>S3C2440_UCON_DIVSHIFT;
  76. clk->divisor+=36;
  77. }else{
  78. //manualcalims44,seemstobe9//
  79. clk->divisor=9;
  80. }
  81. clk->name="fclk";
  82. break;
  83. }
  84. return0;
  85. }
  86. staticints3c2440_serial_resetport(structuart_port*port,
  87. structs3c2410_uartcfg*cfg)
  88. {//重設串口
  89. unsignedlongucon=rd_regl(port,S3C2410_UCON);
  90. dbg("s3c2440_serial_resetport:port=%p(lx),cfg=%p/n",
  91. port,port->mapbase,cfg);
  92. //ensurewedontchangetheclocksettings...//
  93. ucon&=(S3C2440_UCON0_DIVMASK|(3<<10));
  94. wr_regl(port,S3C2410_UCON,ucon|cfg->ucon);//重新設置寄存器UCON
  95. wr_regl(port,S3C2410_ULCON,cfg->ulcon);//重新設置寄存器ULCON
  96. //resetbothfifos//
  97. wr_regl(port,S3C2410_UFCON,cfg->ufcon|S3C2410_UFCON_RESETBOTH);//重啟fifo
  98. wr_regl(port,S3C2410_UFCON,cfg->ufcon);//重新設定寄存器UFCON
  99. return0;
  100. }
  101. staticstructs3c24xx_uart_infos3c2440_uart_inf={//串口設備環(huán)境信息和提供的操作函數
  102. .name="SamsungS3C2440UART",
  103. .type=PORT_S3C2440,
  104. .fifosize=64,
  105. .rx_fifomask=S3C2440_UFSTAT_RXMASK,
  106. .rx_fifoshift=S3C2440_UFSTAT_RXSHIFT,
  107. .rx_fifofull=S3C2440_UFSTAT_RXFULL,
  108. .tx_fifofull=S3C2440_UFSTAT_TXFULL,
  109. .tx_fifomask=S3C2440_UFSTAT_TXMASK,
  110. .tx_fifoshift=S3C2440_UFSTAT_TXSHIFT,
  111. .get_clksrc=s3c2440_serial_getsource,
  112. .set_clksrc=s3c2440_serial_setsource,
  113. .reset_port=s3c2440_serial_resetport,
  114. };
  115. //devicemanagement//
  116. staticints3c2440_serial_probe(structplatform_device*dev)
  117. {//完成串口的添加
  118. dbg("s3c2440_serial_probe:dev=%p/n",dev);
  119. returns3c24xx_serial_probe(dev,&s3c2440_uart_inf);
  120. }
  121. staticstructplatform_drivers3c2440_serial_driver={//注冊串口設備
  122. .probe=s3c2440_serial_probe,
  123. .remove=__devexit_p(s3c24xx_serial_remove),
  124. .driver={
  125. .name="s3c2440-uart",
  126. .owner=THIS_MODULE,
  127. },
  128. };
  129. s3c24xx_console_init(&s3c2440_serial_driver,&s3c2440_uart_inf);
  130. staticint__inits3c2440_serial_init(void)
  131. {//初始化模塊
  132. returns3c24xx_serial_init(&s3c2440_serial_driver,&s3c2440_uart_inf);
  133. }
  134. staticvoid__exits3c2440_serial_exit(void)
  135. {//退出模塊
  136. platform_driver_unregister(&s3c2440_serial_driver);//注銷(xiāo)串口設備
  137. }
  138. module_init(s3c2440_serial_init);
  139. module_exit(s3c2440_serial_exit);
  140. MODULE_DESCRIPTION("SamsungS3C2440,S3C2442SoCSerialportdriver");
  141. MODULE_AUTHOR("BenDooks");
  142. MODULE_LICENSE("GPLv2");
  143. MODULE_ALIAS("platform:s3c2440-uart");

本文引用地址:http://dyxdggzs.com/article/201611/319506.htm

幾個(gè)問(wèn)題需要我們注意:

1.設備如何注冊、注銷(xiāo)

串口驅動(dòng)被作為一個(gè)單獨的模塊被加載進(jìn)內核,在模塊的加載和卸載函數中,只需注冊和注銷(xiāo)一個(gè)platform_driver結構體。

注冊:

[c-sharp]view plaincopy
  1. staticstructplatform_drivers3c2440_serial_driver={
  2. .probe=s3c2440_serial_probe,
  3. .remove=__devexit_p(s3c24xx_serial_remove),
  4. .driver={
  5. .name="s3c2440-uart",
  6. .owner=THIS_MODULE,
  7. },
  8. };

注銷(xiāo):

[c-sharp]view plaincopy
  1. platform_driver_unregister(&s3c2440_serial_driver);

2.幾個(gè)非常重要的結構體

s3c2410_uartcfg :保存ucon ulcon ufcon三個(gè)串口寄存器的值

[c-sharp]view plaincopy
  1. structs3c2410_uartcfg{
  2. unsignedcharhwport;//hardwareportnumber//
  3. unsignedcharunused;
  4. unsignedshortflags;
  5. upf_tuart_flags; //defaultuartflags //
  6. unsignedinthas_fracval;
  7. unsignedlongucon;//valueofuconforport//
  8. unsignedlongulcon;//valueofulconforport//
  9. unsignedlongufcon;//valueofufconforport//
  10. structs3c24xx_uart_clksrc*clocks;
  11. unsignedintclocks_size;
  12. };

s3c24xx_uart_info :提供串口設備環(huán)境信息,并提供三個(gè)函數的接口

[c-sharp]view plaincopy
  1. structs3c24xx_uart_info{
  2. char*name;
  3. unsignedinttype;
  4. unsignedintfifosize;
  5. unsignedlongrx_fifomask;
  6. unsignedlongrx_fifoshift;
  7. unsignedlongrx_fifofull;
  8. unsignedlongtx_fifomask;
  9. unsignedlongtx_fifoshift;
  10. unsignedlongtx_fifofull;
  11. //uartportfeatures//
  12. unsignedinthas_divslot:1;
  13. //clocksourcecontrol//
  14. int(*get_clksrc)(structuart_port*,structs3c24xx_uart_clksrc*clk);
  15. int(*set_clksrc)(structuart_port*,structs3c24xx_uart_clksrc*clk);
  16. //uartcontrols//
  17. int(*reset_port)(structuart_port*,structs3c2410_uartcfg*);
  18. };

platform_device :設備的信息

[c-sharp]view plaincopy
  1. structplatform_device{
  2. constchar*name;
  3. intid;
  4. structdevicedev;
  5. u32num_resources;
  6. structresource*resource;
  7. conststructplatform_device_id*id_entry;
  8. //archspecificadditions//
  9. structpdev_archdataarchdata;
  10. };

platform_driver :設備注冊用

[c-sharp]view plaincopy
  1. structplatform_driver{
  2. int(*probe)(structplatform_device*);
  3. int(*remove)(structplatform_device*);
  4. void(*shutdown)(structplatform_device*);
  5. int(*suspend)(structplatform_device*,pm_message_tstate);
  6. int(*resume)(structplatform_device*);
  7. structdevice_driverdriver;
  8. conststructplatform_device_id*id_table;
  9. };

3.讀寫(xiě)寄存器的宏定義

(1)讀寄存器

unsigned long ucon = rd_regl(port, S3C2410_UCON);

#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))

static unsigned char __raw_readb(unsigned int ptr)

{

return *((volatile unsigned char *)ptr);

}

#define portaddr(port, reg) ((port)->membase + (reg))

(2)寫(xiě)寄存器

wr_regl(port, S3C2410_UCON, ucon);

#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))

#define portaddr(port, reg) ((port)->membase + (reg))

#define __raw_writel(v,p)(*(unsigned long *)(p) = (v))

4.函數的注冊方式

細心的朋友可能會(huì )發(fā)現,我們之前一直使用的是傳統的 device driver 機制(通過(guò) driver_register 函數進(jìn)行注冊)本串口所使用的是一個(gè)設備用 Platform_device 表示,驅動(dòng)用 Platform_driver 進(jìn)行注冊的機制。而后者是在內核2.6版本所提出來(lái)的新事物,其優(yōu)勢在于platform機制將設備本身的資源注冊進(jìn)內核,由內核統一管理,在驅動(dòng)程序中使用這些資源時(shí)通過(guò) platform device 提供的標準接口進(jìn)行申請并使用。這樣提高了驅動(dòng)和資源管理的獨立性,并且擁有較好的可移植性和安全性(這些標準接口是安全的)。關(guān)于這兩種機制更深入的分析,請看以下鏈接:http://blog.csdn.net/jarvis_xian/archive/2011/05/23/6440649.aspx




評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>