1.系统架构
系统划分为三层,即业务层(应用层),中间件层和驱动层.
应用层:专注于业务逻辑功能实现.
中间层:为应用层服务,为应用层提供相关服务接口,也具有少量的业务逻辑.
驱动层:提供硬件底层驱动程序.
分层思想优点:
(1).最大程度隐藏驱动代码,保护了代码的安全性。
(2).接口统一,方便应用层开发。
(3).方便代码管理,同步开发。
2.接口标准化
标准接口分为三部分:驱动层接口、中间件统一接口、应用层接口
驱动接口:由官方提供的统一接口,操作芯片相关寄存器实现某一功能接口(例如:STM32官方提供驱动接口有HAL库、LL库)。
中间件接口:中间件接口分为两类,对驱动层封装接口、供应用层调用接口。
应用层接口:本架构中,对应用层接口标准化并不严格,符合Linux内核编程规范与代码风格即可。
(1).驱动层接口(以STM32 LL库GPIO接口为例)
STM32 LL库是有意法半导体(STMicroelectronics)提供的一个官方标准可以,本库可用STM32CubeMX软件生成(使用STM32CubeMX软件记得及时更新官方最新版本,否则会出现各种奇奇怪怪的问题)。
准备工作:
搭建STM32 GCC编译环境(详情见前面搭建环境的文章)
使用STM32CubeMX软件生成STM32工程代码
修改Makefile文件,输出驱动层.a文件供中间层调用
驱动层接口:(LL_xxx_xxx)
ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx);
ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx,
LL_GPIO_InitTypeDef *GPIO_InitStruct);
void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct);
此类接口都是有官方提供,如需修改,先联系原厂工程师咨询。
(2).中间件接口
中间件接口分为两类:与驱动层对接、供应用层调用
与驱动层对接接口:(xxx_service.c)
此类函数接口以xxx_service的方式命名,实现对硬件接口的驱动功能,基本不包含逻辑类代码。
/// gpio初始化
int gpio_init_service(int argc);
/// gpio释放
int gpio_free_service(void);
/// 获取gpio的电平状态
int gpio_get_pin_service(int pin);
/// 设置gpio为高电平
int gpio_set_pin_service(int pin);
/// 设置gpio为低电平
int gpio_clear_pin_service(int pin);
/// 设置gpio为level电平
int gpio_set_pin_level_service(int pin, int level);
/// 设置gpio为输出引脚类型
int gpio_as_output_service(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 设置gpio为输入引脚类型
int gpio_as_input_service(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 设置gpio为模拟输入
int gpio_as_analog_input_service(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 将gpio设置为pwm输出
int gpio_as_pwm_service(int pin);
/// 设置pwm gpio的输出频率
int gpio_set_pwm_freq_service(int pin, int freq, int duty_cycle);
应用层调用接口:(middle_xxx.c)
此类函数接口主要以mid_xxx_xxx的方式来命名,主要工作为申请内存、创建函数指针等工作。
/// gpio初始化
int mid_gpio_init(int argc);
/// gpio释放
int mid_gpio_free(void);
/// 获取gpio的电平状态
int mid_gpio_get_pin(int pin);
/// 设置gpio为高电平
int mid_gpio_set_pin(int pin);
/// 设置gpio为低电平
int mid_gpio_clear_pin(int pin);
/// 设置gpio为level电平
int mid_gpio_set_pin_level(int pin, int level);
/// 设置gpio为推挽输出引脚类型
int mid_gpio_as_output(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 设置gpio为输入引脚类型
int mid_gpio_as_input(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 设置gpio为模拟输入
int mid_gpio_as_analog_input(int pin, GPIO_PULL_SERVICE Pull_choice);
/// 将gpio设置为pwm输出
int mid_gpio_as_pwm(int pin);
/// 设置pwm gpio的输出频率
int mid_gpio_set_pwm_freq(int pin, int freq, int duty_cycle);
(3).应用层接口
应用层接口标准化并不严格,符合Linux内核编程规范与代码风格即可。
以main函数为例:
int main(int argc, char** argv)
{
///调用middle层接口,现实相关应用逻辑
mid_xxx();
mid_xxx();
....;
}
3、函数调用
应用层 ---> 调用 ---> 中间件(mid_xxx) ---> 调用 ---> 驱动对接接口(xxx_service) --->调用---> 驱动接口(LL_xxx_xxx)
4、分层架构目录
├── application
│ ├── bin
│ ├── burntools
│ ├── doc
│ ├── libs
│ └── src
│ ├── buildmake.pl
│ ├── datamng
│ ├── main.c
│ ├── Makefile
│ ├── massage
│ └── menu
├── driver_os
│ ├── fm33lc0xx
│ ├── stm32f0xx
│ └── stm32g0xx
│ ├── CMSIS
│ ├── Makefile
│ ├── stm32g0xx_hal_conf.h
│ └── STM32G0xx_LL_Driver
└── middle
├── buildMakefile.pl
├── lib
├── Makefile
├── middle_api
│ ├── include
│ └── source
│ └── middle_gpio.c
└── plateform
├── fm33lc0xx
├── stm32f030xx
└── stm32g0xx
├── include
├── libs
└── lib_stm32g0xx.a
└── src
└── gpio_stm32g0xx.c
application:应用层逻辑函数
middle:中间件相关接口
driver_os:官方驱动接口