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

📄 ecostestserialfilter.cpp

📁 基于ecos的redboot
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    pSer.SetBaud(new_cfg->baud_rate, false);
    pSer.SetParity(new_cfg->parity, false);
    pSer.SetDataBits(new_cfg->data_bits, false);
    pSer.SetXONXOFFFlowControl((new_cfg->flags&FLOW_XONXOFF_RX) != 0, false);
    pSer.SetRTSCTSFlowControl((new_cfg->flags&FLOW_RTSCTS_RX) != 0, false);
    pSer.SetDSRDTRFlowControl((new_cfg->flags&FLOW_DSRDTR_RX) != 0, false);
    return pSer.SetStopBits(new_cfg->stop_bits, true); // apply settings
}

// Return false if the serial configuration is not valid for the host.
bool
CeCosTestSerialFilter::VerifyConfig(CeCosSerial &pSer, ser_cfg_t* new_cfg)
{
    ser_cfg_t old_cfg;
    bool rc;

    // Try changing to the new config, recording the result. Then restore
    // the original config.
    rc = SetConfig(pSer, new_cfg, &old_cfg);
    SetConfig(pSer, &old_cfg, NULL);

    return rc;
}

//-----------------------------------------------------------------------------
// Configuration changing function.
//
// First change to the new config and back again to determine if the driver
// can handle the config.
// If not, return error.
//
// Then query the host for its capability to use the config:
// Format out:
//  "@CONFIG:<baud rate code>:<#data bits>:<#stop bits>:<parity on/off>!"
// Format in:
//  OK/ER
//
// On ER, return error.
//
// On OK, change to the new configuration. Resynchronize with the host:
//  Target waits for host to send S(ync) 
//     [host will delay at least .1 secs after changing baud rate so the 
//      line has time to settle.]
//
//  When receiving S(ync), target replies OK to the host which then
//  acknowledges with D(one).
//
//  Host can also send R(esync) which means it didn't receieve the OK. If
//  so the target resends its S(ync) message.
//
// If the synchronization has not succeeded within 1 second
// (configurable in the protocol), both host and target will revert to
// the previous configuration and attempt to synchronize again. If
// this fails, this call will hang and the host will consider the test
// a failure.
//
// To Do:
//  Host&protocol currently only supports:
//   - no/even parity
void
CeCosTestSerialFilter::CMD_ChangeConfig(CeCosSerial &pSer, char* cfg_str)
{
    ser_cfg_t new_cfg, old_cfg;

    ParseConfig(cfg_str, &new_cfg);

    // Return without changing the config if it's not valid.
    if (!VerifyConfig(pSer, &new_cfg)) {
        TargetASCIIWrite(pSer, "ER");
        return;
    }

    // Tell target we're ready to go, wait 1/10 sec, and then change
    // the config.
    TargetASCIIWrite(pSer, "OK");
    CeCosThreadUtils::Sleep(100);
    SetConfig(pSer, &new_cfg, &old_cfg);

    int loops;
    for (loops = 0; loops < 3; loops++) {
        unsigned int len, read;
        unsigned char buffer[2];
        int delay_mticks = 0; // millisecond-ticks. 10 of these per target tick

        // Start by sending a Sync.
        TargetASCIIWrite(pSer, "S");
        for(;;) {
            // Did target reply?
            len = 2;
            read = 0;
            buffer[0] = 0;
            buffer[1] = 0;
            if (!pSer.Read((void*) buffer, len, read)) {
                throw "CMD_ChangeConfig: serial read failure";
            }
            
            if (read) {
                // If only one char read, try to get the next one.
                if (1 == read) {
                    unsigned int read2 = 0;
                    len = 1;
                    if (!pSer.Read((void*) &buffer[1], len, read2)) {
                        throw "CMD_ChangeConfig: serial read failure";
                    }
                    read += read2;
                }

                if (m_bOptSerDebug)
                    PrintHex(buffer, read);

                if ('O' == buffer[0] && 'K' == buffer[1]) {
                    // success!
                    TargetASCIIWrite(pSer, "D");
                    Trace("Config change succeeded.\n");
                    return;
                } else {
                    // Garbage, ask target to resend its OK message.
                    TargetASCIIWrite(pSer, "R");
                }
            } else {
                // Resend Sync message.
                TargetASCIIWrite(pSer, "S");
            }

            CeCosThreadUtils::Sleep(1);
            delay_mticks++;
            // Timeout.
            if (100 == delay_mticks/10)
                break;
        }

        SetConfig(pSer, &old_cfg, NULL);
    }

    // Abort the test.
    Log("FAIL:<target timed out>\n"); 
    Trace("**** Timed out while changing config\n");

    static const char kill_msg[] = "$X00#b8";

    filter_abort_t* msg = new filter_abort_t();
    msg->data_len = strlen(kill_msg);
    msg->data_ptr = (const unsigned char *)kill_msg;

    throw msg;
}

// Set default configuration.
void
CeCosTestSerialFilter::CMD_DefaultConfig(CeCosSerial &pSer)
{
    static const ser_cfg_t default_ser_cfg = { 9600, 
                                               8, 
                                               CeCosSerial::ONE_STOP_BIT,
                                               false };

    TargetASCIIWrite(pSer, "OK");
    SetConfig(pSer, &default_ser_cfg, NULL);
}

// Parse config string from target and set new_cfg accordingly.
// String from target is:
//  <baud rate>:<data bits>:<stop bits>:<parity>:....
void
CeCosTestSerialFilter::ParseConfig(char* args, ser_cfg_t* new_cfg)
{
    int ecos_parity, ecos_stop_bits, ecos_baud_rate, ecos_flags;

    CeCosSerial::StopBitsType t2h_stop_bits[3] = {
        CeCosSerial::ONE_STOP_BIT, 
        CeCosSerial::ONE_POINT_FIVE_STOP_BITS,
        CeCosSerial::TWO_STOP_BITS};
    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);
    SET_VALUE(int, ecos_flags);

    new_cfg->parity = (ecos_parity != 0) ? true : false;
    new_cfg->stop_bits = t2h_stop_bits[ecos_stop_bits - 1];

    // flags is an optional field
    if ( -1 == ecos_flags )
        new_cfg->flags = FLOW_NONE;
    else
        new_cfg->flags = ecos_flags;

    // 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;

    Trace("Parsed Config baud=%d, bParity=%d, stopbits=%d, databits=%d\n",
          new_cfg->baud_rate, (int) new_cfg->parity, new_cfg->stop_bits,
          new_cfg->data_bits);
    Trace("Parsed Config xonxoff_rx=%d,tx=%d, rtscts_rx=%d,tx=%d, "
          "dsrdtr_rx=%d,tx=%d\n",
          (new_cfg->flags & FLOW_XONXOFF_RX) != 0,
          (new_cfg->flags & FLOW_XONXOFF_TX) != 0,
          (new_cfg->flags & FLOW_RTSCTS_RX) != 0,
          (new_cfg->flags & FLOW_RTSCTS_TX) != 0,
          (new_cfg->flags & FLOW_DSRDTR_RX) != 0,
          (new_cfg->flags & FLOW_DSRDTR_TX) != 0);
}

// Always make sure CRC fits in 31 bits. Bit of a hack, but we want
// to send CRC as ASCII without too much hassle.
int
CeCosTestSerialFilter::DoCRC(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;
}

void
CeCosTestSerialFilter::SendChecksum(CeCosSerial &pSer, int crc)
{
    char buffer[128];
    int len;

    len = sprintf(buffer, "%d!", crc);

    TargetWrite(pSer, (const unsigned char*)buffer, len);
}

void
CeCosTestSerialFilter::SendStatus(CeCosSerial &pSer, int state)
{
    if (state)
        TargetWrite(pSer, (unsigned char*) &msg_ok, 2);
    else
        TargetWrite(pSer, (unsigned char*) &msg_er, 2);
}


// Receive test DONE message from target.
void
CeCosTestSerialFilter::ReceiveDone(CeCosSerial &pSer, 
                                   unsigned char* data_in, int size)
{
    static const char msg_done[] = "DONE";
    unsigned char data_reply[4];
    int first = 1;

    TargetRead(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");
                PrintHex(data_in, size);
                Trace("<end>\n");
            }
            Trace("Receiving junk instead of DONE:\n");
            first = 0;
        }
        PrintHex(data_reply, 4);

        data_reply[0] = data_reply[1];
        data_reply[1] = data_reply[2];
        data_reply[2] = data_reply[3];

        // The TargetRead call will handle recovery in case of timeout...
        TargetRead(pSer, &data_reply[3], 1);
    }
}

//-----------------------------------------------------------------------------
// 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.
void
CeCosTestSerialFilter::CMD_TestBinary(CeCosSerial &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";
    }
    int count = 0;
    for (i = 0; i < size; i++) {
        // Output 255 chars, not 256 so that we aren't a multiple/factor of the
        // likely buffer sizes in the system, this can mask problems as I've
        // found to my cost!
        unsigned char c = (unsigned char) (count++ % 255);
        // don't allow $s and @s in the data, nor 0x03 (GDB C-c), nor flow
        // control chars
        if ('$' == c || '@' == c || 0x03 == c || 0x11 == c || 0x13 == c)
            c = (unsigned char) '*';
        data_out[i] = c;
    }

    // Do checksum.
    crc = DoCRC(data_out, size);

⌨️ 快捷键说明

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