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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [tools/] [ecostest/] [common/] [ResetAttributes.cpp] - Blame information for rev 790

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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