【嵌入式软件开发】芯片外设接口测试工具编写 工具主要包含如下接口功能测试 代码展示 工具主要包含如下接口功能测试 RTC时钟 rtc DIDO gpio 串口
【嵌入式软件开发】芯片外设接口测试工具编写
- 工具主要包含如下接口功能测试
- 代码展示
工具主要包含如下接口功能测试
- 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_testint 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 teststatic 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_teststruct 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 0int 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);//periodif(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 6888void 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 1024void 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;}