OK6410-A开发板485串口驱动学习

OK6410-A开发板的串口3是可以外接485模块的,而且在“OK6410-A开发板LINUX3.0.1-2014-09用户手册”中提到485的测试方法:
485测试
是用QT程序进行测试的,好在飞凌为我们提供了源码,打开apptest\QT ApplicationTest\serialport目录的main_form.cpp文件,查看打开串口函数:

int TMainForm::openSerialPort() 
{ 
	int fd = -1; 
 
	portName=portNameComboBox->currentText();
	fd = ::open(portName, O_RDWR|O_NONBLOCK); 
	if (fd < 0) 
	{ 
		QMessageBox::warning(this, tr("Error"), tr("fd1")); 
	    return -1; 
	}

这里打开portNameComboBox下拉框显示的内容,从UI设计器或者源码可以看到:

portNameComboBox = new QComboBox( FALSE, GroupBox5, "portNameComboBox" );
portNameComboBox->insertItem( tr( "/dev/ttySAC0" ) );
portNameComboBox->insertItem( tr( "/dev/ttySAC1" ) );
portNameComboBox->insertItem( tr( "/dev/ttySAC2" ) );
portNameComboBox->insertItem( tr( "/dev/ttySAC3" ) );

好像和其他串口操作没有区别啊,那么485控制IO在哪里操作的呢?初步怀疑被封装在内核里面了,我编译的是linux-3.0.1内核,个人觉得应该是字符设备目录下了,果断打开linux-3.0.1/drivers/char目录,发现forlinx6410_485io.c文件:
驱动模块定义
这里声明了一个485控制模块,先看模块初始化函数:

static int __init rs485io_init(void)
{
	int ret;
	unsigned long tmp;

    //gpk5 pull up
	tmp = __raw_readl(S3C64XX_GPKPUD);
	tmp &= ~(1<<(2*5+1));
	tmp |= 1<<(2*5);
	__raw_writel(tmp,S3C64XX_GPKPUD);

	//gpk5 output mode
	tmp =__raw_readl(S3C64XX_GPKCON);
	tmp &= ~(0xf)<<(5*4);
	tmp |= 1<<(5*4);
	__raw_writel(tmp,S3C64XX_GPKCON);

	//gpk5 output 0
	tmp = __raw_readl(S3C64XX_GPKDAT);
	tmp &= (~(1<<5));
	printk("\n@@@@@@@@@@@\n");
	printk("\ntmp = %lu\n",tmp);
	printk("\n@@@@@@@@@@@\n");
	__raw_writel(tmp,S3C64XX_GPKDAT);  

	ret = misc_register(&misc);
	return ret;
}

初始化函数无外乎设置了几个寄存器的值,涉及到的几个宏定义在linux-3.0.1/arch/arm/mach-s3c64xx/include/mach/gpio-bank-k.h文件中:
GPK宏定义
还是得结合三星手册来看:
GPK寄存器定义
首先配置GPKPUD寄存器:
GPKPUD定义
代码“tmp |= 1<<(25)”就是将GPK5设置为01(下拉使能)。再看GPKCON0寄存器:
GPKCON0定义
每个引脚对应4bit值,那么代码“tmp |= 1<<(5
4)”就是将GPK5设置为0001(输出模式)。最后的GPKDAT操作最简单,寄存器每1位对应一个引脚的输出:
GPKDAT定义
代码“ tmp &= (~(1<<5))”是将GPK5输出为低电平,模块的初始化就这么简单。上面的s3c6410_485io_ioctl是用来修改GPK5输出状态的,但是这个驱动没发现被调用啊,看来还得继续分析串口驱动程序。
打开drivers/tty/serial目录,其中s3c6400.c文件是负责加载串口驱动的,而串口的发送和接收处理在samsung.c文件中(如果不知道对应是哪个驱动编译进内核了,可以编译后查看有xxx.o的对应.c文件,这里也算一个技巧):
串口发送函数
这是串口开始发送处理函数,那句“port->line == 3”判断的是串口3,说明要操作485串口了。变量a为静态变量,第一次使用时需要配置IO引脚,这样的骚操作居然写在内核代码里,我也是醉了。
s3c_gpio_cfgpin函数负责配置IO引脚功能,具体定义在linux-3.0.1/arch/arm/plat-samsung/gpio-config.c文件,有不明白的可见博文 https://www.cnblogs.com/hello2mhb/p/3278709.html
那么S3C_GPIO_SFN宏是干什么的呢,其定义在linux-3.0.1/arch/arm/plat-samsung/include/plat/gpio-cfg.h文件中:
S3C_GPIO_SFN宏分析
可见S3C_GPIO_SFN宏就是对S3C_GPIO_INPUT和S3C_GPIO_OUTPUT来个统一处理,这里的S3C_GPIO_SFN(1))就是将GPK5设置为输出。
这样一来思路就清晰了,使用串口3时内核驱动进行处理,第一次发送需要配置GPK5设置为输出,以后只设置GPK5输出为高电平就可以了。而对于用户端来说使用485串口和使用其他串口操作是一样的了。
如此一来,如果我们想使用其他串口作为485串口,只需修改port->line和forlinx6410_485io模块的初始化函数就可以了。

猜你喜欢

转载自blog.csdn.net/xinxin_2011/article/details/85849886
今日推荐