Chinaunix首页 | 论坛 | 博客
  • 博客访问: 891277
  • 博文数量: 286
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1841
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-09 16:26
文章分类

全部博文(286)

文章存档

2016年(38)

2015年(248)

我的朋友

分类: 嵌入式

2015-05-11 11:26:09

最近在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元。)
阅读(1483) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~