/external/mbed-os/targets/TARGET_ARM_SSG/TARGET_BEETLE/gpio_irq_api.c

https://github.com/adamgreen/gcc4mbed · C · 399 lines · 324 code · 50 blank · 25 comment · 52 complexity · faf498ee50d5d159d72068888d558678 MD5 · raw file

  1. /* mbed Microcontroller Library
  2. * Copyright (c) 2015 ARM Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stddef.h>
  17. #include "cmsis.h"
  18. #include "gpio_irq_api.h"
  19. #include "mbed_error.h"
  20. #define CHANNEL_NUM 32
  21. #define CMSDK_GPIO_0 CMSDK_GPIO0
  22. #define CMSDK_GPIO_1 CMSDK_GPIO1
  23. #define PININT_IRQ 0
  24. static uint32_t channel_ids[CHANNEL_NUM] = {0};
  25. static gpio_irq_handler irq_handler;
  26. static inline void handle_interrupt_in(uint32_t channel) {
  27. uint32_t ch_bit = (1 << channel);
  28. // Return immediately if:
  29. // * The interrupt was already served
  30. // * There is no user handler
  31. // * It is a level interrupt, not an edge interrupt
  32. if (ch_bit <16){
  33. if (((CMSDK_GPIO_0->INTSTATUS) == 0) || (channel_ids[channel] == 0)
  34. || ((CMSDK_GPIO_0->INTTYPESET) == 0))
  35. return;
  36. if ((CMSDK_GPIO_0->INTTYPESET & ch_bit)
  37. && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
  38. irq_handler(channel_ids[channel], IRQ_RISE);
  39. CMSDK_GPIO_0->INTPOLSET = ch_bit;
  40. }
  41. if ((CMSDK_GPIO_0->INTTYPESET & ch_bit)
  42. && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) {
  43. irq_handler(channel_ids[channel], IRQ_FALL);
  44. }
  45. CMSDK_GPIO_0->INTCLEAR = ch_bit;
  46. }
  47. if (ch_bit>=16) {
  48. if (((CMSDK_GPIO_1->INTSTATUS) == 0) || (channel_ids[channel] == 0)
  49. || ((CMSDK_GPIO_1->INTTYPESET) == 0))
  50. return;
  51. if ((CMSDK_GPIO_1->INTTYPESET & ch_bit)
  52. && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
  53. irq_handler(channel_ids[channel], IRQ_RISE);
  54. CMSDK_GPIO_1->INTPOLSET = ch_bit;
  55. }
  56. if ((CMSDK_GPIO_1->INTTYPESET & ch_bit)
  57. && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) {
  58. irq_handler(channel_ids[channel], IRQ_FALL);
  59. }
  60. CMSDK_GPIO_1->INTCLEAR = ch_bit;
  61. }
  62. }
  63. void gpio0_irq0(void) {
  64. handle_interrupt_in(0);
  65. }
  66. void gpio0_irq1(void) {
  67. handle_interrupt_in(1);
  68. }
  69. void gpio0_irq2(void) {
  70. handle_interrupt_in(2);
  71. }
  72. void gpio0_irq3(void) {
  73. handle_interrupt_in(3);
  74. }
  75. void gpio0_irq4(void) {
  76. handle_interrupt_in(4);
  77. }
  78. void gpio0_irq5(void) {
  79. handle_interrupt_in(5);
  80. }
  81. void gpio0_irq6(void) {
  82. handle_interrupt_in(6);
  83. }
  84. void gpio0_irq7(void) {
  85. handle_interrupt_in(7);
  86. }
  87. void gpio0_irq8(void) {
  88. handle_interrupt_in(8);
  89. }
  90. void gpio0_irq9(void) {
  91. handle_interrupt_in(9);
  92. }
  93. void gpio0_irq10(void) {
  94. handle_interrupt_in(10);
  95. }
  96. void gpio0_irq11(void) {
  97. handle_interrupt_in(11);
  98. }
  99. void gpio0_irq12(void) {
  100. handle_interrupt_in(12);
  101. }
  102. void gpio0_irq13(void) {
  103. handle_interrupt_in(13);
  104. }
  105. void gpio0_irq14(void) {
  106. handle_interrupt_in(14);
  107. }
  108. void gpio0_irq15(void) {
  109. handle_interrupt_in(15);
  110. }
  111. void gpio1_irq0(void) {
  112. handle_interrupt_in(16);
  113. }
  114. void gpio1_irq1(void) {
  115. handle_interrupt_in(17);
  116. }
  117. void gpio1_irq2(void) {
  118. handle_interrupt_in(18);
  119. }
  120. void gpio1_irq3(void) {
  121. handle_interrupt_in(19);
  122. }
  123. void gpio1_irq4(void) {
  124. handle_interrupt_in(20);
  125. }
  126. void gpio1_irq5(void) {
  127. handle_interrupt_in(21);
  128. }
  129. void gpio1_irq6(void) {
  130. handle_interrupt_in(22);
  131. }
  132. void gpio1_irq7(void) {
  133. handle_interrupt_in(23);
  134. }
  135. void gpio1_irq8(void) {
  136. handle_interrupt_in(24);
  137. }
  138. void gpio1_irq9(void) {
  139. handle_interrupt_in(25);
  140. }
  141. void gpio1_irq10(void) {
  142. handle_interrupt_in(26);
  143. }
  144. void gpio1_irq11(void) {
  145. handle_interrupt_in(27);
  146. }
  147. void gpio1_irq12(void) {
  148. handle_interrupt_in(28);
  149. }
  150. void gpio1_irq13(void) {
  151. handle_interrupt_in(29);
  152. }
  153. void gpio1_irq14(void) {
  154. handle_interrupt_in(30);
  155. }
  156. void gpio1_irq15(void) {
  157. handle_interrupt_in(31);
  158. }
  159. int gpio_irq_init(gpio_irq_t *obj, PinName pin,
  160. gpio_irq_handler handler, uint32_t id) {
  161. if (pin == NC) {return -1;}
  162. else {
  163. irq_handler = handler;
  164. int found_free_channel = 0;
  165. int i = 0;
  166. for (i=0; i<CHANNEL_NUM; i++) {
  167. if (channel_ids[i] == 0) {
  168. channel_ids[i] = id;
  169. obj->ch = i;
  170. found_free_channel = 1;
  171. break;
  172. }
  173. }
  174. if (!found_free_channel)
  175. return -1;
  176. /* To select a pin for any of the eight pin interrupts, write the pin number
  177. * as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55.
  178. * @see: mbed_capi/PinNames.h
  179. */
  180. if (pin <16) {
  181. CMSDK_GPIO_0->INTENSET |= (0x1 << pin);
  182. }
  183. if (pin >= 16) {
  184. CMSDK_GPIO_1->INTENSET |= (0x1 << pin);
  185. }
  186. void (*channels_irq)(void) = NULL;
  187. switch (obj->ch) {
  188. case 0:
  189. channels_irq = &gpio0_irq0;
  190. break;
  191. case 1:
  192. channels_irq = &gpio0_irq1;
  193. break;
  194. case 2:
  195. channels_irq = &gpio0_irq2;
  196. break;
  197. case 3:
  198. channels_irq = &gpio0_irq3;
  199. break;
  200. case 4:
  201. channels_irq = &gpio0_irq4;
  202. break;
  203. case 5:
  204. channels_irq = &gpio0_irq5;
  205. break;
  206. case 6:
  207. channels_irq = &gpio0_irq6;
  208. break;
  209. case 7:
  210. channels_irq = &gpio0_irq7;
  211. break;
  212. case 8:
  213. channels_irq = &gpio0_irq8;
  214. break;
  215. case 9:
  216. channels_irq = &gpio0_irq9;
  217. break;
  218. case 10:
  219. channels_irq = &gpio0_irq10;
  220. break;
  221. case 11:
  222. channels_irq = &gpio0_irq11;
  223. break;
  224. case 12:
  225. channels_irq = &gpio0_irq12;
  226. break;
  227. case 13:
  228. channels_irq = &gpio0_irq13;
  229. break;
  230. case 14:
  231. channels_irq = &gpio0_irq14;
  232. break;
  233. case 15:
  234. channels_irq = &gpio0_irq15;
  235. break;
  236. case 16:
  237. channels_irq = &gpio1_irq0;
  238. break;
  239. case 17:
  240. channels_irq = &gpio1_irq1;
  241. break;
  242. case 18:
  243. channels_irq = &gpio1_irq2;
  244. break;
  245. case 19:
  246. channels_irq = &gpio1_irq3;
  247. break;
  248. case 20:
  249. channels_irq = &gpio1_irq4;
  250. break;
  251. case 21:
  252. channels_irq = &gpio1_irq5;
  253. break;
  254. case 22:
  255. channels_irq = &gpio1_irq6;
  256. break;
  257. case 23:
  258. channels_irq = &gpio1_irq7;
  259. break;
  260. case 24:
  261. channels_irq = &gpio1_irq8;
  262. break;
  263. case 25:
  264. channels_irq = &gpio1_irq9;
  265. break;
  266. case 26:
  267. channels_irq = &gpio1_irq10;
  268. break;
  269. case 27:
  270. channels_irq = &gpio1_irq11;
  271. break;
  272. case 28:
  273. channels_irq = &gpio1_irq12;
  274. break;
  275. case 29:
  276. channels_irq = &gpio1_irq13;
  277. break;
  278. case 30:
  279. channels_irq = &gpio1_irq14;
  280. break;
  281. case 31:
  282. channels_irq = &gpio1_irq15;
  283. break;
  284. }
  285. NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch),
  286. (uint32_t)channels_irq);
  287. NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
  288. return 0;
  289. }
  290. }
  291. void gpio_irq_free(gpio_irq_t *obj) {
  292. }
  293. void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
  294. unsigned int ch_bit = (1 << obj->ch);
  295. // Clear interrupt
  296. if (obj->ch <16) {
  297. if (!(CMSDK_GPIO_0->INTTYPESET & ch_bit)) {
  298. CMSDK_GPIO_0->INTCLEAR = ch_bit;
  299. }
  300. }
  301. if (obj->ch >= 16) {
  302. if (!(CMSDK_GPIO_1->INTTYPESET & ch_bit)) {
  303. CMSDK_GPIO_1->INTCLEAR = ch_bit;
  304. }
  305. }
  306. // Edge trigger
  307. if (obj->ch <16) {
  308. CMSDK_GPIO_0->INTTYPESET &= ch_bit;
  309. if (event == IRQ_RISE) {
  310. CMSDK_GPIO_0->INTPOLSET |= ch_bit;
  311. if (enable) {
  312. CMSDK_GPIO_0->INTENSET |= ch_bit;
  313. } else {
  314. CMSDK_GPIO_0->INTENCLR |= ch_bit;
  315. }
  316. } else {
  317. CMSDK_GPIO_0->INTPOLCLR |= ch_bit;
  318. if (enable) {
  319. CMSDK_GPIO_0->INTENSET |= ch_bit;
  320. } else {
  321. CMSDK_GPIO_0->INTENCLR |= ch_bit;
  322. }
  323. }
  324. }
  325. if (obj->ch >= 16) {
  326. CMSDK_GPIO_1->INTTYPESET &= ch_bit;
  327. if (event == IRQ_RISE) {
  328. CMSDK_GPIO_1->INTPOLSET |= ch_bit;
  329. if (enable) {
  330. CMSDK_GPIO_1->INTENSET |= ch_bit;
  331. } else {
  332. CMSDK_GPIO_1->INTENCLR |= ch_bit;
  333. }
  334. } else {
  335. CMSDK_GPIO_1->INTPOLCLR |= ch_bit;
  336. if (enable) {
  337. CMSDK_GPIO_1->INTENSET |= ch_bit;
  338. } else {
  339. CMSDK_GPIO_1->INTENCLR |= ch_bit;
  340. }
  341. }
  342. }
  343. }
  344. void gpio_irq_enable(gpio_irq_t *obj) {
  345. NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
  346. }
  347. void gpio_irq_disable(gpio_irq_t *obj) {
  348. NVIC_DisableIRQ((IRQn_Type)(PININT_IRQ + obj->ch));
  349. }