⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ser_filter.cpp

📁 ecos为实时嵌入式操作系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------// Test binary data transmission.// Format in://  <byte size>:<mode>// Format out://  <4 bytes binary checksum><#size bytes data>// If echo mode, also://    Format in://     <#size bytes data>//    Format out://     OK/ER - according to CRC match on incomin data// Format in://  DONE//// To Do://  o Add mode/flag specifying 5-8 bit transfer.//     Test that 0xff gets masked off accordingly when transfered.//     (This should be an INFO result if failing)//  o Clean up the DUPLEX_ECHO implementation. Currently it's an ugly hack//    that doesn't match the arguments / behavior of the two other modes.voidtest_binary(CeCosTestSerial &pSer, char* args){    int size;    cyg_mode_t mode;    unsigned char *data_out, *data_in;    int i;    int crc;    int loop_count = 0;    INIT_VALUE(args);    SET_VALUE(int, size);    SET_VALUE(cyg_mode_t, mode);    // Change behavior for DUPLEX mode.    if (MODE_DUPLEX_ECHO == mode) {        loop_count = size;        size = 1024;                    // must be at least 4*block_size    }    // Generate data.    data_out = (unsigned char*) malloc(size);    if (!data_out) {        fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);        throw "data_out malloc failed";    }    data_in = (unsigned char*) malloc(size);    if (!data_in) {        fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);        throw "data_in malloc failed";    }    for (i = 0; i < size; i++) {        static int count = 0;        unsigned char c = (unsigned char) (count++ & 0xff);        // don't allow $s and @s in the data, nor 0x03 (GDB C-c)        if ('$' == c || '@' == c || 0x03 == c)            c = (unsigned char) '*';        data_out[i] = c;    }    // Do checksum.    crc = do_crc(data_out, size);    // Send checksum to target.    send_checksum(pSer, crc);    switch (mode) {    case MODE_NO_ECHO:    {        // Simple transmit. Don't expect target to echo data back.        target_write(pSer, data_out, size);        receive_done(pSer, NULL, 0);    }    break;    case MODE_EOP_ECHO:    {        int in_crc;        target_write(pSer, data_out, size);        // Expect target to echo the data        target_read(pSer, data_in, size);        // Check echoed data, and reply OK/ER accordingly.        in_crc = do_crc(data_in, size);        send_status(pSer, (in_crc == crc));        // Dump seen/expected on console.        if (in_crc != crc) {            trace("Data seen:\n");            print_hex(data_in, size);            trace("<end>\n");            trace("Data expected:\n");            print_hex(data_out, size);            trace("<end>\n");        }        receive_done(pSer, data_in, size);    }    break;    case MODE_DUPLEX_ECHO:    {        int block_size = 64;        int fail, j;        // This is a simple implementation (maybe too simple).        // Host sends 4 packets with the same size (64 bytes atm).        // Target echoes in this way:        //  packet1 -> packet1        //  packet2 -> packet2, packet2        //  packet3 -> packet3        //  packet4 -> /dev/null        //        // The reads/writes are interleaved in a way that should ensure        // the target out buffer to be full before the target starts to read        // packet3. That is, the target should be both receiving (packet3)        // and sending (packet2) at the same time.        // This code needs restructuring. It's not very obvious what's        // happening: The same block of data is output several times,        // the target echoes the data back (one of the blocks is        // echoed twice). Then the echoed data is compared agains the        // outgoing data block.        fail = 0;        while (loop_count--) {            int i;            for (i = 0; i < block_size*4; i++)                data_in[i] = 0;            // out1: block_size -> block_size            target_write(pSer, data_out, block_size);            // out2: block_size -> 2 x block_size            target_write(pSer, data_out, block_size);            // in1:            target_read(pSer, data_in, block_size);            // out3: block_size -> block_size            target_write(pSer, data_out, block_size);                    // in2:            target_read(pSer, &data_in[block_size], 2*block_size);            // out4: block_size -> 0            target_write(pSer, data_out, block_size);                    // in3:            target_read(pSer, &data_in[block_size*3], block_size);            if (0 == loop_count % 10)                trace("%d loops to go\n", loop_count);            // Verify data.            if (!fail) {                for (j = 0; j < 4 && !fail; j++) {                    for (i = 0; i < block_size && !fail; i++) {                        if (data_out[i] != data_in[j*block_size + i]) {                            fail = 1;                            trace("Failed at byte %d\n", j*block_size + i);                                                        trace("Data seen:\n");                            print_hex(&data_in[j*block_size],                                            block_size);                            trace("<end>\n");                            trace("Data expected:\n");                            print_hex(data_out, block_size);                            trace("<end>\n");                        }                    }                }            }        }        // Check echoed data, and reply OK/ER accordingly.        send_status(pSer, (!fail));        receive_done(pSer, data_in, block_size*4);    }    break;    default:        trace("Unknown mode. Ignoring.\n");    }    // Free buffer.    free(data_in);    free(data_out);}//-----------------------------------------------------------------------------// Test transformations on text transmissions//// This test transmits null-terminated C strings back and forth. Since// the translation is under test and may fail, the length of the data is// (potentially) unknown. Sending with a null-terminator allows proper// recovery even if the translations do not work as intended.//// Format in://  <flags>!<4 bytes binary checksum><C string>// Format out://  <C string>//  OK/ER//// Mode://   MODE_EOP_ECHO://       Receive data, verify CRC, resend data.//       Send OK/ER reply when done.//   MODE_DUPLEX_ECHO://       Receive data, echo data, verify CRC.//       Send OK/ER reply when done.//// To Do://  Implement.voidtest_text(CeCosTestSerial &pSer, char* args){    CYG_UNUSED_PARAM(char*, args);    send_status(pSer, 1);}//-----------------------------------------------------------------------------// Reply to PING packet from target.// Format in://  "!"// Format out://  OKvoidtest_ping(CeCosTestSerial &pSer, char* args){     CYG_UNUSED_PARAM(char*, args);    send_status(pSer, 1);}//-----------------------------------------------------------------------------// Dispatch test command. voiddispatch_command(CeCosTestSerial &pSer, char* cmd){    char* args;    args = strchr(cmd, (int) ':');    if (!args) {        trace("Bogus command (%s) Ignoring.\n", cmd);        return;    }            *args++ = 0;    trace("Dispatching command %s.\n", cmd);    if (0 == strcmp("CONFIG", cmd)) {        change_config(pSer, args);    }     else if (0 == strcmp("DEFCONFIG", cmd)) {        // Note: Currently the arguments are ignored. 9600 8N1 is default.        default_config(pSer);    }    else if (0 == strcmp("BINARY", cmd)) {        test_binary(pSer, args);    }    else if (0 == strcmp("TEXT", cmd)) {        test_text(pSer, args);    }    else if (0 == strcmp("PING", cmd)) {        test_ping(pSer, args);    }    else        trace("Unknown command '%s'.\n", cmd);    trace("Command %s completed.\n", cmd);}bool CALLBACKserial_filter(void*& pBuf,              unsigned int& nRead,              CeCosTestSerial& serial,              CeCosTestSocket& socket,              void* pParem){    ser_filter_state_t* state = (ser_filter_state_t*) pParem;    char* buffer = (char*) pBuf;    // Don't do anything in the null_filter mode.    if (state->null_filter)        return true;    // Allows trace to be called without a reference to the socket...    gdb_socket = &socket;    // This allows the filter to unwind, wherever in the protocol it    // may be, when a $ is detected from the target side.    // When this happens, we may have a trap/exception on the target    // and we want the user to access the target via GDB without    // intervention.    recover_data_len = 0;    state->null_filter = setjmp(fallback_buf) ? true : false;    if (state->null_filter) {        if (recover_data_len) {            unsigned char *s, *d;            d = (unsigned char*) pBuf;            s = (unsigned char*) recover_data;            for (int i = 0; i < recover_data_len; i++)                *d++ = *s++;        }        nRead = recover_data_len;        return true;    }    if (opt_ser_debug && state->first_command_seen)        print_hex((unsigned char*) buffer, nRead);    // Command handling.    // If we are not presently reading a command, look for the    // start marker.    unsigned int i = 0;    if (!state->cmd_flag)        for (; i < nRead; i++) {            if ('@' == buffer[i]) {                state->cmd_flag = 1;                // Send the data before the marker.                if (i)                    socket.send(buffer, i);                break;            }        }    // If reading a command, look for the end marker.    if (state->cmd_flag) {        char c = 0;        while (i < nRead && state->cmd_i < MAX_CMD_LEN) {            c = buffer[i++];            state->cmd[state->cmd_i++] = c;            if ('!' == c) {                if (i != nRead) {                    // Hopefully, we'll never have to cope                     // with this.                    fprintf(stderr,                             "Yikes! We need to unread %d bytes!\n",                            nRead - i);                    throw "Yikes! We need to unread some bytes!";                }                break;            }        }        if (MAX_CMD_LEN == state->cmd_i) {            trace("Received too long command. Ignoring it!\n");            state->cmd_i = 0;            state->cmd_flag = 0;        } else if ('!' == c) {            // Was the command completed?            state->cmd[state->cmd_i - 1] = 0; // terminate cmd            state->cmd_i = 0;            state->cmd_flag = 0;            state->first_command_seen = true;            // skip @ when passing ptr            dispatch_command(serial, &state->cmd[1]);        }        nRead = 0;                      // Never leave anything for caller                                        // This is a violation of the intended                                        // filter function behavior.    }    return true;}#ifdef DEFINE_MAINvoidno_gdb(const char* pszPort, int nBaud, FilterFunc *pSerialToSocketFilterFunc,       void *pParam, bool *pbStop){    trace("no_gdb, listening on %s\n",pszPort);    CeCosTestSocket dummy_socket;    CeCosTestSerial serial;    serial.SetBlockingReads(false);    bool rc=false;    // Open serial device.    if (!serial.Open(pszPort,nBaud)){        ERROR("Couldn't open port %s\n",pszPort);    } else {        // Flush the serial buffer.        serial.Flush();        serial.ClearError();        enum {BUFSIZE=8192};        void *pBuf=malloc(BUFSIZE);        rc=true;        while(rc && (0==pbStop || !(*pbStop))){            unsigned int nRead=0;            while (1) {                if(serial.Read(pBuf,BUFSIZE,nRead)){                    if(nRead>0){                        break;                    }                    CeCosTestUtils::Sleep(1);                } else {                    trace("Serial read failed (%d)\n", errno);                }            }            trace("Serial:%d\n",nRead);            if(pSerialToSocketFilterFunc){                rc=pSerialToSocketFilterFunc(pBuf,nRead,serial,dummy_socket,                                             pParam);            }        }        free(pBuf);    }}intmain(int argc, char** argv){    int nSock = 0;    int baud_rate, nTcpPort;    int opt_no_gdb = 0;    char* ser_port;    int i=1;    while(i<argc){        if(argv[i][0]=='-'){            switch(argv[i][1]){                case 't':                    CeCosTestUtils::EnableTracing(true);                    break;                case 'S':                    opt_ser_debug = 1;                    break;                case 'n':                    opt_no_gdb = 1;                    break;                case 'c':                    opt_console_output = 1;                    break;                default:                    fprintf(stderr,"Unrecognized switch %s\n",argv[i]);                    goto Usage;                    break;            }            for(int j=i;j<argc;j++){                argv[j]=argv[j+1];            }            argc--;            argv[argc]=0;        } else {            i++;        }    }    if(!((3==argc && opt_no_gdb) || (4==argc && !opt_no_gdb)))    {        goto Usage;    }    if (opt_no_gdb) {        ser_port = argv[1];        baud_rate=atoi(argv[2]);    } else {        nTcpPort=atoi(argv[1]);        if(0==nTcpPort){            fprintf(stderr,"Invalid port %s\n",argv[1]);            return main(0,argv); // Provoke usage message        }        ser_port = argv[2];        baud_rate=atoi(argv[3]);        nSock = CeCosTestSocket::Listen(nTcpPort);        if (-1 == nSock) {            fprintf(stderr, "Couldn't access socket.\n");            throw "listen failed";        }    }    while (1) {        ser_filter_state_t state;        gdb_socket = NULL;            try {            if (opt_no_gdb)                no_gdb(ser_port, baud_rate, &serial_filter, &state, NULL);            else                ConnectSocketToSerial(nSock, ser_port, baud_rate,                                       &serial_filter, NULL, &state, NULL);        }         catch (const char* p) {            trace("Caught filter crash: %s\n", p);        }    }    return 0;Usage:    const char *pszMe=CeCosTestUtils::Tail(argv[0]);    fprintf(stderr,"Usage: %s [-t -c -S] TcpIPport SerialPort BaudRate\n",    //                                   1         2          3            pszMe);    fprintf(stderr," or:   %s -n [-t -c -S] SerialPort BaudRate\n",    //                                      1          2            pszMe);    fprintf(stderr, " -t: Enable tracing.\n");    fprintf(stderr, " -S: Output data read from serial line.\n");    fprintf(stderr, " -c: Output data on console instead of via GDB.\n");    fprintf(stderr, " -n: No GDB.\n");    return 1;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -