码迷,mamicode.com
首页 > 系统相关 > 详细

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

时间:2017-04-29 21:09:10      阅读:265      评论:0      收藏:0      [点我收藏+]

标签:data-   running   UI   null   style   target   嵌入   include   系统   

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_device
struct 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 = (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驱动程序架构)

标签:data-   running   UI   null   style   target   嵌入   include   系统   

原文地址:http://www.cnblogs.com/dong1/p/6786056.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!