Mercurial > ecos
diff packages/io/serial/current/tests/ser_test_protocol.inl @ 2:443894e2e912 ecos-v1_2_1-release
Block commit of eCos version 1.2.1
| author | jlarmour |
|---|---|
| date | Tue, 11 May 1999 12:24:34 +0000 |
| parents | |
| children | 1d7f19c9e4d1 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/io/serial/current/tests/ser_test_protocol.inl @@ -0,0 +1,826 @@ +//========================================================================== +// +// ser_test_protocol.c +// +// Serial device driver testing protocol +// +//========================================================================== +//####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-17 +// Description: Protocol implementation used to test eCos serial devices. +// Relies on ser_filter to be present on the host side to +// respond to test requests. +// +// To Do: +// o Clean up. +// o Clean up config change magic. +// o Figure out how to handle kernel dependency +// : without kernel, no timeout. Without timeout, no filter auto detection. +// +//####DESCRIPTIONEND#### + +#include <pkgconf/system.h> +#include <pkgconf/io.h> +#include <pkgconf/io_serial.h> + +#include <cyg/io/io.h> +#include <cyg/io/devtab.h> +#include <cyg/io/ttyio.h> +#include <cyg/infra/diag.h> + +#include <cyg/hal/hal_intr.h> // for reclaiming interrup vector + +//---------------------------------------------------------------------------- +// Definition of which device to run tests on on various platforms. +#if defined(CYGPKG_HAL_POWERPC_COGENT) \ + && defined(CYGPKG_IO_SERIAL_POWERPC_COGENT) \ + && defined(CYGPKG_IO_SERIAL_POWERPC_COGENT_SERIAL_B) +# define TEST_SER_DEV CYGDAT_IO_SERIAL_POWERPC_COGENT_SERIAL_B_NAME +# if defined(CYGPKG_IO_SERIAL_TTY_TTY2) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY2_DEV +# endif +#endif +#if defined(CYGPKG_HAL_ARM_PID) \ + && defined(CYGPKG_IO_SERIAL_ARM_PID) \ + && defined(CYGPKG_IO_SERIAL_ARM_PID_SERIAL0) +# define TEST_SER_DEV CYGDAT_IO_SERIAL_ARM_PID_SERIAL0_NAME +# if defined(CYGPKG_IO_SERIAL_TTY_TTY0) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY0_DEV +# endif +#endif +#if defined(CYGPKG_HAL_ARM_AEB) \ + && defined(CYGPKG_IO_SERIAL_ARM_AEB) \ + && defined(CYGPKG_IO_SERIAL_ARM_AEB_SERIAL1) +# define TEST_SER_DEV CYGDAT_IO_SERIAL_ARM_AEB_SERIAL1_NAME +# if defined(CYGPKG_IO_SERIAL_TTY_TTY1) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV +# endif +#endif +#if defined(CYGPKG_HAL_TX39_JMR3904) \ + && defined(CYGPKG_IO_SERIAL_TX39_JMR3904) \ + && defined(CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0) +# define TEST_SER_DEV CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL0_NAME +# if defined(CYGPKG_IO_SERIAL_TTY_TTY1) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV +# endif +#endif +#if defined(CYGPKG_HAL_MN10300_STDEVAL1) \ + && defined(CYGPKG_IO_SERIAL_MN10300) \ + && defined(CYGPKG_IO_SERIAL_MN10300_SERIAL1) +// Note: Serial1 is *not* the same port as GDB is using. It seems that +// CygMon is interfering with the tests if run on the same port. +// This configuration allows the serial driver to be tested using the +// filter in stand alone mode (option -n). +# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL1_NAME +# if defined(CYGPKG_IO_SERIAL_TTY_TTY1) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV +# endif +#endif +#if defined(CYGPKG_HAL_SPARCLITE_SLEB) \ + && defined(CYGPKG_IO_SERIAL_SPARCLITE_SLEB) \ + && defined(CYGPKG_IO_SERIAL_SPARCLITE_SLEB_CON1) +# define TEST_SER_DEV CYGDAT_IO_SERIAL_SPARCLITE_SLEB_CON1_NAME +# define SER_OVERRIDE_INT_1 CYGNUM_HAL_INTERRUPT_9 +# define SER_OVERRIDE_INT_2 CYGNUM_HAL_INTERRUPT_10 +# if defined(CYGPKG_IO_SERIAL_TTY_TTY0) +# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY0_DEV +# endif +#endif + + +// We can't rely on haldiag for ser_filter detection - it may not define +// a working character reading function. +#ifndef TEST_SER_DEV +# define SER_NOP_TEST +# define TTY_NOP_TEST +# define TEST_SER_DEV "/dev/null" +# define TEST_TTY_DEV "/dev/null" +#else +# ifndef TEST_TTY_DEV +# define TTY_NOP_TEST +# define TEST_TTY_DEV "/dev/null" +# endif +#endif + +//---------------------------------------------------------------------------- +// FIXME: The PPC sometimes sees a spurious byte. There is workaround code +// that can be enabled here. +#define HANDLE_SPURIOUS 1 + +//---------------------------------------------------------------------------- +// The data in buffer and the cmd buffer +#define IN_BUFFER_SIZE 1024 +cyg_uint8 in_buffer[IN_BUFFER_SIZE]; + +cyg_int8 cmd_buffer[128]; + +//---------------------------------------------------------------------------- +// Some types specific to the testing protocol. +typedef enum { + MODE_NO_ECHO = 0, + MODE_EOP_ECHO, + MODE_DUPLEX_ECHO +} cyg_mode_t; + +typedef enum { + TEST_RETURN_OK = ENOERR, + TEST_RETURN_NA +} cyg_test_return_t; + +typedef struct ser_cfg { + cyg_serial_baud_rate_t baud_rate; + cyg_serial_word_length_t data_bits; + cyg_serial_stop_bits_t stop_bits; + cyg_serial_parity_t parity; + // etc... +} cyg_ser_cfg_t; + +//---------------------------------------------------------------------------- +// A few predefined configurations. These must all be valid for any +// given target until change_config is behaving correctly. +cyg_ser_cfg_t test_configs[] = { +#if !defined(CYGPKG_HAL_TX39_JMR3904) && \ + !defined(CYGPKG_HAL_ARM_PID) && \ + !defined(CYGPKG_HAL_ARM_AEB) && \ + !defined(CYGPKG_HAL_MN10300_STDEVAL1) && \ + !defined(CYGPKG_HAL_SPARCLITE_SLEB) + { CYGNUM_SERIAL_BAUD_115200, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE }, +#endif + +#if !defined(CYGPKG_HAL_TX39_JMR3904) && \ + !defined(CYGPKG_HAL_ARM_AEB) && \ + !defined(CYGPKG_HAL_SPARCLITE_SLEB) + { CYGNUM_SERIAL_BAUD_57600, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE }, +#endif + + { CYGNUM_SERIAL_BAUD_38400, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE }, + + { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE }, + +#if !defined(CYGPKG_HAL_TX39_JMR3904) && !defined(CYGPKG_HAL_ARM_PID) + { CYGNUM_SERIAL_BAUD_9600, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE }, +#endif + +#if !defined(CYGPKG_HAL_TX39_JMR3904) && \ + !defined(CYGPKG_HAL_ARM_AEB) && \ + !defined(CYGPKG_HAL_ARM_PID) + // One stop bit, even parity + { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_EVEN }, +#endif + +#if !defined(CYGPKG_HAL_TX39_JMR3904) && \ + !defined(CYGPKG_HAL_ARM_AEB) && \ + !defined(CYGPKG_HAL_ARM_PID) + // Two stop bits, even parity + { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_EVEN }, +#endif + +#if !defined(CYGPKG_HAL_TX39_JMR3904) + // Two stop bits, no parity + { CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8, + CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_NONE }, +#endif +}; + +//---------------------------------------------------------------------------- +// 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(__slot) \ +do { \ + __ptr1 = index(__ptr2, (int) ':'); \ + if (__ptr1) \ + *__ptr1 = 0; \ + v = atoi(__ptr2); \ + __ptr2 = __ptr1+1; \ + (__slot) = v; \ +} while (0) + + +//---------------------------------------------------------------------------- +// CRC magic - it's a bit of a hack for now. +// FIXME: standard definition? +#define ADD_CRC_BYTE(__crc, __c) \ + CYG_MACRO_START \ + (__crc) = ((__crc) << 1) ^ (__c); \ + CYG_MACRO_END + +// FIXME: Hack to allow easy ASCII transfer. +#define FIX_CRC(__crc, __icrc) \ + CYG_MACRO_START \ + __icrc = (int) (__crc); \ + if (__icrc < 0) \ + __icrc = -__icrc; \ + CYG_MACRO_END + +//---------------------------------------------------------------------------- +// Macros for read/write to serial with error cheking. +cyg_uint32 r_stamp; + +// 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_int32 len = 1; // Need something here + cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len); +} +#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)); \ + CYG_TEST_CHECK((ENOERR == __res || -EINTR == __res),"cyg_io_read failed");\ + *(__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)); \ + CYG_TEST_CHECK(ENOERR == __res, "cyg_io_read failed"); \ + 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)); \ + CYG_TEST_CHECK(ENOERR == __res, "cyg_io_write failed"); \ + __res = cyg_io_get_config((__h), \ + CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, \ + 0, &__len); \ + CYG_TEST_CHECK(ENOERR == __res, "DRAIN failed"); \ + 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. +// FIXME: This is still slightly bogus in that it doesn't check for target +// capabilities. Correct way is; +// o try setting new cfg +// o restore +// o if OK: +// o send cfg to target +// o if reply OK: +// o change to new cfg +// +// Host&protocol currently only supports: +// - no/even parity +int +change_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg) +{ + const char cmd[] = "@CONFIG:"; + char reply[2]; + int msglen; + int res; + cyg_uint8 *p1; + + // Prepare and send 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++ = 0; + + CYG_TEST_INFO(&cmd_buffer[1]); + + msglen = strlen(&cmd_buffer[0]); + Tcyg_io_write(handle, &cmd_buffer[0], &msglen); + + msglen = 2; + Tcyg_io_read(handle, &reply[0], &msglen); + + if (reply[0] == 'O') { + // Change config + cyg_serial_info_t serial_info; + int len = sizeof(serial_info); + res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &serial_info, &len); + if (res != ENOERR) { + diag_printf("Can't get serial config - DEVIO error: %d\n", res); + hang(); + } + + serial_info.baud = cfg->baud_rate; + serial_info.word_length = cfg->data_bits; + serial_info.stop = cfg->stop_bits; + serial_info.parity = cfg->parity; + + res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &serial_info, &len); + if (res != ENOERR) { + diag_printf("Can't set serial config - DEVIO error: %d\n", res); + hang(); + } + + res = ENOERR; + } else { + res = ENOSUPP; +#ifdef __DEVELOPER__ + diag_printf("Host didn't accept config (%02x, %02x).\n", + reply[0], reply[1]); +#endif + } + +#if 0 + // FIXME: This is needed to prevent sending data at the new baud rate + // before the host is ready.... Need to fiddle this a bit more. + // Loop counts for ARM and PII in host side source. Replace with + // timed loops. + { + int i; + for (i = 0; i < 100000; i++); + } +#else + cyg_thread_delay(80); // this requires kernel +#endif + + return res; +} + + +//----------------------------------------------------------------------------- +// Host sends CRC in decimal ASCII, terminated with ! +int +read_host_crc(cyg_io_handle_t handle) +{ + int crc, len; + cyg_uint8 ch; + + crc = 0; + while (1) { + len = 1; + Tcyg_io_read(handle, &ch, &len); + if ('!' == ch) + break; + +#ifdef __DEVELOPER__ + if (!((ch >= '0' && ch <= '9'))){ + diag_printf("CHAR: %02x\n", ch); + } +#endif + + CYG_TEST_CHECK((ch >= '0' && ch <= '9'), + "Illegal CRC format from host"); + + 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: +// 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:"; + int msglen; + cyg_uint32 xcrc; + int icrc, host_crc; + cyg_uint8 *p1; + cyg_int8 host_status = 'O'; // host is happy by default + int spurious = 0; + + // 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, chunk_len, i; + 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, 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]; + +#if HANDLE_SPURIOUS + // FIXME: This occassionally reads back a spurious character + // from the transmission. It's not just noise, it's definitely + // a byte from the previously transmitted data. + if (in_buffer[0] != 'O' && in_buffer[1] == 'O') { + spurious = in_buffer[0]; + chunk_len = 1; + Tcyg_io_read(handle, &in_buffer[0], &chunk_len); + if (in_buffer[0] == 'K') { + host_status = 'O'; + } + } +#endif + + // 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); + } + +#if HANDLE_SPURIOUS + if (spurious) { + diag_printf("******* Spurious byte 0x%02x *******\n", spurious); + } +#endif + + } + break; + case MODE_DUPLEX_ECHO: + { + int 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]; + +#if HANDLE_SPURIOUS + // FIXME: This occassionally reads back a spurious character + // from the transmission. It's not just noise, it's definitely + // a byte from the previously transmitted data. + if (in_buffer[0] != 'O' && in_buffer[1] == 'O') { + spurious = in_buffer[0]; + chunk_len = 1; + Tcyg_io_read(handle, &in_buffer[0], &chunk_len); + if (in_buffer[0] == 'K') { + host_status = 'O'; + } + } +#endif + + // 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); + } + +#if HANDLE_SPURIOUS + if (spurious) { + diag_printf("******* Spurious byte 0x%02x *******\n", spurious); + } +#endif + } + break; + default: + CYG_TEST_CHECK(0, "unknown mode"); + } + + + // Verify that the CRC matches the one from the host. + FIX_CRC(xcrc, icrc); +#ifdef __DEVELOPER__ + if (host_crc != icrc) + diag_printf("%d != %d\n", icrc, host_crc); +#endif + CYG_TEST_CHECK(host_crc == icrc, "CRC failed!"); + + // Verify that the host is happy with the data we echoed. + CYG_TEST_CHECK('O' == host_status, "Host failed checksum on echoed data"); + + 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!" +// 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:!"; + char msg2[] = "\n"; + int 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."); +} + +//--------------------------------------------------------------------------- +// Some helper functions to get a test started. +void +test_open_ser( cyg_io_handle_t* handle ) +{ +#ifndef 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(SER_OVERRIDE_INT_1) + HAL_VSR_SET_TO_ECOS_HANDLER(SER_OVERRIDE_INT_1, NULL); +# endif +# if defined(SER_OVERRIDE_INT_2) + HAL_VSR_SET_TO_ECOS_HANDLER(SER_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("No test device specified"); +#endif +} + +void +test_open_tty( cyg_io_handle_t* handle ) +{ +#ifndef 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(SER_OVERRIDE_INT_1) + HAL_VSR_SET_TO_ECOS_HANDLER(SER_OVERRIDE_INT_1, NULL); +# endif +# if defined(SER_OVERRIDE_INT_2) + HAL_VSR_SET_TO_ECOS_HANDLER(SER_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("No test device specified"); +#endif +} + +//--------------------------------------------------------------------------- +// end of ser_test_protocol.inl
