gpio.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: gpio.c
  4. 文件版本: 01.01
  5. 创建作者: zhaoyang
  6. 创建日期: 2023-12-14
  7. 功能说明: gpio驱动程序。
  8. 其它说明:
  9. 修改记录:
  10. [new]-->applay
  11. B_DO_ADJ --> GPIOD_17 --> gpio113 预置返校
  12. B_DO_0 --> GPIOD_03 --> gpio99 预置
  13. B_DO_1 --> GPIOD_19 --> gpio115
  14. B_DO_2 --> GPIOD_02 --> gpio98
  15. B_DO_3 --> GPIOD_09 --> gpio105
  16. B_DO_4 --> GPIOD_18 --> gpio114
  17. B_DO_5 --> GPIOD_16 --> gpio112
  18. B_DO_6 --> GPIOD_07 --> gpio103
  19. B_DO_7 --> GPIOD_08 --> gpio104
  20. B_DO_8 --> GPIOD_06 --> gpio102
  21. T536 start ↓↓↓↓↓↓
  22. RUN_LED --> PB7 --> gpio39
  23. ERR_LED --> PF4 --> gpio164
  24. ESAM_PWR --> PL7 --> gpio159
  25. LINE_LOSS_SET --> PM5 --> gpio389
  26. T536 end ↑↑↑↑↑↑
  27. */
  28. /*------------------------------- 头文件 --------------------------------------
  29. */
  30. #include "bspconfig.h"
  31. #include "gpio.h"
  32. #include "head.h"
  33. #include <rtdm/gpio.h>
  34. /*------------------------------- 宏定义 --------------------------------------
  35. */
  36. #if CFG_BSP_DEBUG
  37. #define _GPIO_DEBUG
  38. #endif
  39. /*------------------------------ 全局变量 -------------------------------------
  40. */
  41. typedef enum
  42. {
  43. SYS_GPIO = 0,
  44. RTDM_GPIO = 1,
  45. } GPIO_TYPE;
  46. unsigned short kc_kout0_stu;
  47. extern uint32_t g_yx_buf[2]; // 预留64个遥信
  48. /*------------------------------ 函数声明 -------------------------------------
  49. */
  50. extern unsigned int change_di_ch(unsigned int di);
  51. int gpio_val_fd[DO_NUM];
  52. int gpio_dev_type[DO_NUM] = {
  53. SYS_GPIO,
  54. }; // 0:系统GPIO, 1:RTDM GPIO
  55. /* 开出gpio */
  56. const int gpio_val[DO_NUM] = {115, 98, 105, 114, 112, 103, 104, 102, 99, 113};
  57. // static int gpio_watchdog_val = 0;
  58. static int gpio_run_led_val = 0;
  59. /*------------------------------ 外部函数 -------------------------------------
  60. */
  61. int sysfs_gpio_unexport(int gpio)
  62. {
  63. char path[64];
  64. int fd;
  65. snprintf(path, sizeof(path), "/sys/class/gpio/unexport");
  66. fd = open(path, O_WRONLY);
  67. if (fd < 0)
  68. {
  69. perror("Failed to open unexport");
  70. return -1;
  71. }
  72. char buf[16];
  73. snprintf(buf, sizeof(buf), "%d", gpio);
  74. if (write(fd, buf, strlen(buf)) < 0)
  75. {
  76. perror("Failed to set GPIO");
  77. close(fd);
  78. return -1;
  79. }
  80. close(fd);
  81. return 0;
  82. }
  83. int sysfs_gpio_export(int gpio)
  84. {
  85. char path[64];
  86. int fd;
  87. // 检查是否已导出
  88. snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d", gpio);
  89. if (access(path, F_OK) == 0)
  90. {
  91. sysfs_gpio_unexport(gpio); // bugfix: 避免重复导出
  92. msleep(50); // 短暂等待让内核处理
  93. }
  94. snprintf(path, sizeof(path), "/sys/class/gpio/export");
  95. fd = open(path, O_WRONLY);
  96. if (fd < 0)
  97. {
  98. perror("Failed to open export");
  99. return -1;
  100. }
  101. char buf[16];
  102. snprintf(buf, sizeof(buf), "%d", gpio);
  103. if (write(fd, buf, strlen(buf)) < 0)
  104. {
  105. perror("Failed to export GPIO");
  106. close(fd);
  107. return -2;
  108. }
  109. close(fd);
  110. return 0;
  111. }
  112. int sysfs_gpio_set_direction(int gpio, int is_output)
  113. {
  114. char path[64];
  115. int fd;
  116. snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", gpio);
  117. fd = open(path, O_WRONLY);
  118. if (fd < 0)
  119. {
  120. perror("Failed to open direction");
  121. return -1;
  122. }
  123. if (write(fd, is_output ? "out" : "in", is_output ? 3 : 2) < 0)
  124. {
  125. perror("Failed to set direction");
  126. close(fd);
  127. return -1;
  128. }
  129. close(fd);
  130. return 0;
  131. }
  132. int sysfs_gpio_set_edge_detect(int gpio, int edge)
  133. {
  134. char path[64];
  135. int fd;
  136. snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", gpio);
  137. fd = open(path, O_WRONLY);
  138. if (fd < 0)
  139. {
  140. perror("Failed to open edge");
  141. close(fd);
  142. return -1;
  143. }
  144. if (write(fd, edge, strlen(edge)) < 0)
  145. {
  146. perror("Failed to set edge");
  147. close(fd);
  148. return -1;
  149. }
  150. close(fd);
  151. return 0;
  152. }
  153. int sysfs_gpio_set_value(int gpio, int value)
  154. {
  155. char path[64];
  156. int fd = -1;
  157. snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", gpio);
  158. fd = open(path, O_WRONLY);
  159. if (fd < 0)
  160. {
  161. perror("Failed to open value");
  162. return -1;
  163. }
  164. if (write(fd, value ? "1" : "0", 1) < 0)
  165. {
  166. perror("Failed to set value");
  167. close(fd);
  168. return -1;
  169. }
  170. return fd;
  171. }
  172. int sysfs_gpio_init(int gpio, int direction)
  173. {
  174. #define GPIO_LOW 0
  175. int ret;
  176. ret = sysfs_gpio_export(gpio);
  177. if (ret < 0)
  178. {
  179. dp_err_n_c("sysfs_gpio_export error ret = %d!", ret);
  180. return -1;
  181. }
  182. ret = sysfs_gpio_set_direction(gpio, direction);
  183. if (ret < 0)
  184. {
  185. dp_err_n_c("sysfs_gpio_set_direction error");
  186. }
  187. return sysfs_gpio_set_value(gpio, GPIO_LOW); // 初始化IO为低电平
  188. }
  189. int is_rtdm_device(int fd)
  190. {
  191. if (gpio_dev_type[fd] > SYS_GPIO)
  192. return 1;
  193. else if (gpio_dev_type[fd] == SYS_GPIO)
  194. return 0;
  195. else
  196. return -1;
  197. }
  198. int rt_write(int fd, char *buf, int len)
  199. {
  200. int value;
  201. if (len <= 0 || buf == NULL)
  202. {
  203. return -1;
  204. }
  205. if (is_rtdm_device(fd) == 1)
  206. {
  207. // Xenomai RTDM设备:需要转换为二进制值
  208. value = atoi(buf);
  209. if (value != 0 && value != 1)
  210. {
  211. dp_err_n_c("value :%d ERR, Please enter '0' or '1'", value);
  212. return -1;
  213. }
  214. return write(fd, &value, sizeof(value));
  215. }
  216. else
  217. {
  218. // 常规系统设备:直接传递字符串
  219. return write(fd, buf, len);
  220. }
  221. }
  222. int rtdm_gpio_init(int gpio, int direction)
  223. {
  224. #define GPIO_LOW 0
  225. char path[64];
  226. int fd = -1, ret;
  227. int value = 1;
  228. snprintf(path, sizeof(path), "/dev/rtdm/3604000.pinctrl/gpio%d", gpio);
  229. fd = open(path, O_RDWR);
  230. if (fd < 0)
  231. {
  232. perror("open");
  233. return -1;
  234. }
  235. if (113 == gpio) /* 预置返校是开入 */
  236. {
  237. ret = ioctl(fd, GPIO_RTIOC_DIR_IN, &value);
  238. }
  239. else
  240. {
  241. ret = ioctl(fd, GPIO_RTIOC_DIR_OUT, &value);
  242. }
  243. if (ret < 0)
  244. {
  245. perror("ioctl DIR_OUT");
  246. close(fd);
  247. return -1;
  248. }
  249. rt_write(gpio_val_fd[DO_OUT0], "0", 2); // 初始化IO为低电平
  250. return fd;
  251. }
  252. int gpio_init(void)
  253. {
  254. #define GPIO_OUTPUT 1
  255. int i;
  256. for (i = 0; i < DO_NUM; i++)
  257. {
  258. gpio_val_fd[i] = rtdm_gpio_init(gpio_val[i], GPIO_OUTPUT);
  259. if (gpio_val_fd[i] < 0)
  260. {
  261. gpio_val_fd[i] = sysfs_gpio_init(gpio_val[i], GPIO_OUTPUT);
  262. if (gpio_val_fd[i] < 0)
  263. {
  264. dp_err_n_c("gpio_val_fd[%d] error", i);
  265. gpio_val_fd[i] = -1;
  266. gpio_dev_type[i] = -1;
  267. return -1;
  268. }
  269. }
  270. else
  271. {
  272. gpio_dev_type[i] = gpio_val_fd[i]; // 保存RTDM设备类型句柄,这里有风险,fd句柄可能为0
  273. }
  274. }
  275. msleep(10); // 延时10ms
  276. kc_kout0_stu = 0;
  277. for (i = DO_OUT1; i < DO_NUM; i++)
  278. {
  279. write(gpio_val_fd[i], "1", 2);
  280. }
  281. return 0;
  282. }
  283. int gpio_exit(void)
  284. {
  285. int i;
  286. for (i = 0; i < DO_NUM; i++)
  287. {
  288. if (gpio_val_fd[i] >= 0)
  289. {
  290. close(gpio_val_fd[i]);
  291. gpio_val_fd[i] = -1;
  292. }
  293. sysfs_gpio_unexport(gpio_val[i]);
  294. }
  295. return 0;
  296. }
  297. /******************************************************************************
  298. 函数名称: gpio_get_di
  299. 函数版本: 01.01
  300. 创建作者:
  301. 创建日期: 2014-11-28
  302. 函数说明: 得到开入的状态
  303. 参数说明: 无
  304. 返回值: 返回开入的状态,每个bit代表一个开入量。
  305. 修改记录:
  306. */
  307. unsigned int gpio_get_di(void)
  308. {
  309. unsigned int dw = 0;
  310. dw = g_yx_buf[0]; // 这里保存的是共享内存的yx值,156us更新一次
  311. return change_di_ch(~dw); // 取反---因为没有短接时,值为1. 所以要取反为0才行
  312. }
  313. /******************************************************************************
  314. 函数名称: gpio_di_fj
  315. 函数版本: 01.01
  316. 创建作者:
  317. 创建日期: 2014-11-28
  318. 函数说明: 读取开出返校遥信值,控制板遥信为YX17~YX18
  319. YX17:选择, YX18:执行
  320. 参数说明: 无
  321. 返回值: 返回遥信值
  322. 修改记录:
  323. */
  324. #ifdef DO_KOUT_CHECK
  325. unsigned short gpio_di_fj(unsigned char index) //(void)
  326. #else
  327. unsigned short gpio_di_fj(void)
  328. #endif
  329. {
  330. unsigned int di = 0;
  331. unsigned short ret = 0;
  332. di = gpio_get_di();
  333. #ifdef DO_KOUT_CHECK
  334. // V4-20;
  335. // ret = (unsigned short)((di >>19) & 0x0001);
  336. ret = (unsigned short)((di >> index) & 0x0001);
  337. #else
  338. ret = (unsigned short)((di >> 23) & 0x0001); // dtu
  339. #endif
  340. return ret;
  341. }
  342. /**
  343. * @brief 读取预置返校的状态
  344. * @author lch (lch_work@foxmail.com)
  345. * @version 1.0
  346. * @date 20251229
  347. * @return * int
  348. * @retval none
  349. *
  350. * @warning none
  351. * @note none
  352. */
  353. int gpioio_get_perset_status(void)
  354. {
  355. char buf[2] = {0};
  356. int ret = 0;
  357. if (gpio_val_fd[DO_IN_PRESET] < 0)
  358. {
  359. dp_err_n_c("gpio_val_fd[DO_IN_PRESET] = %d, not initialized", gpio_val_fd[DO_IN_PRESET]);
  360. return -1;
  361. }
  362. ret = read(gpio_val_fd[DO_IN_PRESET], buf, sizeof(buf));
  363. if (ret > 0)
  364. {
  365. return buf[0] - '0'; // 字符转换为数字
  366. }
  367. return -1;
  368. }
  369. /******************************************************************************
  370. 函数名称: gpio_kout_do
  371. 函数版本: 01.01
  372. 创建作者:
  373. 创建日期: 2014-11-28
  374. 函数说明: 开出
  375. 参数说明: on: 1开出, 0回收
  376. kout: 那一路
  377. 返回值: 无
  378. 修改记录:
  379. */
  380. void gpio_kout_do(int on, unsigned int kout)
  381. {
  382. if (kout > (DO_NUM - DO_OUT_PRESET))
  383. return;
  384. if (on)
  385. {
  386. write(gpio_val_fd[kout + DO_OUT0], "0", 2);
  387. }
  388. else
  389. {
  390. write(gpio_val_fd[kout + DO_OUT0], "1", 2);
  391. }
  392. }
  393. /******************************************************************************
  394. 函数名称: gpio_get_wirelessin
  395. 函数版本: 01.01
  396. 创建作者: sunxi
  397. 创建日期: 2008-09-16
  398. 函数说明: 得到无线遥控的状态。
  399. 参数说明: 无
  400. 返回值: 返回开入的状态,每个bit代表一个开入量。
  401. 修改记录:
  402. */
  403. unsigned int gpio_get_wirelessin(void)
  404. {
  405. register unsigned int dw = 0;
  406. return dw;
  407. }
  408. unsigned int gpio_get_version(void)
  409. {
  410. register unsigned int dw = 0;
  411. return dw;
  412. }
  413. unsigned int gpio_get_addr(void)
  414. {
  415. register unsigned int dw = 0;
  416. return dw;
  417. }
  418. void _led_run_err(void)
  419. {
  420. // 上电就亮错误灯,有错误就继续亮没有就熄灭
  421. static uint8 err_led = 2;
  422. if (rt_err_count())
  423. {
  424. // 错误指示灯常亮且运行熄灭
  425. if (!(err_led & 0x01))
  426. {
  427. err_led |= 1;
  428. // write(gpio_val_fd_other[ERR_LED], "0", 2);
  429. // write(gpio_val_fd_other[RUN_LED], "1", 2);
  430. }
  431. return;
  432. }
  433. if (err_led)
  434. {
  435. err_led = 0;
  436. // write(gpio_val_fd_other[ERR_LED], "1", 2);
  437. }
  438. // 运行指示灯,每隔1s改变状态一次
  439. if (!gpio_run_led_val)
  440. {
  441. gpio_run_led_val = 1;
  442. // write(gpio_val_fd_other[RUN_LED], "0", 2);
  443. }
  444. else
  445. {
  446. gpio_run_led_val = 0;
  447. // write(gpio_val_fd_other[RUN_LED], "1", 2);
  448. }
  449. }
  450. void esam_power_ctrl(int on)
  451. {
  452. // if (on)
  453. // write(gpio_val_fd_other[ESAM_PWR], "1", 2);
  454. // else
  455. // write(gpio_val_fd_other[ESAM_PWR], "0", 2);
  456. }
  457. /*------------------------------ 内部函数 -------------------------------------
  458. */
  459. /*------------------------------ 测试函数 -------------------------------------
  460. */
  461. #ifdef _GPIO_DEBUG
  462. #include "ustimer.h"
  463. #include "rt.h"
  464. int gpio_test(void)
  465. {
  466. int ret = 0;
  467. // unsigned int i;
  468. #if 1
  469. while (1)
  470. {
  471. sleep(5);
  472. gpio_kout_do(1, DO_OUT2 - DO_OUT0);
  473. // gpio_kout_do(1,DO_OUT3-DO_OUT0);
  474. sleep(5);
  475. gpio_kout_do(0, DO_OUT2 - DO_OUT0);
  476. // gpio_kout_do(0,DO_OUT3-DO_OUT0);
  477. /*
  478. for(i=DO_OUT0; i<DO_NUM; i++)
  479. {
  480. rt_printf("kout number = %d!\r", i);
  481. //msleep();
  482. sleep(1);
  483. gpio_kout_do(1,i-DO_OUT0);
  484. sleep(1);
  485. gpio_kout_do(0,i-DO_OUT0);
  486. }
  487. */
  488. }
  489. #endif
  490. return ret;
  491. }
  492. int test_kc_function(void)
  493. {
  494. write(gpio_val_fd[DO_OUT_PRESET], "0", 2); // 预置动作
  495. char gpio_state[2];
  496. int ret;
  497. // 读取GPIO状态
  498. ret = read(gpio_val_fd[DO_IN_PRESET], gpio_state, sizeof(gpio_state));
  499. printf("ret: %d\n", ret);
  500. if (ret > 0)
  501. {
  502. gpio_state[ret] = '\0'; // 添加字符串结束符
  503. printf("PRESET: %s\n", gpio_state); // 应该是"0"或"1"
  504. }
  505. write(gpio_val_fd[DO_OUT0], "0", 2);
  506. sleep(1);
  507. write(gpio_val_fd[DO_OUT0], "1", 2);
  508. write(gpio_val_fd[DO_OUT1], "0", 2);
  509. sleep(1);
  510. write(gpio_val_fd[DO_OUT1], "1", 2);
  511. write(gpio_val_fd[DO_OUT2], "0", 2);
  512. sleep(1);
  513. write(gpio_val_fd[DO_OUT2], "1", 2);
  514. write(gpio_val_fd[DO_OUT3], "0", 2);
  515. sleep(1);
  516. write(gpio_val_fd[DO_OUT3], "1", 2);
  517. write(gpio_val_fd[DO_OUT_PRESET], "1", 2); // 预置动作
  518. // 读取GPIO状态
  519. ret = read(gpio_val_fd[DO_IN_PRESET], gpio_state, sizeof(gpio_state));
  520. printf("ret: %d\n", ret);
  521. if (ret > 0)
  522. {
  523. gpio_state[ret] = '\0'; // 添加字符串结束符
  524. printf("PRESET: %s\n", gpio_state); // 应该是"0"或"1"
  525. }
  526. write(gpio_val_fd[DO_OUT4], "0", 2);
  527. sleep(1);
  528. write(gpio_val_fd[DO_OUT4], "1", 2);
  529. write(gpio_val_fd[DO_OUT5], "0", 2);
  530. sleep(1);
  531. write(gpio_val_fd[DO_OUT5], "1", 2);
  532. write(gpio_val_fd[DO_OUT6], "0", 2);
  533. sleep(1);
  534. write(gpio_val_fd[DO_OUT6], "1", 2);
  535. write(gpio_val_fd[DO_OUT7], "0", 2);
  536. sleep(1);
  537. write(gpio_val_fd[DO_OUT7], "1", 2);
  538. }
  539. #endif