0
点赞
收藏
分享

微信扫一扫

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


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

  • ​​工具主要包含如下接口功能测试​​
  • ​​代码展示​​

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

  • 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;
}


举报

相关推荐

0 条评论