裸机驱动模板
编写裸机驱动,一般都比较随意。这通常导致代码不统一,移植性差。 本例以SPI FLASH来分析一种优秀的裸机驱动编写模板。 ? 首先定义一个设备类。 ? /* ?*flash device class ?*/ typedef struct flash_dev_s{ ?const struct flash_dev_funs *funs;????????? /* Function pointers */ ?uint32?????????????????????flags;????????? /* Devicecharacteristics */ ?hsaddr_t???????????????????start;????????? /* First address*/ ?hsaddr_t???????????????????end;??????????? /* Last address */ ?uint32?????????????????????num_block_infos;/* Number of entries */ ?const flash_block_info_t???*block_info;??? /* Info about oneblock size */ ? ?const void?????????????????*priv;????????? /* Devices privatedata */ } flash_dev_t; ? /* Structure of pointers to functions inthe device driver */ Struct ?flash_dev_funs { ?sys_error_t (*flash_init) (struct flash_dev_s *dev) REENTRANT; ?sys_error_t (*flash_erase_block) (struct flash_dev_s *dev, ??????????????????????????????????? hsaddr_tblock_base) REENTRANT; ?sys_error_t (*flash_program) (struct flash_dev_s *dev, ??????????????????????????????? hsaddr_t base, ??????????????????????????????? const void*ram_base,size_t len) REENTRANT; ?sys_error_t (*flash_read) (struct flash_dev_s *dev, ???????????????????????????? const hsaddr_tbase, ???????????????????????????? void* ram_base,size_t len) REENTRANT; }; 同一种设备类型可能有不同厂家和不同参数的差异,但它的大体功能属性是一致的。我们首先把一致的属性剥离出来,构建一个设备类。类似C++的类,包含数据和操作方法。一个设备驱动模板的雏形就出来了。 ? 我们来看一个设备实例来看它的方便之处。 struct flash_dev_funs mx25l_funs = { ???mspi_init, ???m25lxx_erase_block, ???m25lxx_program, ???m25lxx_read, ???NULL }; ? flash_dev_t n25q256_dev = { ???&mx25l_funs, ???FLAG_FSR_POLL, ???CFG_FLASH_START_ADDRESS, ???0, ???1, ???&n25q256_info, ???NULL }; flash_dev_t w25q16_dev = { ???&mx25l_funs, ?? 0, ??CFG_FLASH_START_ADDRESS, ?? 1, ??&w25q16cv_info, ??NULL }; /*end*/ ? flash_dev_t w25q64cv_dev = { ???&mx25l_funs, ???&w25q64cv_info, NULL }; ? 这里用一个通用设备结构体定义和初始化了多个不同的spi设备实例。我们看到每个设备的不同之处在它们的功能函数和设备属性。当我们需要新增一个设备时,只需定义一个通用设备类,再去添加它自己的操作方法和数据属性就行了。实现这些之后,对外部调用来说就简单了,直接操作这个设备类的统一接口,上层代码不需要做任何改动,提高了驱动移植性。 我们还可以做进一步的函数封装。 例如:把设备操作完全屏蔽,上层代码不需要管是什么设备。 sys_error_t ? ? dev = board_get_flash_dev(); ? ? rv = (*dev->funs->flash_read)(dev,addr,ram,this_read); ? ? ...... } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |