/****************************************************************************** 版权所有: 文件名称: gpio.c 文件版本: 01.01 创建作者: zhaoyang 创建日期: 2023-12-14 功能说明: gpio驱动程序。 其它说明: 修改记录: [old]-->drop gpio0: a0111000.gpio -> gpiochip480 -> GPIO0_0 gpio1: a0112000.gpio -> gpiochip448 -> GPIO1_0 gpio2: a0387000.gpio -> gpiochip416 -> GPIO2_0 gpio3: a0388000.gpio -> gpiochip384 -> GPIO3_0 gpio4: a0919000.gpio -> gpiochip352 -> GPIO4_0 gpio5: a091a000.gpio -> gpiochip320 -> GPIO5_0 gpio6: a091b000.gpio -> gpiochip288 -> GPIO6_0 gpio7: a091c000.gpio -> gpiochip256 -> GPIO7_0 PDO0_1 --> GPIO5_22 --> gpio342 PDO1_1 --> GPIO5_23 --> gpio343 PDO2_1 --> GPIO5_24 --> gpio344 PDO3_1 --> GPIO5_25 --> gpio345 KOUT0 --> GPIO4_29 --> gpio381 KOUT1 --> GPIO4_30 --> gpio382 KOUT2 --> GPIO4_31 --> gpio383 KOUT3 --> GPIO5_0 --> gpio320 KOUT4 --> GPIO5_1 --> gpio321 KOUT5 --> GPIO5_2 --> gpio322 KOUT6 --> GPIO5_3 --> gpio323 KOUT7 --> GPIO5_4 --> gpio324 KOUT8 --> GPIO5_5 --> gpio325 KOUT9 --> GPIO5_6 --> gpio326 // sunxi 20220530 KOUT10 --> GPIO5_7 --> gpio327 // sunxi 20220530 KOUT_EN0 --> GPIO5_8 --> gpio328 // sunxi 20220530 KOUT_EN1 --> GPIO5_9 --> gpio329 KOUT10 --> GPIO2_21 --> gpio437 KOUT_EN0 --> GPIO3_18 --> gpio402 KOUT_EN1 --> GPIO3_19 --> gpio403 RUN led --> GPIO3_17 --> gpio401 ERR led --> GPIO3_20 --> gpio404 // sunxi 20220609 esam_pwr --> GPIO0_10 --> gpio490 esam_pwr --> GPIO2_21 --> gpio437 WTD --> GPIO0_31 --> gpio511 [new]-->applay gpio0: a0111000.gpio -> gpiochip0 -> GPIO0_0 gpio1: a0112000.gpio -> gpiochip32 -> GPIO1_0 gpio2: a0387000.gpio -> gpiochip64 -> GPIO2_0 gpio3: a0388000.gpio -> gpiochip96 -> GPIO3_0 gpio4: a0919000.gpio -> gpiochip128 -> GPIO4_0 gpio5: a091a000.gpio -> gpiochip160 -> GPIO5_0 gpio6: a091b000.gpio -> gpiochip192 -> GPIO6_0 gpio7: a091c000.gpio -> gpiochip224 -> GPIO7_0 PDO0_1 --> GPIO5_22 --> gpio182 PDO1_1 --> GPIO5_23 --> gpio183 PDO2_1 --> GPIO5_24 --> gpio184 PDO3_1 --> GPIO5_25 --> gpio185 KOUT0 --> GPIO4_29 --> gpio157 KOUT1 --> GPIO4_30 --> gpio158 KOUT2 --> GPIO4_31 --> gpio159 KOUT3 --> GPIO5_0 --> gpio160 KOUT4 --> GPIO5_1 --> gpio161 KOUT5 --> GPIO5_2 --> gpio162 KOUT6 --> GPIO5_3 --> gpio163 KOUT7 --> GPIO5_4 --> gpio164 KOUT8 --> GPIO5_5 --> gpio165 KOUT9 --> GPIO5_6 --> gpio166 // zhaoyang 20231214 KOUT10 --> GPIO5_7 --> gpio167 // zhaoyang 20231214 KOUT_EN0 --> GPIO5_8 --> gpio168 // zhaoyang 20231214 KOUT_EN1 --> GPIO5_9 --> gpio169 KOUT10 --> GPIO2_21 --> gpio85 KOUT_EN0 --> GPIO3_18 --> gpio114 KOUT_EN1 --> GPIO3_19 --> gpio115 RUN led --> GPIO3_17 --> gpio113 ERR led --> GPIO3_20 --> gpio116 // zhaoyang 20231214 esam_pwr --> GPIO0_10 --> gpio10 esam_pwr --> GPIO2_21 --> gpio85 WTD --> GPIO0_31 --> gpio31 */ /*------------------------------- 头文件 -------------------------------------- */ #include "bspconfig.h" #include "gpio.h" #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ #if CFG_BSP_DEBUG #define _GPIO_DEBUG #endif /*------------------------------ 全局变量 ------------------------------------- */ unsigned short kc_pwm0_stu; unsigned short kc_pwm1_stu; unsigned short kc_kout0_stu; unsigned short kc_kout1_stu; extern uint32_t g_yx_buf[2]; //预留64个遥信 /*------------------------------ 函数声明 ------------------------------------- */ extern unsigned int change_di_ch(unsigned int di); int gpio_val_fd[DO_NUM]; const int gpio_val[DO_NUM] = {96, 97, 98, 99, 100, 101, 102, 103, 104, 105}; int gpio_val_fd_other[GPIO_NUM_OTHER]; const int gpio_val_other[GPIO_NUM_OTHER] ={39,164,359,197}; // static int gpio_watchdog_val = 0; static int gpio_run_led_val = 0; /*------------------------------ 外部函数 ------------------------------------- */ /****************************************************************************** 函数名称: gpio_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-06-26 函数说明: gpio初始化。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int gpio_init(void) { int i, j; int exportfd, directionfd; char num[10]; char path[50] = ""; //do exportfd = open("/sys/class/gpio/export", O_WRONLY); if (exportfd < 0) { printf("Cannot open GPIO to export it\n"); return -1; } for (i = 0; i < DO_NUM; i ++) { sprintf(num, "%d", gpio_val[i]); write(exportfd, num, 4); gpio_val_fd[i] = -1; } for (i = 0; i < GPIO_NUM_OTHER; i ++) { sprintf(num, "%d", gpio_val_other[i]); write(exportfd, num, 4); gpio_val_fd_other[i] = -1; } close(exportfd); #if 0 // TODO:需根据实际硬件重新对应匹配 for (i = 0; i < DO_NUM; i ++) { sprintf(path, "/sys/class/gpio/gpio%d/value", gpio_val[i]); gpio_val_fd[i] = open(path, O_RDWR); if (gpio_val_fd[i] < 0) { printf("Cannot open GPIO%d value!\n", gpio_val[i]); for(j = 0; j < i; j ++) { close(gpio_val_fd[j]); gpio_val_fd[j] = -1; } return -4; } } // Update the direction of the GPIO to be an output for (i = 0; i < DO_NUM; i ++) { sprintf(path, "/sys/class/gpio/gpio%d/direction", gpio_val[i]); directionfd = open(path, O_RDWR); if (directionfd < 0) { printf("Cannot open GPIO%d direction!\n", gpio_val[i]); return -2; } write(directionfd, "out", 4); write(gpio_val_fd[i], "1", 2); close(directionfd); } #endif msleep(10);// 延时10ms for (i = 0; i < GPIO_NUM_OTHER; i ++) { sprintf(path, "/sys/class/gpio/gpio%d/value", gpio_val_other[i]); gpio_val_fd_other[i] = open(path, O_RDWR); if (gpio_val_fd_other[i] < 0) { printf("Cannot open GPIO%d value!\n", gpio_val_other[i]); for(j = 0; j < i; j ++) { close(gpio_val_fd_other[j]); gpio_val_fd_other[j] = -1; } // for(j = 0; j < DO_NUM; j ++) // { // close(gpio_val_fd[j]); // gpio_val_fd[j] = -1; // } return -5; } } for (i = 0; i < GPIO_NUM_OTHER; i ++) { sprintf(path, "/sys/class/gpio/gpio%d/direction", gpio_val_other[i]); directionfd = open(path, O_RDWR); if (directionfd < 0) { printf("Cannot open GPIO%d direction!\n", gpio_val_other[i]); return -3; } write(directionfd, "out", 4); close(directionfd); } kc_pwm0_stu = 0; kc_pwm1_stu = 0; kc_kout0_stu=0; kc_kout1_stu=0; //其他与底层GPIO相关的配置再此处添加 比如 LED WATCHDOG jack.liu 202009010 // write(gpio_val_fd_other[WATCHDOG], "0", 2);//TODO: 需根据实际硬件重新对应匹配 // gpio_watchdog_val = 0; write(gpio_val_fd_other[RUN_LED], "0", 2); gpio_run_led_val = 0; //上电默认切换到外部232串口 //后续根据投退判断是否需要切换到线损的维护口 write(gpio_val_fd_other[LINE_LOSS_SET], "0", 2); //首次上电,开出合闸,会导致第六路也开出,需要初始化关闭 // write(gpio_val_fd[DO_OUT1], "1", 2); #if 0 // TODO:需根据实际硬件重新对应匹配 for (i = 0; i < DO_NUM; i ++) { write(gpio_val_fd[i], "1", 2); } #endif return 0; } int gpio_exit(void) { int i; int unexportfd; char num[10]; unexportfd = open("/sys/class/gpio/unexport", O_WRONLY); if (unexportfd < 0) { printf("Cannot open GPIO to unexport it\n"); return -1; } for (i = 0; i < DO_NUM; i ++) { if(gpio_val_fd[i] >= 0) { close(gpio_val_fd[i]); gpio_val_fd[i] = -1; } sprintf(num, "%d", gpio_val[i]); write(unexportfd, num, 4); } for (i = 0; i < GPIO_NUM_OTHER; i ++) { if(gpio_val_fd_other[i] >= 0) { close(gpio_val_fd_other[i]); gpio_val_fd_other[i] = -1; } sprintf(num, "%d", gpio_val_other[i]); write(unexportfd, num, 4); } close(unexportfd); return 0; } /****************************************************************************** 函数名称: gpio_get_kin 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-09-16 函数说明: 得到开入的状态。 参数说明: 无 返回值: 返回开入的状态,每个bit代表一个开入量。 修改记录: */ unsigned int gpio_get_kin(unsigned int addr) { register unsigned int dw; unsigned int value[3]; value[0] = *(volatile unsigned int *)addr; value[1] = *(volatile unsigned int *)addr; value[2] = *(volatile unsigned int *)addr; dw = (value[0] & value[1]) | (value[0] & value[2]) | (value[1] & value[2]); return dw; } /****************************************************************************** 函数名称: gpio_get_di 函数版本: 01.01 创建作者: 创建日期: 2014-11-28 函数说明: 得到开入的状态 参数说明: 无 返回值: 返回开入的状态,每个bit代表一个开入量。 修改记录: */ unsigned int gpio_get_di(void) { unsigned int dw = 0; dw = g_yx_buf[0];//这里保存的是共享内存的yx值,156us更新一次 return change_di_ch(~dw);//取反---因为没有短接时,值为1. 所以要取反为0才行 } /****************************************************************************** 函数名称: gpio_di_fj 函数版本: 01.01 创建作者: 创建日期: 2014-11-28 函数说明: 读取开出返校遥信值,控制板遥信为YX17~YX18 YX17:选择, YX18:执行 参数说明: 无 返回值: 返回遥信值 修改记录: */ #ifdef DO_KOUT_CHECK unsigned short gpio_di_fj(unsigned char index)//(void) #else unsigned short gpio_di_fj(void) #endif { unsigned int di=0; unsigned short ret=0; di = gpio_get_di(); #ifdef DO_KOUT_CHECK //V4-20; //ret = (unsigned short)((di >>19) & 0x0001); ret = (unsigned short)((di >>index) & 0x0001); #else ret = (unsigned short)((di >> 23) & 0x0001);//dtu #endif return ret; } static void gpio_kouten_do(int on, unsigned int kouten) { // if (kouten > KOUT_EN1) // return; // if(on) // { // write(gpio_val_fd_other[KOUT_EN0+kouten], "1", 2); // } // else // { // write(gpio_val_fd_other[KOUT_EN0+kouten], "0", 2); // } } /****************************************************************************** 函数名称: gpio_kout_do 函数版本: 01.01 创建作者: 创建日期: 2014-11-28 函数说明: 开出 参数说明: on: 1开出, 0回收 kout: 那一路 返回值: 无 修改记录: */ void gpio_kout_do(int on, unsigned int kout) { //if (kout > (DO_NUM-DO_OUT0)) // return; if(on) { if((kout==6) || (kout==7)) { // gpio_kouten_do(1,KOUT_EN1); kc_kout1_stu |= (1 << kout); } else { // gpio_kouten_do(1,KOUT_EN0); kc_kout0_stu |= (1 << kout); } write(gpio_val_fd[kout+DO_OUT0], "0", 2); } else { write(gpio_val_fd[kout+DO_OUT0], "1", 2); if((kout==6) || (kout==7)) { kc_kout1_stu &= ~(1 << kout); } else { kc_kout0_stu &= ~(1 << kout); } if ((kc_pwm1_stu== 0) &&(kc_kout1_stu == 0)) { // gpio_kouten_do(0,KOUT_EN1); } if ((kc_kout0_stu == 0) && (kc_pwm0_stu==0)) { // gpio_kouten_do(0,KOUT_EN0); } } } /****************************************************************************** 函数名称: gpio_pwm_do 函数版本: 01.01 创建作者: 创建日期: 2014-11-28 函数说明: pwm开出,由于存在kc_pwm_stu,只允许在同一控制路径中开出(例如同一中断或同一线程). 参数说明: on: 1开出, 0回收 返回值: 无 修改记录: */ void gpio_pwm_do(int on, unsigned int kout) { // if (kout >= DO_NUM) // return; if(on) { if((kout==0) || (kout==1)) { // gpio_kouten_do(1,KOUT_EN1); kc_pwm1_stu |= (1 << kout); } else { // gpio_kouten_do(1,KOUT_EN0); kc_pwm0_stu |= (1 << kout); } write(gpio_val_fd[kout], "0", 2); } else { write(gpio_val_fd[kout], "1", 2); if((kout==0) || (kout==1)) { kc_pwm1_stu &= ~(1 << kout); } else { kc_pwm0_stu &= ~(1 << kout); } if ((kc_pwm1_stu== 0) &&(kc_kout1_stu == 0)) { // gpio_kouten_do(0,KOUT_EN1); } if ((kc_kout0_stu == 0) && (kc_pwm0_stu==0)) { // gpio_kouten_do(0,KOUT_EN0); } } } /****************************************************************************** 函数名称: gpio_get_wirelessin 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-09-16 函数说明: 得到无线遥控的状态。 参数说明: 无 返回值: 返回开入的状态,每个bit代表一个开入量。 修改记录: */ unsigned int gpio_get_wirelessin(void) { register unsigned int dw = 0; return dw; } unsigned int gpio_get_version(void) { register unsigned int dw = 0; return dw; } unsigned int gpio_get_addr(void) { register unsigned int dw = 0; return dw; } /****************************************************************************** 函数名称: gpio_watchdog_reset 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-09-16 函数说明: 复位看门狗。 参数说明: 无。 返回值: 无。 修改记录: */ // void gpio_watchdog_reset(void) // { // if(gpio_watchdog_val) // { // gpio_watchdog_val = 0; // write(gpio_val_fd_other[WATCHDOG], "0", 2); // } // else // { // gpio_watchdog_val = 1; // write(gpio_val_fd_other[WATCHDOG], "1", 2); // } // return; // } void _led_run_err(void) { //运行指示灯,每隔0.5s改变状态一次 if(!gpio_run_led_val) { gpio_run_led_val = 1; write(gpio_val_fd_other[RUN_LED], "0", 2); //错误指示灯,跟随RUN灯闪动 if(rt_err_count()) { write(gpio_val_fd_other[ERR_LED], "0", 2); } } else { gpio_run_led_val = 0; write(gpio_val_fd_other[RUN_LED], "1", 2); write(gpio_val_fd_other[ERR_LED], "1", 2); } } void esam_power_ctrl(int on) { if(on) write(gpio_val_fd_other[ESAM_PWR], "1", 2); else write(gpio_val_fd_other[ESAM_PWR], "0", 2); } /*------------------------------ 内部函数 ------------------------------------- */ /*------------------------------ 测试函数 ------------------------------------- */ #ifdef _GPIO_DEBUG #include "ustimer.h" #include "rt.h" int gpio_test(void) { int ret = 0; //unsigned int i; //gpio_kouten_do(1,KOUT_EN1); #if 1 while(1) { sleep(5); gpio_kout_do(1,DO_OUT2-DO_OUT0); //gpio_kout_do(1,DO_OUT3-DO_OUT0); // gpio_pwm_do(1,DO_PWM1); sleep(5); gpio_kout_do(0,DO_OUT2-DO_OUT0); //gpio_kout_do(0,DO_OUT3-DO_OUT0); // gpio_pwm_do(0,DO_PWM1); /* for(i=DO_OUT0; i