📄 ser_test_protocol.inl
字号:
//==========================================================================
//
// ser_test_protocol.c
//
// Serial device driver testing protocol
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// 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
// 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
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// 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
// 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
// License. However the source code for this file must still be made available
// 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 file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov
// Contributors: jskov, gthomas
// 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/infra/cyg_ass.h>
#include <cyg/hal/hal_intr.h> // for reclaiming interrupt vector
//----------------------------------------------------------------------------
// Definition of which device to run tests on on various platforms.
#define NA_MSG "No test device specified"
// Cleaned up drivers will export the testing parameters via CDL.
// When all drivers are changed, replace the TEST_ macros throughout
// with the CYGPRI_ equivalents.
#ifdef 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_TTY_DEV CYGPRI_SER_TEST_TTY_DEV
#endif
// 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
// from the ROM monitor before the test is started.
#if defined(CYGPKG_HAL_POWERPC_MBX) \ && defined(CYGPKG_HAL_QUICC) \ && defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC) \ && defined(CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1)
# define TEST_CRASH_ID "ppcmbx"
# define TEST_SER_DEV CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_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_AM31_STDEVAL1) \ && defined(CYGPKG_IO_SERIAL_MN10300) \ && defined(CYGPKG_IO_SERIAL_MN10300_SERIAL2)
# define TEST_CRASH_ID "am31st"
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME
# if defined(CYGPKG_IO_SERIAL_TTY_TTY2)
# define TEST_TTY_DEV CYGDAT_IO_SERIAL_TTY_TTY1_DEV
# endif
#endif
#if defined(CYGPKG_HAL_MN10300_AM33_STB) \ && defined(CYGPKG_IO_SERIAL_MN10300) \ && defined(CYGPKG_IO_SERIAL_MN10300_SERIAL0)
# define TEST_CRASH_ID "am33st"
# define TEST_SER_DEV CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME
# 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
#ifndef TEST_CRASH_ID
#define TEST_CRASH_ID "......"
#endif
//----------------------------------------------------------------------------
// Crash types
// 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
// test results. For now we just keep it here...
// FAILCODE:<tttttt:cccc:[optional data, separated by :]!>
// tttttt: 6 letter target code
// cccc: crash code (16bit hex value)
#define TEST_CRASH(__h, __code, __msg, args...) \ CYG_MACRO_START \ int __len = 1; \ /* Try to flush remaining input */ \ cyg_thread_delay(50); \ cyg_io_get_config(__h, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, \ 0, &__len); \ diag_printf("FAILCODE:<" TEST_CRASH_ID ":%04x:" __code, ## args); \ diag_printf("!>\n"); \ CYG_FAIL(__msg); \ hang(); \ CYG_MACRO_END
// Target IO
#define TEST_CRASH_IO 0x0000
#define TEST_CRASH_IO_READ "%d", 0x0001
#define TEST_CRASH_IO_WRITE "%d", 0x0002
#define TEST_CRASH_IO_DRAIN "%d", 0x0003
#define TEST_CRASH_IO_GET_CFG "%d", 0x0004
#define TEST_CRASH_IO_SET_CFG "%d", 0x0005
// Target
#define TEST_CRASH_CRC 0x0010
#define TEST_CRASH_CRC_CHAR "%02x", 0x0011
#define TEST_CRASH_CRC_BAD "%08x:%08x", 0x0012
#define TEST_CRASH_CRC_HOST "", 0x0013
// Protocol errors
#define TEST_CRASH_PROT 0x1000
#define TEST_CRASH_PROT_BIN_MODE "%d", 0x1080
#define TEST_CRASH_PROT_TEXT "%d", 0x1100
#define TEST_CRASH_HOST_xx 0xf000
#define TEST_CRASH_HOST_TIMEOUT "%d:%d:%d:%d", 0xf000
// command#, read invocation#, expected, actual
#define TEST_CRASH_HOST_CRC_BAD "%d:%08x:%08x:%d:%02x:%02x", 0xf010
// command#, expected CRC, actual, index, expected char, actual
#define TEST_CRASH_HOST_DUPLEX_BAD "%d:%d:%02x:%02x", 0xf020
// command#, index, expected char, actual
//----------------------------------------------------------------------------
// The data in buffer and the cmd buffer
#ifndef IN_BUFFER_SIZE
# define IN_BUFFER_SIZE 1024
#endif
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;
cyg_uint32 flags;
// etc...
} cyg_ser_cfg_t;
typedef enum {
OPT_SERIAL_DEBUG = 0,
OPT_VERBOSE_LEVEL
} cyg_option_t;
typedef enum {
_NONE = 0,
PROTOCOL_PROGRESS,
PROTOCOL_DATA,
} cyg_verbosity_level_t;
// A few predifined option macros. Use after test_ping().
#define TEST_OPTIONS(__handle, __array) \ test_options(__handle, sizeof(__array)/8, __array)
#define TEST_HOST_DEBUG(__handle) \ CYG_MACRO_START \ cyg_uint32 __options[] = {OPT_SERIAL_DEBUG, 1}; \ test_options((__handle), sizeof(__options)/8, \ __options); \ CYG_MACRO_END
#define TEST_HOST_PROGRESS(__handle) \ CYG_MACRO_START \ cyg_uint32 __options[] = \ {OPT_SERIAL_DEBUG, 1, \ OPT_VERBOSE_LEVEL, PROTOCOL_PROGRESS}; \ test_options((__handle), sizeof(__options)/8, \ __options); \ CYG_MACRO_END
#define TEST_HOST_DATA(__handle) \ CYG_MACRO_START \ cyg_uint32 __options[] = \ {OPT_SERIAL_DEBUG, 1, \ OPT_VERBOSE_LEVEL, PROTOCOL_DATA}; \ test_options((__handle), sizeof(__options)/8, \ __options); \ CYG_MACRO_END
//----------------------------------------------------------------------------
// 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 (0 == CYGINT_IO_SERIAL_TEST_SKIP_9600)
{ CYGNUM_SERIAL_BAUD_9600, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_14400)
#if !defined(CYGPKG_HAL_MN10300_AM31) && \ !defined(CYGPKG_HAL_MN10300_AM33)
{ CYGNUM_SERIAL_BAUD_14400, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#endif
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_38400)
{ CYGNUM_SERIAL_BAUD_38400, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_57600)
#if !defined(CYGPKG_HAL_MN10300_AM33)
{ CYGNUM_SERIAL_BAUD_57600, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_115200)
#if !defined(CYGPKG_HAL_MN10300_STDEVAL1)
{ CYGNUM_SERIAL_BAUD_115200, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
// One stop bit, even parity
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_1, CYGNUM_SERIAL_PARITY_EVEN,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_PARITY_EVEN)
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
// Two stop bits, even parity
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_EVEN,
CYGNUM_SERIAL_FLOW_NONE },
#endif
#endif
#if (0 == CYGINT_IO_SERIAL_TEST_SKIP_STOP_2)
// Two stop bits, no parity
{ CYGNUM_SERIAL_BAUD_19200, CYGNUM_SERIAL_WORD_LENGTH_8,
CYGNUM_SERIAL_STOP_2, CYGNUM_SERIAL_PARITY_NONE,
CYGNUM_SERIAL_FLOW_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; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -