我用的是友善的mini2440开发板,这是linux-2.6.32内核下driver/serial/s3c2440.c 也就是2440的uart驱动注册函数,uart是paltform注册的函数,挂载好文件系统后在文件系统下/dev/ttySAC0 /dev/ttySAC1 /dev/ttySAC2 这说明三个串口的驱动都是能用的,这是内核源码:
#include
#include
#include
#include
#include
#include
#include
#include "samsung.h"
static int s3c2440_serial_setsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
/* todo - proper fclk<>nonfclk switch. */
ucon &= ~S3C2440_UCON_CLKMASK;
if (strcmp(clk->name, "uclk") == 0)
ucon |= S3C2440_UCON_UCLK;
else if (strcmp(clk->name, "pclk") == 0)
ucon |= S3C2440_UCON_PCLK;
else if (strcmp(clk->name, "fclk") == 0)
ucon |= S3C2440_UCON_FCLK;
else {
printk(KERN_ERR "unknown clock source %s\n", clk->name);
return -EINVAL;
}
wr_regl(port, S3C2410_UCON, ucon);
return 0;
}
static int s3c2440_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
unsigned long ucon0, ucon1, ucon2;
switch (ucon & S3C2440_UCON_CLKMASK) {
case S3C2440_UCON_UCLK:
clk->divisor = 1;
clk->name = "uclk";
break;
case S3C2440_UCON_PCLK:
case S3C2440_UCON_PCLK2:
clk->divisor = 1;
clk->name = "pclk";
break;
case S3C2440_UCON_FCLK:
/* the fun of calculating the uart divisors on
* the s3c2440 */
ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
ucon0 &= S3C2440_UCON0_DIVMASK;
ucon1 &= S3C2440_UCON1_DIVMASK;
ucon2 &= S3C2440_UCON2_DIVMASK;
if (ucon0 != 0) {
clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
clk->divisor += 6;
} else if (ucon1 != 0) {
clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
clk->divisor += 21;
} else if (ucon2 != 0) {
clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
clk->divisor += 36;
} else {
/* manual calims 44, seems to be 9 */
clk->divisor = 9;
}
clk->name = "fclk";
break;
}
return 0;
}
static int s3c2440_serial_resetport(struct uart_port *port,
struct s3c2410_uartcfg *cfg)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
port, port->mapbase, cfg);
/* ensure we don't change the clock settings... */
ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
wr_regl(port, S3C2410_ULCON, cfg->ulcon);
/* reset both fifos */
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
return 0;
}
static struct s3c24xx_uart_info s3c2440_uart_inf = {
.name = "Samsung S3C2440 UART",
.type = PORT_S3C2440,
.fifosize = 64,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
.tx_fifofull = S3C2440_UFSTAT_TXFULL,
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
.get_clksrc = s3c2440_serial_getsource,
.set_clksrc = s3c2440_serial_setsource,
.reset_port = s3c2440_serial_resetport,
};
/* device management */
static int s3c2440_serial_probe(struct platform_device *dev)
{
dbg("s3c2440_serial_probe: dev=%p\n", dev);
return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
}
static struct platform_driver s3c2440_serial_driver = {
.probe = s3c2440_serial_probe,
.remove = __devexit_p(s3c24xx_serial_remove),
.driver = {
.name = "s3c2440-uart",
.owner = THIS_MODULE,
},
};
s3c24xx_console_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
static int __init s3c2440_serial_init(void)
{
return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
}
static void __exit s3c2440_serial_exit(void)
{
platform_driver_unregister(&s3c2440_serial_driver);
}
module_init(s3c2440_serial_init);
module_exit(s3c2440_serial_exit);
MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver");
MODULE_AUTHOR("Ben Dooks <>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:s3c2440-uart");
下面是从串口读取数据的程序仅供参考:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "common.h"
#define FALSE -1
#define TRUE 0
#define at01 "AT\r"
#define at02 "ATE0\r"
#define at03 "AT^DGPIOSM=1\r"
#define at04 "AT^DSLP=0,0\r"
#define at05 "AT+CR=1\r"
#define at06 "AT+CRC=1\r"
#define at07 "AT+CMER=2,0,0,2\r"
#define at08 "AT^DSCI=1\r"
#define at09 "AT^DCPI=1\r"
#define at10 "AT+CREG=1\r"
#define at11 "AT^DSQ=1\r"
#define at12 "AT+CFUN=5\r"
#define at13 "AT+CFUN=1\r"
#define at14 "AT+COPS=0\r"
#define at15 "ATD15210684584;\r"
#define at100 "AT+CREG?\r"
//*************delete char***********************************************8
void RemoveChars(char str[],char remove[])
{
int src ,dst,removeArray[256];
src = 0;
memset(removeArray, 0, sizeof(removeArray));
while(remove[src])
{
removeArray[remove[src]] = 1;
src++;
}
src = dst = 0;
do
{
if(!removeArray[str[src]])
{
str[dst++] = str[src];
}
}while(str[src++]);
}
int speed_arr[] = {B115200, B57600, B38400, B19200,
B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {115200, 57600, 38400, 19200,
9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i, status;
struct termios Opt;
if (tcgetattr(fd, &Opt) != 0)
{
perror("SetupSerial baud 1");
return;
}
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
{
perror("tcsetattr fd");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
}
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if (tcgetattr(fd,&options) != 0)
{
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
options.c_iflag = 0;
switch (databits)
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* set to odd check */
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* set to even check */
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 150; /* set 15 seconds timeout */
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
/* end */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
int OpenDev(char *Dev)
{
int fd;
fd = open(Dev, O_RDWR );
if (-1 == fd)
{
perror("Can't Open Serial Port");
return -1;
}
return fd;
}
static int fd_dev;
fd_set rfds;
struct timeval tv;
int retval;
int nread;
char buff[512];
int atsendrecv(char atin[215],int timeout)
{
int returnvalue = 0;
FD_ZERO(&rfds);
FD_SET(fd_dev,&rfds);
tv.tv_sec= timeout;
tv.tv_usec=timeout;
do
{
retval=select(fd_dev+1,&rfds,NULL,NULL,&tv);
if (retval)
{
nread=read(fd_dev,buff,sizeof(buff));
if (nread > 2)
{
buff[nread] = '\0';
RemoveChars(buff,"\r\n");
printf( "Recv<--%s\n\n", buff);
nread = 0;
memset(buff, 0, sizeof(buff));
}
returnvalue = 1;
}
}while(0 < retval);
return returnvalue;
}
int main(int argc, char **argv)
{
int baud;
int creg_status = 0;
char dev[32];
int i;
memset(dev, 0, sizeof(dev));
if (argc < 3)
{
strcpy(dev, "/dev/ttySAC2");
baud = 9600;
}
else
{
strcpy(dev, argv[1]);
baud = atoi(argv[2]);
}
fd_dev = OpenDev(dev);
if (-1 == fd_dev)
{
printf("Open %s Error\n", dev);
exit (0);
}
set_speed(fd_dev, baud);
if (set_Parity(fd_dev,8,1,'N') == FALSE)
{
printf("Set Parity Error\n");
exit (0);
}
do
{
usleep(20);
if((nread = read(fd_dev, buff, sizeof(buff))) > 0)
{
buff[nread] = '\0';
for(i=0; i //uart.data[i] = buff[i];
printf("recv[%d] is 0x%x\n", i, buff[i]);
//printf("recv[%d] is 0x%x\n", i, uart.data[i]);
}
}
else
printf("read failed!\n");
}while(1);
close(fd_dev);
return 0;
}