全部博文(92)
分类: 嵌入式
2010-06-15 09:30:33
s3c2440串口文档
s3c2440的UART提供了三个同步串行IO口,第一个串口都可以使用中断模式和DMA模式,换句话说就是UART可以产生一个中断或者是DMA请求使数据在CPU和UART之间进行传递。UART在系统时钟下可以支持最高位传送为115.2K BPS.如果一个外部设备能过UEXTCLK为UART提供时钟,UART可以达到更高的速度。每个UART通道包括两个64字节的FIFO作为接收数据和发送数据使用。
s3c2440的UART包括可编程的波特率,红外收发,一个或者两个停止位。5位,6们,7位,8位的数据位和校验检测。
每一个UART包括一个波特率产生器,发送器,接收器和一个控制单元。如图11-1所示。波特率产生器可以使用PCLK,FCLK/n或者UEXTCLK之一控制。发送器和接收器包含64字节的FIFO和一个数据移位器。数据先写到FIFO中然后再拷贝到发送移位器中,然后再移位发送通过数据针TxDn。在些期间远端发送过来的数据通过针RxDn进入到移位器中再拷贝到接收器的FIFO中去。
属性
--RxD0,TxD0,RxD1,TxD1,Rxd2,和TxD2都可使用基于DMA的和中断的操作。
--UART通道0,1,和2都拥有IrDA和64字节的FIFO
--UART通道0和1:nRTS0,nCTS0,nRTS1,nCTS1
--收发数据时支持握手
UART的操作
UART的操作,包括数据传输,数据接收,产生中断,波特率的产生回环模式,红外模式和自动流控制。
数据传输
发送的数据帧是可以改变的,它由起始位5~8个数据位一个可选的校验位和1~2个停止位构成。这些都可以通过策略控制器ULCONn设置。数据发送器也可以产生一个停止标志,它可以强迫串口输出逻辑0达一帧的时间,它在一个字传输完成以后阻塞了停止信号的传送。然后继续传输数据到Tx FIFO中。
数据接收
与数据的发送相似,接收到的数据帧也是可以修改的。它包括一个起始位,五到八个数据位,一个可选的校验位和一到两个停止位。接收器可检测到覆盖错误,校验错误,帧错误和终止的情况。每一种情况都会设置一个错误标志位。
--覆盖错误产生的情况是这样的,新数据覆盖掉了还没有来的及取出的旧数据,也就是说接收数据速度快于取出的速度导致一部分数据还没有取出就被新的数据盖掉了。
--校验错误是指接收到的数据经过计算与校验位不符。
--帧错误是指收到的数据不含有停止位。
--终止的情况是指RxDn端保持在逻辑零的状态时间长于一帧数据传送的时间。
接收超时的情况是指在可以接收3个字的时间里没有收到任何的数据,并且在FIFO模式时Rx的FIFO非空。
自动流量控制(AFC)
S3C2440的UART 0和UART 1通过信号nRTS和nCTS支持自动流量控制。在这种情况下,它可以连接到外部的UARTs中去。如果用户想把串口连接到Modem上,需要关闭寄存器UMCONn的自动流控制位,并通过软件控制nRTS信号线。
在AFC模式下,nRTS依赖于接收器,nCTS信号控制着发送器的操作。UART的数据发送器只在nCTS信号使能的时候才把数据传送到FIFO中(在AFC模式下nCTS的意思是其它UART的FIFO已经准备好接收数据了)。
在UART开始接收数据之前,需要先根据数据接收器的FIFO剩余空间设置nRTS的值,如果剩余空间大于32字节则nRTS使能,否则如果剩余空间小于32字节则nRTS关闭(在AFC模式下,nRTS的作用就是表示它所控制的接收器的FIFO准备好接收数据了)。
UART 2不支持AFC功能,因为S3C2440没有nRTS2和nCTS2
非自动流量控制的例子(通过软件控制信号nRTS和nCTS)
接收器对FIFO的操作
1.选择接收模式(中断模式或者DMA模式)
2.检查寄存器UFSTATn中Rx FIFO的值,如果这个值小于32,用户必须设置UMCONn[0]为“1”(使能nRTS),如果值大于32,用户必须设置UMCONn[0]的值为“0”(关闭nRTS)
3.重复第2步。
发送器对FIFO的操作
1.选择一个发送模式(中断或者DMA)
2.检查UMSTATn[0]的值,如果为“1”(使能nCTS),用户写数据到Tx FIFO寄存器
S3C2440的每个UART都有七个状态:覆盖错误,校验错误,帧错误,终止,接收缓冲区已准备好,发送缓冲区空,和发送移位器空。所有这些都对应到UART的状态寄存器中(UTRSTATn/UERSTATn).
覆盖错误,校验错误,帧错误和终止属于接收错误,它们中的任何一个都可以引起一个叫“receive error status”的中断请求。如果这个中断请求在寄存器UCONn中的使能位被置为“1”,并且当这个请求被处理时通过读取UERSTSATn的值可知引起这个中断的信号,也就是找到是哪种错误引起的中断。
FIFO模式与非FIFO模式
在FIFO模式下,接收器从接收移位器中收数据然后写入到FIFO中,如果收到数据的个数达到Rx FIFO的触发点,且在寄存器UCONn中的接收模式被设置成“1”(中断或者轮巡模式),将会产生一个Rx中断。在非FIFO模式下,不论是中断模式还是轮巡模式,只要有数据从接收移位寄存器中传送到数据接收保持寄存器中都会产生一个Rx中断。
在FIFO模式下,如果发送模式在控制寄存器UCONn中被设置成中断模式或者轮巡模式,发送数据要从发送FIFO中传送到发送移位器中,如果在FIFO中剩余的数据个数达到了Tx FIFO的触发点,就是产生一个Tx中断。在非FIFO模式下,发送的数据从发送保持寄存器传送到发送移位器中后会产生一个Tx中断,这个也是要求数据发送方送方式为中断模式或者是轮巡模式。
如果在控制寄存器中数据发送方式和接收方式被设置成DMA模式,那么和上面的情况一样,只是产生的Rx和Tx中断被换成了DMA请求。
UART的错误FIFO
UART有一个“错误状态”FIFO组,它对应着接收器的FIFO,它指示在接收器的FIFO中哪个数据错误了。只有在接收器中错误数据被读取的时候才会产生错误中断。在从URXHn读取数据的时候同时读取UERSTATn寄存器的值就知道这个数据哪里错了,什么错误。
例子
假设UART顺序接收了A B C D E这五个数据,其中接收B的时候发生了帧错误,接收D的时候发生了校验错误。
在接收B的时候不会产生“错误中断”,在接收“D”的时候也不会产生“错误中断”。当读取B数据和D数据的时候“错误中断”才会产生。
波特率的产生
ART的波特率发生器为串行数据的发送与接收提供时钟,波特率发生器的“源时钟”可以是S3C2440的内部系统时钟也可以是外部时钟(UEXTCLK),换句话说就是通过设置UCONn的“时钟”选项可以改变除数因子。波特率是由“源时钟”(PCLK,FCLK/n UEXTCLK)除以16和一个除数因子。公式是这样的:
除数因子=(整型)(“源时钟”除以波特率乘以16)减1
除数因子UBRDIVn的取值范围是1~2^16-1,但当使用外部时钟UEXTCLK时它却可以等于0.(这个外部时钟要低于PCLK)
例如:如果波特率是115200bps,UART的时钟是40MHz,除数因子UBRDIVn是
UBRDIVn = (int)(40000000 / (115200 x 16) ) -1
= (int)(21.7) -1 [round to the nearest whole number]
= 22 -1 = 21
波特率的错误容忍度
UART的帧错误必须低于1.87%
ADS下的串口配置
def.h 中的UART寄存器定义:
#define rULCON0 (*(volatile unsigned *)0x50000000) //UART 0 Line control
#define rUCON0 (*(volatile unsigned *)0x50000004) //UART 0 Control
#define rUFCON0 (*(volatile unsigned *)0x50000008) //UART 0 FIFO control
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control
#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //UART 0 Tx/Rx status
#define rUERSTAT0 (*(volatile unsigned *)0x50000014) //UART 0 Rx error status
#define rUFSTAT0 (*(volatile unsigned *)0x50000018) //UART 0 FIFO status
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status
#define rUBRDIV0 (*(volatile unsigned *)0x50000028) //UART 0 Baud rate divisor
#define rULCON1 (*(volatile unsigned *)0x50004000) //UART 1 Line control
#define rUCON1 (*(volatile unsigned *)0x50004004) //UART 1 Control
#define rUFCON1 (*(volatile unsigned *)0x50004008) //UART 1 FIFO control
#define rUMCON1 (*(volatile unsigned *)0x5000400c) //UART 1 Modem control
#define rUTRSTAT1 (*(volatile unsigned *)0x50004010) //UART 1 Tx/Rx status
#define rUERSTAT1 (*(volatile unsigned *)0x50004014) //UART 1 Rx error status
#define rUFSTAT1 (*(volatile unsigned *)0x50004018) //UART 1 FIFO status
#define rUMSTAT1 (*(volatile unsigned *)0x5000401c) //UART 1 Modem status
#define rUBRDIV1 (*(volatile unsigned *)0x50004028) //UART 1 Baud rate divisor
#define rULCON2 (*(volatile unsigned *)0x50008000) //UART 2 Line control
#define rUCON2 (*(volatile unsigned *)0x50008004) //UART 2 Control
#define rUFCON2 (*(volatile unsigned *)0x50008008) //UART 2 FIFO control
#define rUMCON2 (*(volatile unsigned *)0x5000800c) //UART 2 Modem control
#define rUTRSTAT2 (*(volatile unsigned *)0x50008010) //UART 2 Tx/Rx status
#define rUERSTAT2 (*(volatile unsigned *)0x50008014) //UART 2 Rx error status
#define rUFSTAT2 (*(volatile unsigned *)0x50008018) //UART 2 FIFO status
#define rUMSTAT2 (*(volatile unsigned *)0x5000801c) //UART 2 Modem status
#define rUBRDIV2 (*(volatile unsigned *)0x50008028) //UART 2 Baud rate divisor
#ifdef __BIG_ENDIAN
#define rUTXH0 (*(volatile unsigned char *)0x50000023) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000027) //UART 0 Receive buffer
#define rUTXH1 (*(volatile unsigned char *)0x50004023) //UART 1 Transmission Hold
#define rURXH1 (*(volatile unsigned char *)0x50004027) //UART 1 Receive buffer
#define rUTXH2 (*(volatile unsigned char *)0x50008023) //UART 2 Transmission Hold
#define rURXH2 (*(volatile unsigned char *)0x50008027) //UART 2 Receive buffer
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000023)=(unsigned char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000027)
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004023)=(unsigned char)(ch)
#define RdURXH1() (*(volatile unsigned char *)0x50004027)
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008023)=(unsigned char)(ch)
#define RdURXH2() (*(volatile unsigned char *)0x50008027)
#define UTXH0 (0x50000020+3) //Byte_access address by DMA
#define URXH0 (0x50000024+3)
#define UTXH1 (0x50004020+3)
#define URXH1 (0x50004024+3)
#define UTXH2 (0x50008020+3)
#define URXH2 (0x50008024+3)
#else //Little Endian
#define rUTXH0 (*(volatile unsigned char *)0x50000020) //UART 0 Transmission Hold
#define rURXH0 (*(volatile unsigned char *)0x50000024) //UART 0 Receive buffer
#define rUTXH1 (*(volatile unsigned char *)0x50004020) //UART 1 Transmission Hold
#define rURXH1 (*(volatile unsigned char *)0x50004024) //UART 1 Receive buffer
#define rUTXH2 (*(volatile unsigned char *)0x50008020) //UART 2 Transmission Hold
#define rURXH2 (*(volatile unsigned char *)0x50008024) //UART 2 Receive buffer
#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define RdURXH0() (*(volatile unsigned char *)0x50000024)
#define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
#define RdURXH1() (*(volatile unsigned char *)0x50004024)
#define WrUTXH2(ch) (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
#define RdURXH2() (*(volatile unsigned char *)0x50008024)
#define UTXH0 (0x50000020) //Byte_access address by DMA
#define URXH0 (0x50000024)
#define UTXH1 (0x50004020)
#define URXH1 (0x50004024)
#define UTXH2 (0x50008020)
#define URXH2 (0x50008024)
#endif
Uart.c 文件中定义串口配置函数:
//====================================================
// 语法格式:void myUart_Init(int whichuart, int baud)
// 功能描述: 对Uart进行初始化,以所需要的波特率为输入参数
// 入口参数: UART端口号 波特率
// 出口参数: 无
//=====================================================================
void myUart_Init(int pclk, int baud)
{
if (pclk == 0)
pclk = PCLK;
if(UartNum == 0) //判断是否使用UART0
{
/ /设置GPH端口为UART口
rGPHCON = rGPHCON & (~(0xffff)); //UART0: RXD0<==>GPH3 TXD0<==>GPH2
rGPHCON = rGPHCON | (0xaaa0) ;
rGPHUP = 0x0; //使能上拉功能
rUFCON0=0x00; // 不使用FIFO
rUMCON0=0x00; //不使用自动流控制
rULCON0=0x03; //不采用红外线传输模式,无奇偶校验位,1个停止位,8个数据位
rUCON0=0x245;
/*发送中断为电平方式,接收中断为边沿方式,禁止超时中断,允许产生错误状态中断,禁止回送模式,禁止中止信号,传输模式为中断请求模式,接收模式也为中断请求模式。*/
rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 ); //根据波特率计算UBRDIV0的值
Delay(10);
}
else if(UartNum == 1)
{
rGPHCON = rGPHCON & (~(0xffff)) ; //UART1: RXD1<==>GPH5 TXD1<==>GPH4
rGPHCON = rGPHCON | (0xaaa0) ; //设置GPH端口为UART口
rGPHUP = 0x0; // 使能上拉功能
rUFCON1=0x0;
rUMCON1=0x0;
rULCON1=0x3;
rUCON1=0x245;
rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 );
Delay(10);
}
}
//====================================================
// 语法格式:void myUart_SendByte(char ch)
// 功能描述: 发送字节数据
// 入口参数: 发送的字节数据
// 出口参数: 无
//====================================================================
void myUart_SendByte(char ch)
{
if (UartNum ==0)
{
if(ch=='\n')
{
while(!(rUTRSTAT0 & 0x2)); //等待,直到发送缓冲区为空
// Delay(10); //超级中断的响应速度较慢
WrUTXH0('\r'); //发送回车符
}
while(!(rUTRSTAT0 & 0x2)); //等待,直到发送缓冲区为空
// Delay(10);
WrUTXH0(ch); //发送字符
}
else
{
if(ch=='\n')
{
while(!(rUTRSTAT1 & 0x2)); //等待,直到发送缓冲区为空
// Delay(10); //等待
rUTXH1='\r';
}
while(!(rUTRSTAT1 & 0x2)); //Wait until THR is empty.
// Delay(10);
WrUTXH1(ch);
}
}
//====================================================
// 语法格式:void myUart_Send (char *str)
// 功能描述: 发送字符串
// 入口参数: 字符串指针
// 出口参数: 无
//====================================================================
void myUart_Send (char *str)
{
myUart_Init(0,115200);
while (*str)
myUart_SendByte(*str++);
}
char myUart_ReceiveByte(void)
{
if(UartNum==0)
{
while(!(rUTRSTAT0 & 0x1)); //等待接收数据
return RdURXH0();
}
else if(UartNum==1)
{
while(!(rUTRSTAT1 & 0x1)); //等待接收数据
return RdURXH1();
}
return 0;
}
void myUart_receive(char *string)
{
char *string2 ;
char c;
string2 = string;
myUart_Init(0,115200);
while((c = myUart_ReceiveByte())!='\r')
{
if(c=='\b')
{
if( (int)string2 < (int)string )
{
printf("\b \b");
string--;
}
}
else
{
*string++ = c;
myUart_SendByte(c);
}
}
*string='\0';
myUart_SendByte('\n');
}
void myUart_Printf(char *fmt,...)
{
va_list ap;
char string[256];
va_start(ap,fmt);
vsprintf(string,fmt,ap);
myUart_Send(string);
va_end(ap);
}
U-boot中配置串口:
board/TX2440/TX2440.c中的board_init函数
int board_init (void)
{
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* set up the I/O ports */
gpio->GPGUP = 0x0000FFFF;()
gpio->GPHCON = 0x002AFAAA;(串口0和串口1的nCTS, nRTS, TXD,RXD,还有时钟)
gpio->GPHUP = 0x000007FF;
……
}
cpu\arm920t\s3c24x0\serial.c(串口驱动)