使用firmware

我们在使用Ralink芯片的WiFi时,很多型号是需要在加载模块时也加载固件的,这样做是有好处的,一可以省成本(少了保存固件的存储芯片和生产烧录),二是解决硬件BUG(通过更新固件来解决批量硬件存在的严重BUG),三是功能升级。总之好处多多,怎么都可以挖掘到。
在Linux中关于固件常用到如下函数,其在include/linux/firmware.h声明,在drivers/base/firmware_class.c实现,相应的函数原型如下:
static inline int request_firmware(const struct firmware **fw, const char *name, struct device *device) ;
static inline void release_firmware(const struct firmware *fw) ;
其中firmware结构体定义如下:
struct firmware {
        size_t size;
        const u8 *data;
        struct page **pages;

        /* firmware loader private fields */
        void *priv;
};
而相应的device结构体在include/linux/device.h中定义,我们等会只是构建一个临时的device,该部分在后期的内核模型中再说明,其使用device_initialize函数来初始化,在drivers/base/core.c中定义。
接下来上代码吧:
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/device.h>

#define SLAM_TEST_FIRMWARE "rt73.bin"
static const struct firmware * fwp;

static struct device slam_device = {
        .init_name = "slam0",
};

static void print_firmware_data(char * fw, int size)
{
        u8 buf[size+1];
        memcpy(buf, fw, size);
        buf[size] = '\0';
        printk("firmware data:%x\n", buf);
}

static __init int firmware_operate_init(void)
{
        int ret = 0;

        device_initialize(&slam_device);

        ret = request_firmware(&fwp, SLAM_TEST_FIRMWARE, &slam_device);
        if (ret) {
                printk("Load firmware failed!\n");
                return -1;
        }

        print_firmware_data(fwp->data, fwp->size);

        release_firmware(fwp);

        return 0;
}

static __exit void firmware_operate_exit(void)
{
        printk("%s\n", __func__);
}

module_init(firmware_operate_init);
module_exit(firmware_operate_exit);

MODULE_AUTHOR("xinu");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(SLAM_TEST_FIRMWARE);
相应的Makefile文件内容如下:
obj-m += firmware_operate_example.o

CUR_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6

all:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules

clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean
对应的源码文件目录树如下:
/home/xinu/xinu/linux_kernel_driver_l1/firmware_operate_example/
├── firmware_operate_example.c
└── Makefile
在源码里我读取并打印了rt73.bin的内容,具体请查看你的/lib/firmware目录,可换成你的目录里其他文件试试看。从源码里我们看到对固件操作很简单,其实现在只是涉及到读取固件,读完后还需要使用其来初始化对应芯片呢,这个可以找下Ralink的WiFi源码研究研究。
参考网址:
http://blog.csdn.net/xxxxxlllllxl/article/details/9391449
http://lxr.free-electrons.com/source/samples/firmware_class/firmware_sample_driver.c?v=2.6.30
http://blog.clanzx.net/2013/11/26/linux-firmware-load.html
http://lwn.net/Articles/198461/

评论

此博客中的热门博文

I/O映射之I/O端口

通过Netlink检测网线插拔

使用seq_file