[Setup] 配置网络IP ${local_ip}
SERIAL通过串口发送字符 "mount;echo RESULT:$?\\r\\n"
${data} SERIAL等待字符串 RESULT:0
Should Contain ${data} /dev/mmcblk3p5 on /home/apps type ext4 (rw,relatime,data=ordered)
SERIAL执行sh命令 tftp -gr ltp.sq.tar.bz2 ${tftp_server} 3000 100ms @1
SERIAL执行sh命令 tar -xjf ltp.sq.tar.bz2 -C /home/apps/ 3000 100ms
SERIAL通过串口发送字符 "cd /home/apps/;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "tftp -gr app.sh 192.168.1.1;echo RESULT:$?\\r\\n" @2
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "chmod +x app.sh;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "sed -i '/usr\\/bin\\/bcm8953xspiutil/i\/home/apps/app.sh' /etc/zstart;echo RESULT:$?\\r\\n" @3
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "sync;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SERIAL断开串口
SSH登录 127.0.0.1 root ${nfs_passwd}
${zserial_ret} SSH执行命令 /var/lib/tftpboot/zserial_reboot "/dev/ttyUSB0" 115200 "console_init" "app start" @4
${time_line} Get Lines Containing String ${zserial_ret} the boot take time total
${boot_time} Split String ${time_line}
${ret} SSH执行命令 /var/lib/tftpboot/cmpLittle.sh ${boot_time[5]} 3 @5
Should Contain ${ret} YES
SERIAL初始化串口 ${port} ${baudrate}
SERIAL通过串口发送字符 "\\r\\n"
SERIAL等待字符串 saic_imx6d_fota login:
SERIAL通过串口发送字符 "root\\r\\n"
SERIAL等待字符串 root@saic_imx6d_fota:
SERIAL通过串口发送字符 "sed -i '/\\/home\\/apps\\/app.sh/d' /etc/zstart;echo RESULT:$?\\r\\n" @6
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "rm /home/apps/app.sh;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "rm ltp.sq.tar.bz2;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SERIAL通过串口发送字符 "rm -rf home/apps/ltp.sq/;echo RESULT:$?\\r\\n"
SERIAL等待字符串 RESULT:0
SSH断开连接
备注:不用关注细节的封装(如SERIAL通过串口发送字符、SSH登录),只看流程。
@1:传入ltp压缩包并不是要做LTP测试,只是为了增加mmc使用率,来延长启动时间。
@2:app.sh为简单的打印字符串,方便利用工具抓取来测试启动时间;
cat app.sh:
#!/bin/sh
echo "app start"
@3:通过sed命令编辑启动脚本zstart,在“/usr/bin/bcm8953xspiutil”前面一行加上“/home/apps/app.sh”
@4:通过工具zserial_reboot抓取串口输出,测试启动时间,源代码见附件1
@5:通过shell脚本比较启动时间,小于3s打印YES;
cat cmpLittle.sh
#!/bin/bash
echo "$1 $2"|awk '{if ($1 < $2) print "YES"; else print "NO"}'
@6:用例恢复,删除在启动脚本zstart中增加的文本行
附件1:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
static int fd_serial = 0;
int openComm(const char* port)
{
int fd = -1;
printf("serial device : %s\n", port);
fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd < 0){
printf("open %s failed\n", port);
return -1;
}
//阻塞读取
if(fcntl(fd,F_SETFL,0) < 0){
printf("fcntl failed\n");
}
else{
printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
}
//测试是否为终端设备
#if 0
if(0 == isatty(STDIN_FILENO))
{
printf("standard input is not a terminal device\n");
close(fd);
return -1;
}
#endif
//printf("fd->open=%d\n",fd);
return fd;
}
int setComm(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)
{
int i;
int status;
int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300};
struct termios old_options;
struct termios options;
printf("fd:%d, speed:%d, flow_ctrl:%d, databits:%d, stopbits:%d, parity:%c\n", fd, speed, flow_ctrl, databits, stopbits, parity);
if( tcgetattr( fd, &old_options) != 0)
{
perror("serial cfg failed\n");
return -1;
}
bzero(&options, sizeof(options));
//修改控制模式,保证程序不会占用串口
options.c_cflag |= CLOCAL;
//修改控制模式,使得能够从串口中读取输入数据
options.c_cflag |= CREAD;
//设置串口输入波特率和输出波特率
status = 0;
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
if(tcsetattr(fd, TCSANOW, &options) != 0)
{
perror("tcsetattr fd failed");
return -1;
}
tcflush(fd, TCIOFLUSH);
status = 1;
break;
}
}
if(status == 0){
printf("no %d speed, set default speed 115200\n", speed);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
}
//设置数据流控制
switch(flow_ctrl)
{
case 0 ://不使用流控制
options.c_cflag &= ~CRTSCTS;
break;
case 1 ://使用硬件流控制
options.c_cflag |= CRTSCTS;
break;
case 2 ://使用软件流控制
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
//设置数据位
options.c_cflag &= ~CSIZE; //屏蔽其他标志位
switch (databits)
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return -1;
}
//设置校验位
switch (parity)
{
case 'n':
case 'N': //无奇偶校验位。
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O'://设置为奇校验
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E'://设置为偶校验
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's':
case 'S': //设置为空格
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return -1;
}
// 设置停止位
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return -1;
}
//设置最少字符和等待时间
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
//激活配置 (将修改后的termios数据设置到串口中)
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("set serial config error!\n");
return -1;
}
return 0;
}
void closeComm(int fd)
{
close(fd);
}
int readComm(int fd, char *rcv_buf, int data_len)
{
int len;
len = read(fd, rcv_buf, data_len);
return len;
}
int writeComm(int fd, char *send_buf, int data_len)
{
int len = 0;
len = write(fd, send_buf, data_len);
if (len == data_len )
{
return len;
}
tcflush(fd,TCOFLUSH);
return -1;
}
#define LINE_BUF_SIZE 512
#define READ_BUF_SIZE 1024
int send_cmd(int fd_serial, char *cmd_buf, int cmd_len, char *recv_buf, int recv_len)
{
char read_buf[READ_BUF_SIZE];
char line_buf[LINE_BUF_SIZE];
int ret = 0;
int index = 0;
int i = 0;
int flag = 0;
writeComm(fd_serial, cmd_buf, cmd_len);
if(recv_len == 0 || recv_buf == NULL)
return 0;
index = 0;
memset(read_buf, 0x0, READ_BUF_SIZE);
while(1)
{
ret = readComm(fd_serial, read_buf + index, READ_BUF_SIZE - index);
if(ret > 0){
index = index + ret;
//printf("==>index:%d ret:%d recv_len:%d read_buf:[%s]\n", index, ret, recv_len, read_buf);
if(index < recv_len){
continue;
}
for(i = 0; i < index - recv_len; i++){
if(0 == strncmp(read_buf + i, recv_buf, recv_len)){
//printf("==>[found]\n");
return 0;
}
}
if(index >= READ_BUF_SIZE)
index = 0;
}
}
return 0;
}
int send_reboot(int fd_serial)
{
char cmd_buf[10];
char recv_buf[40];
printf("==> start reboot\n");
cmd_buf[0] = 'r';
cmd_buf[1] = 'e';
cmd_buf[2] = 'b';
cmd_buf[3] = 'o';
cmd_buf[4] = 'o';
cmd_buf[5] = 't';
cmd_buf[6] = '\r';
cmd_buf[7] = '\n';
send_cmd(fd_serial, cmd_buf, 8, NULL, 0);
/*
//ctrl+d
cmd_buf[0] = 4;
strcpy(recv_buf, "kdb:");
send_cmd(fd_serial, cmd_buf, 1, recv_buf, strlen(recv_buf));
//^
cmd_buf[0] = 94;
strcpy(recv_buf, "Return reboots");
send_cmd(fd_serial, cmd_buf, 1, recv_buf, strlen(recv_buf));
// \r\n
cmd_buf[0] = '\r';
cmd_buf[1] = '\n';
send_cmd(fd_serial, cmd_buf, 2, NULL, 0);
*/
return 0;
}
//#define TEST_DEBUG 1
int main(int argc, char **argv)
{
char read_buf[READ_BUF_SIZE];
char read_buf_2[READ_BUF_SIZE];
int i = 0;
int ret = 0;
int bart = 0;
struct timeval tv_start, tv_current;
int total_time;
char line_buf[LINE_BUF_SIZE];
int index;
int index_2;
char *start = NULL;
char *end = NULL;
#ifdef TEST_DEBUG
char test_buf[2048];
int test_index = 0;
memset(test_buf, 0x0, 2048);
#endif
if (argc < 3){
printf("please input param\n");
printf("zserial device bart [start] [end]\n");
printf(" eg:./zserial /dev/ttyUSB0 115200 \"console_init\" \"kzb start\"\n");
return -1;
}
fd_serial = openComm(argv[1]);
if(fd_serial < 0){
return -1;
}
bart = atoi(argv[2]);
printf("open %s %d\n", argv[1], bart);
if(setComm(fd_serial, bart, 0, 8, 1, 'N') < 0){
closeComm(fd_serial);
return -1;
}
if(argc >= 4)
start = argv[3];
if(argc >= 5)
end = argv[4];
send_reboot(fd_serial);
memset(line_buf, 0x0, LINE_BUF_SIZE);
index = 0;
gettimeofday(&tv_start, 0);
while(1)
{
memset(read_buf, 0x0, READ_BUF_SIZE);
ret = readComm(fd_serial, read_buf_2, READ_BUF_SIZE);
if(ret > 0){
index_2 = 0;
for(i = 0; i < ret; i++){
if(read_buf_2[i] != 0){
read_buf[index_2++] = read_buf_2[i];
}
}
ret = index_2;
if(ret < 1)
continue;
#ifdef TEST_DEBUG
if(test_index + ret < 2048){
memcpy(test_buf + test_index, read_buf, ret);
test_index += ret;
}else{
printf("==> test_index:%d ret:%d\n", test_index, ret);
}
#endif
if(index + ret > LINE_BUF_SIZE){
ret = LINE_BUF_SIZE - index;
}
memcpy(line_buf + index, read_buf, ret);
index += ret;
if(index >= LINE_BUF_SIZE || line_buf[index -1] == '\n')
{
//去除空行
if(index == 2 && line_buf[0] == 0xd){
index = 0;
memset(line_buf, 0x0, LINE_BUF_SIZE);
continue;
}
if(line_buf[0] == 0xd)
line_buf[0] = ' ';
if(start){
//printf("{%c}", line_buf[0]);
if(0 == strncmp(line_buf,start,strlen(start))){
gettimeofday(&tv_start, 0);
}
}
gettimeofday(&tv_current, 0);
total_time = (tv_current.tv_sec - tv_start.tv_sec) * 1000000L;
total_time += tv_current.tv_usec - tv_start.tv_usec;
printf("[%f] %s", (double)total_time / 1000000, line_buf);
if(end){
if(0 == strncmp(line_buf,end,strlen(end))){
printf("the boot take time total: %f\n", (double)total_time / 1000000);
break;
}
}
index = 0;
memset(line_buf, 0x0, LINE_BUF_SIZE);
}
}
}
closeComm(fd_serial);
#ifdef TEST_DEBUG
printf("\n=====================================\n");
for(i = 0; i < test_index; i++){
if(test_buf[i]>= 'a' && test_buf[i] <= 'z' || test_buf[i] == '#'){
printf("[%d]%c\n", i, test_buf[i]);
}else{
printf("[%d]%x\n", i, test_buf[i]);
}
}
printf("=====================================\n");
#endif
return 0;
}