最近在RT5350上基于原厂SDK设计串口转换功能,做好以后,要将恢复出厂设置加上,通过长按按钮触发。以下是自己的笔记,发出来供有需要的朋友参考,主要是分享一下思路。
原厂固件在Web页面Administration/Settings Management中提供了恢复出厂设置功能,通过goform提交给goahead处理:
【settings.asp】
LoadDefaultSettings函数在goahead/src/managment.c中定义:
static void LoadDefaultSettings(webs_t wp, char_t *path, char_t *query);
websFormDefine(T("LoadDefaultSettings"), LoadDefaultSettings);
此函数中,用"ralink_init clear 2860"清除配置,随后根据CONFIG宏定义加载配置。
查查还有哪些地方调用了清除配置功能:
[root@zq source]# find . -name "*.c" | xargs grep "ralink_init clear 2860"
./user/goahead/src/management.c: doSystem("ralink_init clear 2860");
./user/goahead/src/management.c: system("ralink_init clear 2860");
./user/goahead/cgi-src/upload_settings.cgi.c: system("ralink_init clear 2860");
./user/rt2880_app/nvram/nvram_daemon.c: system("ralink_init clear 2860");
发现除了goahead,还有nvram_daemon调用过:nvram_daemon.c中关联了GPIO中断,中断触发信号,在信号处理函数中实现WPS功能和加载默认配置功能。
【nvram_daemon.c】
104 int initGpio(void)
105 {
106 #ifndef CONFIG_RALINK_GPIO
107 signal(SIGUSR1, nvramIrqHandler);
108 signal(SIGUSR2, nvramIrqHandler);
109 return 0;
110 #else
111 int fd;
112 ralink_gpio_reg_info info;
113
114 info.pid = getpid();
115 #ifdef CONFIG_RALINK_RT2880
116 info.irq = 0;
117 #else
118 #if defined CONFIG_RALINK_RT3052 && ((CONFIG_RALINK_I2S) || defined (CONFIG_RALINK_I2S_MODULE))
119 info.irq = 43;
120 #elif defined CONFIG_RALINK_RT3883
121 //RT3883 uses gpio 27 for load-to-default
122 info.irq = 27;
123 #else
124 //RT2883, RT3052, RT3352 use gpio 10 for load-to-default
125 info.irq = 10;
126 #endif
127 #endif
…
153 //register my information
154 if (ioctl(fd, RALINK_GPIO_REG_IRQ, &info) < 0)
155 goto ioctl_err;
156 close(fd);
157
158 //issue a handler to handle SIGUSR1 and SIGUSR2
159 signal(SIGUSR1, nvramIrqHandler);
160 signal(SIGUSR2, nvramIrqHandler);
161 return 0;
…
167 #endif
在nvramIrqHandler中断处理函数中:
1. 如果定义了CONFIG_RALINK_RT2880,SIGUSR1传递给goahead的进程处理
2. SIGUSR2触发加载默认配置
--------------------------------------------------------------------------
63 if (signum == SIGUSR1) {
64 #ifdef CONFIG_RALINK_RT2880
65 int gopid;
66 FILE *fp = fopen("/var/run/goahead.pid", "r");
67
68 if (NULL == fp) {
69 printf("nvram: goAhead is not running\n");
70 return;
71 }
72 fscanf(fp, "%d", &gopid);
73 if (gopid < 2) {
74 printf("nvram: goAhead pid(%d) <= 1\n", gopid);
75 return;
76 }
77
78 //send SIGUSR1 signal to goAhead for WPSPBCStart();
79 printf("notify goahead to start WPS PBC..\n");
80 kill(gopid, SIGUSR1);
81 fclose(fp);
82 #else
83 //RT2883, RT3052, RT3883 use a different gpio number for WPS,
84 //which will be registered in goahead instead
85 #endif
给GPIO0引脚持续低电平,串口打印:
ralink_gpio: sending a SIGUSR1 to process 18
The PBC button is pressed but WPS is disabled now.
...
ralink_gpio: sending a SIGUSR2 to process 18
这说明系统检测到了低电平,但设备并未动作,查看进程发现发错了信号,nvram_daemon的PID是17,18是goahead:
# ps
PID USER VSZ STAT COMMAND
…
17 admin 1364 S nvram_daemon
18 admin 1724 S goahead
中断明明是在nvram_daemon中关联的,信号为什么会发给goahead呢?来看看goahead:
【goahead.c】
static int initSystem(void)
-------------------------------------------------
271 static int initSystem(void)
272 {
273 int setDefault(void);
274
275 signal(SIGTSTP, dhcpcHandler);
276 signal(SIGUSR2, SIG_IGN); //忽略了SIGUSR2
…
282 #ifdef CONFIG_RALINK_RT2880
283 signal(SIGUSR1, goaSigHandler);
284 #else
285 goaInitGpio();
286 #endif
static void goaInitGpio()
-------------------------------------------------
214 #ifndef CONFIG_RALINK_RT2880
215 static void goaInitGpio()
216 {
217 int fd;
218 ralink_gpio_reg_info info;
219
220 fd = open("/dev/gpio", O_RDONLY);
…
242 if (ioctl(fd, RALINK_GPIO_REG_IRQ, &info) < 0)
原来goahead中也关联了GPIO中断,显然与nvram_daemon冲突了。
这两个程序中关联GPIO是通过 CONFIG_RALINK_GPIO 和 CONFIG_RALINK_RT2880 两个宏来控制的,来看看编译时这两个宏的定义:
[root@zq source]# vi linux-2.6.21.x/.config
12 # CONFIG_RALINK_RT2880 is not set
15 CONFIG_RALINK_RT5350=y
723 CONFIG_RALINK_GPIO=y
即:CONFIG_RALINK_GPIO有定义(使得nvram_daemon中注册了GPIO中断),而CONFIG_RALINK_RT2880未定义(使得goahead中又注册了GPIO中断)
修改:将nvram_daemon.c和goahead.c中的CONFIG_RALINK_RT2880 替换为CONFIG_RALINK_RT5350 —— 在这两个文件中CONFIG_RALINK_RT2880各只出现了两次(上文已列出并以粗体标注),所以这样改不会影响别的功能。
再测试,对GPIO0给持续低电平,设备复位了:
#
# ralink_gpio: sending a SIGUSR1 to process 17
notify goahead to start WPS PBC..
The PBC button is pressed but WPS is disabled now.
…
Commit crc = 60e0c330
ralink_gpio: sending a SIGUSR2 to process 17
load default and reboot..
The system is going down NOW!
Sending SIGTERM to all processes
Sending SIGKILLralink_gpio: sending a SIGUSR2 to process 17
ralink_gpio: sending a SIGUSR1 to process 17
ralink_gpio: sending a SIGUSR1 to process 17
Requesting system reboot
Restarting system.
复位后检查,设备确实恢复了默认设置。
总结一下,此问题算是SDK的BUG —— 早期针对RT2880芯片做的功能,后面增加RT5350时没有处理好兼容性。
推荐CSDN博客上一篇介绍RT5350 GPIO的文章供参考:ralink5350 gpio按键学习记录
------------------------------------------我是分割线------------------------------------------
顺便宣传一下我们做的模块:
出厂时预置了串口转换功能,可通过Web页面配置:
有需要的朋友可以到淘宝购买(将本页地址复制到订单备注中,然后联系客服,每片模块立减5元。)