【嵌入式软件开发】芯片外设接口测试工具编写

【嵌入式软件开发】芯片外设接口测试工具编写

工具主要包含如下接口功能测试

  • RTC时钟 rtc
  • DIDO gpio
  • 串口 uart
  • 风扇 pwm
  • 网卡通信 net

代码展示


#include <iostream>
#include <string>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/param.h> 
#include <sys/ioctl.h> 
#include <sys/socket.h> 
#include <net/if.h> 
#include <netinet/in.h> 
#include <net/if_arp.h> 
#ifdef SOLARIS 
#include <sys/sockio.h> 
#endif 



//rtc_test
int rtc_test()
{
    int utc = 0;
    int rtc;
    struct rtc_time tm;
    char *oldtz = 0;
    time_t t = 0;

    rtc = open ("/dev/rtc0", O_RDONLY);
    if (rtc < 0)
    {
        rtc = open("/dev/misc/rtc", O_RDONLY);
        if (rtc < 0)
        {
            printf("Could not access RTC.\r\n");
            return -1;
        }

    }
    memset(&tm, 0, sizeof(tm));
    
    if (ioctl(rtc, RTC_RD_TIME, &tm) < 0)
    {
        printf("Could not read time from RTC");
        return -1;
    }

    tm.tm_isdst = -1; // not known
        
    printf("year:%i, month:%i, date:%i\n", tm.tm_year, tm.tm_mon, tm.tm_mday);
    close(rtc);

    return 0;
}


//serial test

static int baudflag_arr[] = {
    921600, 460800, 230400, 115200, 57600, 38400,
    19200,  9600,   4800,   2400,   1800,  1200,
    600,    300,    150,    110,    75,    50
};
static int speed_arr[] = {
    921600,  460800,  230400,  115200,  57600,  38400,
    19200,   9600,    4800,    2400,    1800,   1200,
    600,     300,     150,     110,     75,     50
};


int speed_to_flag(int speed)
{
    int i;

    for (i = 0;  i < sizeof(speed_arr)/sizeof(int);  i++) {
        if (speed == speed_arr[i]) {
            return baudflag_arr[i];
        }
    }
	printf("Unsupported baudrate, use 9600 instead!\n");
//	    fprintf(stderr, "Unsupported baudrate, use 9600 instead!\n");
    return 9600;
}


#include <termio.h>
static struct termio oterm_attr;

int setup_port(int fd, int baud, int databits, int parity, int stopbits)
{
    struct termio term_attr;

    
    if (ioctl(fd, TCGETA, &term_attr) < 0) {
        return -1;
    }

    
    memcpy(&oterm_attr, &term_attr, sizeof(struct termio));

    term_attr.c_iflag &= ~(INLCR | IGNCR | ICRNL | ISTRIP);
    term_attr.c_oflag &= ~(OPOST | ONLCR | OCRNL);
    term_attr.c_lflag &= ~(ISIG | ECHO | ICANON | NOFLSH);
    term_attr.c_cflag &= ~CBAUD;
    term_attr.c_cflag |= CREAD | speed_to_flag(baud);

    
    term_attr.c_cflag &= ~(CSIZE);
    switch (databits) {
        case 5:
            term_attr.c_cflag |= CS5;
            break;

        case 6:
            term_attr.c_cflag |= CS6;
            break;

        case 7:
            term_attr.c_cflag |= CS7;
            break;

        case 8:
        default:
            term_attr.c_cflag |= CS8;
            break;
    }

 
    switch (parity) {
        case 1:  
            term_attr.c_cflag |= (PARENB | PARODD);
            break;

        case 2:  
            term_attr.c_cflag |= PARENB;
            term_attr.c_cflag &= ~(PARODD);
            break;

        case 0:  
        default:
            term_attr.c_cflag &= ~(PARENB);
            break;
    }

    
    switch (stopbits) {
        case 2:  
            term_attr.c_cflag |= CSTOPB;
            break;

        case 1:  
        default:
            term_attr.c_cflag &= ~CSTOPB;
            break;
    }
    term_attr.c_cc[VMIN] = 1;
    term_attr.c_cc[VTIME] = 0;

    if (ioctl(fd, TCSETAW, &term_attr) < 0) {
        return -1;
    }

    if (ioctl(fd, TCFLSH, 2) < 0) {
        return -1;
    }

    return 0;
}

int read_data(int fd, std::string &msg)
{
    int count;
    int ret;

    ret = 0;
    count = 0;

    char buf[1024] = {0};
    msg.clear();
    while(1)
    {
        ret = read(fd, buf, sizeof(buf));
        if(ret < 0)
        {
            std::cout << "Serial : read data error." << std::endl;
            return -1;    
        }
        else if(ret == 0)
        {
            break;
        }
        else
        {
            msg += std::string(buf);
            memset(buf, 0, sizeof(buf));
        }
    }
    
    return msg.length();
}
int write_data(int fd, std::string &buf)
{
    int count;
    int ret;
    int len = buf.length();

    ret = 0;
    count = 0;

    while (len > 0) 
    {
        ret = write(fd, (char*)buf.c_str() + count, len);
        if (ret < 1) 
        {
            std::cout << "Serial : write error." << std::endl;
            break;
        }

        count += ret;
        len = len - ret;
    }

    return count;
}

int reset_port(int fd)
{
    if (ioctl(fd, TCSETAW, &oterm_attr) < 0) {
        return -1;
    }

    return 0;
}
void serial_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "        Serial Port Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s <device> <baud> <databits> <parity> <stopbits> <read_or_write>\n"
            "       serial dev: 1-ttyS1, 2-ttyS2, 3-ttyS3, 4-ttyS4, 5-ttyS5, 6-ttyS6\n"
            "       databits: 5, 6, 7, 8\n"
            "       parity: 0(None), 1(Odd), 2(Even)\n"
            "       stopbits: 1, 2\n"
            "       read_or_write: 0(read), 1(write)\n"
            "Example:\n  %s 1 9600 8 0 1 0\n\n",
            program_name, program_name
           );
}

int serial_test(int argc, char *argv[])
{
    int baud;
    int len;
    int count;
	int j;
    int databits;
    int stopbits;
    int parity;
    int read_or_write;
    int fd[3];
	char Devname_Port[6][11]={
			{"/dev/ttyS1"},
			{"/dev/ttyS2"},
			{"/dev/ttyS3"},
			{"/dev/ttyS4"},
			{"/dev/ttyS5"},
			{"/dev/ttyS6"},
		};
    int PortInit = 0;
    int PortNum = 0;
	
	if (argc < 8) 
	{
        std::cout << "Invalid PortNum (0,..,5)!\n" << std::endl;
        serial_usage(argv[0]);
		return -1;
	}
PortNum = atoi(argv[2]);
	if ((PortNum < 0) || (PortNum > 5)) 
	{
		std::cout << "Invalid PortNum (0,..,5)!" << std::endl;
		return -1;
	}
    baud = atoi(argv[3]);
    if(baud <0 || baud > 921600)
    {
        std::cout << "Invalid baudrate!" << std::endl;
        return -1;
    }
    // baud = 9600;
databits = atoi(argv[4]);
    if(databits < 0 || databits > 8)
    {
        std::cout << "Invalid databits!" << std::endl;
        return -1;
    }

    parity = atoi(argv[5]);
    if(parity < 0 || parity > 2)
    {
        std::cout << "Invalid parity!" << std::endl;
        return -1;
    }

    stopbits = atoi(argv[6]);
    if(stopbits < 0 || stopbits > 2)
    {
        std::cout << "Invalid stopbits!" << std::endl;
        return -1;
    }
if(PortNum == 5)
	{
		baud = 1200;
	}

    // databits = 1;
    // parity = 2;
    // stopbits = 1;
	
	PortInit = 0;

    std::cout << "Serial: open " << Devname_Port[PortNum] << std::endl;
    fd[PortNum] = open(Devname_Port[PortNum], O_RDWR, 0);
    if (fd[PortNum] < 0) 
    {
        std::cout << "Serial open " << Devname_Port[PortNum] << " error!";
        return -1;
    }

    printf("setup_port(fd=%d, baud=%d, databits=%d, parity=%d, stopbits=%d) \n", fd[PortNum], baud, databits, parity, stopbits);
    if (setup_port(fd[PortNum], baud, databits, parity, stopbits))
    {
        close(fd[PortNum]);
        std::cout << "setup_port error" << std::endl;
        return -1;
    }
    PortInit |= 0x01<<PortNum;
std::cout << "Serial : port " << PortNum << " Begin to Send:" << std::endl;
    
    std::string send_msg;
    std::string recv_msg;
    std::cout << "Serial : Please input send msg." << std::endl;
    while(std::cin >> send_msg)
    {
        count = write_data(fd[PortNum], send_msg);
        if(count == 0)
        {
            std::cout << "\t port " << PortNum << " send data error!" << std::endl;
        }
        else
        {
            std::cout << "\t port " << PortNum << " send data success!" << std::endl;
        }
        sleep(1);
        
        recv_msg.clear();
        count = read_data(fd[PortNum], recv_msg);
        if(count > 0)
        {
            std::cout << "Recv msg : " << recv_msg << std::endl;
        }
    }
	
    return 0;
}

//di_test
struct Sta_dido
{
	char dido_state[22];//目前为22锟斤拷前锟斤拷11锟斤拷为do状态 锟斤拷锟斤拷11锟斤拷为di状态
};
#define DIDO_MAGIC_NB	'd'
#define DIDOE_IOC_MAXNR	3

#define DIDO_DO_OUTPUT_HIGH	  _IOW(DIDO_MAGIC_NB,1,char) //锟斤拷锟斤拷
#define DIDO_DO_OUTPUT_LOW    _IOW(DIDO_MAGIC_NB,2,char)  //锟斤拷锟斤拷
#define DIDO_GET_STATUSE      _IOR(DIDO_MAGIC_NB,3,struct Sta_dido)  //锟斤拷取状态

char dido_st[22]={0xff};

void di_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "          DI Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s 2 <DI1~DI6> \n"
            "   DI param: \n"
            "       1- DI1  2-DI2   3-DI3   4-DI4   5-DI5   6-DI6\n"
            "Example:\n  %s 2 2 (test DI2 current value, 0-low 1-high)\n\n",
            program_name, program_name
           );
}

int di_test(int argc, char *argv[])
{
    
    int ret=0;
	char index = 8;
	int i;
	int j = 0;

	fd_set client_fd_set;  
   	struct timeval tv;

    if(argc < 3)
    {
        std::cout << "DI test Invalid PortNum" << std::endl;
        di_usage(argv[0]);
        return -1;
    }

    index = atoi(argv[1]);

    if(index < 1)
        index = 1;
    else if(index > 6)
        index = 6;
    
int fd = open("/dev/clou_dido", 0);
	
	if (fd < 0)
	{
        std::cout << "DIDO: failed to open dido.('/dev/clou_difo open error')" << std::endl;
        std::cout << "if error msg is 'AT91 dido Driver Ver1.0.1at91_dido_open:busy!!!', please kill clmain or other use dido driver program!" << std::endl;
		return -1;
	}
	else
	{
        std::cout << "DIDO: dido dev file open success!" << std::endl;
	}

	ret = ioctl(fd, DIDO_GET_STATUSE, dido_st);
	if(ret)
	{
        std::cout << "DIDO: DIDO_GET_STATUSE error!" << std::endl;
        return -1;
	}else
	{
        std::cout << "Current do status:" << std::endl;
		for(i=0;i<11;i++)
		{
            std::cout << (int)dido_st[i] << " ";
		}
        std::cout << std::endl;

        std::cout << "Current di status:" << std::endl;
		for(i=11;i<22;i++)
		{
            std::cout << (int)dido_st[i] << " ";
		}
        std::cout << std::endl;

        std::cout << "Current DI " << (int)index << " Status : [" << (int)dido_st[index+10] << "]." << std::endl;
	}
close(fd);

    return 0;
}



#define SYSFS_PWM_CHANALE_1  0
#define SYSFS_PWM_CHANALE_2  1
#define SYSFS_PWM_CHANALE_3  2
#define SYSFS_PWM_CHANALE_4  3

#define SYSFS_PWM_START			1
#define SYSFS_PWM_STOP			0

int sama5dxPWMInit(int channel);
int sama5dxPWMConfig(int channel,unsigned long freKHz,unsigned long dutyPercent );
int sama5dxPWMCtrl(int channel,int commad);
int sama5dxPWMPolarity(int channel,const char *polarity);
int sama5dxPWMInit(int channel)
{
	int fd; 
	char dir[50];
	char buf[5];
	sprintf(dir,"/sys/class/pwm/pwmchip%d/export" ,0);
	sprintf(buf,"%d",channel);
	//锟津开端匡拷/sys/class/gpio# echo 48 > export
	
 	fd = open((const char *)dir, O_WRONLY);//export
 	if(fd == -1)
 	{
 		  printf(" export channel%d err!\n",channel);
		   return -1;
 	}
 	write(fd, (const char *)buf ,sizeof(buf));  //export Channel1	   
 	close(fd); 
 	//锟斤拷一锟斤拷使锟斤拷export锟斤拷锟斤拷锟斤拷要使锟斤拷
 	//锟斤拷锟斤拷NUC970 Programming Guide.pdf 锟斤拷P208
 	sama5dxPWMCtrl(channel,SYSFS_PWM_STOP);
	return 0;
	
}

int sama5dxPWMConfig(int channel,unsigned long freKHz,unsigned long dutyPercent )
{
	int fd; 
	unsigned long periodns,dutyns,dutyActu;
	unsigned long long temp;
	char buf[10];
	char dir[50];
	if((freKHz>1000000)||(channel>3))/*小锟斤拷1MHz 锟斤拷锟杰癸拷4锟斤拷通锟斤拷*/
		return -1;
	periodns = 1000000/freKHz; /*ns*/
	dutyActu = (dutyPercent<100)?dutyPercent:100;
	temp = (unsigned long long)periodns*(unsigned long long)dutyActu;
	dutyns = (unsigned long)(temp/100);/*ns*/
	printf("dutyns=%ld  dutyActu=%ld periodns=%ld temp=%lld\n",dutyns,dutyActu,periodns,temp);
	sprintf(buf,"%d",periodns);
	sprintf(dir,"/sys/class/pwm/pwmchip%d/pwm%d/period",0,channel);
	fd = open((const char *)dir, O_WRONLY);//period
if(fd == -1)
	 {
	  printf("open channel%d period err!\n",channel);
	   return -1;
	 }
	 write(fd, (const char *)buf ,sizeof(buf)); 		
	 close(fd);
	 /*set dutyns*/
	sprintf(buf,"%d",dutyns);
	sprintf(dir,"/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle",0,channel);
	fd = open((const char *)dir, O_WRONLY);//duty
	if(fd == -1)
	 {
	 printf("open channel%d duty_cycle err!\n",channel);
	    return -1;
	 }
	 write(fd, (const char *)buf ,sizeof(buf)); 		
	 close(fd);
	 return 0;
}
int sama5dxPWMCtrl(int channel,int commad)
 {
	int fd; 
	char buf[10];
	char dir[50];
	sprintf(buf,"%d",commad);
	sprintf(dir,"/sys/class/pwm/pwmchip%d/pwm%d/enable",0,channel);
	fd = open((const char *)dir, O_WRONLY);//
	if(fd == -1)
	 {
	    printf("open channel%d enable err!\n",channel);
	   return -1;
	 }
	 write(fd, (const char *)buf ,sizeof(buf)); 		
	 close(fd);
	 return 0;
 }


void fanpwm_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "          FANPWM Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s 4 [channle] [freKHz] [dutyPercent] \n"
            "   param: \n"
            "       channle : 1-pwm1 2-pwm2 \n"
            "       freKHz : pwm frequency(Hz) 0~1000 \n"
            "       dutyPercent : pwm duty (%) 0~100\n"
            "Example:\n  %s 4 1 1000 50 (Set PWM1 frequency 1KHz duty 50% \n\n",
            program_name, program_name
           );
}


int fanpwm_test(int argc, char *argv[])
{
    char buff[100];
    int channel,freKHz,dutyPercent; 

    if(argc < 5)
    {
        std::cout << "Invalid Fanpwm number (0,..,1)!" << std::endl;
        std::cout << "Need param [channle] [freKHz] [dutyPercent]." << std::endl;
        fanpwm_usage(argv[0]);
        return -1;
    }
    
    channel= atoi(argv[2]);
    if(channel > 3)		/**/
        channel = 0;
    freKHz= atoi(argv[3]);
    if(freKHz > 1000)		/*PWM锟斤拷频锟斤拷锟斤拷锟斤拷锟斤拷1MHz*/
        freKHz = 1000;
    dutyPercent = atoi(argv[4]);
    if(dutyPercent > 100)
        dutyPercent = 100;
    sama5dxPWMInit(channel);
    sama5dxPWMConfig(channel,freKHz,dutyPercent);
    sama5dxPWMCtrl(channel,SYSFS_PWM_START);
}

#define MAXINTERFACES 16 
#define SERVER_PORT 6888

void network_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "        Network Port Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s 5 <netdevice> \n"
            "       netdevice : 0-eth0, 1-eth1, 2-eth2\n"
            "Example:\n  %s 5 0\n\n",
            program_name, program_name
           );
}
#define BUFF_LEN 1024
void handle_udp_msg(int fd)
{
    char buf[BUFF_LEN];  //鎺ユ敹缂撳啿鍖猴紝1024瀛楄妭
    socklen_t len;
    int count;
    struct sockaddr_in clent_addr;  //clent_addr鐢ㄤ簬璁板綍鍙戦€佹柟鐨勫湴鍧€淇℃伅
    while(1)
    {
        memset(buf, 0, BUFF_LEN);
        len = sizeof(clent_addr);
        count = recvfrom(fd, buf, BUFF_LEN, 0, (struct sockaddr*)&clent_addr, &len);  //recvfrom鏄嫢濉炲嚱鏁帮紝娌℃湁鏁版嵁灏变竴鐩存嫢濉?
        if(count == -1)
        {
            printf("recieve data fail!\n");
            return;
        }
        printf("client:%s\n",buf);  //鎵撳嵃client鍙戣繃鏉ョ殑淇℃伅
        sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&clent_addr, len);  //鍙戦€佷俊鎭粰client锛屾敞鎰忎娇鐢ㄤ簡clent_addr缁撴瀯浣撴寚閽?

    }
}


int network_test(int argc, char *argv[])
{

    //鍙傛暟鍒ゆ柇
    //鍒涘缓 socket锛?鎸囧畾 socket 缃戝崱
    // 鑾峰彇缃戝崱淇℃伅锛屾樉绀哄綋鍓嶄娇鐢ㄧ殑缃戝崱 IP
    // 鎻愮ず閫氫俊娈靛簲璇ユ槸鏈夌殑缃戞IP锛岃緭鍏ラ€氫俊绔?IP 鍚庡紑濮嬪缓绔嬮€氫俊
    // 寮€濮嬭繘琛屾暟鎹€氫俊
    register int socketFd, intrface, retn = 0; 
    struct arpreq arp; 
    struct ifconf ifc; 
	struct ifreq buf[4]; 
	int ret = 0;
    
    char Eth_Device[3][5] = {
        {"eth0"},
        {"eth1"},
        {"eth2"}
    };

	
	int testfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(testfd < 0)
	{
		perror("test socket :");
		std::cout << "Network : test socket error." << std::endl;
		return -1;
	}
    struct sockaddr_in ip_addr[3];
	struct ifreq if_eth;
for(int i = 0; i < 3; ++i)
		{
				strncpy(if_eth.ifr_name, Eth_Device[i], IFNAMSIZ);
				setsockopt(testfd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&if_eth, sizeof(if_eth));
				
				ret = ioctl(testfd, SIOCGIFADDR, (char *)&if_eth);
				if(ret < 0)
				{
					perror("ioctl SIOCGETFADDR : ");
					return -1;
				}
				else
				{
					std::cout << i << " Current Ip address is : " << inet_ntoa(((struct sockaddr_in*)(&if_eth.ifr_addr))->sin_addr) << std::endl;
					memcpy(&ip_addr[i], (void *)&(if_eth.ifr_addr), sizeof(struct sockaddr_in));
				}
		}

	close(testfd);

if(argc < 3)
    {
        std::cout << "Invalid Network test param." << std::endl;
        network_usage(argv[0]);
        return -1;
    }

    int index = atoi(argv[2]);
    if(index < 0 || index > 2)
    {
        std::cout << "Invalid network device number(0...2)!" << std::endl;
        return -1;
    }


    socketFd = socket(AF_INET, SOCK_DGRAM, 0);
    if(socketFd < 0)
    {
        perror("socket: ");
        std::cout << "Network : socket error." << std::endl;
        return -1;
    }
//璇疯緭鍏ラ€氫俊娈礗P鍦板潃鍙婄鍙e彿锛屽噯澶囪繘琛岄€氫俊
    std::cout << "Please connect UDP Client <default Server port " << SERVER_PORT << " > : " << std::endl;
    // struct sockaddr_in ser_addr, client_addr;
    // memset(&ser_addr, 0, sizeof(struct  sockaddr_in));
    // ser_addr.sin_family = AF_INET;
    // ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    // ser_addr.sin_port = htons(SERVER_PORT);

	ip_addr[index].sin_family = AF_INET;
	ip_addr[index].sin_port = htons(SERVER_PORT);
	
    ret = bind(socketFd, (struct sockaddr*)&ip_addr[index], sizeof(ip_addr[index]));
    if(ret < 0)
    {
        std::cout << "Network : bind fail!" << std::endl;
        return -1;
    }


	handle_udp_msg(socketFd);
    close(socketFd);

    return 0;
}
void main_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "  A Simple Device Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s <device> <param...> \n"
            "       device: \n"
            "               1 - RTC test\n"
            "               2 - DI test\n"
            "               3 - Serial test\n"
            "               4 - FANPWM test\n"
            "               5 - NETWORK UDP test\n"
            "Example:\n  %s 1 (test rtc)\n\n",
            program_name, program_name
           );
}
int main(int argc, char *argv[])
{
    if(argc < 2)
    {
        std::cout << "program param error.(need >= 2)." << std::endl;
        main_usage(argv[0]);
        return -1;
    }

    /*
    1 -- rtc 
    2 -- di 1~6
    3 -- 232/485 ttyS0~ttyS6
    4 -- pwm fan /sys/class/pwm/pwmchip0
    */

    int type = atoi(argv[1]);
    int ret = 0;

    switch(type)
{
        case 1:
            {
                //rtc test
                ret = rtc_test();
            }
            break;
        case 2:
            {
                //di test
                ret = di_test(argc, argv);
            }
            break;
        case 3:
            {
                //232/485 test
                ret = serial_test(argc, argv);
            }
            break;
        case 4:
            {
                //pwm test
                ret = fanpwm_test(argc, argv);
            }
            break;
        case 5:
            {
                //network test
                ret = network_test(argc, argv);
            }
            break;
default:
            std::cout << "not this test type! check again." << std::endl;
            ret = -1;
    }
 if(ret < 0)
    {
        std::cout << "test error. please check again." << std::endl;
        return -1;
    }

    std::cout << "test end." << std::endl;

    return 0;
}




猜你喜欢

转载自blog.csdn.net/qq_37596943/article/details/121510862