首页 > 代码库 > 嵌入式系统最小驱动框架(类似linux驱动程序架构)

嵌入式系统最小驱动框架(类似linux驱动程序架构)

2010年就打算把linux里的驱动框架核心代码抠出来的,但是由于懒而且linux代码量大,一直下不了手。最近调试的intel curie里驱动架构也类似linux,代码就少多了,由于工作需要不得不梳理一下这一堆代码,今天花了一下午,把整个BSP部分的驱动核心抽离出来了,并且做了几个小sample。

最小驱动框架核心代码

1、设备管理

device.c

#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <stdint.h>#include <errno.h>#include "../../bsp/soc/soc_config.h"#include "../../bsp/soc/device.h"static struct td_device **all_devices = NULL;static uint32_t all_devices_count = 0;void init_devices(struct td_device **_all_devices, uint32_t _all_devices_count){    if (all_devices != NULL)        /* Devices already init */        return;    /* Link array with root device */    all_devices = _all_devices;    all_devices_count = _all_devices_count;    uint32_t i;    int ret = 0;    for (i = 0; i < all_devices_count; ++i)    {        struct td_device *dev = all_devices[i];        if (dev->driver->init && (ret = dev->driver->init(dev)))        {            dev->powerstate = PM_NOT_INIT;            printf("dev(%d) is not init",dev->id);        }        dev->powerstate = PM_RUNNING;    }}static void resume_devices_from_index(uint32_t i){    int ret = 0;    struct td_device *dev = NULL;    for (; i < all_devices_count; ++i)    {        dev = all_devices[i];        printf("resume device %d", dev->id);        if (dev->powerstate <= PM_SHUTDOWN)        {            ret = -EINVAL;            goto err_resume_device;        }        if (dev->powerstate == PM_RUNNING)            /* Device already running */            continue;        if (dev->driver->resume && (ret = dev->driver->resume(dev)))            goto err_resume_device;        /* Current device resumed */        dev->powerstate = PM_RUNNING;    }    return;err_resume_device:    printf("failed to resume device %d (%d)", dev->id,ret);}void resume_devices(void){    resume_devices_from_index(0);}int suspend_devices(PM_POWERSTATE state){    int32_t i;    int ret = 0;    /* Use the reverse order used for init, i.e. we suspend bus devices first,     * then buses, then top level devices */    for (i = all_devices_count - 1; i >= 0; --i)    {        struct td_device *dev = all_devices[i];        // device already suspended        if (dev->powerstate <= state)            continue;        printf("suspend dev %d", dev->id);        if (!dev->driver->suspend)        {            dev->powerstate = state;            continue;        }        ret = dev->driver->suspend(dev, state);        if (!ret)        {            dev->powerstate = state;            continue;        }        break;    }    if (!ret)        return 0;    /* Suspend aborted, resume all devices starting from where we had     * an issue */    if (state > PM_SHUTDOWN)        resume_devices_from_index(i + 1);    return -1;}

 

device.h

#ifndef __DEVICE_H_#define __DEVICE_H_#include <stdint.h>typedef enum{    PM_NOT_INIT = 0,    PM_SHUTDOWN,    PM_SUSPENDED,    PM_RUNNING,    PM_COUNT} PM_POWERSTATE;struct td_device;struct driver;//struct __packed __aligned(4) td_devicestruct td_device{    void *priv;    struct driver *driver;    PM_POWERSTATE powerstate : 8;    uint8_t id;};struct driver{    int (*init)(struct td_device *dev);    int (*suspend)(struct td_device *dev, PM_POWERSTATE state);    int (*resume)(struct td_device *dev);};int suspend_devices(PM_POWERSTATE state);void resume_devices(void);void init_devices(struct td_device **all_devices, uint32_t all_devices_count);void init_all_devices(void);#endif

 

2、驱动程序配置文件,我这里配置了WDT , CLK , TEST 三个简单的驱动程序。

soc_config.c

#include <stdio.h>#include <stddef.h>#include <stdlib.h>#include <errno.h>#include "../soc/soc_config.h"#include "../soc/device.h"#include "../driver/wdt/wdt.h"#include "../driver/clk/clk.h"#include "../driver/test/test.h"typedef enum{    WDT_ID = 0,    CLK_ID=1,    TEST_ID =2,} DEVICE_ID;struct td_device pf_device_wdt ={    .id = WDT_ID,    .driver = &watchdog_driver,    .priv = &(struct wdt_pm_data){        .a = 1,        .b =2,    },};struct td_device pf_device_clk ={    .id = CLK_ID,    .driver = &clk_driver,    .priv = &(struct clk_data){        .a=5,        .b=6,    },};struct td_device pf_device_test ={    .id = TEST_ID,    .driver = &test_driver,    .priv = &(struct test_data){        .a=3,        .b=4,    },};static struct td_device *qrk_platform_devices[] ={    &pf_device_wdt,    &pf_device_clk,    &pf_device_test,};#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))void init_all_devices(void){    /* Init plateform devices and buses */    init_devices(qrk_platform_devices, ARRAY_SIZE(qrk_platform_devices));}

soc_config.h

#ifndef __SOC_CONFIG_H_#define __SOC_CONFIG_H_extern struct td_device pf_device_wdt;extern struct td_device pf_device_clk;extern struct td_device pf_device_test;#endif

 

3、以上就是驱动架构的最小系统,下面添加一个驱动程序例子test_driver

test.c

#include <stdio.h>#include <stdlib.h>#include "../../soc/soc_config.h"#include "../../soc/device.h"#include "../../driver/test/test.h"int test_init(struct td_device *dev){    return 0;}static int test_suspend(struct td_device *dev, PM_POWERSTATE state){    return 0;}static int test_resume(struct td_device *dev){    return 0;}struct driver test_driver ={    .init = test_init,    .suspend = test_suspend,    .resume = test_resume};

test.h

#ifndef _TEST_H_#define _TEST_H_#include <stdint.h>extern struct driver test_driver;struct test_data{    uint32_t a;    uint32_t b;};#endif

 

5、再写个驱动程序调用实例

main.c

#include <stdio.h>#include "../bsp/soc/device.h"#include "../bsp/soc/soc_config.h"#include "../bsp/driver/test/test.h"int main(){    //driver framework test!    init_all_devices();    //driver struct test!    struct td_device *test_device =(struct td_device *)&pf_device_test;    printf("\r\n===test device(%d) ok!===\r\n",test_device->id);    //driver api test!    struct driver *test_driver = (struct driver *)test_device->driver;    if(test_driver->init(wdt_device)==0)  printf("test init ok!\n");    //driver data test!    struct test_data *data = http://www.mamicode.com/(struct test_data *)test_device->priv;    printf("test_data a:%d,b:%d!\n",data->a,data->b);    return 0;}

 

附件包下载http://files.cnblogs.com/files/dong1/mini_embed_driver_framework.zip

用code::blocks可以直接编译运行。

嵌入式系统最小驱动框架(类似linux驱动程序架构)