Linux应用层开发系列文章目录
第一章:linux应用层框架思想 第二章:linux应用层之串口事件触发 第三章:linux应用层之内存管理
文章目录
Linux应用层开发系列文章目录
前言
一、Linux应用框架是什么?
二、Linux框架怎么搭建
框架结构
三、框架之下五大模块之硬件接口模块
1、uart接口
2、i2c接口
3、gpio接口
4、can接口
总结
前言
首先我建议大家先想一下这个场景(每次重开一个项目–不论是MCU还是LINUX),以下是我个人所想到的
第一:所有的驱动、业务代码重新写是什么概念; 第二:如果还像初阶那样接口初始化业务逻辑放一块儿会有什么后果(举例:天天的像单片机代码复制来复制去,改个参数要去通篇的翻代码找位置去改,效率何其低下,技术水平又体现在哪里); 第三:你的代码总要继承吧,总不能一个公司的N个项目N套代码吧; 第四:人活着就是要折腾就是要进步,不提高水平怎么加薪,怎么养家糊口!!!
这里说明以下Linux为什么要搭建框架的几个重要点:
1、提高开发效率:框架提供了一套通用的解决方案和开发模式,可以避免重复编写相似的代码,节省开发人员的时间和精力。开发人员可以专注于业务逻辑和功能实现,而不必关注底层细节。(各司其职,更好管理,工作更加专一)
2、简化复杂性:许多应用程序具有复杂的功能和模块,使用框架可以将这些功能和模块分解为更小的组件,并提供统一的接口和管理方式,从而简化系统的设计和实现过程。
3、促进标准化和规范化:框架定义了一套统一的开发规范和例程DEMO,使得不同开发人员之间可以更容易地协作和交流。同时框架还可以提供一些通用的功能和组件,帮助开发人员快速构建高质量的应用程序。
4、提供扩展性和灵活性:框架通常具有良好的可扩展性和灵活性,可以根据具体需求进行定制和扩展。开发人员可以根据需要添加新的功能模块或替换现有的组件,而不必修改整个系统。(N个项目也可共用一套代码,做预编译切换或更具出场配置切换等等方法去实现)
一、Linux应用框架是什么?
不了解的话不妨参考一下RTOS的架构,这里以国产RT-Thread举例:
其实也比较好看出来,rtthread这个基础结构已经包含了内核接口(内存管理、线程管理、线程通信/同步、时钟管理、等等),设备驱动接口(uart、spi、can、iic、pwm、等等),组件接口(类shell、日志管理、posix接口、文件系统操作接口、等等),软件包接口(理解为第三方库,可以留也可以舍) 应用框架简单可以理解为为业务开发去封装通用的API接口,然后API都提供给我们了,那么接下来我们可以说只要做一件事,那就是专注于业务逻辑的开发。
那我们要做Linux应用层框架应该包含哪些内容呢?
二、Linux框架怎么搭建
框架结构
借助rtthread的架构经验,个人觉得需要这样几个部分
1、第三方库模块 2、通用标准模块 3、硬件驱动模块 4、业务逻辑模块 5、工具模块
下面是我自己构思的思维导图可以细究一下
三、框架之下五大模块之硬件接口模块
接下来就以五大模块为基础去分别讲解每个模块的实际用处。 直接上代码吧,理论不如实践!
1、uart接口
uart_drv.c如下:
/**
*@brief 设置串口数据位,停止位和效验位, 波特率
*@param baude 类型 uint32_t 波特率
*@param databits 类型 uint32_t 数据位
*@param stopbits 类型 uint32_t 停止位
*@param parity 类型 uint32_t 效验
*/
int Uart_Init(char *uart_path,int32_t baude,uint32_t databits,uint32_t stopbits,uint32_t parity)
{
USART_TypeDef Uart_Paras;
int fd = -1;
//获取串口设备描述符
fd = open(uart_path, O_RDWR|O_NOCTTY);
if (fd < 0)
{
log_message(LOG_ERROR, "Fail to Open %s device", uart_path);
return -1;
}
//参数设置
Uart_Paras.baudrate = baude;
Uart_Paras.databits = databits;
Uart_Paras.stopbits = stopbits;
Uart_Paras.parity = parity;
if (set_uart_params(fd,&Uart_Paras))
{
log_message(LOG_ERROR, "%s device set para failed", uart_path);
return -1;
}
return fd;
}
/**
*@brief Uart_Send_Data
*@param fd 类型 int 打开的串口文件句柄
*@param buf 类型 u8
*@param length 类型 int 数据位
*/
bool Uart_Send_Data(int fd, char *buf, size_t length)
{
if (write(fd, buf, length)< 0)
{
LOG("UART SEND ERROR");
return FALSE;
}
return TRUE;
}
/**
*@brief Uart_Read_Data
*@param fd 类型 int 打开的串口文件句柄
*@param buf 类型 u8
*@param length 类型 int 数据位
*/
bool Uart_Read_Data(int fd, char *buf, size_t length)
{
if (read(fd, buf, length)< 0)
{
LOG("UART READ ERROR");
return FALSE;
}
return TRUE;
}
2、i2c接口
i2c_drv.c如下:
/**
* @name I2c_Drv_Init
* @brief 向无寄存器地址的i2c从设备发送数据/命令
* @param fd: i2c从设备文件描述符
* @param filename: iicbainhao
* @param slave_addr: dizhi
* @retval 成功: 0
* 失败: -1
*/
int I2c_Drv_Init(int fd,char *filename, unsigned char slave_address)
{
// 打开I2C设备文件
if ((fd = open(filename, O_RDWR)) < 0) {
LOG("Failed to open the I2C bus");
return -1;
}
if(ioctl(fd,I2C_TENBIT,0) < 0)
{
LOG("Failed to set I2C_TENBIT!\n");
close(fd);
return - 1;
}
// 设置I2C从设备地址
if (ioctl(fd