//==========================================================================
|
//==========================================================================
|
//
|
//
|
// ser_test_protocol.c
|
// ser_test_protocol.c
|
//
|
//
|
// Serial device driver testing protocol
|
// Serial device driver testing protocol
|
//
|
//
|
//==========================================================================
|
//==========================================================================
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
// -------------------------------------------
|
// -------------------------------------------
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
//
|
//
|
// eCos is free software; you can redistribute it and/or modify it under
|
// eCos is free software; you can redistribute it and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
// Software Foundation; either version 2 or (at your option) any later version.
|
// Software Foundation; either version 2 or (at your option) any later version.
|
//
|
//
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for more details.
|
// for more details.
|
//
|
//
|
// You should have received a copy of the GNU General Public License along
|
// You should have received a copy of the GNU General Public License along
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
//
|
//
|
// As a special exception, if other files instantiate templates or use macros
|
// As a special exception, if other files instantiate templates or use macros
|
// or inline functions from this file, or you compile this file and link it
|
// or inline functions from this file, or you compile this file and link it
|
// with other works to produce a work based on this file, this file does not
|
// with other works to produce a work based on this file, this file does not
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// by itself cause the resulting work to be covered by the GNU General Public
|
// License. However the source code for this file must still be made available
|
// License. However the source code for this file must still be made available
|
// in accordance with section (3) of the GNU General Public License.
|
// in accordance with section (3) of the GNU General Public License.
|
//
|
//
|
// This exception does not invalidate any other reasons why a work based on
|
// This exception does not invalidate any other reasons why a work based on
|
// this file might be covered by the GNU General Public License.
|
// this file might be covered by the GNU General Public License.
|
//
|
//
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// at http://sources.redhat.com/ecos/ecos-license/
|
// -------------------------------------------
|
// -------------------------------------------
|
//####ECOSGPLCOPYRIGHTEND####
|
//####ECOSGPLCOPYRIGHTEND####
|
//==========================================================================
|
//==========================================================================
|
//#####DESCRIPTIONBEGIN####
|
//#####DESCRIPTIONBEGIN####
|
//
|
//
|
// Author(s): jskov
|
// Author(s): jskov
|
// Contributors: jskov, gthomas
|
// Contributors: jskov, gthomas
|
// Date: 1999-03-17
|
// Date: 1999-03-17
|
// Description: Protocol implementation used to test eCos serial devices.
|
// Description: Protocol implementation used to test eCos serial devices.
|
// Relies on ser_filter to be present on the host side to
|
// Relies on ser_filter to be present on the host side to
|
// respond to test requests.
|
// respond to test requests.
|
//
|
//
|
// To Do:
|
// To Do:
|
// o Clean up.
|
// o Clean up.
|
// o Clean up config change magic.
|
// o Clean up config change magic.
|
// o Figure out how to handle kernel dependency
|
// o Figure out how to handle kernel dependency
|
// : without kernel, no timeout. Without timeout, no filter auto detection.
|
// : without kernel, no timeout. Without timeout, no filter auto detection.
|
//
|
//
|
//####DESCRIPTIONEND####
|
//####DESCRIPTIONEND####
|
|
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
|
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
|
|
#include // for reclaiming interrupt vector
|
#include // for reclaiming interrupt vector
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Definition of which device to run tests on on various platforms.
|
// Definition of which device to run tests on on various platforms.
|
|
|
#define NA_MSG "No test device specified"
|
#define NA_MSG "No test device specified"
|
|
|
// Cleaned up drivers will export the testing parameters via CDL.
|
// Cleaned up drivers will export the testing parameters via CDL.
|
// When all drivers are changed, replace the TEST_ macros throughout
|
// When all drivers are changed, replace the TEST_ macros throughout
|
// with the CYGPRI_ equivalents.
|
// with the CYGPRI_ equivalents.
|
#ifdef CYGPRI_SER_TEST_CRASH_ID
|
#ifdef CYGPRI_SER_TEST_CRASH_ID
|
# define TEST_CRASH_ID CYGPRI_SER_TEST_CRASH_ID
|
# define TEST_CRASH_ID CYGPRI_SER_TEST_CRASH_ID
|
# define TEST_SER_DEV CYGPRI_SER_TEST_SER_DEV
|
# define TEST_SER_DEV CYGPRI_SER_TEST_SER_DEV
|
# define TEST_TTY_DEV CYGPRI_SER_TEST_TTY_DEV
|
# define TEST_TTY_DEV CYGPRI_SER_TEST_TTY_DEV
|
#endif
|
#endif
|
|
|
// Note that CYGPRI_SER_TEST_OVERRIDE_INT_1 and CYGPRI_SER_TEST_OVERRIDE_INT_2
|
// Note that CYGPRI_SER_TEST_OVERRIDE_INT_1 and CYGPRI_SER_TEST_OVERRIDE_INT_2
|
// may also be exported. These identify interrupts that should be reclaimed
|
// may also be exported. These identify interrupts that should be reclaimed
|
// from the ROM monitor before the test is started.
|
// from the ROM monitor before the test is started.
|
|
|
#if defined(CYGPKG_HAL_POWERPC_MBX) \
|
#if defined(CYGPKG_HAL_POWERPC_MBX) \
|
&& defined(CYGPKG_HAL_QUICC) \
|
&& defined(CYGPKG_HAL_QUICC) \
|
&& defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC) \
|
&& defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC) \
|
&& defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1)
|
&& defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1)
|
# define TEST_CRASH_ID "ppcmbx"
|
# define TEST_CRASH_ID "ppcmbx"
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY1)
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY1)
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
|
# endif
|
# endif
|
#endif
|
#endif
|
#if defined(CYGPKG_HAL_MN10300_AM31_STDEVAL1) \
|
#if defined(CYGPKG_HAL_MN10300_AM31_STDEVAL1) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300_SERIAL2)
|
&& defined(CYGPKG_IO_SERIAL_MN10300_SERIAL2)
|
# define TEST_CRASH_ID "am31st"
|
# define TEST_CRASH_ID "am31st"
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY2)
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY2)
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
|
# endif
|
# endif
|
#endif
|
#endif
|
#if defined(CYGPKG_HAL_MN10300_AM33_STB) \
|
#if defined(CYGPKG_HAL_MN10300_AM33_STB) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300) \
|
&& defined(CYGPKG_IO_SERIAL_MN10300_SERIAL0)
|
&& defined(CYGPKG_IO_SERIAL_MN10300_SERIAL0)
|
# define TEST_CRASH_ID "am33st"
|
# define TEST_CRASH_ID "am33st"
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME
|
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY0)
|
# if defined(CYGPKG_IO_SERIAL_TTY_TTY0)
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY0_DEV
|
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY0_DEV
|
# endif
|
# endif
|
#endif
|
#endif
|
|
|
// We can't rely on haldiag for ser_filter detection - it may not define
|
// We can't rely on haldiag for ser_filter detection - it may not define
|
// a working character reading function.
|
// a working character reading function.
|
#ifndef TEST_SER_DEV
|
#ifndef TEST_SER_DEV
|
# define SER_NOP_TEST
|
# define SER_NOP_TEST
|
# define TTY_NOP_TEST
|
# define TTY_NOP_TEST
|
# define TEST_SER_DEV "/dev/null"
|
# define TEST_SER_DEV "/dev/null"
|
# define TEST_TTY_DEV "/dev/null"
|
# define TEST_TTY_DEV "/dev/null"
|
#else
|
#else
|
# ifndef TEST_TTY_DEV
|
# ifndef TEST_TTY_DEV
|
# define TTY_NOP_TEST
|
# define TTY_NOP_TEST
|
# define TEST_TTY_DEV "/dev/null"
|
# define TEST_TTY_DEV "/dev/null"
|
# endif
|
# endif
|
#endif
|
#endif
|
|
|
#ifndef TEST_CRASH_ID
|
#ifndef TEST_CRASH_ID
|
#define TEST_CRASH_ID "......"
|
#define TEST_CRASH_ID "......"
|
#endif
|
#endif
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Crash types
|
// Crash types
|
// Eventually this will be moved into a separate header file so a script
|
// Eventually this will be moved into a separate header file so a script
|
// can read the definitions and use the output formats/codes to analyze
|
// can read the definitions and use the output formats/codes to analyze
|
// test results. For now we just keep it here...
|
// test results. For now we just keep it here...
|
|
|
// FAILCODE:
|
// FAILCODE:
|
// tttttt: 6 letter target code
|
// tttttt: 6 letter target code
|
// cccc: crash code (16bit hex value)
|
// cccc: crash code (16bit hex value)
|
|
|
#define TEST_CRASH(__h, __code, __msg, args...) \
|
#define TEST_CRASH(__h, __code, __msg, args...) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
int __len = 1; \
|
int __len = 1; \
|
/* Try to flush remaining input */ \
|
/* Try to flush remaining input */ \
|
cyg_thread_delay(50); \
|
cyg_thread_delay(50); \
|
cyg_io_get_config(__h, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, \
|
cyg_io_get_config(__h, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, \
|
0, &__len); \
|
0, &__len); \
|
diag_printf("FAILCODE:<" TEST_CRASH_ID ":%04x:" __code, ## args); \
|
diag_printf("FAILCODE:<" TEST_CRASH_ID ":%04x:" __code, ## args); \
|
diag_printf("!>\n"); \
|
diag_printf("!>\n"); \
|
CYG_FAIL(__msg); \
|
CYG_FAIL(__msg); \
|
hang(); \
|
hang(); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
// Target IO
|
// Target IO
|
#define TEST_CRASH_IO 0x0000
|
#define TEST_CRASH_IO 0x0000
|
#define TEST_CRASH_IO_READ "%d", 0x0001
|
#define TEST_CRASH_IO_READ "%d", 0x0001
|
#define TEST_CRASH_IO_WRITE "%d", 0x0002
|
#define TEST_CRASH_IO_WRITE "%d", 0x0002
|
#define TEST_CRASH_IO_DRAIN "%d", 0x0003
|
#define TEST_CRASH_IO_DRAIN "%d", 0x0003
|
#define TEST_CRASH_IO_GET_CFG "%d", 0x0004
|
#define TEST_CRASH_IO_GET_CFG "%d", 0x0004
|
#define TEST_CRASH_IO_SET_CFG "%d", 0x0005
|
#define TEST_CRASH_IO_SET_CFG "%d", 0x0005
|
|
|
// Target
|
// Target
|
#define TEST_CRASH_CRC 0x0010
|
#define TEST_CRASH_CRC 0x0010
|
#define TEST_CRASH_CRC_CHAR "%02x", 0x0011
|
#define TEST_CRASH_CRC_CHAR "%02x", 0x0011
|
#define TEST_CRASH_CRC_BAD "%08x:%08x", 0x0012
|
#define TEST_CRASH_CRC_BAD "%08x:%08x", 0x0012
|
#define TEST_CRASH_CRC_HOST "", 0x0013
|
#define TEST_CRASH_CRC_HOST "", 0x0013
|
|
|
// Protocol errors
|
// Protocol errors
|
#define TEST_CRASH_PROT 0x1000
|
#define TEST_CRASH_PROT 0x1000
|
#define TEST_CRASH_PROT_BIN_MODE "%d", 0x1080
|
#define TEST_CRASH_PROT_BIN_MODE "%d", 0x1080
|
#define TEST_CRASH_PROT_TEXT "%d", 0x1100
|
#define TEST_CRASH_PROT_TEXT "%d", 0x1100
|
|
|
#define TEST_CRASH_HOST_xx 0xf000
|
#define TEST_CRASH_HOST_xx 0xf000
|
#define TEST_CRASH_HOST_TIMEOUT "%d:%d:%d:%d", 0xf000
|
#define TEST_CRASH_HOST_TIMEOUT "%d:%d:%d:%d", 0xf000
|
// command#, read invocation#, expected, actual
|
// command#, read invocation#, expected, actual
|
#define TEST_CRASH_HOST_CRC_BAD "%d:%08x:%08x:%d:%02x:%02x", 0xf010
|
#define TEST_CRASH_HOST_CRC_BAD "%d:%08x:%08x:%d:%02x:%02x", 0xf010
|
// command#, expected CRC, actual, index, expected char, actual
|
// command#, expected CRC, actual, index, expected char, actual
|
#define TEST_CRASH_HOST_DUPLEX_BAD "%d:%d:%02x:%02x", 0xf020
|
#define TEST_CRASH_HOST_DUPLEX_BAD "%d:%d:%02x:%02x", 0xf020
|
// command#, index, expected char, actual
|
// command#, index, expected char, actual
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// The data in buffer and the cmd buffer
|
// The data in buffer and the cmd buffer
|
#ifndef IN_BUFFER_SIZE
|
#ifndef IN_BUFFER_SIZE
|
# define IN_BUFFER_SIZE 1024
|
# define IN_BUFFER_SIZE 1024
|
#endif
|
#endif
|
cyg_uint8 in_buffer[IN_BUFFER_SIZE];
|
cyg_uint8 in_buffer[IN_BUFFER_SIZE];
|
|
|
cyg_int8 cmd_buffer[128];
|
cyg_int8 cmd_buffer[128];
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Some types specific to the testing protocol.
|
// Some types specific to the testing protocol.
|
typedef enum {
|
typedef enum {
|
MODE_NO_ECHO = 0,
|
MODE_NO_ECHO = 0,
|
MODE_EOP_ECHO,
|
MODE_EOP_ECHO,
|
MODE_DUPLEX_ECHO
|
MODE_DUPLEX_ECHO
|
} cyg_mode_t;
|
} cyg_mode_t;
|
|
|
typedef enum {
|
typedef enum {
|
TEST_RETURN_OK = ENOERR,
|
TEST_RETURN_OK = ENOERR,
|
TEST_RETURN_NA
|
TEST_RETURN_NA
|
} cyg_test_return_t;
|
} cyg_test_return_t;
|
|
|
typedef struct ser_cfg {
|
typedef struct ser_cfg {
|
cyg_serial_baud_rate_t baud_rate;
|
cyg_serial_baud_rate_t baud_rate;
|
cyg_serial_word_length_t data_bits;
|
cyg_serial_word_length_t data_bits;
|
cyg_serial_stop_bits_t stop_bits;
|
cyg_serial_stop_bits_t stop_bits;
|
cyg_serial_parity_t parity;
|
cyg_serial_parity_t parity;
|
cyg_uint32 flags;
|
cyg_uint32 flags;
|
// etc...
|
// etc...
|
} cyg_ser_cfg_t;
|
} cyg_ser_cfg_t;
|
|
|
typedef enum {
|
typedef enum {
|
OPT_SERIAL_DEBUG = 0,
|
OPT_SERIAL_DEBUG = 0,
|
OPT_VERBOSE_LEVEL
|
OPT_VERBOSE_LEVEL
|
} cyg_option_t;
|
} cyg_option_t;
|
|
|
typedef enum {
|
typedef enum {
|
_NONE = 0,
|
_NONE = 0,
|
PROTOCOL_PROGRESS,
|
PROTOCOL_PROGRESS,
|
PROTOCOL_DATA,
|
PROTOCOL_DATA,
|
} cyg_verbosity_level_t;
|
} cyg_verbosity_level_t;
|
|
|
|
|
// A few predifined option macros. Use after test_ping().
|
// A few predifined option macros. Use after test_ping().
|
#define TEST_OPTIONS(__handle, __array) \
|
#define TEST_OPTIONS(__handle, __array) \
|
test_options(__handle, sizeof(__array)/8, __array)
|
test_options(__handle, sizeof(__array)/8, __array)
|
|
|
#define TEST_HOST_DEBUG(__handle) \
|
#define TEST_HOST_DEBUG(__handle) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
cyg_uint32 __options[] = {OPT_SERIAL_DEBUG, 1}; \
|
cyg_uint32 __options[] = {OPT_SERIAL_DEBUG, 1}; \
|
test_options((__handle), sizeof(__options)/8, \
|
test_options((__handle), sizeof(__options)/8, \
|
__options); \
|
__options); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
#define TEST_HOST_PROGRESS(__handle) \
|
#define TEST_HOST_PROGRESS(__handle) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
cyg_uint32 __options[] = \
|
cyg_uint32 __options[] = \
|
{OPT_SERIAL_DEBUG, 1, \
|
{OPT_SERIAL_DEBUG, 1, \
|
OPT_VERBOSE_LEVEL, PROTOCOL_PROGRESS}; \
|
OPT_VERBOSE_LEVEL, PROTOCOL_PROGRESS}; \
|
test_options((__handle), sizeof(__options)/8, \
|
test_options((__handle), sizeof(__options)/8, \
|
__options); \
|
__options); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
#define TEST_HOST_DATA(__handle) \
|
#define TEST_HOST_DATA(__handle) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
cyg_uint32 __options[] = \
|
cyg_uint32 __options[] = \
|
{OPT_SERIAL_DEBUG, 1, \
|
{OPT_SERIAL_DEBUG, 1, \
|
OPT_VERBOSE_LEVEL, PROTOCOL_DATA}; \
|
OPT_VERBOSE_LEVEL, PROTOCOL_DATA}; \
|
test_options((__handle), sizeof(__options)/8, \
|
test_options((__handle), sizeof(__options)/8, \
|
__options); \
|
__options); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// A few predefined configurations. These must all be valid for any
|
// A few predefined configurations. These must all be valid for any
|
// given target until change_config is behaving correctly.
|
// given target until change_config is behaving correctly.
|
cyg_ser_cfg_t test_configs[] = {
|
cyg_ser_cfg_t test_configs[] = {
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_9600)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_9600)
|
{ CYGNUM_SERIAL_BAUD_9600, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_9600, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_14400)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_14400)
|
#if !defined(CYGPKG_HAL_MN10300_AM31) && \
|
#if !defined(CYGPKG_HAL_MN10300_AM31) && \
|
!defined(CYGPKG_HAL_MN10300_AM33)
|
!defined(CYGPKG_HAL_MN10300_AM33)
|
{ CYGNUM_SERIAL_BAUD_14400, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_14400, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_38400)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_38400)
|
{ CYGNUM_SERIAL_BAUD_38400, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_38400, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_57600)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_57600)
|
#if !defined(CYGPKG_HAL_MN10300_AM33)
|
#if !defined(CYGPKG_HAL_MN10300_AM33)
|
{ CYGNUM_SERIAL_BAUD_57600, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_57600, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_115200)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_115200)
|
#if !defined(CYGPKG_HAL_MN10300_STDEVAL1)
|
#if !defined(CYGPKG_HAL_MN10300_STDEVAL1)
|
{ CYGNUM_SERIAL_BAUD_115200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_115200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
|
// One stop bit, even parity
|
// One stop bit, even parity
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_EVEN,
|
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_EVEN,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
|
// Two stop bits, even parity
|
// Two stop bits, even parity
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_EVEN,
|
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_EVEN,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
|
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
|
// Two stop bits, no parity
|
// Two stop bits, no parity
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
|
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_NONE,
|
CYGNUM_SERIAL_FLOW_NONE },
|
CYGNUM_SERIAL_FLOW_NONE },
|
#endif
|
#endif
|
};
|
};
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Macros to help extract values from the argument string.
|
// Macros to help extract values from the argument string.
|
// Note: This is probably not an ideal solution, but it was easy to make :)
|
// Note: This is probably not an ideal solution, but it was easy to make :)
|
|
|
#define INIT_VALUE(__args) \
|
#define INIT_VALUE(__args) \
|
unsigned int v; \
|
unsigned int v; \
|
char *__ptr1, *__ptr2 = (__args)
|
char *__ptr1, *__ptr2 = (__args)
|
|
|
#define SET_VALUE(__slot) \
|
#define SET_VALUE(__slot) \
|
do { \
|
do { \
|
__ptr1 = index(__ptr2, (int) ':'); \
|
__ptr1 = index(__ptr2, (int) ':'); \
|
if (__ptr1) \
|
if (__ptr1) \
|
*__ptr1 = 0; \
|
*__ptr1 = 0; \
|
v = atoi(__ptr2); \
|
v = atoi(__ptr2); \
|
__ptr2 = __ptr1+1; \
|
__ptr2 = __ptr1+1; \
|
(__slot) = v; \
|
(__slot) = v; \
|
} while (0)
|
} while (0)
|
|
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// CRC magic - it's a bit of a hack for now.
|
// CRC magic - it's a bit of a hack for now.
|
// FIXME: standard definition?
|
// FIXME: standard definition?
|
#define ADD_CRC_BYTE(__crc, __c) \
|
#define ADD_CRC_BYTE(__crc, __c) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
(__crc) = ((__crc) << 1) ^ (__c); \
|
(__crc) = ((__crc) << 1) ^ (__c); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
// FIXME: Hack to allow easy ASCII transfer.
|
// FIXME: Hack to allow easy ASCII transfer.
|
#define FIX_CRC(__crc, __icrc) \
|
#define FIX_CRC(__crc, __icrc) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
__icrc = (int) (__crc); \
|
__icrc = (int) (__crc); \
|
if (__icrc < 0) \
|
if (__icrc < 0) \
|
__icrc = -__icrc; \
|
__icrc = -__icrc; \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Macros for read/write to serial with error cheking.
|
// Macros for read/write to serial with error cheking.
|
static volatile cyg_uint32 r_stamp;
|
static volatile cyg_uint32 r_stamp;
|
static volatile int aborted;
|
static volatile int aborted;
|
|
|
// This routine will be called if the read "times out"
|
// This routine will be called if the read "times out"
|
static void
|
static void
|
do_abort(void *handle)
|
do_abort(void *handle)
|
{
|
{
|
cyg_io_handle_t io_handle = (cyg_io_handle_t)handle;
|
cyg_io_handle_t io_handle = (cyg_io_handle_t)handle;
|
cyg_int32 len = 1; // Need something here
|
cyg_int32 len = 1; // Need something here
|
cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len);
|
cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len);
|
aborted = 1;
|
aborted = 1;
|
}
|
}
|
#include "timeout.inl"
|
#include "timeout.inl"
|
|
|
// Read with timeout (__t = timeout in ticks, int* __r = result)
|
// Read with timeout (__t = timeout in ticks, int* __r = result)
|
#define Tcyg_io_read_timeout(__h, __d, __l, __t, __r) \
|
#define Tcyg_io_read_timeout(__h, __d, __l, __t, __r) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
int __res; \
|
int __res; \
|
r_stamp = timeout((__t), do_abort, (__h)); \
|
r_stamp = timeout((__t), do_abort, (__h)); \
|
__res = cyg_io_read((__h), (__d), (__l)); \
|
__res = cyg_io_read((__h), (__d), (__l)); \
|
if (ENOERR != __res && -EINTR != __res) { \
|
if (ENOERR != __res && -EINTR != __res) { \
|
TEST_CRASH(__h, TEST_CRASH_IO_READ, \
|
TEST_CRASH(__h, TEST_CRASH_IO_READ, \
|
"cyg_io_read/timeout failed", __res); \
|
"cyg_io_read/timeout failed", __res); \
|
} \
|
} \
|
*(__r) = __res; \
|
*(__r) = __res; \
|
untimeout(r_stamp); \
|
untimeout(r_stamp); \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
#define Tcyg_io_read(__h, __d, __l) \
|
#define Tcyg_io_read(__h, __d, __l) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
int __res = cyg_io_read((__h), (__d), (__l)); \
|
int __res = cyg_io_read((__h), (__d), (__l)); \
|
if (ENOERR != __res) { \
|
if (ENOERR != __res) { \
|
TEST_CRASH(__h, TEST_CRASH_IO_READ, \
|
TEST_CRASH(__h, TEST_CRASH_IO_READ, \
|
"cyg_io_read failed", __res); \
|
"cyg_io_read failed", __res); \
|
} \
|
} \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
#define Tcyg_io_write(__h, __d, __l) \
|
#define Tcyg_io_write(__h, __d, __l) \
|
CYG_MACRO_START \
|
CYG_MACRO_START \
|
int __res; \
|
int __res; \
|
cyg_uint32 __len = 1; \
|
cyg_uint32 __len = 1; \
|
__res = cyg_io_write((__h), (__d), (__l)); \
|
__res = cyg_io_write((__h), (__d), (__l)); \
|
if (ENOERR != __res) { \
|
if (ENOERR != __res) { \
|
TEST_CRASH(__h, TEST_CRASH_IO_WRITE, \
|
TEST_CRASH(__h, TEST_CRASH_IO_WRITE, \
|
"cyg_io_write failed", __res); \
|
"cyg_io_write failed", __res); \
|
} \
|
} \
|
__res = cyg_io_get_config((__h), \
|
__res = cyg_io_get_config((__h), \
|
CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, \
|
CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, \
|
0, &__len); \
|
0, &__len); \
|
if (ENOERR != __res) { \
|
if (ENOERR != __res) { \
|
TEST_CRASH(__h, TEST_CRASH_IO_DRAIN, \
|
TEST_CRASH(__h, TEST_CRASH_IO_DRAIN, \
|
"DRAIN failed", __res); \
|
"DRAIN failed", __res); \
|
} \
|
} \
|
CYG_MACRO_END
|
CYG_MACRO_END
|
|
|
|
|
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
// Some libc like functions that are handy to have around.
|
// Some libc like functions that are handy to have around.
|
static int
|
static int
|
strlen(const char *c)
|
strlen(const char *c)
|
{
|
{
|
int l = 0;
|
int l = 0;
|
while (*c++) l++;
|
while (*c++) l++;
|
return l;
|
return l;
|
}
|
}
|
|
|
static char*
|
static char*
|
strcpy(char* dest, const char* src)
|
strcpy(char* dest, const char* src)
|
{
|
{
|
char c;
|
char c;
|
while ((c = *src++)) {
|
while ((c = *src++)) {
|
*dest++ = c;
|
*dest++ = c;
|
}
|
}
|
*dest = c;
|
*dest = c;
|
|
|
return dest;
|
return dest;
|
}
|
}
|
|
|
static char*
|
static char*
|
itoa(char* dest, int v)
|
itoa(char* dest, int v)
|
{
|
{
|
char b[16];
|
char b[16];
|
char* p = &b[16];
|
char* p = &b[16];
|
|
|
*--p = 0;
|
*--p = 0;
|
if (v) {
|
if (v) {
|
while (v){
|
while (v){
|
*--p = (v % 10) + '0';
|
*--p = (v % 10) + '0';
|
v = v / 10;
|
v = v / 10;
|
}
|
}
|
} else
|
} else
|
*--p = '0';
|
*--p = '0';
|
|
|
return strcpy(dest, p);
|
return strcpy(dest, p);
|
}
|
}
|
|
|
#define min(_a, _b) ((_a) < (_b)) ? (_a) : (_b)
|
#define min(_a, _b) ((_a) < (_b)) ? (_a) : (_b)
|
|
|
void
|
void
|
hang(void)
|
hang(void)
|
{
|
{
|
while (1);
|
while (1);
|
}
|
}
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Configuration changing function.
|
// Configuration changing function.
|
//
|
//
|
// First change to the new config and back again to determine if the driver
|
// First change to the new config and back again to determine if the driver
|
// can handle the config.
|
// can handle the config.
|
// If not, return error.
|
// If not, return error.
|
//
|
//
|
// Then query the host for its capability to use the config:
|
// Then query the host for its capability to use the config:
|
// Format out:
|
// Format out:
|
// "@CONFIG::<#data bits>:<#stop bits>::!"
|
// "@CONFIG::<#data bits>:<#stop bits>::!"
|
// Format in:
|
// Format in:
|
// OK/ER
|
// OK/ER
|
//
|
//
|
// On ER, return error.
|
// On ER, return error.
|
//
|
//
|
// On OK, change to the new configuration. Resynchronize with the host:
|
// On OK, change to the new configuration. Resynchronize with the host:
|
// Target waits for host to send S(ync)
|
// Target waits for host to send S(ync)
|
// [host will delay at least .1 secs after changing baud rate so the
|
// [host will delay at least .1 secs after changing baud rate so the
|
// line has time to settle.]
|
// line has time to settle.]
|
//
|
//
|
// When receiving S(ync), target replies OK to the host which then
|
// When receiving S(ync), target replies OK to the host which then
|
// acknowledges with D(one).
|
// acknowledges with D(one).
|
//
|
//
|
// Host can also send R(esync) which means it didn't receieve the OK. If
|
// Host can also send R(esync) which means it didn't receieve the OK. If
|
// so the target resends its S(ync) message.
|
// so the target resends its S(ync) message.
|
//
|
//
|
// If the synchronization has not succeeded within 1 second
|
// If the synchronization has not succeeded within 1 second
|
// (configurable in the protocol), both host and target will revert to
|
// (configurable in the protocol), both host and target will revert to
|
// the previous configuration and attempt to synchronize again. If
|
// the previous configuration and attempt to synchronize again. If
|
// this fails, this call will hang and the host will consider the test
|
// this fails, this call will hang and the host will consider the test
|
// a failure.
|
// a failure.
|
//
|
//
|
// To Do:
|
// To Do:
|
// Host&protocol currently only supports:
|
// Host&protocol currently only supports:
|
// - no/even parity
|
// - no/even parity
|
int
|
int
|
change_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg)
|
change_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg)
|
{
|
{
|
cyg_serial_info_t old_cfg, new_cfg;
|
cyg_serial_info_t old_cfg, new_cfg;
|
const char cmd[] = "@CONFIG:";
|
const char cmd[] = "@CONFIG:";
|
char reply[2];
|
char reply[2];
|
int msglen;
|
int msglen;
|
int res, len;
|
int res, len;
|
cyg_uint8 *p1;
|
cyg_uint8 *p1;
|
|
|
// Prepare the command.
|
// Prepare the command.
|
p1 = &cmd_buffer[0];
|
p1 = &cmd_buffer[0];
|
p1 = strcpy(p1, &cmd[0]);
|
p1 = strcpy(p1, &cmd[0]);
|
p1 = itoa(p1, cfg->baud_rate);
|
p1 = itoa(p1, cfg->baud_rate);
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, cfg->data_bits);
|
p1 = itoa(p1, cfg->data_bits);
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, cfg->stop_bits);
|
p1 = itoa(p1, cfg->stop_bits);
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, cfg->parity);
|
p1 = itoa(p1, cfg->parity);
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, cfg->flags);
|
p1 = itoa(p1, cfg->flags);
|
*p1++ = '!';
|
*p1++ = '!';
|
*p1 = 0; // note: we may append to this later
|
*p1 = 0; // note: we may append to this later
|
|
|
// Tell user what we're up to.
|
// Tell user what we're up to.
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
|
|
// Change to new config and then back to determine if the driver likes it.
|
// Change to new config and then back to determine if the driver likes it.
|
len = sizeof(old_cfg);
|
len = sizeof(old_cfg);
|
res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO,
|
res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO,
|
&old_cfg, &len);
|
&old_cfg, &len);
|
res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO,
|
res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO,
|
&new_cfg, &len);
|
&new_cfg, &len);
|
|
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
TEST_CRASH(handle, TEST_CRASH_IO_GET_CFG,
|
TEST_CRASH(handle, TEST_CRASH_IO_GET_CFG,
|
"Can't get serial config", res);
|
"Can't get serial config", res);
|
}
|
}
|
|
|
new_cfg.baud = cfg->baud_rate;
|
new_cfg.baud = cfg->baud_rate;
|
new_cfg.word_length = cfg->data_bits;
|
new_cfg.word_length = cfg->data_bits;
|
new_cfg.stop = cfg->stop_bits;
|
new_cfg.stop = cfg->stop_bits;
|
new_cfg.parity = cfg->parity;
|
new_cfg.parity = cfg->parity;
|
new_cfg.flags = cfg->flags;
|
new_cfg.flags = cfg->flags;
|
|
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
&new_cfg, &len);
|
&new_cfg, &len);
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
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
|
// Driver didn't like it. It will not have changed anything, so it's
|
// safe to return now.
|
// safe to return now.
|
if (ENOERR != res) {
|
if (ENOERR != res) {
|
// Let user know that the config was skipped due to the target.
|
// Let user know that the config was skipped due to the target.
|
const char txt_tskipped[] = "- skipped by target!";
|
const char txt_tskipped[] = "- skipped by target!";
|
p1 = strcpy(p1, txt_tskipped);
|
p1 = strcpy(p1, txt_tskipped);
|
*p1 = 0;
|
*p1 = 0;
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
return res;
|
return res;
|
}
|
}
|
|
|
// Succeeded. Change back to the original config so we can communicate
|
// Succeeded. Change back to the original config so we can communicate
|
// with the host.
|
// with the host.
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
&old_cfg, &len);
|
&old_cfg, &len);
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
|
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
"Can't set serial config", res);
|
"Can't set serial config", res);
|
}
|
}
|
|
|
// Send command to host and read host's reply.
|
// Send command to host and read host's reply.
|
msglen = strlen(&cmd_buffer[0]);
|
msglen = strlen(&cmd_buffer[0]);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
msglen = 2;
|
msglen = 2;
|
Tcyg_io_read(handle, &reply[0], &msglen);
|
Tcyg_io_read(handle, &reply[0], &msglen);
|
|
|
// Did host accept configuration?
|
// Did host accept configuration?
|
if ('O' != reply[0] || 'K' != reply[1]) {
|
if ('O' != reply[0] || 'K' != reply[1]) {
|
// Let user know that the config was skipped due to the host.
|
// Let user know that the config was skipped due to the host.
|
const char txt_hskipped[] = "- skipped by host!";
|
const char txt_hskipped[] = "- skipped by host!";
|
p1 = strcpy(p1, txt_hskipped);
|
p1 = strcpy(p1, txt_hskipped);
|
*p1 = 0;
|
*p1 = 0;
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
diag_printf("Host didn't accept config (%02x, %02x).\n",
|
diag_printf("Host didn't accept config (%02x, %02x).\n",
|
reply[0], reply[1]);
|
reply[0], reply[1]);
|
|
|
res = ENOSUPP;
|
res = ENOSUPP;
|
return res;
|
return res;
|
}
|
}
|
|
|
// Now change config and wait for host to send us a S(ync)
|
// Now change config and wait for host to send us a S(ync)
|
// character.
|
// character.
|
// Loop until protocol exchange completed. This may hang (as seen
|
// Loop until protocol exchange completed. This may hang (as seen
|
// from the host), but only when we get totally lost, in which
|
// 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
|
// case there's not much else to do really. In this case the host
|
// will consider the test a FAIL.
|
// will consider the test a FAIL.
|
len = sizeof(new_cfg);
|
len = sizeof(new_cfg);
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
&new_cfg, &len);
|
&new_cfg, &len);
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
"Can't set serial config/2", res);
|
"Can't set serial config/2", res);
|
}
|
}
|
|
|
{
|
{
|
int change_succeeded = 0;
|
int change_succeeded = 0;
|
int using_old_config = 0;
|
int using_old_config = 0;
|
char in_buf[1];
|
char in_buf[1];
|
int len;
|
int len;
|
int saw_host_sync;
|
int saw_host_sync;
|
|
|
for (;;) {
|
for (;;) {
|
aborted = 0; // global abort flag
|
aborted = 0; // global abort flag
|
|
|
// FIXME: Timeout time needs to be configurable, and needs to
|
// FIXME: Timeout time needs to be configurable, and needs to
|
// be sent to the host before getting here. That would allow
|
// be sent to the host before getting here. That would allow
|
// changing the timeout by just rebuilding the test - without
|
// changing the timeout by just rebuilding the test - without
|
// changing the host software.
|
// changing the host software.
|
saw_host_sync = 0;
|
saw_host_sync = 0;
|
r_stamp = timeout(100, do_abort, handle);
|
r_stamp = timeout(100, do_abort, handle);
|
while(!aborted) {
|
while(!aborted) {
|
len = 1;
|
len = 1;
|
in_buf[0] = 0;
|
in_buf[0] = 0;
|
res = cyg_io_read(handle, in_buf, &len);
|
res = cyg_io_read(handle, in_buf, &len);
|
if (ENOERR != res && -EINTR != res) {
|
if (ENOERR != res && -EINTR != res) {
|
// We may have to reset the driver here if the fail
|
// We may have to reset the driver here if the fail
|
// was due to a framing or parity error.
|
// was due to a framing or parity error.
|
break;
|
break;
|
}
|
}
|
if ('R' == in_buf[0]) {
|
if ('R' == in_buf[0]) {
|
// Resync - host didn't see our message. Try again.
|
// Resync - host didn't see our message. Try again.
|
saw_host_sync = 0;
|
saw_host_sync = 0;
|
} else if ('S' == in_buf[0] && !saw_host_sync) {
|
} else if ('S' == in_buf[0] && !saw_host_sync) {
|
// In sync - reply to host if we haven't already
|
// In sync - reply to host if we haven't already
|
char ok_msg[2] = "OK";
|
char ok_msg[2] = "OK";
|
int ok_len = 2;
|
int ok_len = 2;
|
Tcyg_io_write(handle, ok_msg, &ok_len);
|
Tcyg_io_write(handle, ok_msg, &ok_len);
|
saw_host_sync = 1;
|
saw_host_sync = 1;
|
} else if ('D' == in_buf[0] && saw_host_sync) {
|
} else if ('D' == in_buf[0] && saw_host_sync) {
|
// Done - exchange completed.
|
// Done - exchange completed.
|
change_succeeded = 1;
|
change_succeeded = 1;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
untimeout(r_stamp);
|
untimeout(r_stamp);
|
|
|
if (change_succeeded) {
|
if (change_succeeded) {
|
// If we had to revert to the old configuration, return error.
|
// If we had to revert to the old configuration, return error.
|
if (using_old_config)
|
if (using_old_config)
|
return -EIO;
|
return -EIO;
|
else
|
else
|
return ENOERR;
|
return ENOERR;
|
}
|
}
|
|
|
// We didn't synchronize with the host. Due to an IO error?
|
// We didn't synchronize with the host. Due to an IO error?
|
if (ENOERR != res && -EINTR != res) {
|
if (ENOERR != res && -EINTR != res) {
|
// We may have to reset the driver if the fail was due to
|
// We may have to reset the driver if the fail was due to
|
// a framing or parity error.
|
// a framing or parity error.
|
}
|
}
|
|
|
// Revert to the old configuration and try again.
|
// Revert to the old configuration and try again.
|
len = sizeof(old_cfg);
|
len = sizeof(old_cfg);
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO,
|
&old_cfg, &len);
|
&old_cfg, &len);
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
cyg_thread_delay(10); // Some chips don't like changes to happen to fast...
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG,
|
"Can't set serial config/3", res);
|
"Can't set serial config/3", res);
|
}
|
}
|
using_old_config = 1;
|
using_old_config = 1;
|
}
|
}
|
|
|
}
|
}
|
}
|
}
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
// Host sends CRC in decimal ASCII, terminated with !
|
// Host sends CRC in decimal ASCII, terminated with !
|
int
|
int
|
read_host_crc(cyg_io_handle_t handle)
|
read_host_crc(cyg_io_handle_t handle)
|
{
|
{
|
int crc, len;
|
int crc, len;
|
cyg_uint8 ch;
|
cyg_uint8 ch;
|
|
|
crc = 0;
|
crc = 0;
|
while (1) {
|
while (1) {
|
len = 1;
|
len = 1;
|
Tcyg_io_read(handle, &ch, &len);
|
Tcyg_io_read(handle, &ch, &len);
|
if ('!' == ch)
|
if ('!' == ch)
|
break;
|
break;
|
|
|
if (!((ch >= '0' && ch <= '9'))){
|
if (!((ch >= '0' && ch <= '9'))){
|
TEST_CRASH(handle, TEST_CRASH_CRC_CHAR,
|
TEST_CRASH(handle, TEST_CRASH_CRC_CHAR,
|
"Illegal CRC format from host", ch);
|
"Illegal CRC format from host", ch);
|
}
|
}
|
|
|
crc = crc*10 + (ch - '0');
|
crc = crc*10 + (ch - '0');
|
}
|
}
|
|
|
return crc;
|
return crc;
|
}
|
}
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// Test binary data transmission.
|
// Test binary data transmission.
|
// Format out:
|
// Format out:
|
// "@BINARY::!"
|
// "@BINARY::!"
|
// Format in:
|
// Format in:
|
// !<#size bytes data>
|
// !<#size bytes data>
|
// For echo modes, also:
|
// For echo modes, also:
|
// Format out:
|
// Format out:
|
// <#size bytes data>
|
// <#size bytes data>
|
// Format in:
|
// Format in:
|
// OK/ER
|
// OK/ER
|
// Format out:
|
// Format out:
|
// DONE
|
// DONE
|
//
|
//
|
// The last DONE allows the host to eat bytes if target is sending too many.
|
// The last DONE allows the host to eat bytes if target is sending too many.
|
//
|
//
|
// Mode:
|
// Mode:
|
// MODE_NO_ECHO:
|
// MODE_NO_ECHO:
|
// Just receive data and verify CRC.
|
// Just receive data and verify CRC.
|
// MODE_EOP_ECHO:
|
// MODE_EOP_ECHO:
|
// Receive data, verify CRC, resend data.
|
// Receive data, verify CRC, resend data.
|
// Expect OK/ER reply from host when done.
|
// Expect OK/ER reply from host when done.
|
// MODE_DUPLEX_ECHO:
|
// MODE_DUPLEX_ECHO:
|
// Receive data, echo data, verify CRC.
|
// Receive data, echo data, verify CRC.
|
// Expect OK/ER reply from host when done.
|
// Expect OK/ER reply from host when done.
|
//
|
//
|
// Note:
|
// Note:
|
// Using diag_printf while talking with the host may cause some funky
|
// Using diag_printf while talking with the host may cause some funky
|
// errors (bytes from the host side being lost!?!?)
|
// errors (bytes from the host side being lost!?!?)
|
//
|
//
|
// To Do:
|
// To Do:
|
// MODE_DUPLEX_ECHO:
|
// MODE_DUPLEX_ECHO:
|
// The current implementation is simple and may not stress the
|
// The current implementation is simple and may not stress the
|
// driver enough. Also, it's command packet format doesn't match
|
// driver enough. Also, it's command packet format doesn't match
|
// that of the other modes.
|
// that of the other modes.
|
|
|
cyg_test_return_t
|
cyg_test_return_t
|
test_binary(cyg_io_handle_t handle, int size, cyg_mode_t mode)
|
test_binary(cyg_io_handle_t handle, int size, cyg_mode_t mode)
|
{
|
{
|
const char cmd[] = "@BINARY:";
|
const char cmd[] = "@BINARY:";
|
int msglen;
|
int msglen;
|
cyg_uint32 xcrc;
|
cyg_uint32 xcrc;
|
int icrc, host_crc;
|
int icrc, host_crc;
|
cyg_uint8 *p1;
|
cyg_uint8 *p1;
|
cyg_int8 host_status = 'O'; // host is happy by default
|
cyg_int8 host_status = 'O'; // host is happy by default
|
|
|
// Verify that the test can be run with available ressources.
|
// Verify that the test can be run with available ressources.
|
if (MODE_EOP_ECHO == mode && size > IN_BUFFER_SIZE)
|
if (MODE_EOP_ECHO == mode && size > IN_BUFFER_SIZE)
|
return TEST_RETURN_NA;
|
return TEST_RETURN_NA;
|
|
|
// Prepare and send the command.
|
// Prepare and send the command.
|
p1 = &cmd_buffer[0];
|
p1 = &cmd_buffer[0];
|
p1 = strcpy(p1, &cmd[0]);
|
p1 = strcpy(p1, &cmd[0]);
|
p1 = itoa(p1, size);
|
p1 = itoa(p1, size);
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, mode);
|
p1 = itoa(p1, mode);
|
*p1++ = '!';
|
*p1++ = '!';
|
*p1++ = 0;
|
*p1++ = 0;
|
|
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
|
|
msglen = strlen(&cmd_buffer[0]);
|
msglen = strlen(&cmd_buffer[0]);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
|
|
// Get CRC back.
|
// Get CRC back.
|
host_crc = read_host_crc(handle);
|
host_crc = read_host_crc(handle);
|
|
|
// Depending on mode, start reading data.
|
// Depending on mode, start reading data.
|
xcrc = 0;
|
xcrc = 0;
|
switch (mode) {
|
switch (mode) {
|
case MODE_NO_ECHO:
|
case MODE_NO_ECHO:
|
{
|
{
|
// Break transfers into chunks no larger than the buffer size.
|
// Break transfers into chunks no larger than the buffer size.
|
int tx_len, chunk_len, i;
|
int tx_len, chunk_len, i;
|
while (size > 0) {
|
while (size > 0) {
|
chunk_len = min(IN_BUFFER_SIZE, size);
|
chunk_len = min(IN_BUFFER_SIZE, size);
|
tx_len = chunk_len;
|
tx_len = chunk_len;
|
size -= chunk_len;
|
size -= chunk_len;
|
|
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
|
|
for (i = 0; i < tx_len; i++) {
|
for (i = 0; i < tx_len; i++) {
|
ADD_CRC_BYTE(xcrc, in_buffer[i]);
|
ADD_CRC_BYTE(xcrc, in_buffer[i]);
|
}
|
}
|
}
|
}
|
|
|
// Reply that we have completed the test.
|
// Reply that we have completed the test.
|
{
|
{
|
const char msg_done[] = "DONE";
|
const char msg_done[] = "DONE";
|
|
|
chunk_len = strlen(&msg_done[0]);
|
chunk_len = strlen(&msg_done[0]);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
}
|
}
|
|
|
}
|
}
|
break;
|
break;
|
case MODE_EOP_ECHO:
|
case MODE_EOP_ECHO:
|
{
|
{
|
// We have already checked that the in buffer is large enough.
|
// We have already checked that the in buffer is large enough.
|
int i, tx_len, chunk_len;
|
int i, tx_len, chunk_len;
|
chunk_len = tx_len = size;
|
chunk_len = tx_len = size;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
|
|
for (i = 0; i < tx_len; i++) {
|
for (i = 0; i < tx_len; i++) {
|
ADD_CRC_BYTE(xcrc, in_buffer[i]);
|
ADD_CRC_BYTE(xcrc, in_buffer[i]);
|
}
|
}
|
|
|
// Echo data back.
|
// Echo data back.
|
chunk_len = size;
|
chunk_len = size;
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
|
|
// Now read host side's status
|
// Now read host side's status
|
chunk_len = 2;
|
chunk_len = 2;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
host_status = in_buffer[0];
|
host_status = in_buffer[0];
|
|
|
// Reply that we have completed the test.
|
// Reply that we have completed the test.
|
{
|
{
|
const char msg_done[] = "DONE";
|
const char msg_done[] = "DONE";
|
|
|
chunk_len = strlen(&msg_done[0]);
|
chunk_len = strlen(&msg_done[0]);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
}
|
}
|
}
|
}
|
break;
|
break;
|
case MODE_DUPLEX_ECHO:
|
case MODE_DUPLEX_ECHO:
|
{
|
{
|
int chunk_len;
|
int chunk_len;
|
int block_size = 64;
|
int block_size = 64;
|
|
|
// This is a simple implementation (maybe too simple).
|
// This is a simple implementation (maybe too simple).
|
// Host sends 4 packets with the same size (64 bytes atm).
|
// Host sends 4 packets with the same size (64 bytes atm).
|
// Target echoes in this way:
|
// Target echoes in this way:
|
// packet1 -> packet1
|
// packet1 -> packet1
|
// packet2 -> packet2, packet2
|
// packet2 -> packet2, packet2
|
// packet3 -> packet3
|
// packet3 -> packet3
|
// packet4 -> /dev/null
|
// packet4 -> /dev/null
|
//
|
//
|
// The reads/writes are interleaved in a way that should ensure
|
// The reads/writes are interleaved in a way that should ensure
|
// the target out buffer to be full before the target starts to read
|
// the target out buffer to be full before the target starts to read
|
// packet3. That is, the target should be both receiving (packet3)
|
// packet3. That is, the target should be both receiving (packet3)
|
// and sending (packet2) at the same time.
|
// and sending (packet2) at the same time.
|
|
|
while (size--) {
|
while (size--) {
|
// block_size -> block_size
|
// block_size -> block_size
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
|
|
// block_size -> 2 x block_size
|
// block_size -> 2 x block_size
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
|
|
// block_size -> block_size
|
// block_size -> block_size
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_write(handle, &in_buffer[0], &chunk_len);
|
|
|
// block_size -> 0
|
// block_size -> 0
|
chunk_len = block_size;
|
chunk_len = block_size;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
}
|
}
|
|
|
// Kill the CRC. Leave packet verification to the host for now.
|
// Kill the CRC. Leave packet verification to the host for now.
|
xcrc = host_crc = 0;
|
xcrc = host_crc = 0;
|
|
|
// Now read host side's status
|
// Now read host side's status
|
chunk_len = 2;
|
chunk_len = 2;
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
Tcyg_io_read(handle, &in_buffer[0], &chunk_len);
|
host_status = in_buffer[0];
|
host_status = in_buffer[0];
|
|
|
// Reply that we have completed the test.
|
// Reply that we have completed the test.
|
{
|
{
|
const char msg_done[] = "DONE";
|
const char msg_done[] = "DONE";
|
|
|
chunk_len = strlen(&msg_done[0]);
|
chunk_len = strlen(&msg_done[0]);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
Tcyg_io_write(handle, &msg_done[0], &chunk_len);
|
}
|
}
|
}
|
}
|
break;
|
break;
|
default:
|
default:
|
TEST_CRASH(handle, TEST_CRASH_PROT_BIN_MODE,
|
TEST_CRASH(handle, TEST_CRASH_PROT_BIN_MODE,
|
"Unknown mode", mode);
|
"Unknown mode", mode);
|
break;
|
break;
|
}
|
}
|
|
|
|
|
// Verify that the CRC matches the one from the host.
|
// Verify that the CRC matches the one from the host.
|
FIX_CRC(xcrc, icrc);
|
FIX_CRC(xcrc, icrc);
|
if (host_crc != icrc) {
|
if (host_crc != icrc) {
|
TEST_CRASH(handle, TEST_CRASH_CRC_BAD,
|
TEST_CRASH(handle, TEST_CRASH_CRC_BAD,
|
"Input CRC failed", icrc, host_crc);
|
"Input CRC failed", icrc, host_crc);
|
}
|
}
|
|
|
// Verify that the host is happy with the data we echoed.
|
// Verify that the host is happy with the data we echoed.
|
if ('O' != host_status) {
|
if ('O' != host_status) {
|
TEST_CRASH(handle, TEST_CRASH_CRC_HOST,
|
TEST_CRASH(handle, TEST_CRASH_CRC_HOST,
|
"Output CRC failed");
|
"Output CRC failed");
|
}
|
}
|
|
|
CYG_TEST_PASS("Binary test completed");
|
CYG_TEST_PASS("Binary test completed");
|
return TEST_RETURN_OK;
|
return TEST_RETURN_OK;
|
}
|
}
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// Test transformations on text transmissions
|
// Test transformations on text transmissions
|
// Format out:
|
// Format out:
|
// "@TEXT:!<4 bytes binary checksum>"
|
// "@TEXT:!<4 bytes binary checksum>"
|
// Format in:
|
// Format in:
|
// ""
|
// ""
|
// OK/ER
|
// OK/ER
|
//
|
//
|
// Mode:
|
// Mode:
|
// MODE_EOP_ECHO:
|
// MODE_EOP_ECHO:
|
// Receive data, verify CRC, resend data.
|
// Receive data, verify CRC, resend data.
|
// Expect OK/ER reply from host when done.
|
// Expect OK/ER reply from host when done.
|
// MODE_DUPLEX_ECHO:
|
// MODE_DUPLEX_ECHO:
|
// Receive data, echo data, verify CRC.
|
// Receive data, echo data, verify CRC.
|
// Expect OK/ER reply from host when done.
|
// Expect OK/ER reply from host when done.
|
//
|
//
|
cyg_test_return_t
|
cyg_test_return_t
|
test_text(cyg_io_handle_t handle, cyg_mode_t mode, const char* s_base,
|
test_text(cyg_io_handle_t handle, cyg_mode_t mode, const char* s_base,
|
const char* s_out, const char* s_in)
|
const char* s_out, const char* s_in)
|
{
|
{
|
return TEST_RETURN_NA;
|
return TEST_RETURN_NA;
|
}
|
}
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// Send PING to host, verifying the filter's presence.
|
// Send PING to host, verifying the filter's presence.
|
// Format out:
|
// Format out:
|
// "@PING:!"
|
// "@PING:!"
|
// Format in:
|
// Format in:
|
// "OK"
|
// "OK"
|
// or
|
// or
|
// No response if directly connected to GDB.
|
// No response if directly connected to GDB.
|
//
|
//
|
// This call only returns if the ser_filter is listening. Otherwise it
|
// This call only returns if the ser_filter is listening. Otherwise it
|
// sends N/A and hangs.
|
// sends N/A and hangs.
|
void
|
void
|
test_ping(cyg_io_handle_t handle)
|
test_ping(cyg_io_handle_t handle)
|
{
|
{
|
char msg[] = "@PING:" TEST_CRASH_ID "!";
|
char msg[] = "@PING:" TEST_CRASH_ID "!";
|
char msg2[] = "\n";
|
char msg2[] = "\n";
|
int msglen = strlen(msg);
|
int msglen = strlen(msg);
|
int res;
|
int res;
|
|
|
msglen = strlen(msg);
|
msglen = strlen(msg);
|
Tcyg_io_write(handle, msg, &msglen);
|
Tcyg_io_write(handle, msg, &msglen);
|
|
|
// Now read host side's status
|
// Now read host side's status
|
msglen = 2;
|
msglen = 2;
|
Tcyg_io_read_timeout(handle, &in_buffer[0], &msglen, 100, &res);
|
Tcyg_io_read_timeout(handle, &in_buffer[0], &msglen, 100, &res);
|
if (ENOERR == res && 'O' == in_buffer[0] && 'K' == in_buffer[1])
|
if (ENOERR == res && 'O' == in_buffer[0] && 'K' == in_buffer[1])
|
return;
|
return;
|
|
|
msglen = strlen(msg2);
|
msglen = strlen(msg2);
|
Tcyg_io_write(handle, msg2, &msglen);
|
Tcyg_io_write(handle, msg2, &msglen);
|
|
|
CYG_TEST_NA("No host side testing harness detected.");
|
CYG_TEST_NA("No host side testing harness detected.");
|
}
|
}
|
|
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// Send OPT to host, setting options in the filter.
|
// Send OPT to host, setting options in the filter.
|
// Format out:
|
// Format out:
|
// "@OPT:option1,value1:...:optionN,valueN!"
|
// "@OPT:option1,value1:...:optionN,valueN!"
|
// Format in:
|
// Format in:
|
// "OK"
|
// "OK"
|
//
|
//
|
// Only integer values can be used. Any option not recognized by the
|
// Only integer values can be used. Any option not recognized by the
|
// filter will be silently ignored.
|
// filter will be silently ignored.
|
void
|
void
|
test_options(cyg_io_handle_t handle, int count, cyg_uint32* options)
|
test_options(cyg_io_handle_t handle, int count, cyg_uint32* options)
|
{
|
{
|
const char cmd[] = "@OPT:";
|
const char cmd[] = "@OPT:";
|
int msglen;
|
int msglen;
|
cyg_uint8 *p1;
|
cyg_uint8 *p1;
|
|
|
// Prepare and send the command.
|
// Prepare and send the command.
|
p1 = &cmd_buffer[0];
|
p1 = &cmd_buffer[0];
|
p1 = strcpy(p1, &cmd[0]);
|
p1 = strcpy(p1, &cmd[0]);
|
while(count--) {
|
while(count--) {
|
p1 = itoa(p1, *options++); // option
|
p1 = itoa(p1, *options++); // option
|
*p1++ = ':';
|
*p1++ = ':';
|
p1 = itoa(p1, *options++); // value
|
p1 = itoa(p1, *options++); // value
|
*p1++ = ':';
|
*p1++ = ':';
|
}
|
}
|
*(p1-1) = '!';
|
*(p1-1) = '!';
|
*p1++ = 0;
|
*p1++ = 0;
|
|
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
CYG_TEST_INFO(&cmd_buffer[1]);
|
|
|
msglen = strlen(&cmd_buffer[0]);
|
msglen = strlen(&cmd_buffer[0]);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
Tcyg_io_write(handle, &cmd_buffer[0], &msglen);
|
|
|
// Now read host side's status
|
// Now read host side's status
|
msglen = 2;
|
msglen = 2;
|
Tcyg_io_read(handle, &in_buffer[0], &msglen);
|
Tcyg_io_read(handle, &in_buffer[0], &msglen);
|
}
|
}
|
|
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// Some helper functions to get a test started.
|
// Some helper functions to get a test started.
|
void
|
void
|
test_open_ser( cyg_io_handle_t* handle )
|
test_open_ser( cyg_io_handle_t* handle )
|
{
|
{
|
#if defined(CYGPKG_IO_SERIAL_DEVICES) && !defined(SER_NOP_TEST)
|
#if defined(CYGPKG_IO_SERIAL_DEVICES) && !defined(SER_NOP_TEST)
|
Cyg_ErrNo res;
|
Cyg_ErrNo res;
|
|
|
if (cyg_test_is_simulator)
|
if (cyg_test_is_simulator)
|
CYG_TEST_NA("Cannot run from simulator");
|
CYG_TEST_NA("Cannot run from simulator");
|
|
|
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
|
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
|
# endif
|
# endif
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
|
# endif
|
# endif
|
#endif
|
#endif
|
|
|
res = cyg_io_lookup(TEST_SER_DEV, handle);
|
res = cyg_io_lookup(TEST_SER_DEV, handle);
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_SER_DEV);
|
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_SER_DEV);
|
}
|
}
|
#else
|
#else
|
CYG_TEST_NA(NA_MSG);
|
CYG_TEST_NA(NA_MSG);
|
#endif
|
#endif
|
}
|
}
|
|
|
void
|
void
|
test_open_tty( cyg_io_handle_t* handle )
|
test_open_tty( cyg_io_handle_t* handle )
|
{
|
{
|
#if defined(CYGPKG_IO_SERIAL_TTY) && !defined(TTY_NOP_TEST)
|
#if defined(CYGPKG_IO_SERIAL_TTY) && !defined(TTY_NOP_TEST)
|
Cyg_ErrNo res;
|
Cyg_ErrNo res;
|
|
|
if (cyg_test_is_simulator)
|
if (cyg_test_is_simulator)
|
CYG_TEST_NA("Cannot run from simulator");
|
CYG_TEST_NA("Cannot run from simulator");
|
|
|
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
|
#if defined(HAL_VSR_SET_TO_ECOS_HANDLER)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_1)
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_1, NULL);
|
# endif
|
# endif
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
|
# if defined(CYGPRI_SER_TEST_OVERRIDE_INT_2)
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
|
HAL_VSR_SET_TO_ECOS_HANDLER(CYGPRI_SER_TEST_OVERRIDE_INT_2, NULL);
|
# endif
|
# endif
|
#endif
|
#endif
|
|
|
res = cyg_io_lookup(TEST_TTY_DEV, handle);
|
res = cyg_io_lookup(TEST_TTY_DEV, handle);
|
if (res != ENOERR) {
|
if (res != ENOERR) {
|
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_TTY_DEV);
|
CYG_TEST_FAIL_FINISH("Can't lookup " TEST_TTY_DEV);
|
}
|
}
|
#else
|
#else
|
CYG_TEST_NA(NA_MSG);
|
CYG_TEST_NA(NA_MSG);
|
#endif
|
#endif
|
}
|
}
|
|
|
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
// end of ser_test_protocol.inl
|
// end of ser_test_protocol.inl
|
|
|