OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [tools/] [src/] [tools/] [ecostest/] [common/] [ResetAttributes.cpp] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//####COPYRIGHTBEGIN####
2
//                                                                          
3
// ----------------------------------------------------------------------------
4
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5
//
6
// This program is part of the eCos host tools.
7
//
8
// This program is free software; you can redistribute it and/or modify it 
9
// under the terms of the GNU General Public License as published by the Free 
10
// Software Foundation; either version 2 of the License, or (at your option) 
11
// any later version.
12
// 
13
// This program is distributed in the hope that it will be useful, but WITHOUT 
14
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16
// more details.
17
// 
18
// You should have received a copy of the GNU General Public License along with
19
// this program; if not, write to the Free Software Foundation, Inc., 
20
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
//
22
// ----------------------------------------------------------------------------
23
//                                                                          
24
//####COPYRIGHTEND####
25
//#####DESCRIPTIONBEGIN####
26
//
27
// Author(s):     sdf
28
// Contributors:  sdf
29
// Date:          1999-04-01
30
// Description:   Holds information related to target reset
31
// Usage:
32
//
33
//####DESCRIPTIONEND####
34
#include "eCosStd.h"
35
#include "eCosThreadUtils.h"
36
#include "eCosTrace.h"
37
#include "ResetAttributes.h"
38
 
39
const CResetAttributes CResetAttributes::NoReset;
40
 
41
CResetAttributes::CResetAttributes(LPCTSTR psz) :
42
  // Default values:
43
  m_nDelay(1000),
44
  m_nReadTimeout(10*1000),
45
  m_nBaud(38400)
46
{
47
  // Remove spaces
48
  while(*psz){
49
    if(!_istspace(*psz)){
50
      m_str+=*psz;
51
    }
52
    psz++;
53
  }
54
}
55
 
56
/*
57
LPCTSTR CResetAttributes::Image(int nErr)
58
{
59
  switch(nErr){
60
    case RESET_OK:
61
      return _T("RESET_OK");
62
      break;
63
    case RESET_ILLEGAL_DEVICE_CODE:
64
      return _T("Illegal device code");
65
      break;
66
    case RESET_NO_REPLY:
67
      return _T("No reply from reset unit");
68
      break;
69
    case RESET_BAD_CHECKSUM:
70
      return _T("Bad checksum");
71
      break;
72
    case RESET_BAD_ACK:
73
      return _T("Bad ack");
74
      break;
75
    default:
76
      return _T("Unknown reset error");
77
      break;
78
  }
79
}
80
*/
81
void CResetAttributes::SuckThreadFunc()
82
{
83
  m_strResetOutput=_T("");
84
 
85
  // Board has apparently been powered on.  Suck initial output.
86
  ResetLog(String::SFormat(_T("Reading board startup output from %s with timeout of %d seconds..."),(LPCTSTR)m_strAuxPort,m_nReadTimeout/1000));
87
 
88
  enum {BUFSIZE=512};
89
  TCHAR buf[1+BUFSIZE];
90
  memset(buf,0,BUFSIZE); // safety for string functions in IsValidReset
91
  do {
92
    unsigned int dwRead=0;
93
    // We are working in non-blocking mode
94
    if(m_Socket.Ok()){
95
      if(!m_Socket.Peek(dwRead)||!m_Socket.recv(buf,MIN(dwRead,BUFSIZE))){
96
        break;
97
      }
98
    } else if (!m_Serial.Read(buf,BUFSIZE,dwRead)){
99
      m_Serial.ClearError();
100
      continue;
101
    }
102
    if(dwRead>0){
103
      buf[dwRead]=_TCHAR('\0');
104
 
105
      // Remove unprintable characters
106
      String str;
107
      for(const TCHAR *t=buf;*t;t++){
108
        if(_istprint(*t)){
109
          str+=*t;
110
        }
111
      }
112
 
113
      if(m_pfnReset){
114
        ENTERCRITICAL;
115
        m_pfnReset(m_pfnResetparam,str);
116
        LEAVECRITICAL;
117
      }
118
 
119
      ResetLog(str);
120
      m_strResetOutput+=str;
121
 
122
      if(IsValidReset()){
123
        break;
124
      }
125
//    } else { // Nothing read
126
//      CeCosThreadUtils::Sleep(50);
127
    }
128
  } while (0==m_tResetOccurred || Now()-m_tResetOccurred<m_nReadTimeout);
129
 
130
  if(0==m_strResetOutput.size()){
131
    ResetLog(_T("No response from board"));
132
  } else {
133
    if(m_pfnReset){
134
      ENTERCRITICAL;
135
      m_pfnReset(m_pfnResetparam,_T("\n"));
136
      LEAVECRITICAL;
137
    }
138
    TRACE(_T("%s"),(LPCTSTR)m_strResetOutput);
139
  }
140
}
141
 
142
bool CResetAttributes::Reset(Action action,bool bCheckOutput)
143
{
144
  m_tResetOccurred=0;
145
  m_strResetOutput=_T("");
146
  bool rc=false;
147
  CeCosSocket sock;
148
  String strStatus;
149
  strStatus.Format(_T("Reset target using %s %s port=%s(%d) read timeout=%d delay=%d"),
150
    (LPCTSTR)m_strHostPort,(LPCTSTR)m_strControl,
151
    (LPCTSTR)m_strAuxPort, m_nBaud, m_nReadTimeout, m_nDelay);
152
  if(bCheckOutput){
153
    strStatus+=_T(" expect(");
154
    for(unsigned int i=0;i<m_arValidResetStrings.size();i++){
155
      if(i>0){
156
        strStatus+=_TCHAR(',');
157
      }
158
      strStatus+=m_arValidResetStrings[i];
159
    }
160
    strStatus+=_T(")");
161
  }
162
  ResetLog(strStatus);
163
 
164
  // Open up communication to port whence we read the board startup
165
  bool bThreadDone=false;
166
  bCheckOutput&=(m_strAuxPort.size()>0);
167
  if(bCheckOutput){
168
    TRACE(_T("Opening %s\n"),(LPCTSTR)m_strAuxPort);
169
    if(CeCosSocket::IsLegalHostPort(m_strAuxPort)){
170
      // tcp/ip port
171
      if(!m_Socket.Connect(m_strAuxPort,m_nReadTimeout)){
172
        ResetLog(String::SFormat(_T("Failed to open %s - %s"),(LPCTSTR)m_strAuxPort,(LPCTSTR)m_Socket.SocketErrString()));
173
        return false;
174
      }
175
    } else {
176
      // Comms device
177
      m_Serial.SetBlockingReads(false);
178
      if(m_Serial.Open(m_strAuxPort,m_nBaud)){
179
        m_Serial.Flush();
180
      } else {
181
        ResetLog(String::SFormat(_T("Failed to open comms port %s - %s"),(LPCTSTR)m_strAuxPort,(LPCTSTR)m_Serial.ErrString()));
182
        return false;
183
      }
184
    }
185
    CeCosThreadUtils::RunThread(SSuckThreadFunc,this,&bThreadDone,_T("SSuckThreadFunc"));
186
  } else {
187
    ResetLog(_T("[not checking output]"));
188
  }
189
 
190
  // This will be true if we need to talk to a reset server, false to talk down a local port
191
  bool bRemote=CeCosSocket::IsLegalHostPort(m_strHostPort);
192
  if(bRemote){
193
    if(sock.Connect(m_strHostPort,10*1000)){
194
      // Write the message to the socket
195
      int nDelay=(action==ON_OFF || action==OFF_ON)?m_nDelay:0;
196
      TRACE(_T("-Control=%s -Action=%d -Delay=%d"),(LPCTSTR)m_strControl,action,nDelay);
197
      if(sock.sendString(String::SFormat(_T("-Control=%s -Action=%d -Delay=%d"),(LPCTSTR)m_strControl,action,nDelay),_T("Reset control codes"), 10*1000)){
198
        // Wait for an acknowledgement
199
        String strResponse;
200
        if(sock.recvString(strResponse, _T("Response"), nDelay+20*1000)){
201
          rc=(0==strResponse.size());
202
          if(!rc && m_pfnReset){
203
            ResetLog(String::SFormat(_T("Reset server reports error '%s'"),(LPCTSTR)strResponse));
204
          }
205
        } else {
206
          ResetLog(String::SFormat(_T("Failed to read response from reset server %s - %s"),(LPCTSTR)m_strHostPort,(LPCTSTR)sock.SocketErrString()));
207
        }
208
      } else {
209
        ResetLog(String::SFormat(_T("Failed to contact reset server %s - %s"),(LPCTSTR)m_strHostPort,(LPCTSTR)sock.SocketErrString()));
210
      }
211
      m_tResetOccurred=Now();
212
      if(bCheckOutput){
213
        if(!rc){
214
          // force thread to time out
215
          m_tResetOccurred=Now()-m_nReadTimeout;
216
        }
217
        CeCosThreadUtils::WaitFor(bThreadDone); // do not apply a timeout - the thread has one
218
        rc=IsValidReset();
219
        ResetLog(rc?_T("Reset output valid"):_T("Reset output INVALID"));
220
      }
221
    } else {
222
      ResetLog(String::SFormat(_T("Failed to contact reset server %s - %s"),(LPCTSTR)m_strHostPort,(LPCTSTR)sock.SocketErrString()));
223
    }
224
  } else {
225
    // Sending something locally
226
    m_tResetOccurred=Now();
227
    unsigned int nWritten;
228
    m_Serial.Write((void *)(LPCTSTR)m_strControl,1,nWritten);
229
    if(bCheckOutput){
230
      CeCosThreadUtils::WaitFor(bThreadDone);  // do not apply a timeout - the thread has one
231
      rc=IsValidReset();
232
      ResetLog(rc?_T("Reset output valid"):_T("Reset output INVALID"));
233
    }
234
  }
235
 
236
  if(m_Socket.Ok()){
237
    m_Socket.Close();
238
  } else {
239
    m_Serial.Close();
240
  }
241
  return rc && bCheckOutput;
242
}
243
 
244
// We expect to be passed a string that starts with "xxx(yyy)"
245
// and the task is to extract xxx into strID and yyy into strArg
246
const TCHAR *CResetAttributes::GetIdAndArg (LPCTSTR psz,String &strID,String &strArg)
247
{
248
  const TCHAR *cEnd=_tcschr(psz,_TCHAR('('));
249
  if(cEnd){
250
    strID=String(psz,cEnd-psz);
251
    int nNest=0;
252
    for(const TCHAR *c=cEnd;*c;c++){
253
      if(_TCHAR('(')==*c){
254
        nNest++;
255
      } else if(_TCHAR(')')==*c){
256
        nNest--;
257
        if(0==nNest){
258
          strArg=String(cEnd+1,c-(cEnd+1));
259
          return c+1;
260
        }
261
      }
262
    }
263
    assert(false);
264
  }
265
  return 0;
266
}
267
 
268
// Do the reset
269
CResetAttributes::ResetResult CResetAttributes::Reset (LogFunc *pfnLog, void *pfnLogparam,bool bCheckOnly)
270
{
271
  m_pfnReset=pfnLog;
272
  m_pfnResetparam=pfnLogparam;
273
 
274
  // First we clean up the reset string so as to make subsequent parsing less complicated.
275
  // Spaces have already been removed in the ctor
276
 
277
  // Check paren matching:
278
  int nNest=0;
279
  for(const TCHAR *c=m_str;*c;c++){
280
    if(_TCHAR('(')==*c){
281
      nNest++;
282
    } else if(_TCHAR(')')==*c){
283
      nNest--;
284
      if(nNest<0){
285
        ResetLog(_T("Too many right parentheses"));
286
        return INVALID_STRING;
287
      }
288
    }
289
  }
290
  if(nNest>0){
291
    ResetLog(_T("Too many left parentheses"));
292
    return INVALID_STRING;
293
  }
294
 
295
  return Parse(m_str,bCheckOnly);
296
}
297
 
298
// This function parses the reset string, whose form is something like:
299
//     expect($T05) 3(off(ginga:5000,a1) delay(2000) on(ginga:5000,a1,com1,38400,10000))
300
// It is recursive (which is another reason elementary syntax checking was carried out above)
301
// and calls itself to perform repeats [e.g. 3(...)]
302
CResetAttributes::ResetResult CResetAttributes::Parse (LPCTSTR psz,bool bCheckOnly)
303
{
304
  enum {ARGSEP=_TCHAR(',')};
305
  bool bCheck=false;
306
  for(const TCHAR *c=psz;*c;){
307
    String strID,strArg;
308
    c=GetIdAndArg(c,strID,strArg);
309
    if(0==c){
310
      ResetLog(_T("Invalid reset string"));
311
      return INVALID_STRING;
312
    }
313
 
314
    if(isdigit(*(LPCTSTR)strID)){
315
      // Process a repeat-until-reset.  Syntax is n(resetstring)
316
      int nRepeat=_ttoi(strID);
317
      if(0==nRepeat){
318
        ResetLog(_T("Invalid reset string"));
319
        return INVALID_STRING;
320
      }
321
      if(bCheckOnly){
322
        return Parse(strArg,true);
323
      } else {
324
        while(nRepeat--){
325
          ResetResult r=Parse(strArg);
326
          if(RESET_OK==r||INVALID_STRING==r){
327
            return r;
328
          }
329
        }
330
      }
331
    } else if (_T("expect")==strID) {
332
      //   Expected string(s).  e.g. expect(str1,str2,...).
333
      strArg.Chop(m_arValidResetStrings,ARGSEP,true);
334
    } else if (_T("port")==strID) {
335
      // Port information.      e.g. port(com1,38400,1000)
336
      // This information will apply to all subsequent actions until overwritten.
337
      // Specifically args are:
338
      //   0. Port
339
      //   1. Baud
340
      //   2. Read timeout
341
      StringArray ar;
342
      int nArgs=strArg.Chop(ar,ARGSEP,true);
343
      if(nArgs>0){
344
        m_strAuxPort=ar[0];
345
      }
346
      if(nArgs>1){
347
        m_nBaud=_ttoi(ar[1]);
348
      }
349
      if(nArgs>2){
350
        m_nReadTimeout=_ttoi(ar[2]);
351
      }
352
    } else if (_T("off")==strID || _T("on")==strID || _T("on_off")==strID || _T("off_on")==strID) {
353
      // Action information.      e.g. off(ginga:500,A4,com1,38400,10000,1000)
354
      // Specifically args are:
355
      //   0. Reset host:port
356
      //   1. Control string
357
      //   2. Port
358
      //   3. Baud
359
      //   4. Read timeout
360
      //   5. Delay
361
      StringArray ar;
362
      int nArgs=strArg.Chop(ar,ARGSEP,true);
363
      if(nArgs>0){
364
        m_strHostPort=ar[0];
365
      }
366
      if(nArgs>1){
367
        m_strControl=ar[1];
368
      }
369
      if(nArgs>2){
370
        m_strAuxPort=ar[2];
371
      }
372
      if(nArgs>3){
373
        m_nBaud=_ttoi(ar[3]);
374
      }
375
      if(nArgs>4){
376
        m_nReadTimeout=_ttoi(ar[4]);
377
      }
378
      if(nArgs>5){
379
        m_nDelay=_ttoi(ar[5]);
380
      }
381
 
382
      if(0==m_strHostPort.size()){
383
        ResetLog(_T("Failed to specify reset host:port"));
384
        return INVALID_STRING;
385
      }
386
 
387
      Action action=ON; // prevent compiler warning
388
      if(_T("on")==strID){
389
        action=ON;
390
      } else if(_T("off")==strID){
391
        action=OFF;
392
      } else if(_T("on_off")==strID){
393
        action=ON_OFF;
394
      } else if(_T("off_on")==strID){
395
        action=OFF_ON;
396
      }
397
 
398
      if(!bCheckOnly && Reset(action,bCheck||action==ON_OFF||action==OFF_ON)){
399
        return RESET_OK;
400
      }
401
      bCheck ^= 1;
402
    } else if (_T("delay")==strID) {
403
      // Delay for a given time right now.      e.g. delay(1000)
404
      // Specifically args are:
405
      //   0. msec to delay
406
      TRACE(_T("CeCosThreadUtils::Sleep %d\n"),_ttoi(strArg));
407
      if(!bCheckOnly){
408
        CeCosThreadUtils::Sleep(_ttoi(strArg));
409
      }
410
    } else {
411
      ResetLog(String::SFormat(_T("Unrecognized command '%s'"),(LPCTSTR)strID));
412
      return INVALID_STRING;
413
    }
414
  }
415
  ResetLog(_T("Target reset not verified"));
416
  return NOT_RESET;
417
}
418
 
419
// Log some output to the reset log function.
420
void CResetAttributes::ResetLog(LPCTSTR psz)
421
{
422
  if(m_pfnReset){
423
    ENTERCRITICAL;
424
    m_pfnReset(m_pfnResetparam,String::SFormat(_T("%s >>> %s\n"),(LPCTSTR)CeCosTrace::Timestamp(),psz));
425
    TRACE(_T("%s"),psz);
426
    LEAVECRITICAL;
427
  }
428
}
429
 
430
bool CResetAttributes::IsValidReset()
431
{
432
  unsigned int n=0;
433
  ENTERCRITICAL;
434
  for(int i=m_arValidResetStrings.size()-1;i>=0;--i){
435
    if(_tcsstr(m_strResetOutput,m_arValidResetStrings[i])){
436
      n++;
437
    }
438
  }
439
  LEAVECRITICAL;
440
  return n==m_arValidResetStrings.size();
441
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.