首页 > 代码库 > 嵌入式系统最小驱动框架(类似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驱动程序架构)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。