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

📄 ser_filter.cpp

📁 ecos为实时嵌入式操作系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=================================================================////        ser_filter.cxx////        Serial test filter////=================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License.  You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus.  Portions created// by Cygnus are Copyright (C) 1998, 1999 Cygnus Solutions.// All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s):     jskov// Contributors:  jskov// Date:          1999-03-01// Description:   This program acts as a filter between GDB and the test//                running on the target, allowing testing of the serial//                driver without confusing GDB.// Usage:         Run the program with one argument, the serial port//                on with the target is connected.//                Run serial test in GDB, connecting to the target with//                'target remote localhost:5678'.//// To Do://  o Add timeout setup and handling for recovery, can rely on testing//    agent to control global timeout.//  o Saving chunks that caused transfer failure?//     - In SEND with echo, do CRC on 32-byte sub-packets//  o Additional To Do items under each sub-protocol function.//  o Option to get all serial IO written (in hex, > and < prepends //    input/output lines) to a file.//  o Clean up the mess in this file....//####DESCRIPTIONEND#####include "stdafx.h"#include "eCosTest.h"#include "eCosTestSocket.h"#include "eCosTestSerial.h"#include <setjmp.h>#ifdef _WIN32#define CYG_UNUSED_PARAM( _type_, _name_ ) _name_#else#define CYG_UNUSED_PARAM( _type_, _name_ ) {    \  _type_ __tmp1 = (_name_);                     \  _type_ __tmp2 = __tmp1;                       \  __tmp1 = __tmp2;                              \}#endif// This gets uglier and uglier...CeCosTestSocket* gdb_socket;int opt_ser_debug = 0;int opt_console_output = 0;jmp_buf fallback_buf;enum {MAX_CMD_LEN=128};struct ser_filter_state_t {    bool null_filter;    int cmd_i;    int cmd_flag;    char cmd[MAX_CMD_LEN];    // We need this to avoid outputting serial tracing while GDB is trying to    // connect, or it will get confused.    bool first_command_seen;    ser_filter_state_t() :        null_filter(0),        cmd_i(0),        cmd_flag(0),        first_command_seen(0)        {}};typedef struct ser_cfg {    int baud_rate;    int data_bits;    CeCosTestSerial::StopBitsType stop_bits;    bool parity;    // etc...} ser_cfg_t;typedef enum {    MODE_NO_ECHO = 0,    MODE_EOP_ECHO,    MODE_DUPLEX_ECHO} cyg_mode_t;char msg_ok[] = "OK";char msg_er[] = "ER";//----------------------------------------------------------------------------// Macros to help extract values from the argument string.// Note: This is probably not an ideal solution, but it was easy to make :)#define INIT_VALUE(__args)                      \    unsigned int v;                             \    char *__ptr1, *__ptr2 = (__args)#define SET_VALUE(__type, __slot)               \{                                               \    __ptr1 = strchr(__ptr2, (int) ':');         \    if (__ptr1)                                 \        *__ptr1 = 0;                            \    v = atoi(__ptr2);                           \    __ptr2 = __ptr1+1;                          \    (__slot) = (__type) v;                      \}//------------------------// Output helpers.// Encode string in an O-packet and send it to GDB.void gdb_write(const char* pszStr){    if (gdb_socket) {        static const char hexchars[] = "0123456789abcdef";        char* packet = new char[strlen(pszStr)*2+6];        char* p = packet;        *p++ = '$';        *p++ = 'O';        unsigned char crc = 'O';        char c;        for (;;) {            c = *pszStr++;            if (0 == c)                break;            char h = hexchars[(c >> 4) & 0x0f];            char l = hexchars[c & 0x0f];            *p++ = h;            *p++ = l;            crc = (unsigned char) (crc + h + l);        };        *p++ = '#';        *p++ = hexchars[(crc >> 4) & 0x0f];        *p++ = hexchars[crc & 0x0f];                // Only try to send once. If it fails, it's probably because        // GDB has disconnected.        gdb_socket->send(packet, p - packet);        gdb_socket->recv(&c, 1);        delete [] packet;    }}voidconsole_write(const char* pszStr){    fputs(pszStr, stderr);    fflush(stderr);}voidtrace(const char* pszFormat, ...){    va_list marker;    va_start (marker, pszFormat);    CeCosTestUtils::String str;    str.vFormat(pszFormat,marker);    va_end (marker);    // Prefix with [f]    CeCosTestUtils::String str2("[f] ");    str2 += str;    if (opt_console_output)        console_write((const char*) str2);    else        gdb_write((const char*) str2);}voidprint_hex(unsigned char* d1, int len){    int offset = 0;    int i;    char buf[128];    int width = 8;    while (len) {        int count = min(width, len);        char* p = buf;        p += sprintf(p, "%04x ", offset);        // Print hex values.        for (i = 0; i < count; i++)            p += sprintf(p, "%02x ", d1[i]);        for (     ; i < width   ; i++)            p += sprintf(p, ".. ");        // Print ASCII string        p += sprintf(p, "'");        for (i = 0; i < count; i++) {            int c = d1[i];            if (' ' >= c || 'z' <= c)                c = '.';            p += sprintf(p, "%c", c);        }        sprintf(p, "'\n");        trace("%s", buf);                len -= count;        offset += count;        d1 += count;    }}voidtarget_write(CeCosTestSerial &pSer, const unsigned char* buffer, int len){    unsigned int __written;    do {        if (!(pSer.Write((void*) buffer, len, __written))) {            fprintf(stderr, "Writing %d bytes to serial failed\n", len);            fprintf(stderr, strerror(errno));            throw "serial write failed";        }        buffer += __written;        len -= __written;    } while (len);}// Yuck! There is probably a better way to do this...void* recover_data;int   recover_data_len;booltarget_read(CeCosTestSerial &pSer, unsigned char* buffer, int len){    unsigned int __read;    int __total_read = 0;    unsigned char* __buffer_base = buffer;    int __timeouts = 0;    int __timeout_failure = 0;    do {        if (!(pSer.Read((void*) buffer, len, __read))) {            fprintf(stderr,"Reading %d bytes from serial failed (read %d).\n",                    len, __read);            fprintf(stderr, strerror(errno));            throw "serial read failed";        }        __total_read += __read;        unsigned int i;        for (i = 0; i < __read; i++) {            if ('$' == buffer[i]) {                trace("**** Detected $ -- resuming as null filter ****\n");                trace("Data received %d bytes (of %d) from target:\n",                       __total_read, len);                print_hex(__buffer_base, __total_read);                trace("<end>\n");                recover_data = (void*) &buffer[i];                recover_data_len = __read - i;                longjmp(fallback_buf, 1);            }        }        if (0 == __read) {            CeCosTestUtils::Sleep(20);            __timeouts++;            if (25 == __timeouts) {                __timeouts = 0;                if (5 == __timeout_failure++) {                    trace("**** Timed out while reading -- resuming as null filter\n");                    trace("Data received %d bytes (of %d) from target:\n",                           __total_read, len);                    print_hex(__buffer_base, __total_read);                    trace("<end>\n");                    static const char kill_msg[] = "$X00#b8";                    recover_data_len = strlen(kill_msg);                    recover_data = (void*) kill_msg;                    longjmp(fallback_buf, 2);                }            }        } else {            __timeouts = 0;            __timeout_failure = 0;        }        buffer += __read;        len -= __read;    } while (len);    return true;}// Send C ASCII string to target.void target_ASCII_write(CeCosTestSerial &pSer, const char* s) {     target_write(pSer, (const unsigned char*) s, strlen(s)); };//------------------------// Configuration Command.void parse_config(char* cfg_str, ser_cfg_t* new_cfg);void change_config(char* cfg_str);// Return false if the serial configuration is not valid for the host.int verify_config(ser_cfg_t* cfg){    CYG_UNUSED_PARAM(ser_cfg_t*, cfg);    // FIXME: Assume OK for now.    return 1;}// Set serial configuration.voidset_config(CeCosTestSerial &pSer, const ser_cfg_t* cfg){    pSer.SetBaud(cfg->baud_rate, false);    pSer.SetParity(cfg->parity, false);    pSer.SetDataBits(cfg->data_bits, false);    pSer.SetStopBits(cfg->stop_bits, true); // apply settings}// Set default serial configuration.void default_config(CeCosTestSerial &pSer);//-----------------------------------------------------------------------------// Change serial configuration.// To Do://   Proper (full) implementation.voidchange_config(CeCosTestSerial &pSer, char* cfg_str){    ser_cfg_t new_cfg;    parse_config(cfg_str, &new_cfg);    if (verify_config(&new_cfg)) {        target_ASCII_write(pSer, "OK");        set_config(pSer, &new_cfg);    } else {        target_ASCII_write(pSer, "ER");    }}// Set default configuration.voiddefault_config(CeCosTestSerial &pSer){    static const ser_cfg_t default_ser_cfg = { 9600,                                                8,                                                CeCosTestSerial::ONE,                                                false };    target_ASCII_write(pSer, "OK");    set_config(pSer, &default_ser_cfg);}// Parse config string from target and set new_cfg accordingly.// String from target is://  <baud rate>:<data bits>:<stop bits>:<parity>:....voidparse_config(char* args, ser_cfg_t* new_cfg){    int ecos_parity, ecos_stop_bits, ecos_baud_rate;    CeCosTestSerial::StopBitsType t2h_stop_bits[3] = {        CeCosTestSerial::ONE,         CeCosTestSerial::ONE_POINT_FIVE,        CeCosTestSerial::TWO};    INIT_VALUE(args);    SET_VALUE(int, ecos_baud_rate);    SET_VALUE(int, new_cfg->data_bits);    SET_VALUE(int, ecos_stop_bits);    SET_VALUE(int, ecos_parity);    new_cfg->parity = (ecos_parity) ? true : false;    new_cfg->stop_bits = t2h_stop_bits[ecos_stop_bits - 1];    // eCos->human translation of serial baud rate. This table must    // match the one in io/serial/current/include/serialio.h    static const int tt_baud_rate[] = {        -1,                                 // 0 invalid        50,                                 // 1 50        75,                                 // 2 75        110,                                // 3        135,                                // 4 134_5        150,                                // 5        200,                                // 6 200        300,                                // 7        600,                                // 8        1200,                               // 9        1800,                               // 10 1800        2400,                               // 11        3600,                               // 12 3600        4800,                               // 13        7200,                               // 14 7200        9600,                               // 15        14400,                              // 16 14400        19200,                              // 17        38400,                              // 18        57600,                              // 19        115200,                             // 20        234000                              // 21 234000    };    if (ecos_baud_rate > 0 && ecos_baud_rate < (int) sizeof(tt_baud_rate))        ecos_baud_rate = tt_baud_rate[ecos_baud_rate];    else        ecos_baud_rate = -2;    new_cfg->baud_rate = ecos_baud_rate;}// Always make sure CRC fits in 31 bits. Bit of a hack, but we want// to send CRC as ASCII without too much hassle.intdo_crc(unsigned char* data, int size){    int i;    unsigned long crc;    for (i = 0, crc = 0; i < size; i++) {        crc = (crc << 1) ^ data[i];     // FIXME: standard definition?    }    i = (int) crc;    if (i < 0)        i = -i;    return i;}voidsend_checksum(CeCosTestSerial &pSer, int crc){    char buffer[128];    int len;    len = sprintf(buffer, "%d!", crc);    target_write(pSer, (const unsigned char*)buffer, len);}voidsend_status(CeCosTestSerial &pSer, int state){    if (state)        target_write(pSer, (unsigned char*) &msg_ok, 2);    else        target_write(pSer, (unsigned char*) &msg_er, 2);}// Receive test DONE message from target.voidreceive_done(CeCosTestSerial &pSer, unsigned char* data_in, int size){    static const char msg_done[] = "DONE";    unsigned char data_reply[4];    int first = 1;    target_read(pSer, data_reply, 4);    while (0 != strncmp((char*) data_reply, msg_done, 4)) {        if (first) {            if (data_in && size) {                trace("Data received from target:\n");                print_hex(data_in, size);                trace("<end>\n");            }            trace("Receiving junk instead of DONE:\n");            first = 0;        }        print_hex(data_reply, 4);        data_reply[0] = data_reply[1];        data_reply[1] = data_reply[2];        data_reply[2] = data_reply[3];        // The target_read call will handle recovery in case of timeout...        target_read(pSer, &data_reply[3], 1);    }}

⌨️ 快捷键说明

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