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

📄 ser_test_protocol.inl

📁 开放源码实时操作系统源码.
💻 INL
📖 第 1 页 / 共 3 页
字号:

//----------------------------------------------------------------------------
// Macros for read/write to serial with error cheking.
static volatile cyg_uint32 r_stamp;
static volatile int aborted;

// This routine will be called if the read "times out"
static void
do_abort(void *handle)
{
    cyg_io_handle_t io_handle = (cyg_io_handle_t)handle;
    cyg_uint32 len = 1;  // Need something here
    cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len);
    aborted = 1;
}
#include "timeout.inl"

// Read with timeout (__t = timeout in ticks, int* __r = result)
#define Tcyg_io_read_timeout(__h, __d, __l, __t, __r)           \
    CYG_MACRO_START                                             \
    int __res;                                                  \
    r_stamp = timeout((__t), do_abort, (__h));                  \
    __res = cyg_io_read((__h), (__d), (__l));                   \
    if (ENOERR != __res && -EINTR != __res) {                   \
        TEST_CRASH(__h, TEST_CRASH_IO_READ,                     \
                   "cyg_io_read/timeout failed", __res);        \
    }                                                           \
    *(__r) = __res;                                             \
    untimeout(r_stamp);                                         \
    CYG_MACRO_END

#define Tcyg_io_read(__h, __d, __l)                     \
    CYG_MACRO_START                                     \
    int __res = cyg_io_read((__h), (__d), (__l));       \
    if (ENOERR != __res) {                              \
        TEST_CRASH(__h, TEST_CRASH_IO_READ,             \
                   "cyg_io_read failed", __res);        \
    }                                                   \
    CYG_MACRO_END

#define Tcyg_io_write(__h, __d, __l)                                    \
    CYG_MACRO_START                                                     \
    int __res;                                                          \
    cyg_uint32 __len = 1;                                               \
    __res = cyg_io_write((__h), (__d), (__l));                          \
    if (ENOERR != __res) {                                              \
        TEST_CRASH(__h, TEST_CRASH_IO_WRITE,                            \
                   "cyg_io_write failed", __res);                       \
    }                                                                   \
    __res = cyg_io_get_config((__h),                                    \
                              CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN,    \
                              0, &__len);                               \
    if (ENOERR != __res) {                                              \
        TEST_CRASH(__h, TEST_CRASH_IO_DRAIN,                            \
                   "DRAIN failed", __res);                              \
    }                                                                   \
    CYG_MACRO_END


//----------------------------------------------------------------------------
// Some libc like functions that are handy to have around.
static int
strlen(const char *c)
{
    int l = 0;
    while (*c++) l++;
    return l;
}

static char*
strcpy(char* dest, const char* src)
{
    char c;
    while ((c = *src++)) {
        *dest++ = c;
    }
    *dest = c;

    return dest;
}

static char*
itoa(char* dest, int v)
{
    char b[16];
    char* p = &b[16];

    *--p = 0;
    if (v) {
        while (v){
            *--p = (v % 10) + '0';
            v = v / 10;
        }
    } else
        *--p = '0';

    return strcpy(dest, p);
}

#define min(_a, _b) ((_a) < (_b)) ? (_a) : (_b)

void
hang(void)
{
    while (1);
}

//-----------------------------------------------------------------------------
// 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>:<flow control code>!"
// 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
int
change_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg)
{
    cyg_serial_info_t old_cfg, new_cfg;
    const char cmd[] = "@CONFIG:";
    char reply[2];
    cyg_uint32 msglen;
    int res;
    cyg_uint32 len;
    char *p1;

    // Prepare the command.
    p1 = &cmd_buffer[0];
    p1 = strcpy(p1, &cmd[0]);
    p1 = itoa(p1, cfg->baud_rate);
    *p1++ = ':';
    p1 = itoa(p1, cfg->data_bits);
    *p1++ = ':';
    p1 = itoa(p1, cfg->stop_bits);
    *p1++ = ':';
    p1 = itoa(p1, cfg->parity);
    *p1++ = ':';
    p1 = itoa(p1, cfg->flags);
    *p1++ = '!';
    *p1 = 0;                            // note: we may append to this later

    // Tell user what we're up to.
    CYG_TEST_INFO((char *)&cmd_buffer[1]);

    // Change to new config and then back to determine if the driver likes it.
    len = sizeof(old_cfg);
    res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, 
                            &old_cfg, &len);
    res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, 
                            &new_cfg, &len);

    if (res != ENOERR) {
        TEST_CRASH(handle, TEST_CRASH_IO_GET_CFG, 
                   "Can't get serial config", res);
    }

    new_cfg.baud = cfg->baud_rate;
    new_cfg.word_length = cfg->data_bits;
    new_cfg.stop = cfg->stop_bits;
    new_cfg.parity = cfg->parity;
    new_cfg.flags = cfg->flags;

    res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
                            &new_cfg, &len);
    cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...

    // Driver didn't like it. It will not have changed anything, so it's
    // safe to return now.
    if (ENOERR != res) {
        // Let user know that the config was skipped due to the target.
        const char txt_tskipped[] = "- skipped by target!";
        p1 = strcpy(p1, txt_tskipped);
        *p1 = 0;
        CYG_TEST_INFO(&cmd_buffer[1]);
        return res;
    }

    // Succeeded. Change back to the original config so we can communicate
    // with the host.
    res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
                            &old_cfg, &len);
    cyg_thread_delay(10); // Some chips don't like changes to happen to fast...

    if (res != ENOERR) {
        TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, 
                   "Can't set serial config", res);
    }

    // Send command to host and read host's reply.
    msglen = strlen(&cmd_buffer[0]);
    Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
    msglen = 2;
    Tcyg_io_read(handle, &reply[0], &msglen);

    // Did host accept configuration?
    if ('O' != reply[0] || 'K' != reply[1]) {
        // Let user know that the config was skipped due to the host.
        const char txt_hskipped[] = "- skipped by host!";
        p1 = strcpy(p1, txt_hskipped);
        *p1 = 0;
        CYG_TEST_INFO(&cmd_buffer[1]);
        diag_printf("Host didn't accept config (%02x, %02x).\n",
                    reply[0], reply[1]);

        res = ENOSUPP;
        return res;
    }

    // Now change config and wait for host to send us a S(ync)
    // character.  
    // Loop until protocol exchange completed. This may hang (as seen
    // from the host), but only when we get totally lost, in which
    // case there's not much else to do really. In this case the host
    // will consider the test a FAIL.
    len = sizeof(new_cfg);
    res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
                            &new_cfg, &len);
    cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...
    if (res != ENOERR) {
        TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, 
                   "Can't set serial config/2", res);
    }

    {
        int change_succeeded = 0;
        int using_old_config = 0;
        char in_buf[1];
        cyg_uint32 len;
        int saw_host_sync;

        for (;;) {
            aborted = 0;                    // global abort flag

            // FIXME: Timeout time needs to be configurable, and needs to
            // be sent to the host before getting here. That would allow
            // changing the timeout by just rebuilding the test - without
            // changing the host software.
            saw_host_sync = 0;
            r_stamp = timeout(100, do_abort, handle);
            while(!aborted) {
                len = 1;
                in_buf[0] = 0;
                res = cyg_io_read(handle, in_buf, &len);
                if (ENOERR != res && -EINTR != res) {
                    // We may have to reset the driver here if the fail
                    // was due to a framing or parity error.
                    break;
                }
                if ('R' == in_buf[0]) {
                    // Resync - host didn't see our message. Try again.
                    saw_host_sync = 0;
                } else if ('S' == in_buf[0] && !saw_host_sync) {
                    // In sync - reply to host if we haven't already
                    char ok_msg[2] = "OK";
                    cyg_uint32 ok_len = 2;
                    Tcyg_io_write(handle, ok_msg, &ok_len);
                    saw_host_sync = 1;
                } else if ('D' == in_buf[0] && saw_host_sync) {
                    // Done - exchange completed.
                    change_succeeded = 1;
                    break;
                }
            }
            untimeout(r_stamp);

            if (change_succeeded) {
                // If we had to revert to the old configuration, return error.
                if (using_old_config)
                    return -EIO;
                else
                    return ENOERR;
            }

            // We didn't synchronize with the host. Due to an IO error?
            if (ENOERR != res && -EINTR != res) {
                // We may have to reset the driver if the fail was due to
                // a framing or parity error.
            }

            // Revert to the old configuration and try again.
            len = sizeof(old_cfg);
            res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, 
                                    &old_cfg, &len);
            cyg_thread_delay(10);  // Some chips don't like changes to happen to fast...
            if (res != ENOERR) {
                TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
                           "Can't set serial config/3", res);
            }
            using_old_config = 1;
        }

    }
}


//-----------------------------------------------------------------------------
// Host sends CRC in decimal ASCII, terminated with !
int
read_host_crc(cyg_io_handle_t handle)
{
    int crc;
    cyg_uint32 len;
    cyg_uint8 ch;

    crc = 0;
    while (1) {
        len = 1;
        Tcyg_io_read(handle, &ch, &len);
        if ('!' == ch)
            break;

        if (!((ch >= '0' && ch <= '9'))){
            TEST_CRASH(handle, TEST_CRASH_CRC_CHAR,
                       "Illegal CRC format from host", ch);
        }

        crc = crc*10 + (ch - '0');
    }

    return crc;
}

//---------------------------------------------------------------------------
// Test binary data transmission.
// Format out:
//  "@BINARY:<byte size>:<mode>!"
// Format in:
//  <checksum>!<#size bytes data>
// For echo modes, also:
//     Format out:
//      <#size bytes data>
//     Format in:

⌨️ 快捷键说明

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