📄 ser_test_protocol.inl
字号:
// OK/ER
// Format out:
// DONE
//
// The last DONE allows the host to eat bytes if target is sending too many.
//
// Mode:
// MODE_NO_ECHO:
// Just receive data and verify CRC.
// MODE_EOP_ECHO:
// Receive data, verify CRC, resend data.
// Expect OK/ER reply from host when done.
// MODE_DUPLEX_ECHO:
// Receive data, echo data, verify CRC.
// Expect OK/ER reply from host when done.
//
// Note:
// Using diag_printf while talking with the host may cause some funky
// errors (bytes from the host side being lost!?!?)
//
// To Do:
// MODE_DUPLEX_ECHO:
// The current implementation is simple and may not stress the
// driver enough. Also, it's command packet format doesn't match
// that of the other modes.
cyg_test_return_t
test_binary(cyg_io_handle_t handle, int size, cyg_mode_t mode)
{
const char cmd[] = "@BINARY:";
cyg_uint32 msglen;
cyg_uint32 xcrc;
int icrc, host_crc;
char *p1;
cyg_int8 host_status = 'O'; // host is happy by default
// Verify that the test can be run with available ressources.
if (MODE_EOP_ECHO == mode && size > IN_BUFFER_SIZE)
return TEST_RETURN_NA;
// Prepare and send the command.
p1 = &cmd_buffer[0];
p1 = strcpy(p1, &cmd[0]);
p1 = itoa(p1, size);
*p1++ = ':';
p1 = itoa(p1, mode);
*p1++ = '!';
*p1++ = 0;
CYG_TEST_INFO(&cmd_buffer[1]);
msglen = strlen(&cmd_buffer[0]);
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
// Get CRC back.
host_crc = read_host_crc(handle);
// Depending on mode, start reading data.
xcrc = 0;
switch (mode) {
case MODE_NO_ECHO:
{
// Break transfers into chunks no larger than the buffer size.
int tx_len, i;
cyg_uint32 chunk_len;
while (size > 0) {
chunk_len = min(IN_BUFFER_SIZE, size);
tx_len = chunk_len;
size -= chunk_len;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
for (i = 0; i < tx_len; i++) {
ADD_CRC_BYTE(xcrc, in_buffer[i]);
}
}
// Reply that we have completed the test.
{
const char msg_done[] = "DONE";
chunk_len = strlen(&msg_done[0]);
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
}
}
break;
case MODE_EOP_ECHO:
{
// We have already checked that the in buffer is large enough.
int i, tx_len;
cyg_uint32 chunk_len;
chunk_len = tx_len = size;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
for (i = 0; i < tx_len; i++) {
ADD_CRC_BYTE(xcrc, in_buffer[i]);
}
// Echo data back.
chunk_len = size;
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
// Now read host side's status
chunk_len = 2;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
host_status = in_buffer[0];
// Reply that we have completed the test.
{
const char msg_done[] = "DONE";
chunk_len = strlen(&msg_done[0]);
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
}
}
break;
case MODE_DUPLEX_ECHO:
{
cyg_uint32 chunk_len;
int block_size = 64;
// 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.
while (size--) {
// block_size -> block_size
chunk_len = block_size;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
chunk_len = block_size;
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
// block_size -> 2 x block_size
chunk_len = block_size;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
chunk_len = block_size;
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
chunk_len = block_size;
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
// block_size -> block_size
chunk_len = block_size;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
chunk_len = block_size;
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
// block_size -> 0
chunk_len = block_size;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
}
// Kill the CRC. Leave packet verification to the host for now.
xcrc = host_crc = 0;
// Now read host side's status
chunk_len = 2;
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
host_status = in_buffer[0];
// Reply that we have completed the test.
{
const char msg_done[] = "DONE";
chunk_len = strlen(&msg_done[0]);
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
}
}
break;
default:
TEST_CRASH(handle, TEST_CRASH_PROT_BIN_MODE,
"Unknown mode", mode);
break;
}
// Verify that the CRC matches the one from the host.
FIX_CRC(xcrc, icrc);
if (host_crc != icrc) {
TEST_CRASH(handle, TEST_CRASH_CRC_BAD,
"Input CRC failed", icrc, host_crc);
}
// Verify that the host is happy with the data we echoed.
if ('O' != host_status) {
TEST_CRASH(handle, TEST_CRASH_CRC_HOST,
"Output CRC failed");
}
CYG_TEST_PASS("Binary test completed");
return TEST_RETURN_OK;
}
//---------------------------------------------------------------------------
// Test transformations on text transmissions
// Format out:
// "@TEXT:<mode>!<4 bytes binary checksum><C string>"
// Format in:
// "<C string>"
// OK/ER
//
// Mode:
// MODE_EOP_ECHO:
// Receive data, verify CRC, resend data.
// Expect OK/ER reply from host when done.
// MODE_DUPLEX_ECHO:
// Receive data, echo data, verify CRC.
// Expect OK/ER reply from host when done.
//
cyg_test_return_t
test_text(cyg_io_handle_t handle, cyg_mode_t mode, const char* s_base,
const char* s_out, const char* s_in)
{
return TEST_RETURN_NA;
}
//---------------------------------------------------------------------------
// Send PING to host, verifying the filter's presence.
// Format out:
// "@PING:<crash id>!"
// Format in:
// "OK"
// or
// No response if directly connected to GDB.
//
// This call only returns if the ser_filter is listening. Otherwise it
// sends N/A and hangs.
void
test_ping(cyg_io_handle_t handle)
{
char msg[] = "@PING:" TEST_CRASH_ID "!";
char msg2[] = "\n";
cyg_uint32 msglen = strlen(msg);
int res;
msglen = strlen(msg);
Tcyg_io_write(handle, msg, &msglen);
// Now read host side's status
msglen = 2;
Tcyg_io_read_timeout(handle, &in_buffer[0], &msglen, 100, &res);
if (ENOERR == res && 'O' == in_buffer[0] && 'K' == in_buffer[1])
return;
msglen = strlen(msg2);
Tcyg_io_write(handle, msg2, &msglen);
CYG_TEST_NA("No host side testing harness detected.");
}
//---------------------------------------------------------------------------
// Send OPT to host, setting options in the filter.
// Format out:
// "@OPT:option1,value1:...:optionN,valueN!"
// Format in:
// "OK"
//
// Only integer values can be used. Any option not recognized by the
// filter will be silently ignored.
void
test_options(cyg_io_handle_t handle, int count, cyg_uint32* options)
{
const char cmd[] = "@OPT:";
cyg_uint32 msglen;
char *p1;
// Prepare and send the command.
p1 = &cmd_buffer[0];
p1 = strcpy(p1, &cmd[0]);
while(count--) {
p1 = itoa(p1, *options++); // option
*p1++ = ':';
p1 = itoa(p1, *options++); // value
*p1++ = ':';
}
*(p1-1) = '!';
*p1++ = 0;
CYG_TEST_INFO(&cmd_buffer[1]);
msglen = strlen(&cmd_buffer[0]);
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
// Now read host side's status
msglen = 2;
Tcyg_io_read(handle, &in_buffer[0], &msglen);
}
//---------------------------------------------------------------------------
// Some helper functions to get a test started.
void
test_open_ser( cyg_io_handle_t* handle )
{
#if defined(CYGPKG_IO_SERIAL_DEVICES) && !defined(SER_NOP_TEST)
Cyg_ErrNo res;
if (cyg_test_is_simulator)
CYG_TEST_NA("Cannot run from simulator");
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
# endif
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
# endif
#endif
res = cyg_io_lookup(TEST_SER_DEV, handle);
if (res != ENOERR) {
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_SER_DEV);
}
#else
CYG_TEST_NA(NA_MSG);
#endif
}
void
test_open_tty( cyg_io_handle_t* handle )
{
#if defined(CYGPKG_IO_SERIAL_TTY) && !defined(TTY_NOP_TEST)
Cyg_ErrNo res;
if (cyg_test_is_simulator)
CYG_TEST_NA("Cannot run from simulator");
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
# endif
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
# endif
#endif
res = cyg_io_lookup(TEST_TTY_DEV, handle);
if (res != ENOERR) {
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_TTY_DEV);
}
#else
CYG_TEST_NA(NA_MSG);
#endif
}
//---------------------------------------------------------------------------
// end of ser_test_protocol.inl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -