如何获得arm驱动,arm驱动程序
chanong
|简介Uart是嵌入式系统中非常重要的模块,充当CPU和用户之间的桥梁。用户向程序输入信息,CPU向终端输出一些信息。所有这些都依赖于UART。本文介绍了UART 原理以及如何编写基于Exynos4412 UART 控制器的驱动程序。
什么是UART? UART是Universal Asynchronous Receiver/Transmitter(通常也简称为UART),是异步接收器和发送器,是设备间异步通信的重要模块。 UART负责处理数据总线与串口之间的串/并、并/串转换,并指定帧格式。如果通讯伙伴使用相同的帧格式和波特率,数据总线就可以进行通讯,无需共享。由于它使用时钟信号,仅用两条信号线(Rx、Tx)完成通信过程,因此也称为异步串行通信。通过UART总线双向通信实现全双工发送和接收。在嵌入式设计中,UART用于主机和辅助设备之间的通信,例如汽车音响和外部AP之间的通信,与PC的通信包括与监控调试器和EEPROM等其他设备的通信。通常必须添加合适的电平转换器,例如SP3232E或SP3485。 UART 还可用于RS-232、RS-485 通信或与计算机端口的连接。 UART广泛应用于手机、工控、PC等应用。 UART 通信方法UART 使用异步和串行通信方法。串行通信串行通信是指利用传输线按顺序一位一位地发送数据。它就像一列,每个数据元素一个接一个地垂直放置。如下图所示,传输是一位一位串行传输,每个时钟周期传输一位。这种传输方式比较简单,速度较慢,但使用的总线较少。通常,这可以通过一根接收线和一根串行通信来实现。这只需一根传输线即可实现。缺点是需要添加额外的数据来控制数据帧的开始和结束。其特点是通信线路简单,只需一根简单的电缆即可通信,降低了成本,适合需要远距离通信但通信速度较慢的应用场合。并行通信并行通信就像一排人平行移动并同时进行传输。这种通信方式每个时钟周期发送的数据量与总线宽度成正比,但实现起来比较复杂。异步通信异步通信以一个字符为传输单位,虽然所通信的两个字符之间的时间间隔不是恒定的,但同一字符内两个相邻位之间的时间间隔是恒定的。在异步通信技术中,数据发送方和数据接收方之间没有同步时钟,只有一条数据信号线,但发送方和接收方按照协商好的协议(固定频率)对数据进行采样。数据发送方以每秒57600位的速率发送数据,接收方也以57600位的速率接收数据,保证数据有效、正确。波特率通常用于指定异步通信双方的通信速度,单位为bps(比特每秒)。采用同步通信方式传输数据信号时,同时发送同步时钟信号,使发送端和接收端的数据采样频率同步。如下图所示,同步通信时,信号线1为同步时钟信号线,其电平以恒定频率变化。频率周期为t,在每个电平的上升沿后同步发出信号。数据信号线2进行采样(高电平代表1,低电平代表0),根据采样数据的电平得到输出数据信息。如果双方时钟不同步,接收方将不知道采样周期,无法正确获取数据信息。帧格式的数据传输速率用波特率表示,即每秒传输的位数。例如,如果数据传输速率为120个字符/秒,每个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则传输的波特率为10120=1200。字符/秒=1200 波特。
数据通信格式如下。各位的含义如下。起始位:先发送一个逻辑“0”信号,表示传输一个字符的开始。 *数据位:可以是5 至8 位,带有逻辑“0”或“1”。 ASCII码(7位)、扩展BCD码(8位)等Little endian 传输*校验位:将此位添加到数据位后,“1”位的个数必须为偶数(偶校验)或奇数(奇校验) *停止位:传输结束字符数据标识。它可以高达1 位、1.5 位或2 位。 *空闲位:逻辑“1”状态,表示当前线路上没有数据传输。注意:由于异步通信是以字符为单位进行的,因此接收设备在收到起始信号后,如果能在一个字符的传输时间内与发送设备保持同步,就可以正确接收数据。当下一个字符的起始位到来时,重新调整同步(依靠起始位的检测实现发送方和接收方时钟的自同步)。有关RS-232、RS-422、RS-232 485 等标准,请参阅文章《一篇文章了解什么是串口,UART、RS-232、RS-422、RS-485》 Exynos4412 Uart。本文以基于Cortex-A9架构Exynos4412的UART为例进行介绍。特性Exynos4412 UART 有四个独立通道,每个通道都可以在中断或DMA 模式下运行。这意味着UART可以发出中断或DMA请求以在UART和CPU之间传输数据。当使用系统时钟时,Exynos4412 UART波特率可以达到4Mbps。每个UART 通道包含两个用于接收和发送的FIFO:通道0 有一个256 字节发送FIFO 和一个256 字节接收FIFO。通道1 和4 有一个64 字节发送FIFO 和一个64 字节接收FIFO。图3的通道2具有16字节发送FIFO和16字节接收FIFO。您可以对UART 的波特率进行编程,包括:每个红外接收/发送通道支持1 个停止位、2 个数据位、5、6、7 或8 位,每个UART 还包括波特率发生器、发送器、接收器和控制逻辑。
Uart控制器功能模块每个UART包括波特率发生器、发送器、接收器和控制单元,如上图所示。首先,发送数据CPU将数据写入发送FIFO,然后UART自动将数据写入发送FIFO。数据被复制到“发送移位器”(transmit shifter),它把数据逐位发送到TxDn数据线(根据配置的格式,插入一个起始位,检查并停止)。接收移位器逐位接收RxDn 数据线上的数据,并将其复制到CPU 可以读取数据的FIFO 中。 UART实现异步通信,其采样速度由波特率决定,而波特率发生器的工作频率由PCLK(外围设备频率)和FCLK/n(CPU工作分频)决定。UEXTCLK(外部输入时钟)3个时钟作为输入频率,波特率设置寄存器可编程,用户可以设置波特率来确定发送和接收频率。发送器和接收器包括64 字节FIFO 和数据移位器。 UART通信是面向字节流的,将要发送的数据写入FIFO后,复制到数据移位器(1字节大小)并从发送数据端TXDn发送出去。同样,接收移位器通过RXDn 引脚(1 字节大小)接收接收数据,并将其复制到FIFO 接收缓冲区。 (1)数据传输传输的数据帧是可编程的,其长度由用户指定,由一个起始位、5到8个数据位、一个可选的奇偶校验位和1到2个停止位组成。它可以通过设置ULCONn 寄存器来设置。发射机还可以生成由全零数据帧组成的终止信号。当当前传输数据传输完成时,模块发送终止信号。发送结束信号后,可以通过先进先出(FIFO)或发送保持寄存器(NON-FIFO)继续发送数据。 (2) 数据接收接收端的数据还可以编程检测溢出错误、奇偶校验错误、成帧错误和终止条件,并且可以为每个错误设置错误标志。 ? 溢出错误:在读取旧数据之前,新数据覆盖了旧数据。 ? 奇偶校验错误:接收数据校验失败,接收方检测到接收数据无效。 ? 帧错误:接收到的数据没有有效的停止位。无法确定数据帧结束? 退出条件:RxDn 接收到逻辑0 状态,持续时间长于一个数据帧的传输时间(3) 自动浮点控制AFC(自动浮点控制) UART0 和UART1 支持nRTS 和nCTS 自动流控制。对于AFC,通信伙伴的nRTS 和nCTS 引脚分别连接到伙伴的nCTS 和nRTS 引脚。数据帧的发送和接收由软件控制。当AFC打开时,发送器在发送或接收之前必须确定nCTS信号的状态,并且当接收到nCTS激活信号时发送数据帧。 nCTS 引脚连接到其对应引脚的nRTS 引脚。在接收器准备好接收数据帧之前,接收器FIFO 有超过32 个字节的空闲空间,并且nRTS 引脚发送激活信号。如果接收器FIFO 的可用空间少于32 字节,则nRTS 将设置为非活动状态。时钟源选择Exynos4412 UART 有八种时钟源选择:XXTI、XusbXTI、SCLK_HDMI24M、SCLK_USBPHY0、SCLK_HDMIPHY、SCLKMPLL_USER_T、SCLKEPLL 和SCLKVPLL,并由CLK_SRC_PERIL0 寄存器控制。选择时钟源后,还可以通过DIVUART0-4设置分频系数,该分频系数由CLK_DIV_PERIL0寄存器控制。来自分频器的时钟称为SCLK UART。 SCLK UART经过上图的“UCLK Generator”后,得到UCLK,其频率就成为UART的波特率。
“UCLK 发生器”通过两个寄存器进行配置:UBRDIVn(UART 波特率分频器)和UFRACVALn。 UART 配置寄存器ULCONnbite[6] 红外模式选择串口0 是否使用红外模式: 0=正常通信模式1=红外通信模式Byte [5:3] 验证模式选择串口0 是否使用红外模式配置串口使用的验证方式0:0xx=无奇偶校验100=奇奇偶校验101=偶奇偶校验110=强制验证/检测(如果) 1111=强制验证/检测(如果0) [2] 停止位设置串行端口0 停止位数量: 0=每个数据帧1 个停止位1=每个数据帧2 个停止位[1:0] 数据位设置串行端口上的数据位数0: 00=5 个数据位01=6 个数据位10=7 个数据位11=8 个数据位通用配置寄存器这是:
ULCON2=0x3;//Normalmode,Noparity,Onestopbit,8databitsUCONn[15:12] FCLK 分频比如果UART0 选择FCLK 作为时钟源,则设置其FCLK 分频比UART0 工作时钟频率=FCLK/FCLK 分钟频率+ 6[11:10] UART 时钟源选择选择UART0 工作时钟PCLK、UEXTCLK、FCLK/n:00,10=PCLK01=UEXTCLK11=FCLK/n,选择FCLK/n 作为UART0 工作时钟,如果选择,则必须进行其他设置。请保持原样。详情请查看硬件手册[9] 设置UART0 中断请求类型与发送数据中断产生类型在非FIFO 发送模式下,一旦发送数据缓冲区变空就会产生中断信号。 一旦达到发送数据触发条件,就会产生中断信号。 中断信号: 0=脉冲触发1=电平触发[8] 接收数据中断产生类型设置UART0 中断请求类型。在非FIFO 发送模式下,接收到数据后立即产生中断信号;在FIFO 发送模式下,数据触发时立即产生中断信号: 0=脉冲触发1=电平触发[7] 设置接收数据超时是否产生接收中断如果接收数据时超时: 0=不使能超时中断1=使能超时中断10=7 个数据位11=8 个数据位[6] 接收数据错误中断设置异常时是否产生接收状态中断信号例如接收数据时发生发送中止、帧错误或校验错误: 0=不生成错误状态中断1=生成错误状态中断[5] 环回模式如果该位被设置,则UART 进入环回模式。该模式仅用于测试0=正常模式1=环回模式[4] 如果设置该位,则发送终止信号。 UART 发送帧长度结束信号。完成后,该位自动返回00=正常传输1=发送终止信号[3:2] 发送模式设置将数据写入发送缓冲区的方法00=禁用01=中断请求或查询模式10=DMA0 请求[1:0] ]接收模式设置将数据写入接收缓冲区的方法。 00=禁用01=中断请求或查询模式10=DMA0 请求该寄存器的一般结构为:
UCON2=0x5;//Interruptrequestorpollingmode 一般情况下,裸机情况下采用轮询模式。 UTRSTATn UTRSTATn 寄存器用于指示是否已发送数据以及是否已接收数据。其格式如下图所示。上面的“缓冲区”实际上就是下面所示的FIFO。如果不使用函数,则假定其深度为1。读取数据时,将bit[0] 设置为1 后,通过轮询和检查的方式从URXHn 寄存器中读取数据。读取数据时,将bit[1]设置为1后进行轮询和检查后再读取。来自URXHn 寄存器的数据UTXHn 寄存器写入数据发送数据;UTXHn 寄存器(UART TRANSMIT BUFFER REGISTER)
CPU将数据写入该寄存器,UART将其存储在缓冲区中并自动发送。 URXHn寄存器(UART接收缓冲寄存器)
当UART接收到数据时,会读取该寄存器来检索数据。 UFRACVALn 计算波特率。根据指定的波特率和选择的时钟源频率,UBRDIVn 寄存器(其中n 为0 到4,对应5 个UART 通道)的值可以使用以下公式计算:
UBRDIVn=(int)(UART Clock/(buadratex16))1 通过以上公式计算出的UBRDIVn 寄存器的值不一定是整数。 UBRDIVn 寄存器取其整数部分,较小的部分由UFRACVALn 寄存器设置。 UFRACVALn 寄存器中的值生成波特率并使速率更加准确。 [示例] 如果UART 时钟为100MHz,则波特率必须为115200bps。
100000000/(115200x16)1=54.251=53.25UBRDIVn=整数部分=53UFRACVALn/16=小数部分=0.25UFRACVALn=4 电路图外围电路图: SP3232EEA 用于将TTL 电平转换为RS232 电平。我用的是COM2。外围设备和核心板连接原理图显示了连接到GPA 的UART 收发器引脚。打开exynos4412芯片手册。只需将GPA1的低8位设置为0x22即可。
示例代码中的裸机代码主要实现了三个函数:uart_init()、putc()、getc()。 uart_init() 该函数主要配置UART。波特率为115200,数据位:8,奇偶校验位:0,停止位:1,未设置流控制。 Windows下常用串口工具的配置信息必须完全匹配,如下所示。 putc()函数向串口发送数据,其实现逻辑是轮询并检查寄存器UART2.UTRSTAT2以确定bit[1]是否设置为1。存储要发送到UART2.UTXH2的数据。仅数据。 getc() 该函数从串口接收数据。其实现逻辑是轮询并检查寄存器UART2.UTRSTAT2以确定bit[0]是否设置为1。如果设置为1,则表示。表示数据已准备好并且可以从寄存器中检索。 UART2.URXH2 获取数据。
/**UART2*/typedefstruct{unsignedintULCON2;unsignedintUCON2;unsignedintUFCON2;unsignedintUMCON2;unsignedintUTRSTAT2;unsignedintUERSTAT2;unsignedintUFSTAT2;unsignedintUMSTAT2;unsignedintUTXH2;unsignedintURXH2;unsignedintUBRDIV2;unsignedintUFRACVAL2;unsignedintUINTP 2;unsignedintUINTSP2;unsignedintUINTM 2;}uart2;#defineUART2(*(易失性uart2* )0x13820000 )/*GPA1*/typedefstruct{unsignedintCON;unsignedintDAT;unsignedintPUD;unsignedintDRV;unsignedintCONPDN;unsignedintPUDPDN;}gpa1;#defineGPA1(*(volatilegpa1*)0x11400020)voiduart_init(){/*UART2初始化*/GPA1.CON=(GPA1 . CON ~0xFF)|(0x22);//GPA1_0:RX;GPA1_1:TXUART2.ULCON2=0x3;//普通模式,无奇偶校验,一位停止位,8个数据位UART2.UCON2=0x5;//中断请求轮询模式//波特率:src_lock:100MhzUART2.UB RDIV2=0x35;UART2.UFRACVAL2=0x4 ;}voidputc(constchardata){while(!(UART2.UTRSTAT20X2));UART2.UTXH2=data;if(data=='\n')putc(' \r ');}chargetc(void){chardata; while (!(UART2.UTRSTAT20x1));data=UART2.URXH2;if((data=='\n')||(data=='\r' )) {putc('\n');putc('\r');}elseputc(data);returndata;}voidputs(constchar*pstr){while(*pstr!='\0')putc(*pstr++ ); }voidgets(char*p){chardata;while ( (data=getc())!='\r'){if(data=='\b'){p--;}*p++=data; }if (data=='\r')*p++='\n';*p='\0';}








