gpio_request 原形代碼

?? 其原型為 int gpio_request(unsigned gpio, const char *label) 先說說其參數,gpio則為你要申請的哪一個管腳,label則是為其取一個名字。其具體實現如下:

[cpp] view plaincopyprint?
  1. int?gpio_request(unsigned?gpio,?const?char?*label)???
  2. {???
  3. ????????struct?gpio_desc?*desc;//這個自己看源碼? ??
  4. ????????struct?gpio_chip?*chip;//這個自己看源碼? ??
  5. ????????int???status?=?-EINVAL;???
  6. ????????unsigned?long??flags;??
  7. ????????spin_lock_irqsave(&gpio_lock,?flags);//屏蔽中斷 ??
  8. ????????if?(!gpio_is_valid(gpio))//判斷是否有效,也就是參數的取值范圍判斷? ??
  9. ?????????????goto?done;???
  10. ????????desc?=?&gpio_desc[gpio];???
  11. //這個是關鍵gpio_desc為定義的一個全局的數組變量,這個函數的實值也就是, ??
  12. //用gpio_desc里面的一個變量來表示數組中的這個元素已經被申請了,而這個變量就是下面會看到的desc->flags。? ??
  13. chip?=?desc->chip;//按理說這個這個全局的gpio_desc如果沒有初始化的話,這個chip就為空了,隨后就直接返回-EINVAL了。? ??
  14. if?(chip?==?NULL)如果不為空繼續往下走???
  15. ??goto?done;??
  16. if?(!try_module_get(chip->owner))???
  17. ??goto?done;??
  18. /*?NOTE:??gpio_request()?can?be?called?in?early?boot,??
  19. ??*?before?IRQs?are?enabled,?for?non-sleeping?(SOC)?GPIOs.??
  20. ??*/??
  21. if?(test_and_set_bit(FLAG_REQUESTED,?&desc->flags)?==?0)?{??
  22. //這里測試并設置flags的第FLAG_REQUESTED位,如果沒有被申請就返回該位的原值0,分析到這兒,也差不多滿足了我的個人要求。? ??
  23. ??desc_set_label(desc,?label???:?"?");???
  24. ??status?=?0;???
  25. }?else?{???
  26. ??status?=?-EBUSY;???
  27. ??module_put(chip->owner);???
  28. ??goto?done;???
  29. }??
  30. if?(chip->request)?{???
  31. ??/*?chip->request?may?sleep?*/???
  32. ??spin_unlock_irqrestore(&gpio_lock,?flags);???
  33. ??status?=?chip->request(chip,?gpio?-?chip->base);???
  34. ??spin_lock_irqsave(&gpio_lock,?flags);??
  35. ??if?(status?<?0)?{???
  36. ???desc_set_label(desc,?NULL);???
  37. ???module_put(chip->owner);???
  38. ???clear_bit(FLAG_REQUESTED,?&desc->flags);???
  39. ??}???
  40. }??
  41. done:???
  42. if?(status)???
  43. ??pr_debug("gpio_request:?gpio-%d?(%s)?status?%d\n",???
  44. ???gpio,?label???:?"?",?status);???
  45. spin_unlock_irqrestore(&gpio_lock,?flags);???
  46. return?status;???
  47. }??

davinci 平臺:?
[cpp] view plaincopyprint?
  1. /*??
  2. *?TI?DaVinci?GPIO?Support??
  3. *??
  4. *?Copyright?(c)?2006?David?Brownell??
  5. *?Copyright?(c)?2007,?MontaVista?Software,?Inc.?<source@mvista.com>??
  6. *??
  7. *?This?program?is?free?software;?you?can?redistribute?it?and/or?modify??
  8. *?it?under?the?terms?of?the?GNU?General?Public?License?as?published?by??
  9. *?the?Free?Software?Foundation;?either?version?2?of?the?License,?or??
  10. *?(at?your?option)?any?later?version.??
  11. */???
  12. ??
  13. #include?<linux/errno.h>? ??
  14. #include?<linux/kernel.h>? ??
  15. #include?<linux/list.h>? ??
  16. #include?<linux/module.h>? ??
  17. #include?<linux/err.h>? ??
  18. #include?<linux/bitops.h>? ??
  19. ??
  20. #include?<asm/irq.h>? ??
  21. #include?<asm/io.h>? ??
  22. #include?<asm/hardware/clock.h>? ??
  23. ??
  24. #include?<asm/arch/irqs.h>? ??
  25. #include?<asm/arch/hardware.h>? ??
  26. #include?<asm/arch/gpio.h>? ??
  27. #include?<asm/arch/cpu.h>? ??
  28. ??
  29. #include?<asm/mach/irq.h>? ??
  30. ??
  31. /*???
  32. 該文件實現了gpio的各種應用功能和向內核注冊gpio的中斷例程等功能。??
  33. 用戶的驅動程序可調用gpio_request和gpio_free使用或釋放該gpio,??
  34. 可以調用gpio_direction_input和gpio_direction_output函數設置gpio輸入輸出方向,??
  35. 調用gpio_get_value和gpio_set_value獲取設置值。??
  36. */???
  37. ??
  38. static?DEFINE_SPINLOCK(gpio_lock);???
  39. ??
  40. /*?總共有DAVINCI_N_GPIO(71)個gpio引腳,故使用相應多的bit來記錄這些引腳的使用狀態?*/???
  41. static?DECLARE_BITMAP(gpio_in_use,?DAVINCI_N_GPIO);???
  42. ??
  43. /*??
  44. 申請一個gpio,其實就是檢查該gpio是否空閑,如果空閑就可以使用并將該gpio相應的bit置位??
  45. (在gpio_in_use中)。??
  46. */???
  47. int?gpio_request(unsigned?gpio,?const?char?*tag)???
  48. {???
  49. ????if?(gpio?>=?DAVINCI_N_GPIO)???
  50. ????????return?-EINVAL;???
  51. ????if?(test_and_set_bit(gpio,?gpio_in_use))???
  52. ????????return?-EBUSY;???
  53. ????return?0;???
  54. }???
  55. EXPORT_SYMBOL(gpio_request);???
  56. ??
  57. /*??
  58. 釋放一個gpio,其實就是清除gpio相應的控制bit位(在gpio_in_use中)。??
  59. */???
  60. void?gpio_free(unsigned?gpio)???
  61. {???
  62. ????if?(gpio?>=?DAVINCI_N_GPIO)???
  63. ????????return;???
  64. ????clear_bit(gpio,?gpio_in_use);???
  65. }???
  66. EXPORT_SYMBOL(gpio_free);???
  67. ??
  68. /*?獲得gpio_controller結構體指針,gpio_controller結構體是gpio的核心控制單元,里面包含??
  69. gpio的設置和數據寄存器。該結構體和__gpio_to_controller函數在/include/asm-arm/??
  70. arch-davinci/gpio.h中定義,具體如下:??
  71. struct?gpio_controller?{??
  72. ????u32????dir;??
  73. ????u32????out_data;??
  74. ????u32????set_data;??
  75. ????u32????clr_data;??
  76. ????u32????in_data;??
  77. ????u32????set_rising;??
  78. ????u32????clr_rising;??
  79. ????u32????set_falling;??
  80. ????u32????clr_falling;??
  81. ????u32????intstat;??
  82. };??
  83. ?
  84. static?inline?struct?gpio_controller?*__iomem??
  85. __gpio_to_controller(unsigned?gpio)??
  86. {??
  87. ????void?*__iomem?ptr;??
  88. ????if?(gpio?>=?DAVINCI_N_GPIO)??
  89. ????????return?NULL;??
  90. ?
  91. ????if?(gpio?<?32)??
  92. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x10);??
  93. ????else?if?(gpio?<?64)??
  94. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x38);??
  95. ????else?if?(gpio?<?96)??
  96. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x60);??
  97. ????else??
  98. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x88);??
  99. ????return?ptr;??
  100. }??
  101. 由上面的定義和ti的SPRUE25.pdf手冊可以看出,__gpio_to_controller函數返回的是??
  102. gpio_controller結構體到第一個成員dir的虛擬地址。獲取了這個結構體指針后,??
  103. 便可以控制相應的gpio了。dm644x共有71個gpio,??
  104. 所以使用三個gpio_controller結構體控制,關于這個后面會由更詳細的分析,??
  105. */???
  106. /*?create?a?non-inlined?version?*/???
  107. static?struct?gpio_controller?*__iomem?gpio2controller(unsigned?gpio)???
  108. {???
  109. ????return?__gpio_to_controller(gpio);???
  110. }???
  111. ??
  112. /*???
  113. 向某個gpio設置值,0或1。如果向gpio寫1,則向set_data寄存器相應的位置1,如果寫0,??
  114. 則向clr_data寄存器相應的位置1.__gpio_mask函數在gpio.h中定義,定義如下,??
  115. static?inline?u32?__gpio_mask(unsigned?gpio)??
  116. {??
  117. ????return?1?<<?(gpio?%?32);??
  118. }??
  119. 因為71個引腳由3個結構體控制,第一個控制前32個gpio,第二個控制次32個gpio,??
  120. 最后一個控制剩余的7個gpio,故__gpio_mask函數的作用是找到在其相應控制結構體里的偏移數,??
  121. 比如gpio34,那么其由第二個結構體控制,在這個機構體里的偏移是3(從0開始算,就是第二位)。??
  122. 使用這個函數之前,必須確認該gpio設置成輸出模式。??
  123. */???
  124. /*??
  125. *?Assuming?the?pin?is?muxed?as?a?gpio?output,?set?its?output?value.??
  126. */???
  127. void?__gpio_set(unsigned?gpio,?int?value)???
  128. {???
  129. ????struct?gpio_controller?*__iomem?g?=?gpio2controller(gpio);???
  130. ????//?設置gpio的值? ??
  131. ????__raw_writel(__gpio_mask(gpio),?value???&g->set_data?:?&g->clr_data);????
  132. }???
  133. EXPORT_SYMBOL(__gpio_set);???
  134. ??
  135. /*???
  136. 通過讀取in_data寄存器相應該gpio的位來讀取gpio的值。??
  137. 使用這個函數之前,必須確認該gpio設置成輸入模式,否則獲得到值不可預料。???
  138. */???
  139. /*??
  140. *?Read?the?pin's?value?(works?even?if?it's?set?up?as?output);??
  141. *?returns?zero/nonzero.??
  142. *??
  143. *?Note?that?changes?are?synched?to?the?GPIO?clock,?so?reading?values?back??
  144. *?right?after?you've?set?them?may?give?old?values.??
  145. */???
  146. int?__gpio_get(unsigned?gpio)???
  147. {???
  148. ????struct?gpio_controller?*__iomem?g?=?gpio2controller(gpio);???
  149. ????/*?讀取gpio的值,!!的目的是使得返回的值為0或1.*/???
  150. ????return?!!(__gpio_mask(gpio)?&?__raw_readl(&g->in_data));???????
  151. }??????????????????????????????????????????????????????????????????????????????????????????????????????????????????}???
  152. EXPORT_SYMBOL(__gpio_get);???
  153. ??
  154. /*???
  155. 通過dir寄存器相應該gpio的位來設置gpio輸入輸出方向,為0,則設置成輸出,為1,則設置出輸入。??
  156. 該函數是設置成輸入,故設置dir寄存器為1.??
  157. ?正如應為所說的,必須確認該引腳是作為gpio功能,而不是某個模塊到功能,比如spi。通過PINMUX0??
  158. 和PINMUX1兩個寄存器來設置。??
  159. */???
  160. /*--------------------------------------------------------------------------*/???
  161. ??
  162. /*??
  163. *?board?setup?code?*MUST*?set?PINMUX0?and?PINMUX1?as??
  164. *?needed,?and?enable?the?GPIO?clock.??
  165. */???
  166. int?gpio_direction_input(unsigned?gpio)???
  167. {???
  168. ????struct?gpio_controller?*__iomem?g?=?gpio2controller(gpio);???
  169. ????u32?temp;???
  170. ????u32?mask;???
  171. ??
  172. ????if?(!g)???
  173. ????????return?-EINVAL;???
  174. ????spin_lock(&gpio_lock);???
  175. ????mask?=?__gpio_mask(gpio);???
  176. ????temp?=?__raw_readl(&g->dir);???
  177. ????temp?|=?mask;????//?設置成1? ??
  178. ????__raw_writel(temp,?&g->dir);????//?設置該gpio為輸入? ??
  179. ????spin_unlock(&gpio_lock);???
  180. ????return?0;???
  181. }???
  182. EXPORT_SYMBOL(gpio_direction_input);???
  183. ??
  184. /*??
  185. 通過dir寄存器相應該gpio的位來設置gpio輸入輸出方向,為0,則設置成輸出,為1,則設置出輸入。??
  186. 該函數是設置成輸出,故設置dir寄存器為0.??
  187. value參數用于選擇gpio設置成輸出后該gpio輸出的值。??
  188. */???
  189. int?gpio_direction_output(unsigned?gpio,?int?value)???
  190. {???
  191. ????struct?gpio_controller?*__iomem?g?=?gpio2controller(gpio);???
  192. ????u32?temp;???
  193. ????u32?mask;???
  194. ????if?(!g)???
  195. ????????return?-EINVAL;???
  196. ??
  197. ????spin_lock(&gpio_lock);???
  198. ????mask?=?__gpio_mask(gpio);???
  199. ????temp?=?__raw_readl(&g->dir);???
  200. ????temp?&=?~mask;????//?設置成0?? ??
  201. ????//設置該gpio輸出值? ??
  202. ????__raw_writel(mask,?value???&g->set_data?:?&g->clr_data);???
  203. ????__raw_writel(temp,?&g->dir);????//?設置gpio為輸出? ??
  204. ????spin_unlock(&gpio_lock);???
  205. ????return?0;???
  206. }???
  207. EXPORT_SYMBOL(gpio_direction_output);???
  208. ??
  209. /*??
  210. 向gpio設置值,0或1。??
  211. */???
  212. void?gpio_set_value(unsigned?gpio,?int?value)???
  213. {???
  214. ????if?(__builtin_constant_p(value))?{???
  215. ????????struct?gpio_controller?*__iomem?g;???
  216. ????????u32?mask;???
  217. ??
  218. ????????if?(gpio?>=?DAVINCI_N_GPIO)???
  219. ????????????__error_inval_gpio();???
  220. ??
  221. ????????g?=?__gpio_to_controller(gpio);???
  222. ????????mask?=?__gpio_mask(gpio);???
  223. ????????if?(value)???
  224. ????????????__raw_writel(mask,?&g->set_data);????//?該gpio輸出高? ??
  225. ??
  226. ????????else???
  227. ????????????__raw_writel(mask,?&g->clr_data);????//?該gpio輸出低? ??
  228. ??
  229. ????????return;???
  230. ????}???
  231. ??
  232. ????__gpio_set(gpio,?value);???
  233. }???
  234. EXPORT_SYMBOL(gpio_set_value);???
  235. ??
  236. /*??
  237. 讀取gpio的值,0或1.??
  238. */???
  239. int?gpio_get_value(unsigned?gpio)???
  240. {???
  241. ????struct?gpio_controller?*__iomem?g;???
  242. ??
  243. ????if?(!__builtin_constant_p(gpio))/*?判斷該gpio值是否為編譯時常數,如果是常數,??
  244. ?????????????????????????????????????函數返回?1,否則返回?0?*/???
  245. ????????return?__gpio_get(gpio);???
  246. ??
  247. ????if?(gpio?>=?DAVINCI_N_GPIO)???
  248. ????????return?__error_inval_gpio();???
  249. ??
  250. ????g?=?__gpio_to_controller(gpio);???
  251. ???????
  252. ????//?讀取該gpio的值? ??
  253. ??
  254. ????return?!!(__gpio_mask(gpio)?&?__raw_readl(&g->in_data));???
  255. }???
  256. EXPORT_SYMBOL(gpio_get_value);???
  257. ??
  258. /*??
  259. *?We?expect?irqs?will?normally?be?set?up?as?input?pins,?but?they?can?also?be??
  260. *?used?as?output?pins?...?which?is?convenient?for?testing.??
  261. *??
  262. *?NOTE:?GPIO0..GPIO7?also?have?direct?INTC?hookups,?which?work?in?addition??
  263. *?to?their?GPIOBNK0?irq?(but?with?a?bit?less?overhead).?But?we?don't?have??
  264. *?a?good?way?to?hook?those?up?...??
  265. *??
  266. *?All?those?INTC?hookups?(GPIO0..GPIO7?plus?five?IRQ?banks)?can?also??
  267. *?serve?as?EDMA?event?triggers.??
  268. */???
  269. ??
  270. /*??
  271. 禁止相應該irq的gpio的中斷。每個gpio都可以作為中斷的來源,其中gpio0-gpio7是獨立的中斷來源,??
  272. 也就是分配獨立的中斷號,其他gpio則共用5個GPIOBNK中斷線。其優先級可以在board-evm.c??
  273. 中設置(已經介紹過)。在dm644x平臺上,中斷是電平邊緣觸發的,禁止中斷其實就是既不設置??
  274. 上升沿觸發,也不設置下降沿觸發。??
  275. */???
  276. static?void?gpio_irq_disable(unsigned?irq)???
  277. {???
  278. ????struct?gpio_controller?*__iomem?g?=?get_irq_chipdata(irq);???
  279. ????u32?mask?=?__gpio_mask(irq_to_gpio(irq));???
  280. ??
  281. ????__raw_writel(mask,?&g->clr_falling);????//?清除下降沿觸發? ??
  282. ??
  283. ????__raw_writel(mask,?&g->clr_rising);????????//?清除上升沿觸發? ??
  284. ??
  285. }???
  286. ??
  287. /*??
  288. 中斷使能。??
  289. 在dm644x平臺上,中斷是電平邊緣觸發的,其實就是設置為上升沿或下降沿中斷。??
  290. */???
  291. static?void?gpio_irq_enable(unsigned?irq)???
  292. {???
  293. ????struct?gpio_controller?*__iomem?g?=?get_irq_chipdata(irq);???
  294. ????u32?mask?=?__gpio_mask(irq_to_gpio(irq));???
  295. ??
  296. ????//?如果先前為下降沿中斷,則使能為下降沿中斷? ??
  297. ??
  298. ????if?(irq_desc[irq].status?&?IRQT_FALLING)???
  299. ????????__raw_writel(mask,?&g->set_falling);???
  300. ???????
  301. ????//?如果先前為上升沿中斷,則使能為上升沿中斷? ??
  302. ??
  303. ????if?(irq_desc[irq].status?&?IRQT_RISING)???????
  304. ????????__raw_writel(mask,?&g->set_rising);???
  305. }???
  306. ??
  307. /*??
  308. 設置中斷類型。??
  309. 在dm644x平臺上,中斷有上升沿和下降沿兩種觸發方式。??
  310. */???
  311. static?int?gpio_irq_type(unsigned?irq,?unsigned?trigger)???
  312. {???
  313. ????struct?gpio_controller?*__iomem?g?=?get_irq_chipdata(irq);???
  314. ????u32?mask?=?__gpio_mask(irq_to_gpio(irq));???
  315. ??
  316. ????if?(trigger?&?~(IRQT_FALLING?|?IRQT_RISING))???
  317. ????????return?-EINVAL;???
  318. ??
  319. ????irq_desc[irq].status?&=?~IRQT_BOTHEDGE;???
  320. ????irq_desc[irq].status?|=?trigger;???
  321. ??
  322. ????__raw_writel(mask,?(trigger?&?IRQT_FALLING)???
  323. ???????????&g->set_falling?:?&g->clr_falling);?????//?設置為下降沿觸發? ??
  324. ??
  325. ????__raw_writel(mask,?(trigger?&?IRQT_RISING)???
  326. ???????????&g->set_rising?:?&g->clr_rising);????//?設置為上升沿觸發? ??
  327. ??
  328. ????return?0;???
  329. }???
  330. ??
  331. /*???
  332. 該結構體用于注冊到所有irq的中斷描述結構體中(struct?irqdesc),??
  333. 而所有中斷描述結構體定義成一個全局數組irq_desc?。??
  334. */???
  335. static?struct?irqchip?gpio_irqchip?=?{???
  336. ????.unmask????????=?gpio_irq_enable,?/*?用于使能中斷,??
  337. ?????????????????????????????????????在enable_irq()等內核函數中會用到。*/???????
  338. ????.mask????????=?gpio_irq_disable,/*?用于禁止中斷,??
  339. ?????????????????????????????????????在disable_irq()等內核函數中會用到。*/???
  340. ????.type????????=?gpio_irq_type,?/*?用于設置中斷類型,??
  341. ?????????????????????????????????????在set_irq_type()內核函數中會用到。*/???
  342. };???
  343. ??
  344. /*??
  345. 該函數將在下面的davinci_gpio_irq_setup中使用,將被注冊到五個gpio?bank中斷的??
  346. irq_desc結構中,目的是處理所有級聯的gpio中斷。所謂級聯的中斷,?就是指有n個中斷??
  347. 共用同一個中斷線。??
  348. 在dm644x平臺中,除了gpio0-gpio7外,其他63個gpio都共用五個gpiobank中斷線,在這里,??
  349. gpio0-gpio7也被注冊到gpiobank中斷線,但實際上并不會使用,因為它們擁有自己的??
  350. 中斷線。其中,gpio0-gpio15共用IRQ_GPIOBNK0(56)中斷線,gpio16-gpio31共用??
  351. IRQ_GPIOBNK1(57)中斷線,gpio32-gpio47共用IRQ_GPIOBNK2(58)中斷線,??
  352. gpio48-gpio63共用IRQ_GPIOBNK4(59)中斷線,gpio64-gpio70共用??
  353. IRQ_GPIOBNK5(60)中斷線,??
  354. 因為寄存器是32位的,所以實際上只有三組寄存器,第一組包含bank0和bank1,??
  355. 也就是gpio0-gpio31,第二組包含bank2和bank3,也就是gpio32-gpio63,??
  356. 第三組包含bank4和bank5,也就是gpio64-gpio70,剩余了25個位沒有使用。??
  357. */???
  358. static?void???
  359. gpio_irq_handler(unsigned?irq,?struct?irqdesc?*desc,?struct?pt_regs?*regs)???
  360. {???
  361. ????struct?gpio_controller?*__iomem?g?=?get_irq_chipdata(irq);???
  362. ????u32?mask?=?0xffff;???
  363. ??
  364. ????/*?we?only?care?about?one?bank?*/???
  365. ????//?如果bank中斷線是寄數,則說明該中斷的中斷狀態位在INTSTATn寄存器的高16位? ??
  366. ??
  367. ????if?(irq?&?1)???
  368. ????????mask?<<=?16;???
  369. ??
  370. ????/*?temporarily?mask?(level?sensitive)?parent?IRQ?*/???
  371. ????desc->chip->ack(irq);//?該ack函數會在arch/arm/mach-davinci/irq.c中注冊。? ??
  372. ??
  373. ????while?(1)?{???
  374. ????????u32????????status;???
  375. ????????struct?irqdesc????*gpio;???
  376. ????????int????????n;???
  377. ????????int????????res;???
  378. ??
  379. ????????/*?ack?any?irqs?*/???
  380. ????????/*gpio中斷發生后,硬件會在INTSTATn寄存器中置位相應位,??
  381. ?????????以備程序查詢,確定是哪個gpio*/???
  382. ????????status?=?__raw_readl(&g->intstat)?&?mask;????
  383. ????????if?(!status)???
  384. ????????????break;???
  385. ????????__raw_writel(status,?&g->intstat);????//?向該位寫1清除? ??
  386. ??
  387. ????????if?(irq?&?1)???
  388. ????????????status?>>=?16;???
  389. ??
  390. ????????/*?now?demux?them?to?the?right?lowlevel?handler?*/???
  391. ????????//?從下面的davinci_gpio_irq_setup函數可以看出來以下程序的運作。? ??
  392. ??
  393. ????????n?=?(int)get_irq_data(irq);????//?獲取該bank對應的第一個gpio號? ??
  394. ??
  395. ????????gpio?=?&irq_desc[n];????//?獲取該bank第一個gpio號對應的中斷描述符? ??
  396. ??
  397. ????????while?(status)?{????//?該bank可能有多個gpio發生了中斷? ??
  398. ??
  399. ????????????res?=?ffs(status);????//?獲取第一個發生了中斷的位(1-32)? ??
  400. ??
  401. ????????????n?+=?res;????/*?獲得該gpio的中斷線(系統實際上只有64(0-63)個中斷線,??
  402. ????????????????????????但那些共用的gpio的中斷也有自己的斷描述符和中斷線(從64開始),??
  403. ????????????????????????僅僅是為了管理,不能通過request_irq()函數來申請。*/???
  404. ????????????gpio?+=?res;????//?????獲得該gpio的中斷描述符? ??
  405. ??
  406. ???????????????
  407. ????????????/*?調用下面注冊的do_simple_IRQ例程??
  408. ?????????????其又會調用用戶通過request_irq()??
  409. ?????????????注冊的中斷例程??
  410. ????????????*/???
  411. ????????????desc_handle_irq(n?-?1,?gpio?-?1,?regs);???????
  412. ????????????status?>>=?res;???????????
  413. ????????}???
  414. ????}???
  415. ????desc->chip->unmask(irq);????//?打開該irq中斷線? ??
  416. ??
  417. ????/*?now?it?may?re-trigger?*/???
  418. }???
  419. ??
  420. /*??
  421. *?NOTE:?for?suspend/resume,?probably?best?to?make?a?sysdev?(and?class)??
  422. *?with?its?suspend/resume?calls?hooking?into?the?results?of?the?set_wake()??
  423. *?calls?...?so?if?no?gpios?are?wakeup?events?the?clock?can?be?disabled,??
  424. *?with?outputs?left?at?previously?set?levels,?and?so?that?VDD3P3V.IOPWDN0??
  425. *?can?be?set?appropriately?for?GPIOV33?pins.??
  426. */???
  427. /*??
  428. 注冊gpio中斷例程到內核中,并初始化了一些寄存器。??
  429. 該函數將會被board_evm.c(其淺析已經發表)中的evm_init()函數調用。具體調用過程如下:??
  430. start_kernel()-->setup_arch()-->init_machine?=?mdesc->init_machine??
  431. (init_machine是個全局函數指針變量,其指向的就是已經注冊到機器描述符里evm_init());??
  432. 調用函數指針init_machine()的例程是customize_machine(),其定義為??
  433. arch_initcall(customize_machine),所以,接下來的調用過程是:??
  434. start_kernel()-->do_basic_setup()-->do_initcalls()-->customize_machine()-->??
  435. init_machine()(也就是evm_init())-->davinci_gpio_irq_setup。??
  436. 從上可以看出經歷了兩個過程,才調用davinci_gpio_irq_setup例程來初始化gpio中斷。??
  437. */???
  438. int?__init?davinci_gpio_irq_setup(void)???
  439. {???
  440. ????unsigned????gpio,?irq,?bank,?banks;???
  441. ????struct?clk????*clk;???
  442. ??
  443. ????clk?=?clk_get(NULL,?"gpio");????//?獲取時鐘? ??
  444. ??
  445. ????if?(IS_ERR(clk))?{???
  446. ????????printk(KERN_ERR?"Error?%ld?getting?gpio?clock?\n",???
  447. ?????????PTR_ERR(clk));???
  448. ????????return?0;???
  449. ????}???
  450. ??
  451. ????clk_enable(clk);????//?使能gpio時鐘并打開該模塊電源? ??
  452. ??
  453. ??
  454. ????for?(gpio?=?0,?irq?=?gpio_to_irq(0),?bank?=?(cpu_is_davinci_dm355()?????
  455. ?????IRQ_DM355_GPIOBNK0?:?(cpu_is_davinci_dm6467()?????
  456. ?????IRQ_DM646X_GPIOBNK0?:?IRQ_GPIOBNK0));????//?dm644x的IRQ_GPIOBNK0(56)? ??
  457. ??
  458. ?????gpio?<?DAVINCI_N_GPIO;?bank++)?{????//?dm644x的DAVINCI_N_GPIO(71)? ??
  459. ??
  460. ????????struct?gpio_controller????*__iomem?g?=?gpio2controller(gpio);???
  461. ????????unsigned????????i;???
  462. ??
  463. ????????//?關該bank所有gpio的中斷? ??
  464. ??
  465. ????????__raw_writel(~0,?&g->clr_falling);???
  466. ????????__raw_writel(~0,?&g->clr_rising);???
  467. ??
  468. ????????/*?set?up?all?irqs?in?this?bank?*/???
  469. ????????//?同一個bank的所有gpio共用一個中斷例程gpio_irq_handler? ??
  470. ??
  471. ????????set_irq_chained_handler(bank,?gpio_irq_handler);???
  472. ????????set_irq_chipdata(bank,?g);???
  473. ????????set_irq_data(bank,?(void?*)irq);???
  474. ??
  475. ????????for?(i?=?0;?i?<?16?&&?gpio?<?DAVINCI_N_GPIO;???
  476. ?????????i++,?irq++,?gpio++)?{???
  477. ????????????set_irq_chip(irq,?&gpio_irqchip);????/*?注冊用于gpio中斷禁止、設能??
  478. ?????????????????????????????????????????????????和類型選擇的回調例程?*/???
  479. ????????????set_irq_chipdata(irq,?g);????????????//?保存控制結構體(寄存器)的地址? ??
  480. ??
  481. ????????????set_irq_handler(irq,?do_simple_IRQ);/*?為每個gpio中斷設置同一個中??
  482. ????????????????????????????????????????????????????斷例程do_simple_IRQ*/???
  483. ????????????set_irq_flags(irq,?IRQF_VALID);????????//?fiq中斷有效? ??
  484. ??
  485. ????????}???
  486. ????}???
  487. /*??????
  488. 一個共用bank中斷線的gpio中斷發生后的大致的流程是:??
  489. -->?gpio_irq_handler?-->?do_simple_IRQ?-->?__do_irq?-->???
  490. action->handler(用戶使用request_irq()注冊的中斷例程)??
  491. */???
  492. ????/*?BINTEN?--?per-bank?interrupt?enable.?genirq?would?also?let?these??
  493. ?????*?bits?be?set/cleared?dynamically.??
  494. ?????*/???
  495. ????if?(cpu_is_davinci_dm355())???
  496. ????????banks?=?0x3f;???
  497. ????else???
  498. ????????banks?=?0x1f;???
  499. ???????
  500. ????//?向BINTEN寄存器寫入0x1f(共5個位,每個位控制1個bank),打開所有的bank中斷? ??
  501. ??
  502. ????__raw_writel(banks,?(void?*__iomem)???
  503. ?????????IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x08));???
  504. ??
  505. ????printk(KERN_INFO?"DaVinci:?%d?gpio?irqs\n",?irq?-?gpio_to_irq(0));???
  506. ??
  507. ????return?0;???
  508. }???
  509. ??
  510. ???
  511. ??
  512. ??
  513. gpio.h???
  514. ??
  515. ??
  516. /*??
  517. *?TI?DaVinci?GPIO?Support??
  518. *??
  519. *?Copyright?(c)?2006?David?Brownell??
  520. *?Copyright?(c)?2007,?MontaVista?Software,?Inc.?<source@mvista.com>??
  521. *??
  522. *?This?program?is?free?software;?you?can?redistribute?it?and/or?modify??
  523. *?it?under?the?terms?of?the?GNU?General?Public?License?as?published?by??
  524. *?the?Free?Software?Foundation;?either?version?2?of?the?License,?or??
  525. *?(at?your?option)?any?later?version.??
  526. */???
  527. ??
  528. #ifndef????__DAVINCI_GPIO_H? ??
  529. #define????__DAVINCI_GPIO_H? ??
  530. ??
  531. /*??
  532. *?basic?gpio?routines??
  533. *??
  534. *?board-specific?init?should?be?done?by?arch/.../.../board-XXX.c?(maybe??
  535. *?initializing?banks?together)?rather?than?boot?loaders;?kexec()?won't??
  536. *?go?through?boot?loaders.??
  537. *??
  538. *?the?gpio?clock?will?be?turned?on?when?gpios?are?used,?and?you?may?also??
  539. *?need?to?pay?attention?to?PINMUX0?and?PINMUX1?to?be?sure?those?pins?are??
  540. *?used?as?gpios,?not?with?other?peripherals.??
  541. *??
  542. *?GPIOs?are?numbered?0..(DAVINCI_N_GPIO-1).?For?documentation,?and?maybe??
  543. *?for?later?updates,?code?should?write?GPIO(N)?or:??
  544. *?-?GPIOV18(N)?for?1.8V?pins,?N?in?0..53;?same?as?GPIO(0)..GPIO(53)??
  545. *?-?GPIOV33(N)?for?3.3V?pins,?N?in?0..17;?same?as?GPIO(54)..GPIO(70)??
  546. *??
  547. *?For?GPIO?IRQs?use?gpio_to_irq(GPIO(N))?or?gpio_to_irq(GPIOV33(N))?etc??
  548. *?for?now,?that's?!=?GPIO(N)??
  549. */???
  550. #define????GPIO(X)????????(X)????????/*?0?<=?X?<=?70?*/? ??
  551. #define????GPIOV18(X)????(X)????????/*?1.8V?i/o;?0?<=?X?<=?53?*/? ??
  552. #define????GPIOV33(X)????((X)+54)????/*?3.3V?i/o;?0?<=?X?<=?17?*/? ??
  553. ??
  554. /*???
  555. 寄存器都是32位到,每位對應一個gpio。??
  556. */???
  557. struct?gpio_controller?{???
  558. ????u32????dir;????????????//?gpio方向設置寄存器? ??
  559. ??
  560. ????u32????out_data;????????//?gpio設置為輸出時,表示輸出狀態(0或1)? ??
  561. ??
  562. ????u32????set_data;????????//?gpio設置為輸出時,用于輸出高電平? ??
  563. ??
  564. ????u32????clr_data;????????//?gpio設置為輸出時,用于輸出低電平? ??
  565. ??
  566. ????u32????in_data;????????//?gpio設置為輸入時,用于讀取輸入值? ??
  567. ??
  568. ????u32????set_rising;????????//?gpio中斷上升沿觸發設置? ??
  569. ??
  570. ????u32????clr_rising;????????//?gpio中斷上升沿觸發清除? ??
  571. ??
  572. ????u32????set_falling;????//?gpio中斷下降沿觸發設置? ??
  573. ??
  574. ????u32????clr_falling;????//?gpio中斷下降沿觸發清除? ??
  575. ??
  576. ????u32????intstat;????????//?gpio中斷狀態位,由硬件設置,可讀取,寫1時清除。? ??
  577. ??
  578. };???
  579. ??
  580. /*?The?__gpio_to_controller()?and?__gpio_mask()?functions?inline?to?constants??
  581. *?with?constant?parameters;?or?in?outlined?code?they?execute?at?runtime.??
  582. *??
  583. *?You'd?access?the?controller?directly?when?reading?or?writing?more?than??
  584. *?one?gpio?value?at?a?time,?and?to?support?wired?logic?where?the?value??
  585. *?being?driven?by?the?cpu?need?not?match?the?value?read?back.??
  586. *??
  587. *?These?are?NOT?part?of?the?cross-platform?GPIO?interface??
  588. */???
  589. static?inline?struct?gpio_controller?*__iomem???
  590. __gpio_to_controller(unsigned?gpio)???
  591. {???
  592. ????void?*__iomem?ptr;???
  593. ??
  594. ????if?(gpio?>=?DAVINCI_N_GPIO)???
  595. ????????return?NULL;???
  596. ??
  597. ????if?(gpio?<?32)???
  598. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x10);???
  599. ????else?if?(gpio?<?64)???
  600. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x38);???
  601. ????else?if?(gpio?<?96)???
  602. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x60);???
  603. ????else???
  604. ????????ptr?=?(void?*__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE?+?0x88);???
  605. ??
  606. ????return?ptr;???
  607. }???
  608. ??
  609. static?inline?u32?__gpio_mask(unsigned?gpio)???
  610. {???
  611. ????return?1?<<?(gpio?%?32);???
  612. }???
  613. ??
  614. /*?The?get/set/clear?functions?will?inline?when?called?with?constant??
  615. *?parameters,?for?low-overhead?bitbanging.?Illegal?constant?parameters??
  616. *?cause?link-time?errors.??
  617. *??
  618. *?Otherwise,?calls?with?variable?parameters?use?outlined?functions.??
  619. */???
  620. extern?int?__error_inval_gpio(void);???
  621. ??
  622. extern?void?__gpio_set(unsigned?gpio,?int?value);???
  623. extern?int?__gpio_get(unsigned?gpio);???
  624. ??
  625. /*?Returns?zero?or?nonzero;?works?for?gpios?configured?as?inputs?OR??
  626. *?as?outputs.??
  627. *??
  628. *?NOTE:?changes?in?reported?values?are?synchronized?to?the?GPIO?clock.??
  629. *?This?is?most?easily?seen?after?calling?gpio_set_value()?and?then?immediatly??
  630. *?gpio_get_value(),?where?the?gpio_get_value()?would?return?the?old?value??
  631. *?until?the?GPIO?clock?ticks?and?the?new?value?gets?latched.??
  632. */???
  633. extern?int?gpio_get_value(unsigned?gpio);???
  634. extern?void?gpio_set_value(unsigned?gpio,?int?value);???
  635. ??
  636. ??
  637. /*?powerup?default?direction?is?IN?*/???
  638. extern?int?gpio_direction_input(unsigned?gpio);???
  639. extern?int?gpio_direction_output(unsigned?gpio,?int?value);???
  640. ??
  641. #include?<asm-generic/gpio.h>????/*?cansleep?wrappers?*/? ??
  642. ??
  643. extern?int?gpio_request(unsigned?gpio,?const?char?*tag);???
  644. extern?void?gpio_free(unsigned?gpio);???
  645. ??
  646. static?inline?int?gpio_to_irq(unsigned?gpio)???
  647. {???
  648. ????return?DAVINCI_N_AINTC_IRQ?+?gpio;???
  649. }???
  650. ??
  651. static?inline?int?irq_to_gpio(unsigned?irq)???
  652. {???
  653. ????return?irq?-?DAVINCI_N_AINTC_IRQ;???
  654. }???
  655. ??
  656. #endif????????????????/*?__DAVINCI_GPIO_H?*/ ??
  657. ???


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/253697.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/253697.shtml
英文地址,請注明出處:http://en.pswp.cn/news/253697.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【noip模擬】德充符

時間限制&#xff1a;2s 內存限制&#xff1a;512MB 【題目描述】 申徒嘉和鄭子產都是伯昏無人的學生&#xff0c;子產因為申徒嘉是殘疾人&#xff0c;非常看不起他&#xff0c;于是想要刁難他。 子產給了申徒嘉 n個數 a1,a2...an。 現在他要求申徒嘉重新排列這些數&#xff0c…

做好數據挖掘模型的9條經驗總結

愛數據學習社 welcome數據挖掘是利用業務知識從數據中發現和解釋知識(或稱為模式)的過程&#xff0c;這種知識是以自然或者人工形式創造的新知識。當前的數據挖掘形式&#xff0c;是在20世紀90年代實踐領域誕生的&#xff0c;是在集成數據挖掘算法平臺發展的支撐下適合商業分析…

json及JavaBean轉json

先來看看JSON&#xff1a; 什么是JSON&#xff1a; JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。 JSON是用字符串來表示Javascript對象&#xff0c;例如可以在Servlet中發送一個JSON格式的字符串給客戶端Javascript&#xff0c;Javascript可以執行這個字符串…

數字后端——低功耗設計物理實施

一、低功耗設計方案綜述 為了實現集成電路的低功耗設計目標&#xff0c;我們需要在系統設計階段就采用低功耗設計方案&#xff0c;因為隨著設計流程的逐步推進&#xff0c;到了芯片設計實現階段&#xff0c;降低芯片功耗的方法將越來越少&#xff0c;可節省功耗的百分比將不斷下…

Eclipse里修改SVN的用戶名和密碼

刪除Eclipse subclipse plugin中記住的SVN用戶名密碼&#xff1a; 1&#xff09; 查看你的Eclipse中使用的是什么SVN Interface windows > preference > Team > SVN #SVN Interface 2.&#xff09;如果是用的JavaHL, 找到以下目錄并刪除auth目錄. 刪除C:\Users\…

Omap3530 的GPIO中斷設置

Omap3530 的GPIO中斷設置&#xff1a; 1.配置成GPIO&#xff0c;申請GPIO中斷 omap_cfg_reg(OMAP3_KBD_GPIO);配置成gpio if (gpio_request(OMAP3_KBD_GPIO, "kbd7279 IRQ") < 0) printk(KERN_ERR "Failed to request GPIO%d for kbd IRQ/n");//申請GPI…

H5項目開發分享——用Canvas合成文字

以前曾用Canvas合成、裁剪、圖片等《用H5中的Canvas等技術制作海報》。這次用Canvas來畫文字。 下圖中“老王考到駕照后”這幾個字是畫在Canvas上的&#xff0c;與在PS中打入的字非常接近&#xff0c;毫無違和感。 前面一段時間也在研讀JavaScript設計模式相關的知識&#xff0…

SQLServer約束介紹

約束定義 對于數據庫來說&#xff0c;基本表的完整性約束分為列級約束條件和表級約束條件&#xff1a; 列級約束條件 列級約束條件是對某一個特定列的約束&#xff0c;包含在列定義中&#xff0c;可以直接跟在該列的其他定義之后&#xff0c;用空格分隔&#xff0c;不用指定列名…

CMOS圖像傳感器——SNR計算

圖像質量評價在計算機視覺,人工智能,高清視頻傳輸上面有很廣泛的應用。目前,圖像質量評價主要分為三個方向,有參考圖像的質量評價,半參考的圖像質量評價,以及無參考的圖像質量評價。許多時候,我們利用CIS采集的RAW DATA本身就是含噪信號,因為我們往往不知道感興趣的像素…

Java this 關鍵字的用法

this 關鍵字的用法 this 在類中就是代表當前對象&#xff0c;可以通過 this 關鍵字完成當前 對象的成員屬性、成員方法和構造方法的調用。 那么何時用 this? 當在定義類中的方法時&#xff0c;如果需要調用該類對象&#xff0c;就可以用 this 來表示這個對象。也就是說&#x…

TMDS——最小化傳輸差分信號及其協議

過渡調制差分信號&#xff0c;也被稱為最小化傳輸差分信號&#xff0c;是指通過異或及異或非等邏輯算法將原始信號數據轉換成10位&#xff0c;前8為數據由原始信號經運算后獲得&#xff0c;第9位指示運算的方式&#xff0c;第10位用來對應直流平衡&#xff08;DC-balanced&…

順大勢逆小勢策略之代碼實現及可行性分析

閱讀原文&#xff1a;quant.la/Article/Vie… 前言 資產配置多元化是投資的唯一免費午餐 —— 馬克維茨。 在市場中有兩種策略&#xff1a;趨勢策略和震蕩策略。趨勢追蹤策略的特點在大行情的波動段找到有效的交易信號。而震蕩策略則是一種反趨勢策略&#xff0c;一波大幅上漲后…

數字圖像處理——中值濾波及其改進算法

一、算法介紹 中值濾波器是非線性濾波器的一個例子&#xff0c;它在保留圖像特征方面非常有效。 但是&#xff0c;濾波器的窗口大小直接影響中值濾波器的性能。 較小的窗口保留了特征&#xff0c;但會導致噪聲抑制的減少。 在較大窗口的情況下&#xff0c;噪聲抑制很高&#xf…

Spring整合web開發

正常整合Servlet和Spring沒有問題的 public class UserServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ApplicationContext applicationContext new ClassPathXmlApplica…

環信快速集成,以及實際集成中遇到的坑

一.pod集成遇到的問題 1.直接pod 安裝 pod EaseUI, :git > https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git 在這個過程中&#xff0c;如果你pod已經安裝了sdwebimage&#xff0c;mjrefresh等他自身包含的三方&#xff0c;就需要在你的podfile里面把這個給刪…

PAFF 和MBAFF

PAFF 和MBAFF&#xff1a;當對隔行掃描圖像進行編碼時&#xff0c;每幀包括兩個場&#xff0c;由于兩個場之間存在較大的掃描間隔&#xff0c;這樣&#xff0c;對運動圖像來說&#xff0c;幀中相鄰兩行之間的空間相關性相對于逐行掃描時就會減小&#xff0c;因此這時對兩個場分…

Test435678

2345魚57洋炮456789轉載于:https://www.cnblogs.com/rhxuza1993/p/9534938.html

用NPOI從DataBase到Excel '2

NPOI的C# Helper代碼2 1 public static MemoryStream ExportXls(DataTable dt)2 {3 HSSFWorkbook wk new HSSFWorkbook();4 ISheet sheet null;5 6 string sheetName "Sheet1";7 if (!string.Is…

CMOS圖像傳感器——噪聲模型

由于CMOS圖像傳感噪聲的復雜性和不可控性,學者們一直在尋求一種能對其比較精確表的噪聲模型。在圖像降噪領域,為了降低算法設計的復雜度,人們普遍采用基于信道相關噪聲的模型(即加性噪聲),但其缺點就是不能精確地表示傳感器的噪聲。于是Hirakawa提出了一 種精確CMOS傳感器…

????TCp傳輸粘包問題

解決TCP網絡傳輸“粘包”問題 當前在網絡傳輸應用中&#xff0c;廣泛采用的是TCP/IP通信協議及其標準的socket應用開發編程接口&#xff08;API&#xff09;。TCP/IP傳輸層有兩個并列的協 議&#xff1a;TCP和UDP。其中TCP&#xff08;transport control protocol&#xff0c;傳…