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

📄 ecostestserialfilter.cpp

📁 基于ecos的redboot
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//####COPYRIGHTBEGIN####
//                                                                          
// ----------------------------------------------------------------------------
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
//
// This program is part of the eCos host tools.
//
// This program 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 of the License, or (at your option) 
// any later version.
// 
// This program 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
// this program; if not, write to the Free Software Foundation, Inc., 
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// ----------------------------------------------------------------------------
//                                                                          
//####COPYRIGHTEND####
//=================================================================
//
//        eCosTestSerialFilter.cpp
//
//        Serial test filter class
//
//=================================================================
//=================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):     jskov
// Contributors:  jskov
// Date:          1999-03-01
// Description:   This filter sits between GDB and the test running on
//                the target, allowing testing of the serial driver 
//                without confusing GDB.
// To Do:
//  o Add timeout setup and handling for recovery, can rely on testing
//    agent to control global timeout.
//  o Saving chunks that caused transfer failure?
//     - In SEND with echo, do CRC on 32-byte sub-packets
//  o Additional To Do items under each sub-protocol function.
//  o Option to get all serial IO written (in hex, > and < prepends 
//    input/output lines) to a file.
//  o Clean up the mess in this file....
//####DESCRIPTIONEND####

#include "eCosStd.h"

#include "eCosTestSerialFilter.h"
#include "eCosThreadUtils.h"

char msg_ok[] = "OK";
char msg_er[] = "ER";



CeCosTestSerialFilter::CeCosTestSerialFilter():
  m_bOptConsoleOutput(false), 
  m_bOptSerDebug(false), 
  m_bOptFilterTrace(false),
  m_xUnreadBuffer(NULL),
  m_nUnreadBufferIndex(0), 
  m_nUnreadBufferSize(0), 
  m_xStoredTraceBuffer(NULL),
  m_nStoredTraceBufferSize(0),
  m_bNullFilter(false), 
  m_nCmdIndex(0), 
  m_bCmdFlag(false), 
  m_bFirstCommandSeen(false),
  m_cGDBSocket(NULL)
{
}

CeCosTestSerialFilter::~CeCosTestSerialFilter()
{
}

//------------------------
// Output helpers.

// Encode string in an O-packet and send it to GDB.
void 
CeCosTestSerialFilter::GDBWrite(const char* pszStr)
{
    if (m_cGDBSocket) {
        static const char hexchars[] = "0123456789abcdef";
        char* packet = new char[strlen(pszStr)*2+6];
        char* p = packet;

        *p++ = '$';
        *p++ = 'O';
        unsigned char crc = 'O';
        char c;
        for (;;) {
            c = *pszStr++;
            if (0 == c)
                break;

            char h = hexchars[(c >> 4) & 0x0f];
            char l = hexchars[c & 0x0f];
            *p++ = h;
            *p++ = l;
            crc = (unsigned char) (crc + h + l);
        };

        *p++ = '#';
        *p++ = hexchars[(crc >> 4) & 0x0f];
        *p++ = hexchars[crc & 0x0f];
        
        // Only try to send once. If it fails, it's probably because
        // GDB has disconnected.
        m_cGDBSocket->send(packet, p - packet);
        m_cGDBSocket->recv(&c, 1);

        delete [] packet;
    }
}

void
CeCosTestSerialFilter::ConsoleWrite(const char* pszStr)
{
    fputs(pszStr, stderr);
    fflush(stderr);
}

void
CeCosTestSerialFilter::Trace(const char* pszFormat, ...)
{
  
  va_list marker;
  va_start (marker, pszFormat);
  
  for(int nLength=100;nLength;) {
    char *buf=new char[1+nLength];
    int n=vsnprintf(buf+4, nLength-4, pszFormat, marker ); 
    if(-1==n){
      nLength*=2;  // NT behavior
    } else if (n<nLength){
      memcpy(buf,"[f] ",4);
      if (m_bOptConsoleOutput) {
        ConsoleWrite(buf);
      } else {
        GDBWrite(buf);
      }
      nLength=0;   // trigger exit from loop
    } else {
      nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
    }
    delete [] buf;
  }
  
  va_end (marker);
  
}

void
CeCosTestSerialFilter::Log(const char* pszFormat, ...)
{
  va_list marker;
  va_start (marker, pszFormat);
  
  for(int nLength=100;nLength;) {
    char *buf=new char[1+nLength];
    int n=vsnprintf(buf, nLength, pszFormat, marker ); 
    if(-1==n){
      nLength*=2;  // NT behavior
    } else if (n<nLength){
      if (m_bOptConsoleOutput) {
        ConsoleWrite(buf);
      } else {
        GDBWrite(buf);
      }
      nLength=0;   // trigger exit from loop
    } else {
      nLength=n+1; // UNIX behavior generally, or NT behavior when buffer size exactly matches required length
    }
    delete [] buf;
  }
  
  va_end (marker);
}


void
CeCosTestSerialFilter::PrintHex(const unsigned char* d1, int len, data_origin_t origin/*=SF_TARGET*/)
{
    int offset = 0;
    int i;
    char buf[128];
    int width = 8;

    while (len) {
        int count = MIN(width, len);
        char* p = buf;
        switch (origin) {
        case SF_TARGET:
            p += sprintf(p, "T");
            break;
        case SF_FILTER:
            p += sprintf(p, "F");
            break;
        }
        p += sprintf(p, ":%04x ", offset);
        // Print hex values.
        for (i = 0; i < count; i++)
            p += sprintf(p, "%02x ", d1[i]);
        for (     ; i < width   ; i++)
            p += sprintf(p, ".. ");

        // Print ASCII string
        p += sprintf(p, "'");
        for (i = 0; i < count; i++) {
            int c = d1[i];
            if (' ' > c || 'z' < c)
                c = '.';
            p += sprintf(p, "%c", c);
        }
        sprintf(p, "'\n");

        Trace("%s", buf);

        len -= count;
        offset += count;
        d1 += count;
    }
}

void
CeCosTestSerialFilter::TargetWrite(CeCosSerial &pSer, 
                                    const unsigned char* buffer, int len)
{
    unsigned int __written;

    if (m_bOptFilterTrace)
        PrintHex(buffer, len, SF_FILTER);

    do {
        if (!(pSer.Write((void*) buffer, len, __written))) {
            fprintf(stderr, "Writing %d bytes to serial failed\n", len);
            fprintf(stderr, "%s", (LPCTSTR)pSer.ErrString());
            throw "serial write failed";
        }
        buffer += __written;
        len -= __written;
    } while (len);

}


bool
CeCosTestSerialFilter::TargetRead(CeCosSerial &pSer, 
                                  unsigned char* buffer, int len)
{
    unsigned int __read;
    int __total_read = 0;
    unsigned char* __buffer_base = buffer;
    int __timeouts = 0;
    int __timeout_failure = 0;
    int __orig_len = len;

    do {
        // First check for unread data.
        if (m_nUnreadBufferSize) {
            int i = 0;
            __read = 0;
            while (i < len && m_nUnreadBufferIndex < m_nUnreadBufferSize) {
                buffer[i++] = m_xUnreadBuffer[m_nUnreadBufferIndex++];
                __read++;
            }
            
            if (m_nUnreadBufferIndex == m_nUnreadBufferSize) {
                free(m_xUnreadBuffer);
                m_nUnreadBufferSize = 0;
                m_nUnreadBufferIndex = 0;
            }
        } else { 
            // Then read directly from serial.
            if (!(pSer.Read((void*) buffer, len, __read))) {
                fprintf(stderr,"Reading %d bytes from serial failed (read %d).\n",
                        len, __read);
                char *pszErr=pSer.ErrString().GetCString();
                fprintf(stderr, "%s", pszErr);
                delete [] pszErr;
                throw "serial read failed";
            }
        }

        __total_read += __read;
        unsigned int i;
        for (i = 0; i < __read; i++) {
            if ('$' == buffer[i]) {

                Log("FAIL:<target crashed>\n"); 

                Trace("**** Detected $ -- resuming as null filter ****\n");

                Trace("Data received %d bytes (of %d) from target:\n", 
                      __total_read, __orig_len);
                PrintHex(__buffer_base, __total_read);
                Trace("<end>\n");

                filter_abort_t* msg = new filter_abort_t();
                msg->data_ptr = &buffer[i];
                msg->data_len = __read - i;

                throw msg;
            }
        }

        if (0 == __read) {
            CeCosThreadUtils::Sleep(20);
            __timeouts++;
            if (25 == __timeouts) {
                __timeouts = 0;
                if (5 == __timeout_failure++) {
                    Log("FAIL:<target timed out>\n"); 

                    Trace("**** Timed out while reading -- resuming as null filter\n");

                    Trace("Data received %d bytes (of %d) from target:\n", 
                          __total_read, __orig_len);
                    PrintHex(__buffer_base, __total_read);
                    Trace("<end>\n");

                    static const char kill_msg[] = "$X00#b8";

                    filter_abort_t* msg = new filter_abort_t();
                    msg->data_len = strlen(kill_msg);
                    msg->data_ptr = (const unsigned char *)kill_msg;

                    throw msg;
                }
            }
        } else {
            __timeouts = 0;
            __timeout_failure = 0;
        }

        buffer += __read;
        len -= __read;

    } while (len);

    return true;
}

// Send C ASCII string to target.
void 
CeCosTestSerialFilter::TargetASCIIWrite(CeCosSerial &pSer, const char* s) 
{ 
    TargetWrite(pSer, (const unsigned char*) s, strlen(s)); 
}

//------------------------
// Configuration Command.
// Set serial configuration.
bool
CeCosTestSerialFilter::SetConfig(CeCosSerial &pSer, 
                                 const ser_cfg_t* new_cfg, 
                                 ser_cfg_t* old_cfg)
{
    // Note that for flow control, we assume that *both* receive and transmit
    // flow control are set or not set
    if (old_cfg) {
        old_cfg->baud_rate = pSer.GetBaud();
        old_cfg->parity = (0 != pSer.GetParity()) ? true : false;
        old_cfg->data_bits = pSer.GetDataBits();
        old_cfg->stop_bits = pSer.GetStopBits();
        old_cfg->flags = pSer.GetXONXOFFFlowControl() ? FLOW_XONXOFF_RX : 0;
        old_cfg->flags |= pSer.GetRTSCTSFlowControl() ? FLOW_RTSCTS_RX : 0;
        old_cfg->flags |= pSer.GetDSRDTRFlowControl() ? FLOW_DSRDTR_RX : 0;
    }

⌨️ 快捷键说明

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