作者: 宋立新
Email:[email protected]
恍然大悟后,当然也就不奇怪了。 不过当时 __initdata 修饰符确实给我们带来很大的困惑。
事情的经过是这样的。
通常我们设置mfp寄存器是在系统的启动阶段统一设置的, 所以 lc6830.c 中会有一个数组:
static mfp_cfg_t saar_mfp_cfg[] __initdata = {
RF_IF5_GPIO,
DF_INT_RnB_ND_INT_RnB,
…
};
系统初始化时,会调用:
pxa3xx_mfp_config(ARRAY_AND_SIZE(saar_mfp_cfg));
从而完成 mfp 寄存器的设置。
这里简单介绍一下 mfp 寄存器。
英文为: multi-function pin register
Marvell 的 AP 集成度很高, 为了以最小的 PIN 脚数量支持最多的功能, pxa935 上的绝大多数 pin 脚可以内部路由到 6 种不同的功能上。 路由到那个功能就通过 mfp 寄存器的第3位设置。
Mfp 还可以用于设置某个 PIN 脚在系统待机时的状态, 是输出高电平, 输出低电平,还是处于输入状态, 等等。
我们的蓝牙模块有几种工作模式:
在不使用蓝牙时,如果系统进入待机状态,则希望该模块处于最低功耗状态,此时,控制其power 的 GPIO 应该输出低, 以切换其电源。
而正在使用蓝牙功能时,如果系统进入待机状态,则希望该模块处于较低功耗状态,此时,控制其power 的 GPIO 应该输出高, 以保持正常的功能, 比如,能够唤醒 AP。
于是,模仿上面的数组,我们定义了如下数组:
322 static mfp_cfg_t __initdata wlan_bt_powerdown_high_mfp_cfg[] = {
323 GPIO174_BT_WIFI_POWER_GPIO_ON,
324 };
325 static mfp_cfg_t __initdata wlan_bt_powerdown_low_mfp_cfg[] = {
326 GPIO174_BT_WIFI_POWER_GPIO,
327 };
其中对 GPIO174 对应的 PIN 脚进行了相反的定义。 这样, 在打开蓝牙模块时,我们会调用:
pxa3xx_mfp_config(ARRAY_AND_SIZE(wlan_bt_powerdown_high_mfp_cfg));
而在关闭蓝牙模块时:
pxa3xx_mfp_config(ARRAY_AND_SIZE(wlan_bt_powerdown_low_mfp_cfg));
这样,确保该 PIN 脚处于合适的状态。
当时,使用工具 /root/bin/ureg_test 去读寄存器, 发现设置没有生效!
使用 trace32 跟踪代码, 发现该数组定义的数据结构各字段值不正确, 有时为0,有时为一些异常值!
苦思冥想, 终于发现定义数据结构时,直接模仿了 saar_mfp_cfg 的定义, 而 saar_mfp_cfg 只在开机时使用, 我们的数据却要在开机后使用!
将 __initdata 修饰符去掉后, 发现一切正常了!
说明: 所有 __init* 修饰的数据,函数都用于说明它们只在系统开机阶段使用,其占用的空间会在系统完成启动后释放。 此时, 它们不再有效。