GPIO可配置的选项:
AM33XX_SLEWCTRL_FAST: 高速管脚 AM33XX_SLEWCTRL_SLOW: 低速管脚 AM33XX_PULL_DISA: 关闭内部上下拉 AM33XX_PIN_OUTPUT: 输出下拉 AM33XX_PIN_OUTPUT_PULLUP: 输出上拉 AM33XX_PIN_INPUT: 关闭内部上下拉,并配置成输入 AM33XX_PIN_INPUT_PULLUP: 开启内部上拉,并配置成输入 AM33XX_PIN_INPUT_PULLDOWN: 开启内部下拉,并配置成输入
_AM33XX_MUXENTRY(UART1_TXD, 0, "uart1_txd", "mmc2_sdwp", "d_can1_rx", "i2c1_scl", NULL, "pr1_uart0_txd_mux1", NULL, "gpio0_15"), 其中: “uart1_txd” 对应步骤3的OMAP_MUX_MODE0 “mmc2_sdwp” 对应步骤3的OMAP_MUX_MODE1 “d_can1_rx” 对应步骤3的OMAP_MUX_MODE2 “i2c1_scl” 对应步骤3的OMAP_MUX_MODE3 “pr1_uart0_txd_mux1” 对应步骤3的OMAP_MUX_MODE5 “gpio0_15” 对应步骤3的OMAP_MUX_MODE7
按照原理图增加uart1-uart5驱动需要修改两个文件:mux33xx.c board-am335xevm.c
mux33xx.c中:
uart1 uart2原来定义的里面就有无需修改
_AM33XX_MUXENTRY(MII1_RXD3, 0,
"mii1_rxd3", "uart3_rxd", "rgmii1_rd3", "mmc0_dat5",
"mmc1_dat2", NULL, "mcasp0_axr0", "gpio2_18"),
_AM33XX_MUXENTRY(MII1_RXD2, 0,
"mii1_rxd2", "uart3_txd", "rgmii1_rd2", "mmc0_dat4",
"mmc1_dat3", NULL, "mcasp0_axr1", "gpio2_19"),
_AM33XX_MUXENTRY(MII1_TXD3, 0,
"mii1_txd3", NULL, "rgmii1_td3", "uart4_rxd",
"mcasp1_fsx", "mmc2_dat1", "mcasp0_fsr", "gpio0_16"),
_AM33XX_MUXENTRY(MII1_TXD2, 0,
"mii1_txd2", NULL, "rgmii1_td2", "uart4_txd",
"mcasp1_axr0", "mmc2_dat2", "mcasp0_ahclkx", "gpio0_17"),
_AM33XX_MUXENTRY(MII1_RXDV, 0,
"mii1_rxdv", NULL, "rgmii1_rctl", "uart5_txd",
"mcasp1_aclx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
_AM33XX_MUXENTRY(MII1_RXDV, 0,
"mii1_rxdv", NULL, "rgmii1_rctl", "uart5_txd",
"mcasp1_aclx", "mmc2_dat0", "mcasp0_aclkr", "gpio3_4"),
board-am335xevm.c里面需要配置管脚模式及初始化:
/* Module pin mux for uart2 */
static struct pinmux_config uart2_pin_mux[] = {
{"spi0_sclk.uart2_rxd", OMAP_MUX_MODE1 | AM33XX_SLEWCTRL_SLOW |
AM33XX_PIN_INPUT_PULLUP},
{"spi0_d0.uart2_txd", OMAP_MUX_MODE1 | AM33XX_PULL_UP |
AM33XX_PULL_DISA |
AM33XX_SLEWCTRL_SLOW},
{NULL, 0},
};
/* Module pin mux for uart1 */
static struct pinmux_config uart1_pin_mux[] = {
{"uart1_rxd.uart1_rxd", OMAP_MUX_MODE0 | AM33XX_SLEWCTRL_SLOW | AM33XX_PIN_INPUT_PULLUP},
{"uart1_txd.uart1_txd", OMAP_MUX_MODE0 | AM33XX_PULL_UP |
AM33XX_PULL_DISA |
AM33XX_SLEWCTRL_SLOW},
{NULL, 0},
};
/* Module pin mux for uart3 */
static struct pinmux_config uart3_pin_mux[] = {
{"mii1_rxd3.uart3_rxd", OMAP_MUX_MODE1 | AM33XX_SLEWCTRL_SLOW | AM33XX_PIN_INPUT_PULLUP},
{"mii1_rxd2.uart3_txd", OMAP_MUX_MODE1 | AM33XX_PULL_UP |
AM33XX_PULL_DISA |
AM33XX_SLEWCTRL_SLOW},
{NULL, 0},
};
/* Module pin mux for uart4 */
static struct pinmux_config uart4_pin_mux[] = {
{"mii1_txd3.uart4_rxd", OMAP_MUX_MODE3 | AM33XX_SLEWCTRL_SLOW | AM33XX_PIN_INPUT_PULLUP},
{"mii1_txd2.uart4_txd", OMAP_MUX_MODE3 | AM33XX_PULL_UP |
AM33XX_PULL_DISA |
AM33XX_SLEWCTRL_SLOW},
{NULL, 0},
};
/* Module pin mux for uart5 */
static struct pinmux_config uart5_pin_mux[] = {
{"mii1_col.uart5_rxd", OMAP_MUX_MODE3 | AM33XX_SLEWCTRL_SLOW | AM33XX_PIN_INPUT_PULLUP},
{"mii1_rxdv.uart5_txd", OMAP_MUX_MODE3 | AM33XX_PULL_UP |
AM33XX_PULL_DISA |
AM33XX_SLEWCTRL_SLOW},
{NULL, 0},
};
初始化:
/* setup uart5 */
static void uart5_init(int evm_id, int profile)
{
setup_pin_mux(uart5_pin_mux);
return;
}
/* setup uart4 */
static void uart4_init(int evm_id, int profile)
{
setup_pin_mux(uart4_pin_mux);
return;
}
/* setup uart3 */
static void uart3_init(int evm_id, int profile)
{
setup_pin_mux(uart3_pin_mux);
return;
}
/* setup uart2 */
static void uart2_init(int evm_id, int profile)
{
setup_pin_mux(uart2_pin_mux);
return;
}
/* setup uart1 */
static void uart1_init(int evm_id, int profile)
{
setup_pin_mux(uart1_pin_mux);
return;
}
{uart1_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{uart2_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{uart3_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{uart4_init, DEV_ON_BASEBOARD, PROFILE_ALL},
{uart5_init, DEV_ON_BASEBOARD, PROFILE_ALL},
编译后进行测试,驱动增加完成。
串口测试程序源码:
串口接收到什么数据然后发出什么数据
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <termios.h>
#include <stdlib.h>
struct termios gsTio[5];
pthread_t gsThreadId;
struct stru_run_param
{
fd_set rfds; //文件描述符集
int ptid[5]; //打开的通讯口句柄。
signed char cid[5]; //通讯口状态标示
signed char cnt; //打开通讯口个数
signed char brun; //监视线程运行控制标识
} Serial_RunPar;
//串口线程
void thread_serial(void* arg)
{
struct stru_run_param *prp;
unsigned char buff[5][1024];
struct timeval tmv;
int bRecCnt[5],retval,i,maxid,wCount;
int aaa=0,k;
char bbb[10];
memset(buff,0,1024);
bbb[9]='\n';
prp = (struct stru_run_param*)arg;
if(prp->cnt == 0)
{
printf("There is no serial port needing for watching!\n");
pthread_exit(0);
}
maxid = prp->ptid[0];
for(i=1; i<prp->cnt; i++) //取出最大的文件描述符
{
if(maxid < prp->ptid[i])
maxid = prp->ptid[i];
}
prp->brun = 1;
while(prp->brun){
tmv.tv_sec = 0;
tmv.tv_usec = 50000; //线程周期50毫秒
sleep(1);
for(i=0; i<prp->cnt; i++){
retval = select(maxid + 1, &prp->rfds, NULL, NULL, &tmv);
if(retval != 0 && retval != -1){ //检测到有数据接收
printf("get data from serial\n");
if((bRecCnt[i] = read(prp->ptid[i], buff[i], 1024)) == -1){
perror("serial port read");
FD_CLR(prp->ptid[i], &prp->rfds);
}else{
wCount = write(prp->ptid[i],buff[i],bRecCnt[i]);
printf("receive data OK!count=%d\n",wCount);
wCount=0;
for(k=0;k<bRecCnt[i];k++){
printf("%02x ",buff[i][k]);
}
printf("\n");
memset(buff[i],0,1024);
}
}else{
FD_ZERO(&prp->rfds); //超时或出错后清除文件描述符集
for(i=0; i<prp->cnt; i++)
FD_SET(prp->ptid[i], &prp->rfds); //重新添加一下
}
}
}
printf("serial port thread exit\n");
pthread_exit(0);
}
//开启串口线程
signed char CreateSerialWatchThread()
{
int ret;
ret = pthread_create(&gsThreadId, NULL, (void *(*)(void*))thread_serial, (void*)&Serial_RunPar);
if(ret != 0)
{
printf("Create serial port thread error!\n");
return -1;
}
return 1;
}
//打开串口函数
signed char OpenSerial(signed char COM, signed int baud, signed char data,
signed char stop, signed char check, signed char typ)
{
signed char path[16];
struct termios newtio;
sprintf(path, "/dev/ttyO%d", COM); //ttyO*
Serial_RunPar.ptid[Serial_RunPar.cnt] = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
if (Serial_RunPar.ptid[Serial_RunPar.cnt] < 0)
{
printf("Can not open serial port %s!\n", path);
return -1;
}else{
printf("open serial port %s\n",path);
}
//读取旧设置
if(tcgetattr(Serial_RunPar.ptid[Serial_RunPar.cnt], &gsTio[Serial_RunPar.cnt]) != 0)
{
printf("Can not get serial port %s attributes!\n", path);
return -1;
}
bzero(&newtio, sizeof(newtio));
//字符大小
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_lflag = 0;
newtio.c_oflag = 0;
newtio.c_iflag = IXOFF | IXON;
//波特率
switch(baud)
{
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 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
}
//数据位
if(data == 8)
newtio.c_cflag |= CS8;
else if(data == 7)
newtio.c_cflag |= CS7;
//停止位
if(stop == 1)
newtio.c_cflag &= ~CSTOPB;
else if(stop == 2)
newtio.c_cflag |= ~CSTOPB;
//奇偶校验位
switch(check)
{
case 0:
newtio.c_cflag &= ~PARENB;
break;
case 1:
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
break;
case 2:
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_iflag |= (INPCK);
break;
}
//最小字符和等待时间
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
//处理未接收字符
tcflush(Serial_RunPar.ptid[Serial_RunPar.cnt], TCIFLUSH);
//激活新设置
if(tcsetattr(Serial_RunPar.ptid[Serial_RunPar.cnt], TCSANOW, &newtio) != 0)
{
printf("Can not set serial port %s attributes!\n", path);
return -1;
}
//将文件描述符加入描述符集
FD_SET(Serial_RunPar.ptid[Serial_RunPar.cnt], &Serial_RunPar.rfds);
Serial_RunPar.cid[Serial_RunPar.cnt] = COM;
Serial_RunPar.cnt += 1;
return 1;
}
void main()
{
FD_ZERO(&Serial_RunPar.rfds);
//OpenSerial(4, 2400, 8, 1, 2, 1);
OpenSerial(4, 115200, 8, 1, 2, 1);
CreateSerialWatchThread();
while(1);
}