基于DJYOS的UART驱动编写指导手册

news2025/7/7 4:10:56

1.概述

DJYOS设计通用的串口驱动模型,在此模型的基础上,移植到不同硬件平台时,只需提供若干硬件操作函数,即可完成串口驱动开发,使开发工作变得简单而快速执行效率高。
DJYOS源代码都有特定的存放位置,
建议文件路径:在eclipse工程中的目录中为:
src->OS_code->bsp->cpudrv->src->cpu_peri_uart.c。
相应的头文件目录为:
src->OS_code->bsp->cpudrv-> src->cpu_peri_uart.h。
在文件系统(硬盘)中的目录结构是:
djysrc\bsp\cpudrv\cpu_name\src\cpu_peri_uart.c。
如果UART为CPU所在板件的板级外设,则
建议文件路径:在eclipse工程中的目录中为:
src->OS_code->bsp->boarddrv->src->chip_name.c。
相应的头文件目录为:
src->OS_code->bsp-> boarddrv -> src-> chip_name.h。
在文件系统(硬盘)中的目录结构是:
djysrc\bsp \chipdrv\chip_name\chip_name.c。

本指导手册简明扼要的介绍了都江堰操作系统的UART驱动模型,着重讲解了在此驱动架构下编写具体UART控制芯片的驱动编写方法。

2.驱动架构

UART驱动架构如图 21所示。该模型包括通用设备驱动driver.c及 UART通用层uart.c及底层硬件驱动部分cpu_peri_uart.c。它具有明显分层结构,顶层是应用程序,它通过访问设备驱动接口层访问串口通用接层;串口通用层是底层驱动与设备驱动之间桥梁,它调用了若干钩子函数,通过钩子函数间接访问实现串口收发。最下面一层是由BSP设计者提供的硬件驱动,BSP设计者只需要按照要求实现钩子函数。
BSP驱动程序人员的工作是编写图 21中底层驱动部分代码,它是根据具体UART控制器(即不同的CPU)实现与硬件相关的UART寄存器级别的操作。
驱动编写的主要工作,是:
1、初始化uart硬件。
2、实现3个回调函数。
3、若使用中断,则还要实现中断服务函数。
4、若printk使用uart(绝大多数情况是这样),则要实现PutChark、Putsk、GetChark、Getsk这几个函数。
在这里插入图片描述

图 2-1UART驱动架构图

3.UART驱动接口

3.1.初始化函数

3.1.1.Step1:初始化硬件

1、包括默认的参数配置,如IO、波特率、停止位、奇偶校验位等;
2、挂载UART中断到中断系统,并配置UART的中断类型,如配置为异步信号;

3.1.2.Step2:初始化参数结构体

UART初始化参数数据类型为truct tagUartParam,初始化该数据类型变量的成员,并调用函数UART_InstallPort(),注册UART为设备,并将它添加到资源列表。
对该函数的参数struct tagUartParam作如说明。
代码 3-1 UART参数初始化结构体

// 串口模块初始化结构体
struct tagUartParam
{
    const char *Name;					//UART名称,如UART0
    u32 TxRingBufLen;					//发送缓冲区配置字节数
    u32 RxRingBufLen;					//接收缓冲区配置字节数
    u32 Baud;							//默认的波特率
    ptu32_t UartPortTag;				//UART私有标签,如寄存器基址
    UartStartSend StartSend;			//启动发送回调函数指针
    UartDirectSend DirectlySend;		//直接轮询发送回调函数指针
    UartControl UartCtrl;				//控制函数回调函数指针
};

DJYOS通用驱动架构是先将用户发送数据保存到发送环形缓冲区,然后通过操作系统的通信方式(如信号量通信)通知驱动层将发送环形缓冲区中的数据写入UART控制器的发送寄存器;同理,驱动接收到的数据缓存到接收环形缓冲区,然后通知应用层读取接收环形缓冲区数据。
发送和接收缓冲区的初始化由UART_InstallPort()完成,BSP驱动编程人员只需配置struct tagUartParam中的参数TxRingBufLen和RxRingBufLen,它们分别是配置发送和接收缓冲区的字节长度。此外,UartPortTag为私有标签,对于UART,需赋值为UART控制器的寄存器基址。
UART三个回调函数参数的原型如所示,其中PrivateTag就是结构体中UART的私有标签,寄存器基址。
代码 3-2 UART回调函数类型定义

typedef u32 (* UartStartSend)(ptu32_t PrivateTag,u32 timeout);
typedef u32 (* UartDirectSend)(ptu32_t PrivateTag,u8 *send_buf,u32 len,u32 timeout);
typedef ptu32_t (*UartControl)(ptu32_t PrivateTag,u32 cmd, u32 data1,u32 data2);

3.1.3.Step3:挂载设备

挂载设备API函数UART_InstallPort(),该函数完成了如下功能:
1、初始化串口发送或接收所需的信号量或互斥量;
2、动态分配发送和接收数据的环形缓冲区空间,并初始化环形缓冲区;
3、动态分配UART的控制块UCB,并将UART添加为通用设备(即driver);
4、操作成功,则返回UCB指针,否则,返回NULL。
值得注意的是,UART驱动编程人员对添加串口设备的函数返回值的判断是极其重要的步骤,并将有效的返回值保存为静态变量。如所示,UART_Param是已经初始化好的参数结构类型,pUartCB是定义在C文件中类型为static struct tagUartCB *的静态变量数组,UART_InstallPort()返回值保存到该静态变量。
代码 3-3 添加串口设备

	pUartCB[serial_no] = UART_InstallPort(&UART_Param);
	if( pUartCB[serial_no] == NULL)
		return 0;
	else
		return 1;

3.2.回调函数

DJYOS的UART驱动架构采用注册回调函数的方式,能有效的将串口通用层和硬件驱动层分开,实现模块化编程。本章将对回调函数的编程要求进行详细的说明,它们是BSP驱动开发人员应该着重关心的部分。

3.2.1.启动发送

static u32 __UART_SendStart (tagUartReg *Reg,u32 Timeout)
参数:
Reg:UART控制寄存器基址。
Timeout:超时时间,单位us。
返回:发送字节数。
说明:该函数的关键在于启动发送功能,如触发发送中断,在中断实现发送数据的功能。比较通用的方法是填写FIFO深度的数据,触发发送中断,部分UART控制器能够实现不发送数据仍然能触发发送中断的功能,该函数将得到进一步的简化。
部分核心示例代码如代码 34所示,调用UART_PortRead读取发送环形缓冲区数据,数据大小为FIFO深度的字节数,并填写到FIFO,然后使能中断。注意,若启动发送时UART硬件缓冲区非空,则无须发送触发发送中断。
代码 3-4 启动发送

__UART_TxIntDisable(Reg);
if(__UART_TxTranEmpty(Reg))
{
    fifodep = UART_PortRead(pUartCB[port],ch,fifodep,0);//读FIFO大小数据
    for(num = 0; num < fifodep; num++)
    {
        Reg->D = ch[num];
    }
}
__UART_TxIntEnable(Reg);

3.2.2.直接发送

static u32 __UART_SendDirectly(tagUartReg *Reg,u8 *SendBuf,u32 Len,u32 Timeout)
参数:
Reg:UART控制寄存器基址。
SendBuf: 发送数据缓冲地址。
Len:发送字节数。
Timeout:超时时间,单位us。
返回:发送字节数。
说明:串口轮询发送的功能,主要实现操作系统未启动时的串口发送功能。由于轮询发送是比较耗时的发送方式,因此,有必要对发送过程进行超时处理,同时,发送过程必须关闭中断。
部分核心示例代码如代码 35所示,判断发送缓冲区为空后,往硬件发送寄存器中写数据,直到发送完成,若等待超时,则退出循环。发送过程必须关闭中断。
代码 3-5 轮询发送

__UART_TxIntDisable(Reg);
for(result=0; result < len; result ++)
{
	// 超时或者发送缓冲为空时退出
	while((false == __UART_TxTranEmpty(Reg))&& (timeout > 0))
	{
		timeout--;
		Djy_DelayUs(1);
	}
	if(timeout == 0)
		break;
	Reg->D = send_buf[result];
}
__UART_TxIntEnable(Reg);

3.2.3.控制函数

static ptu32_t __UART_Ctrl(tagUartReg *Reg,u32 Cmd, u32 Data1,u32 Data2)
参数:
Reg:UART控制寄存器基址。
Cmd:串口命令字,参见源码uart.h头文件定义。
Data1、Data2:含义依Cmd而定。
返回:0,执行成功,其他,自定义。
说明:底层驱动的控制函数主要完成与具体硬件相关的控制功能,如设置波特率、配置串口参数、暂停启动串口等。UART控制命令及参数说明如表 3-1所示,需要注意,并非所有的命令都需要用到,驱动编程人员须根据实际情况选择使用的命令。
表 3-1 UART控制命令
在这里插入图片描述

3.3.中断函数

因为采用中断的方式收发数据效率更高,对CPU的消耗低,所以建议驱动编写人员采用中断的方式实现UART的收发。
首先,必须将UART的中断号添加到critical文件夹下面的C文件critical.c中tg_IntUsed数组,使中断系统初始化时,将对应的UART中断号添加到中断系统中;其次,UART初始化时,配置UART中断类型和触发条件等。最后,完成中断服务函数UART_ISR。

3.3.1.中断实现过程

比较典型的UART中断函数实现过程如图 31所示。
在中断服务函数内部,通过读中断标志位判断中断类型,并进入不同的处理过程。接收中断时,将接收数据写入接收缓冲区;发送中断表示当前硬件FIFO中数据已经发送完成,则继续读发送缓冲区数据,直至发送结束;帧错误中断是指发生了校验、帧格式或起始结束位错误时的中断。无论是发送还是接收中断,都需要注意清中断标志位。

图 31 UART中断流程图

3.3.2.注意事项

中断服务函数的实现过程因UART控制器的不同,处理情况也有所差异,列出如下注意事项,以供参考。
1、中断服务函数中要注意通过判断中断标志来区分中断类型,并及时清中断标志;
2、中断类型为发送中断时,UART_PortRead()返回为0,则表示发送环形缓冲区中无数据,建议关闭发送中断;
3、帧错误处理方式由应用程序通过Ctrl函数注册,登记发生错误时弹出的事件。

4.移植建议

由于大部分的UART控制器的设计基本相似,因此,BSP程序人员可采取下面的步骤快速的完成DJYOS驱动架构下UART底层驱动的开发。
1、拷贝其他工程已测试通过的UART驱动文件cpu_peri_uart.c/cpu_peri_uart.h;
2、添加UART的中断号到critical.c文件下面tg_IntUsed数组;
3、修改cpu_peri_uart.c/cpu_peri_uart.h中与具体UART寄存器相关的部分;
4、实现中断收发数据,并测试通过。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录为小电机安装一个5012编码器(多摩川协议)的过程

目录 1. 编码器接口板介绍 2. 编码器接口板安装 3. 角度读取软件实现 4.总结 为了能得到更精确的角度&#xff0c;于是想要通过在测试电机上安装一个编码器来获取更精确的角度&#xff0c;方便日后调试或者校验使用&#xff0c;这里记录下操作的步骤。 1. 编码器接口板介绍…

Github Actions 自动同步到 Gitee

目录引言具体方案引言 平时开源代码一般已Github为主&#xff0c;但是会遇到网不好的情况&#xff0c;于是考虑将Github仓库自动同步到Gitee上&#xff0c;作为备份。考虑不能手动做这个事情&#xff0c;于是想到了Github Actions 自动化同步到Gitee中 具体方案 假设Github已…

Mybatis Plus一对多联表查询及分页解决方案

文章目录需求需求分析分页问题说明分页问题原因一对多场景一一对多场景二性能优化优化解决方案需求 查询用户信息列表&#xff0c;其中包含用户对应角色信息&#xff0c;页面检索条件有根据角色名称查询用户列表&#xff1b; 需求分析 一个用户对应多个角色&#xff0c;用户…

java计算机毕业设计ssm党支部在线学习

项目介绍 本党支部在线学习是针对目前学习的实际需求,从实际工作出发,对过去的学习系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构、概念、模型、原…

【深度学习】torch.utils.data.DataLoader相关用法 | dataloader数据加载器 | pytorch

文章目录前言一、DataLoader介绍二、DataLoader的子方法&#xff08;可调用方法&#xff09;前言 dataloader数据加载器属于是深度学习里面非常基础的一个概念了&#xff0c;基本所有的图像项目都会用上&#xff0c;这篇博客就把它的相关用法总结一下。 之所以要写这篇&#x…

1-1 开源许可证GPL, BSD, MIT, Mozilla, Apache, LGPL的介绍

文章目录前言开源许可证由来开源许可证类型开源许可证介绍GPL协议BSD协议MIT协议Mozilla许可Apache协议LGPL开源协议前言 开源许可证&#xff08;Open source licenses&#xff09;&#xff0c;广义来讲是指一种被用于计算机软件或其他产品的&#xff0c;允许在指定的条款内使…

zMemif: go语言高性能网络库

简介 开发zMemif的主要动机是go有很高的处理能力&#xff0c;但是内置的udp库的确有些寒酸&#xff0c; 纯c开发效率又有些低&#xff0c;虽然可以用nff-go来实现go和dpdk的融合&#xff0c;但是cgo编译的确有点烦人&#xff0c;而且这个项目似乎也死了。然后考虑到容器的场景…

单点登录以及实现(前后端分离和前后端不分离方式)

本文主要使用springSecurity来实现&#xff0c;其他实现请参照其原理自行研究。 一&#xff0c;单系统登录机制 1、http无状态协议 web应用采用browser/server架构&#xff0c;http作为通信协议。http是无状态协议&#xff0c;浏览器的每一次请求&#xff0c;服务器会独立处…

谷粒学院(三) 项目前端知识

一、VS Code 1、插件安装 为方便后续开发&#xff0c;建议安装如下插件&#xff08;红色矩形框标记的插件&#xff09;2、创建项目 vscode本身没有新建项目的选项&#xff0c;所以要先创建一个空的文件夹&#xff0c;如project_xxxx。 然后打开vscode&#xff0c;再在vscode里面…

二维随机向量的数学期望E与协方差σ

目录 1. 二维随机向量(X,Y)的数学期望EX, EY 2. 二维随机向量函数zg(X,Y)的数学期望EZ 3. 二维随机向量(X,Y)的方差DX, DY 4. 二维随机向量的性质&#xff08;和、积的数学期望E与方差D&#xff09; 5. 二维随机向量的协方差COV和相关系数ρ 5.1 协方差COV定义 5.2 协方…

私有数据传参

在串口工具进行输入&#xff1a; echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led1灯点亮 echo 0 > /dev/myled1 ---->led1灯熄灭 echo 1 > /dev/myled2 ---->led1灯点亮 echo 0 >…

java计算机毕业设计springboot+vue员工管理系统

项目介绍 本员工管理系统是针对目前村委会管理的实际需求,从实际工作出发,对过去的员工管理系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构、概念、…

无线蓝牙耳机什么牌子好一点?2022年蓝牙耳机推荐

喜欢听音乐&#xff0c;自然离不开耳机的支持&#xff0c;一款优质且时尚的耳机&#xff0c;能够带来极致的音效&#xff0c;可是该如何选择合适的耳机&#xff0c;成为了摆在眼前一个很重要问题如果这个问题一直萦绕在你的脑海中&#xff0c;那么下面的选择相信定不会错。 TO…

多线程异步方法Spring Security框架的SecurityContext无法获取认证信息的原因及解决方案

Spring Security是Spring生态提供的用户应用安全保护的一个安全框架&#xff0c;其提供了一种高度可定制的实现身份认证(Authentication)&#xff0c;授权&#xff08;Authorization&#xff09;以及对常见的web攻击手段做防护的方法。 之前我的博客Oauth2与Spring Security框架…

章鱼网络 Community Call #4|推进章鱼社区治理

全长5922字&#xff0c;预计阅读 15 分钟 撰文&#xff1a;MiX 微信交流&#xff1a;MixMetaverse 北京时间2022年11月8日21点&#xff0c;章鱼网络举行第4期 Community Call&#xff0c;10月8日是章鱼一周年庆典&#xff0c;所以本次 Community Call 我们讨论了最近2个月内很…

git可视化工具-sourceTree

1. 下载 官网的下载地址&#xff0c;可以根据自己的电脑操作系统选择合适的版本下载&#xff0c;我下载的是windows版本 Sourcetree | Free Git GUI for Mac and Windows A Git GUI that offers a visual representation of your repositories. Sourcetree is a free Git clie…

ArcGIS提取图斑四至点,可不再是四至范围哦

上一期我们向大家介绍了 ArcGIS计算图斑四至坐标原来这么简单&#xff01;可不要在走弯路哦_GIS思维的博客-CSDN博客​​ArcGIS计算图斑四至坐标原来这么简单&#xff01;可不要在走弯路哦https://blog.csdn.net/kinghxj/article/details/127941005 今天我们要向大家介绍一下 …

Gem5 for Ubuntu20.04

一、安装Ubuntu 参考教程&#xff1a;史上最全最新Ubuntu20.04安装教程&#xff08;图文&#xff09; - 知乎 (zhihu.com) 1. 查看Ubuntu版本号命令&#xff1a; lsb_release -a 显示如下&#xff1a; Distributor ID: Ubuntu //类别是ubuntu Description: Ubuntu 2…

LeetCode力扣刷题——指针三剑客之二:树

树 一、数据结构介绍 作为&#xff08;单&#xff09;链表的升级版&#xff0c;我们通常接触的树都是二叉树&#xff08;binary tree&#xff09;&#xff0c;即每个节点最多有 两个子节点&#xff1b;且除非题目说明&#xff0c;默认树中不存在循环结构。LeetCode 默认的树表示…

树的孩子兄弟链存储表示创建、遍历等算法

【实验目的】 1. 掌握树的孩子兄弟链存储表示。 2. 掌握树的创建、遍历等算法。 【问题描述】 树的创建及其操作。 【基本要求】 1. 创建树的孩子兄弟链式存储表示。假设以二元组(F,C)的形式输入一颗树的诸边&#xff0c;其中F表示双亲结点标识&#xff0c;C表示孩子结点…