drv_gpio_ch32f20x.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-01-21 charlown first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <rthw.h>
  13. #include "board.h"
  14. #include "ch32f20x_gpio.h"
  15. #ifdef RT_USING_PIN
  16. #ifndef ITEM_NUM
  17. #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
  18. #endif
  19. struct pin_info
  20. {
  21. rt_base_t pin;
  22. rt_uint32_t gpio_pin;
  23. rt_uint32_t portsource;
  24. rt_uint32_t pinsource;
  25. GPIO_TypeDef *gpio;
  26. };
  27. /*
  28. *pin: assign number, start 0
  29. *group: such GPIOA, use 'A'
  30. *gpio_pin: such GPIO_PIN_0, use '0'
  31. */
  32. #define ASSIGN_PIN(pin, group, gpio_pin) \
  33. { \
  34. pin, GPIO_Pin_##gpio_pin, GPIO_PortSourceGPIO##group, GPIO_PinSource##gpio_pin, GPIO##group \
  35. }
  36. #define NOT_USE_PIN \
  37. { \
  38. -1, 0, 0, 0, 0 \
  39. }
  40. static const struct pin_info pin_info_list[] = {
  41. #if defined(GPIOA)
  42. ASSIGN_PIN(0, A, 0),
  43. ASSIGN_PIN(1, A, 1),
  44. ASSIGN_PIN(2, A, 2),
  45. ASSIGN_PIN(3, A, 3),
  46. ASSIGN_PIN(4, A, 4),
  47. ASSIGN_PIN(5, A, 5),
  48. ASSIGN_PIN(6, A, 6),
  49. ASSIGN_PIN(7, A, 7),
  50. ASSIGN_PIN(8, A, 8),
  51. ASSIGN_PIN(9, A, 9),
  52. ASSIGN_PIN(10, A, 10),
  53. ASSIGN_PIN(11, A, 11),
  54. ASSIGN_PIN(12, A, 12),
  55. ASSIGN_PIN(13, A, 13),
  56. ASSIGN_PIN(14, A, 14),
  57. ASSIGN_PIN(15, A, 15),
  58. #endif
  59. #if defined(GPIOB)
  60. ASSIGN_PIN(16, B, 0),
  61. ASSIGN_PIN(17, B, 1),
  62. ASSIGN_PIN(18, B, 2),
  63. ASSIGN_PIN(19, B, 3),
  64. ASSIGN_PIN(20, B, 4),
  65. ASSIGN_PIN(21, B, 5),
  66. ASSIGN_PIN(22, B, 6),
  67. ASSIGN_PIN(23, B, 7),
  68. ASSIGN_PIN(24, B, 8),
  69. ASSIGN_PIN(25, B, 9),
  70. ASSIGN_PIN(26, B, 10),
  71. ASSIGN_PIN(27, B, 11),
  72. ASSIGN_PIN(28, B, 12),
  73. ASSIGN_PIN(29, B, 13),
  74. ASSIGN_PIN(30, B, 14),
  75. ASSIGN_PIN(31, B, 15),
  76. #endif
  77. #if defined(GPIOC)
  78. ASSIGN_PIN(32, C, 0),
  79. ASSIGN_PIN(33, C, 1),
  80. ASSIGN_PIN(34, C, 2),
  81. ASSIGN_PIN(35, C, 3),
  82. ASSIGN_PIN(36, C, 4),
  83. ASSIGN_PIN(37, C, 5),
  84. ASSIGN_PIN(38, C, 6),
  85. ASSIGN_PIN(39, C, 7),
  86. ASSIGN_PIN(40, C, 8),
  87. ASSIGN_PIN(41, C, 9),
  88. ASSIGN_PIN(42, C, 10),
  89. ASSIGN_PIN(43, C, 11),
  90. ASSIGN_PIN(44, C, 12),
  91. ASSIGN_PIN(45, C, 13),
  92. ASSIGN_PIN(46, C, 14),
  93. ASSIGN_PIN(47, C, 15),
  94. #endif
  95. #if defined(GPIOD)
  96. ASSIGN_PIN(48, D, 0),
  97. ASSIGN_PIN(49, D, 1),
  98. ASSIGN_PIN(50, D, 2),
  99. ASSIGN_PIN(51, D, 3),
  100. ASSIGN_PIN(52, D, 4),
  101. ASSIGN_PIN(53, D, 5),
  102. ASSIGN_PIN(54, D, 6),
  103. ASSIGN_PIN(55, D, 7),
  104. ASSIGN_PIN(56, D, 8),
  105. ASSIGN_PIN(57, D, 9),
  106. ASSIGN_PIN(58, D, 10),
  107. ASSIGN_PIN(59, D, 11),
  108. ASSIGN_PIN(60, D, 12),
  109. ASSIGN_PIN(61, D, 13),
  110. ASSIGN_PIN(62, D, 14),
  111. ASSIGN_PIN(63, D, 15),
  112. #endif
  113. #if defined(GPIOE)
  114. ASSIGN_PIN(64, E, 0),
  115. ASSIGN_PIN(65, E, 1),
  116. ASSIGN_PIN(66, E, 2),
  117. ASSIGN_PIN(67, E, 3),
  118. ASSIGN_PIN(68, E, 4),
  119. ASSIGN_PIN(69, E, 5),
  120. ASSIGN_PIN(70, E, 6),
  121. ASSIGN_PIN(71, E, 7),
  122. ASSIGN_PIN(72, E, 8),
  123. ASSIGN_PIN(73, E, 9),
  124. ASSIGN_PIN(74, E, 10),
  125. ASSIGN_PIN(75, E, 11),
  126. ASSIGN_PIN(76, E, 12),
  127. ASSIGN_PIN(77, E, 13),
  128. ASSIGN_PIN(78, E, 14),
  129. ASSIGN_PIN(79, E, 15),
  130. #endif
  131. };
  132. static const struct pin_info *pin_info_list_find(rt_base_t pin)
  133. {
  134. const struct pin_info *item = RT_NULL;
  135. if ((pin != -1) && (pin < ITEM_NUM(pin_info_list)))
  136. {
  137. item = pin_info_list[pin].pin == -1 ? RT_NULL : &pin_info_list[pin];
  138. }
  139. return item;
  140. }
  141. static rt_base_t pin_info_list_find_pin(rt_uint16_t portsource, rt_uint16_t pinsource)
  142. {
  143. rt_base_t pin = -1;
  144. int index;
  145. for (index = 0; index < ITEM_NUM(pin_info_list); index++)
  146. {
  147. if (pin_info_list[index].portsource == portsource && pin_info_list[index].pinsource == pinsource)
  148. {
  149. pin = pin_info_list[index].pin;
  150. break;
  151. }
  152. }
  153. return pin;
  154. }
  155. /*
  156. *use: 0 using the exti line, -1 do not using
  157. */
  158. struct exti_line_irq
  159. {
  160. rt_uint16_t nvic_priority;
  161. rt_uint16_t nvic_subpriority;
  162. rt_uint32_t exit_line;
  163. IRQn_Type irqn;
  164. int use;
  165. struct rt_pin_irq_hdr bind_irq_hdr;
  166. };
  167. static struct exti_line_irq exti_line_irq_list[] = {
  168. {5, 0, EXTI_Line0, EXTI0_IRQn, 0, {
  169. .pin = -1,
  170. }},
  171. {5, 0, EXTI_Line1, EXTI1_IRQn, 0, {
  172. .pin = -1,
  173. }},
  174. {5, 0, EXTI_Line2, EXTI2_IRQn, 0, {
  175. .pin = -1,
  176. }},
  177. {5, 0, EXTI_Line3, EXTI3_IRQn, 0, {
  178. .pin = -1,
  179. }},
  180. {5, 0, EXTI_Line4, EXTI4_IRQn, 0, {
  181. .pin = -1,
  182. }},
  183. {5, 0, EXTI_Line5, EXTI9_5_IRQn, 0, {
  184. .pin = -1,
  185. }},
  186. {5, 0, EXTI_Line6, EXTI9_5_IRQn, 0, {
  187. .pin = -1,
  188. }},
  189. {5, 0, EXTI_Line7, EXTI9_5_IRQn, 0, {
  190. .pin = -1,
  191. }},
  192. {5, 0, EXTI_Line8, EXTI9_5_IRQn, 0, {
  193. .pin = -1,
  194. }},
  195. {5, 0, EXTI_Line9, EXTI9_5_IRQn, 0, {
  196. .pin = -1,
  197. }},
  198. {5, 0, EXTI_Line10, EXTI15_10_IRQn, 0, {
  199. .pin = -1,
  200. }},
  201. {5, 0, EXTI_Line11, EXTI15_10_IRQn, 0, {
  202. .pin = -1,
  203. }},
  204. {5, 0, EXTI_Line12, EXTI15_10_IRQn, 0, {
  205. .pin = -1,
  206. }},
  207. {5, 0, EXTI_Line13, EXTI15_10_IRQn, 0, {
  208. .pin = -1,
  209. }},
  210. {5, 0, EXTI_Line14, EXTI15_10_IRQn, 0, {
  211. .pin = -1,
  212. }},
  213. {5, 0, EXTI_Line15, EXTI15_10_IRQn, 0, {
  214. .pin = -1,
  215. }},
  216. };
  217. static struct exti_line_irq *exti_line_irq_list_find(rt_int16_t pin)
  218. {
  219. struct exti_line_irq *item = RT_NULL;
  220. int index;
  221. for (index = 0; index < ITEM_NUM(exti_line_irq_list); index++)
  222. {
  223. if (exti_line_irq_list[index].bind_irq_hdr.pin == pin)
  224. {
  225. item = &exti_line_irq_list[index];
  226. break;
  227. }
  228. }
  229. return item;
  230. }
  231. static rt_err_t exti_line_irq_list_bind(struct rt_pin_irq_hdr *irq_hdr)
  232. {
  233. rt_err_t ret = RT_EFULL;
  234. rt_base_t level;
  235. struct exti_line_irq *item;
  236. int index;
  237. for (index = 0; index < ITEM_NUM(exti_line_irq_list); index++)
  238. {
  239. if (exti_line_irq_list[index].bind_irq_hdr.pin == -1 && exti_line_irq_list[index].use != -1)
  240. {
  241. item = &exti_line_irq_list[index];
  242. break;
  243. }
  244. }
  245. if (item != RT_NULL)
  246. {
  247. level = rt_hw_interrupt_disable();
  248. item->bind_irq_hdr.pin = irq_hdr->pin;
  249. item->bind_irq_hdr.mode = irq_hdr->mode;
  250. item->bind_irq_hdr.hdr = irq_hdr->hdr;
  251. item->bind_irq_hdr.args = irq_hdr->args;
  252. rt_hw_interrupt_enable(level);
  253. ret = RT_EOK;
  254. }
  255. return ret;
  256. }
  257. static rt_err_t exti_line_irq_list_unbind(rt_int16_t pin)
  258. {
  259. rt_err_t ret = RT_EEMPTY;
  260. rt_base_t level;
  261. struct exti_line_irq *item;
  262. item = exti_line_irq_list_find(pin);
  263. if (item != RT_NULL)
  264. {
  265. level = rt_hw_interrupt_disable();
  266. item->bind_irq_hdr.pin = -1;
  267. rt_hw_interrupt_enable(level);
  268. ret = RT_EOK;
  269. }
  270. return ret;
  271. }
  272. void ch32f2_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
  273. {
  274. const struct pin_info *item;
  275. GPIO_InitTypeDef gpio_initstruct;
  276. item = pin_info_list_find(pin);
  277. if (item == RT_NULL)
  278. {
  279. return;
  280. }
  281. gpio_initstruct.GPIO_Pin = item->gpio_pin;
  282. gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;
  283. gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
  284. if (mode == PIN_MODE_OUTPUT)
  285. {
  286. gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;
  287. }
  288. else if (mode == PIN_MODE_INPUT)
  289. {
  290. gpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  291. }
  292. else if (mode == PIN_MODE_INPUT_PULLUP)
  293. {
  294. gpio_initstruct.GPIO_Mode = GPIO_Mode_IPU;
  295. }
  296. else if (mode == PIN_MODE_INPUT_PULLDOWN)
  297. {
  298. gpio_initstruct.GPIO_Mode = GPIO_Mode_IPD;
  299. }
  300. else if (mode == PIN_MODE_OUTPUT_OD)
  301. {
  302. gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_OD;
  303. }
  304. GPIO_Init(item->gpio, &gpio_initstruct);
  305. }
  306. void ch32f2_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
  307. {
  308. const struct pin_info *item;
  309. item = pin_info_list_find(pin);
  310. if (item == RT_NULL)
  311. {
  312. return;
  313. }
  314. GPIO_WriteBit(item->gpio, item->gpio_pin, (BitAction)value);
  315. }
  316. int ch32f2_pin_read(rt_device_t dev, rt_base_t pin)
  317. {
  318. const struct pin_info *item;
  319. item = pin_info_list_find(pin);
  320. if (item == RT_NULL)
  321. {
  322. return PIN_LOW;
  323. }
  324. return GPIO_ReadInputDataBit(item->gpio, item->gpio_pin);
  325. }
  326. rt_err_t ch32f2_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args),
  327. void *args)
  328. {
  329. struct rt_pin_irq_hdr bind_item;
  330. bind_item.pin = pin;
  331. bind_item.mode = mode;
  332. bind_item.hdr = hdr;
  333. bind_item.args = args;
  334. return exti_line_irq_list_bind(&bind_item);
  335. }
  336. rt_err_t ch32f2_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
  337. {
  338. return exti_line_irq_list_unbind(pin);
  339. }
  340. rt_err_t ch32f2_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
  341. {
  342. struct exti_line_irq *find;
  343. const struct pin_info *item;
  344. rt_base_t level;
  345. EXTI_InitTypeDef EXTI_InitStructure;
  346. NVIC_InitTypeDef NVIC_InitStructure;
  347. find = exti_line_irq_list_find(pin);
  348. if (find == RT_NULL)
  349. return RT_EINVAL;
  350. item = pin_info_list_find(pin);
  351. if (item == RT_NULL)
  352. return RT_EINVAL;
  353. if (enabled == PIN_IRQ_ENABLE)
  354. {
  355. level = rt_hw_interrupt_disable();
  356. GPIO_EXTILineConfig(item->portsource, item->pinsource);
  357. EXTI_InitStructure.EXTI_Line = find->exit_line;
  358. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  359. switch (find->bind_irq_hdr.mode)
  360. {
  361. case PIN_IRQ_MODE_RISING:
  362. {
  363. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  364. break;
  365. }
  366. case PIN_IRQ_MODE_FALLING:
  367. {
  368. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  369. break;
  370. }
  371. case PIN_IRQ_MODE_RISING_FALLING:
  372. {
  373. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  374. break;
  375. }
  376. default:
  377. break;
  378. }
  379. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  380. EXTI_Init(&EXTI_InitStructure);
  381. NVIC_InitStructure.NVIC_IRQChannel = find->irqn;
  382. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = find->nvic_priority;
  383. NVIC_InitStructure.NVIC_IRQChannelSubPriority = find->nvic_subpriority;
  384. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  385. NVIC_Init(&NVIC_InitStructure);
  386. rt_hw_interrupt_enable(level);
  387. }
  388. else
  389. {
  390. level = rt_hw_interrupt_disable();
  391. EXTI_InitStructure.EXTI_Line = find->exit_line;
  392. EXTI_InitStructure.EXTI_LineCmd = DISABLE;
  393. EXTI_Init(&EXTI_InitStructure);
  394. NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
  395. NVIC_Init(&NVIC_InitStructure);
  396. rt_hw_interrupt_enable(level);
  397. }
  398. return RT_EOK;
  399. }
  400. /*PX.XX*/
  401. rt_base_t ch32f2_pin_get(const char *name)
  402. {
  403. rt_uint16_t portsource, pinsource;
  404. int sz;
  405. sz = rt_strlen(name);
  406. if (sz == 4)
  407. {
  408. portsource = name[1] - 0x41;
  409. pinsource = name[3] - 0x30;
  410. return pin_info_list_find_pin(portsource, pinsource);
  411. }
  412. if (sz == 5)
  413. {
  414. portsource = name[1];
  415. pinsource = (name[3] - 0x30) * 10 + (name[4] - 0x30);
  416. return pin_info_list_find_pin(portsource, pinsource);
  417. }
  418. return -1;
  419. }
  420. const static struct rt_pin_ops pin_ops = {
  421. .pin_mode = ch32f2_pin_mode,
  422. .pin_write = ch32f2_pin_write,
  423. .pin_read = ch32f2_pin_read,
  424. .pin_attach_irq = ch32f2_pin_attach_irq,
  425. .pin_detach_irq = ch32f2_pin_detach_irq,
  426. .pin_irq_enable = ch32f2_pin_irq_enable,
  427. .pin_get = ch32f2_pin_get,
  428. };
  429. int rt_hw_pin_init(void)
  430. {
  431. #ifdef GPIOA
  432. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  433. #endif
  434. #ifdef GPIOB
  435. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  436. #endif
  437. #ifdef GPIOC
  438. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  439. #endif
  440. #ifdef GPIOD
  441. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
  442. #endif
  443. #ifdef GPIOE
  444. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
  445. #endif
  446. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  447. return rt_device_pin_register("pin", &pin_ops, RT_NULL);
  448. }
  449. rt_inline void exti_irq_handler(rt_uint16_t seq)
  450. {
  451. if (EXTI_GetITStatus(exti_line_irq_list[seq].exit_line) == SET)
  452. {
  453. EXTI_ClearITPendingBit(exti_line_irq_list[seq].exit_line);
  454. if (exti_line_irq_list[seq].use != -1 &&
  455. exti_line_irq_list[seq].bind_irq_hdr.pin != -1 &&
  456. exti_line_irq_list[seq].bind_irq_hdr.hdr != RT_NULL)
  457. {
  458. exti_line_irq_list[seq].bind_irq_hdr.hdr(exti_line_irq_list[seq].bind_irq_hdr.args);
  459. }
  460. }
  461. }
  462. void EXTI0_IRQHandler(void)
  463. {
  464. rt_interrupt_enter();
  465. exti_irq_handler(0);
  466. rt_interrupt_leave();
  467. }
  468. void EXTI1_IRQHandler(void)
  469. {
  470. rt_interrupt_enter();
  471. exti_irq_handler(1);
  472. rt_interrupt_leave();
  473. }
  474. void EXTI2_IRQHandler(void)
  475. {
  476. rt_interrupt_enter();
  477. exti_irq_handler(2);
  478. rt_interrupt_leave();
  479. }
  480. void EXTI3_IRQHandler(void)
  481. {
  482. rt_interrupt_enter();
  483. exti_irq_handler(3);
  484. rt_interrupt_leave();
  485. }
  486. void EXTI4_IRQHandler(void)
  487. {
  488. rt_interrupt_enter();
  489. exti_irq_handler(4);
  490. rt_interrupt_leave();
  491. }
  492. void EXTI9_5_IRQHandler(void)
  493. {
  494. rt_interrupt_enter();
  495. exti_irq_handler(5);
  496. exti_irq_handler(6);
  497. exti_irq_handler(7);
  498. exti_irq_handler(8);
  499. exti_irq_handler(9);
  500. rt_interrupt_leave();
  501. }
  502. void EXTI15_10_IRQHandler(void)
  503. {
  504. rt_interrupt_enter();
  505. exti_irq_handler(10);
  506. exti_irq_handler(11);
  507. exti_irq_handler(12);
  508. exti_irq_handler(13);
  509. exti_irq_handler(14);
  510. exti_irq_handler(15);
  511. rt_interrupt_leave();
  512. }
  513. #endif /* RT_USING_PIN */