标签: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可以直接编译运行。
标签:data- running UI null style target 嵌入 include 系统
原文地址:http://www.cnblogs.com/dong1/p/6786056.html