imx6ull开发板添加串口4,并监视串口3和串口4内容

我又来整理笔记了!!!!

1.向正点原子imx6ull(Mini)开发板烧录出厂系统

首先我们要将出厂系统通过Mftool工具烧录到开发板上,烧录好的系统是自带uart1和uart3串口,将内核版本相同的Linux内核传到Ubuntu(跟上一篇一样,版本一定要一样),使用build.sh编译内核,

根据正点原子教程创建VSCODE工程并屏蔽部分内容(不屏蔽也可以,就是找文件麻烦一点,参开正点原子驱动开发手册)

2.向开发板添加UART4

找到imx6ul-pinfunc.h文件查看宏定义找到UART4有关的宏定义,然后

在imx6ull-alientek-emmc.dts中,在pinctrl_uart3: uart3grp这个函数下方创建uart4的节点

创建节点

pinctrl_uart4: uart4grp {
    fsl,pins = <
    MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX   0x1b0b1
    MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX   0x1b0b1
    >;
};

找到到&uart3,在下面添加uart4的节点

添加节点

&uart4 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_uart4>;
    status = "okay";
};

注意使用查找功能(Ctrl+F)查看是否串口重用,将重用的进行屏蔽

然后编译设备树

make dtbs

将设备树和镜像拷贝到tftp目录下

sudo cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /home/lxy/linux/tftpboot/ -f
sudo cp arch/arm/boot/zImage /home/lxy/linux/tftpboot/ -f

启动开发板进入Uboot模式 (出现倒计时时候按回车键),设置IP(如果开始就设置好的话这里可以不用再次设置)

setenv ipaddr 192.168.150.8
​
setenv ethaddr b8:ae:1d:01:00:00
​
setenv gatewayip 192.168.150.1
​
setenv netmask 255.255.255.0
​
setenv serverip 192.168.150.16
​
saveenv

设置bootcmd 和bootargs环境变量以便从tftp下载zImage和dtb

//从emmc启动文件系统
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
//网络启动内核和设置树
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;'
saveenv

在Uboot下使用bootz命令重启开发板,(注意:不能按复位,因为它下载在DRAM中,掉电就没了)系统自动下载镜像和设备树到DRAM,(先ping一下虚拟机看是否可以ping通,如果不通需要再次设置ip和服务器)

启动后查看/dev如下,出现ttymxc3

imx6ull开发板添加串口4,并监视串口3和串口4内容_第1张图片

3.编写应用程序 

首先要设置开发板静态IP和挂载网络文件系统(参考上一篇文章)

使用select函数监视串口信息

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define   F_UART3   "/dev/ttymxc2"   //串口3
#define   F_UART4   "/dev/ttymxc3"   //串口4
#define   MAX		3                //串口数量

void Open_File();                           //打开文件,参数为描述符集合
void Close_File(int buf[MAX]);						    //关闭文件,参数为描述符集合
void Set_select(int buf[MAX]);							//布置监视任务并获取结果
int Read_file(int fd, char *buf, int size);				//读文件信息,参数:文件描述符,信息缓冲区,一次读的字节数
void Write_Uart(char *buf, int fd);						//向串口发送数据,参数:写入的数据,文件描述符
int max(int a, int b);
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);		//初始化串口,参数:文件描述符,波特率,数据位,是否校验,停止位

char bufferR[10];                                       //读取数据缓冲区
char bufferW[8] = "Hellow";								//写入数据
static int file_descri[MAX];

void main()
{
    
    Open_File();

    Set_select(file_descri);

	Close_File(file_descri);
	
}


void Open_File(int buf[MAX])
{

	if((file_descri[0]=open(F_UART3,O_RDWR,0777))<0)
	{
		printf("uart3failed\n");
	}
	else
    {
		printf("uart3uccess\n");
		set_opt(file_descri[0], 115200, 8, 'N', 1); 

	}

    if((file_descri[1]=open(F_UART4,O_RDWR,0777))<0)
	{
		printf("uart4failed\n");
	}
	else
    {
		printf("uart4uccess\n");
		set_opt(file_descri[1], 115200, 8, 'N', 1);
	}
}


void Close_File(int buf[MAX])
{
    close(buf[0]);
    close(buf[1]);
}

int Read_file(int fd, char *buf, int size)
{
	int len = 0;
	len = read(fd, buf, size);
	printf("len = %d,read:%s\n", len,bufferR); //读
	if(-1==len) {
		return -1;
	}
	return len;
}


void Write_Uart(char *buf, int fd)
{
    int len = strlen(buf);
    write(fd,bufferW,len);
}



void Set_select(int buf[MAX])
{
    while(1)
	{
		int ret = 0;
		fd_set fs_read;
        
        //布置监视任务
        //置空读集
		FD_ZERO(&fs_read);
		FD_SET(buf[0], &fs_read);
        FD_SET(buf[1], &fs_read);

    
       //监视 
		while(FD_ISSET(buf[0],&fs_read)||FD_ISSET(buf[1],&fs_read))
		{
			FD_ZERO(&fs_read);
            FD_SET(buf[0],&fs_read);
			FD_SET(buf[1],&fs_read);
			ret = select(max(buf[0],buf[1])+1, &fs_read, NULL, NULL, NULL);
			if(ret < 0)
            {
                if(errno == EINTR) break;
                perror("select");
                exit(1);
            }
	
			if(FD_ISSET(buf[0], &fs_read))
			{
				if(-1 == Read_file(buf[0],bufferR,2))
				{
					break;
				}
				Write_Uart(bufferW, buf[0]);  
			}
            if(FD_ISSET(buf[1], &fs_read))
            {
                if(-1 == Read_file(buf[1],bufferR,1))
				{
					break;
				}
				Write_Uart(bufferW, buf[1]); 
            }
			

		}
    }

}

//选两个文件描述符大的
int max(int a, int b)
{
	if(a > b) return a;
	else return b;
}



//串口通用初始化函数
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;//定义结构体newtio和oldtio
	//将原串口的数据取到oldtio
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	//将newio清零和设置c_cflag
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;//使能接收和忽略控制线
	newtio.c_cflag &= ~CSIZE;
	//设置数据位
	switch( nBits )
	{
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
	}
	//设置校验位
	switch( nEvent )
	{
		//偶校验
		case 'O':
			newtio.c_cflag |= PARENB;//使能奇偶校验
			newtio.c_cflag |= PARODD;//偶校验
			newtio.c_iflag |= (INPCK | ISTRIP);//输入校验并忽略第八位
			break;
		case 'E': 
			newtio.c_iflag |= (INPCK | ISTRIP);
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;//取消偶校验(置零偶校验位),开启奇校验
			break;
		case 'N':  
			newtio.c_cflag &= ~PARENB;//不进行奇偶校验
			break;
	}
	//设置波特率
	switch( nSpeed )
	{
		case 2400:
			cfsetispeed(&newtio, B2400);
			cfsetospeed(&newtio, B2400);
			break;
		case 4800:
			cfsetispeed(&newtio, B4800);
			cfsetospeed(&newtio, B4800);
			break;
		case 9600:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
	}
	//设置停止位
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;//一位停止位
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;//两位停止位

	newtio.c_cc[VTIME]  = 0;//不设置读取超时
	newtio.c_cc[VMIN] = 0;//读取最小字符数为0

	tcflush(fd,TCIFLUSH);//清空缓冲区
	
	//使配置生效
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	//	printf("set done!\n\r");
	return 0;
}

使用交叉编译arm-linux-gnueabihf-gcc器进行编译,

arm-linux-gnueabihf-gcc uart34App.c -o uart34App

然后拷贝到Ubuntu的nfs目录下,在开发板运行,这里要使用minicom,出厂系统里边自带了,正点原子驱动开发手册查看使用教程即可,使用串口调试助手通过USB转TTL模块将电脑和开发板连接可以进行测试,程序亲测能用。

好的!终于把自己的零散笔记整理起来了!!!

你可能感兴趣的:(Imx6ull开发板学习,linux,c语言)