/* returns true if is recoverable (temporary),
 *  false if it is an  error that is permanent.
 */
bool asynchErrorHandler(NdbTransaction * trans, Ndb* ndb) 
{  
  NdbError error = trans->getNdbError();
  switch(error.status)
  {
  case NdbError::Success:
    return false;
    break;
    
  case NdbError::TemporaryError:
    /**
     * The error code indicates a temporary error.
     * The application should typically retry.
     * (Includes classifications: NdbError::InsufficientSpace, 
     *  NdbError::TemporaryResourceError, NdbError::NodeRecoveryError,
     *  NdbError::OverloadError, NdbError::NodeShutdown 
     *  and NdbError::TimeoutExpired.)
     *     
     * We should sleep for a while and retry, except for insufficient space
     */
    if(error.classification == NdbError::InsufficientSpace)
      return false;
    milliSleep(10);  
    tempErrors++;  
    return true;
    break;    
  case NdbError::UnknownResult:
    std::cout << error.message << std::endl;
    return false;
    break;
  default:
  case NdbError::PermanentError:
    switch (error.code)
    {
    case 499:
    case 250:
      milliSleep(10);    
      return true; // SCAN errors that can be retried. Requires restart of scan.
    default:
      break;
    }
    //ERROR
    std::cout << error.message << std::endl;
    return false;
    break;
  }
  return false;
}
Exemplo n.º 2
0
QByteArray IpcChannel::receiveMessage(int timeoutMsecs)
{
    disconnect(m_socket, SIGNAL(readyRead()), 0, 0);
#   ifdef _WIN32
    // Win32 workaround - see waitForDisconnected()
    QElapsedTimer timer;
    timer.start();
    while (m_socket->state() != QLocalSocket::UnconnectedState &&
           (timeoutMsecs == -1 || timer.elapsed() < timeoutMsecs))
    {
        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
        milliSleep(1);
        if (appendCurrentMessage())
        {
            QByteArray msg = m_message;
            clearCurrentMessage();
            return msg;
        }
    }
#   else
    while (m_socket->waitForReadyRead(timeoutMsecs))
    {
        if (appendCurrentMessage())
        {
            QByteArray msg = m_message;
            clearCurrentMessage();
            return msg;
        }
    }
#   endif
    throw DisplazError("Could not read message from socket: %s",
                       m_socket->errorString());
}
Exemplo n.º 3
0
bool IpcChannel::waitForDisconnected(int timeoutMsecs)
{
#   ifdef _WIN32
    // Aaaarghhh.  QLocalSocket::waitForDisconnected() seems like it's meant to
    // be a synchronous version for use without an event loop.  However,
    // qt-4.8.6 on windows (and it appears many other versions, including
    // latest qt-5) have a bug in waitForDisconnected(): it uses a separate
    // thread to do the actual write via an internal QWindowsPipeWriter.
    // QLocalSocket is notified when the data has has been written via a
    // connection, but this is a QueuedConnection due to being in a separate
    // thread, so the signal never gets seen unless an event loop is used.
    QElapsedTimer timer;
    timer.start();
    while (m_socket->state() != QLocalSocket::UnconnectedState &&
           (timeoutMsecs == -1 || timer.elapsed() < timeoutMsecs))
    {
        QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
        milliSleep(1); // Crude, but whatever.  This is a workaround.
    }
    return m_socket->state() == QLocalSocket::UnconnectedState;
#   else
    if (m_socket->state() == QLocalSocket::UnconnectedState)
        return true;
    return m_socket->waitForDisconnected(timeoutMsecs);
#   endif
}
Exemplo n.º 4
0
std::unique_ptr<IpcChannel> IpcChannel::connectToServer(QString serverName, int timeoutMsecs)
{
    std::unique_ptr<QLocalSocket> socket(new QLocalSocket());
    QElapsedTimer timer;
    timer.start();
    qint64 currTimeout = timeoutMsecs;
    while (true)
    {
        socket->connectToServer(serverName);
        if (socket->waitForConnected(currTimeout))
            return std::unique_ptr<IpcChannel>(new IpcChannel(socket.release()));
        if (timeoutMsecs >= 0)
            currTimeout = timeoutMsecs - timer.elapsed();
        if (socket->error() == QLocalSocket::SocketTimeoutError)
        {
            return std::unique_ptr<IpcChannel>();
        }
        else if (socket->error() == QLocalSocket::UnknownSocketError)
        {
            // "Unknown" errors on linux may result in the socket getting into
            // a bad state from which it never recovers.  Make a new one.
            socket.reset(new QLocalSocket());
        }
        // For maximum robustness, consider all other errors to be retryable.
        //
        // Some errors such as ServerNotFoundError may seem fatal, but a race
        // condition may occur where the remote instance has only just started
        // and hasn't created the socket yet.  Prevent busy looping on these
        // kinds of conditions by including a small sleep between retries.
        milliSleep(1);
    }
}
/**
 * Callback executed when transaction has return from NDB
 */
static void
callback(int result, NdbTransaction* trans, void* aObject)
{
  async_callback_t * cbData = (async_callback_t *)aObject;
  if (result<0)
  {
    /**
     * Error: Temporary or permanent?
     */
    if (asynchErrorHandler(trans,  (Ndb*)cbData->ndb)) 
    {
      closeTransaction((Ndb*)cbData->ndb, cbData);
      while(populate((Ndb*)cbData->ndb, cbData->data, cbData) < 0)
	milliSleep(10);
    }
    else
    {
      std::cout << "Restore: Failed to restore data " 
		<< "due to a unrecoverable error. Exiting..." << std::endl;
      delete cbData;
      asynchExitHandler((Ndb*)cbData->ndb);
    }
  } 
  else 
  {
    /**
     * OK! close transaction
     */
    closeTransaction((Ndb*)cbData->ndb, cbData);
    delete cbData;
  }
}
Exemplo n.º 6
0
//! \brief Sends a message of 5 bytes to the USBDM device over EP0.
//!
//!  An immediate response is expected
//!
//! @param data - Entry \n
//!    data[0]    = N, the number of bytes to receive from the device \n
//!    data[1]    = Command byte \n
//!    data[2..5] = parameter(s) for OSBDM command \n
//! @note data must be an array of at least 5 bytes even if there are no parameters!
//!
//! @param data - Exit \n
//!    data[0]      = cmd response from OSBDM\n
//!    data[1..N-1] = data response from the device (cleared on error)\n
//!
//! @return \n
//!    == BDM_RC_OK (0)     => Success, OK response from device\n
//!    == BDM_RC_USB_ERROR  => USB failure \n
//!    == else              => Error code from Device
//!
USBDM_ErrorCode bdm_usb_recv_ep0(unsigned char *data, unsigned *actualRxSize) {
    unsigned char size = data[0];   // Transfer size is the first byte
    unsigned char cmd  = data[1];   // OSBDM/TBDML Command byte
    int rc;
    int retry = 5;

    *actualRxSize = 0;

    if (usbDeviceHandle == NULL) {
        print("bdm_usb_recv_ep0() - ERROR : Device handle NULL!\n");
        data[0] = BDM_RC_DEVICE_NOT_OPEN;
        return BDM_RC_DEVICE_NOT_OPEN;
    }

#ifdef LOG_LOW_LEVEL
    print("============================\n");
    print("bdm_usb_recv_ep0(%s, size=%d) - \n", getCommandName(cmd), size);
    if (data[1] == CMD_USBDM_DEBUG)
        print("bdm_usb_recv_ep0() - Debug cmd = %s\n", getDebugCommandName(data[2]));
    printDump(data, 6);
#endif // LOG_LOW_LEVEL

    do {
        rc = libusb_control_transfer(usbDeviceHandle,
                                     LIBUSB_REQUEST_TYPE_VENDOR|EP_CONTROL_IN,      // bmRequestType
                                     cmd,                                           // bRequest
                                     data[2]+(data[3]<<8),                          // wValue
                                     data[4]+(data[5]<<8),                          // wIndex
                                     (unsigned char*)data,                          // ptr to data buffer (for Rx)
                                     size,                                          // wLength = size of transfer
                                     5*timeoutValue                                 // timeout
                                    );
        if (rc < 0) {
            print("bdm_usb_recv_ep0(size=%d) - Transfer error (USB error = %s) - retry %d \n", size, libusb_strerror((libusb_error)rc), retry);
            milliSleep(100); // So we don't monopolise the USB
        }
    } while ((rc < 0) && (--retry>0));

    if (rc < 0) {
        print("bdm_usb_recv_ep0() - Transfer failed (USB error = %s)\n", libusb_strerror((libusb_error)rc));
        data[0] = BDM_RC_USB_ERROR;
        *actualRxSize = 0;
    }
    else {
        *actualRxSize = (unsigned) rc;
    }
    if ((data[0] != BDM_RC_OK) && (data[0] != cmd)) { // Error at BDM?
        print("bdm_usb_recv_ep0() - Cmd Failed (%s):\n", getErrorName(data[0]));
        printDump(data,*actualRxSize);
        memset(&data[1], 0x00, size-1);
        return (USBDM_ErrorCode)data[0];
    }
#ifdef LOG_LOW_LEVEL
    print("bdm_usb_recv_ep0(size = %d, recvd = %d):\n", size, rc);
    printDump(data,rc);
#endif // LOG_LOW_LEVEL

    return(BDM_RC_OK);
}
//====================================================================
//! ICP mode - program BDM Flash memory
//!
//! @param addr    32-bit memory address
//! @param count   number of bytes to program
//! @param data    Pointer to buffer containing data
//!
//! @return
//!      - == ICP_RC_OK => success \n
//!      - != ICP_RC_OK => fail, see \ref ICP_ErrorType
//!
ICP_ErrorType ICP_Program(unsigned int  addr,
                          unsigned int  count,
                          unsigned char *data) {

   unsigned int dataSize; // Bytes to program this row
   ICP_ErrorType rc;
   unsigned int temp;
   int doBlock;
   unsigned int doneCount     = 0;

   lastCommand = ICP_PROGRAM;

   Logging::print("ICP_Program() - Programming [%8.8X-%8.8X]\n", addr, addr+count-1);

   // Have to program within a row in each iteration
   // so there are size and alignment issues.
   while (count > 0) {
      // Bytes to end of current row
      dataSize = ICP_MAX_DATA_SIZE - (addr & (ICP_MAX_DATA_SIZE - 1));
      if (dataSize > count) { // Take down to number actually remaining
         dataSize = count;
      }
      // Check if empty block (all 0xFF)
      doBlock = false;
      for (temp = 0; temp < dataSize; temp++) {
         doBlock = doBlock || (data[temp] != 0xFF);
      }
      if (doBlock) { // Only program non-Blank blocks
         Logging::print("ICP_Program() - Programming block %4.4X-%4.4X\n", addr, addr+dataSize-1);
         Logging::printDump(data, dataSize);

         rc =  (ICP_ErrorType)bdm_usb_raw_send_ep0(ICP_PROGRAM,     // bRequest
                                                   addr,            // wValue  = Start address
                                                   addr+dataSize-1, // wIndex  = End address
                                                   dataSize,        // wLength = # bytes
                                                   data);           // Data to program
         if (rc != ICP_RC_OK) {
            Logging::print("ICP_Program() - Failed bdm_usb_raw_send_ep0()\n");
            return rc;
         }
         milliSleep(20);
         rc = getResult();
         if (rc != ICP_RC_OK) {
            Logging::print("ICP_Program() - Failed icp_get_result() rc = %d\n", rc);
            return rc;
         }
      }
      else {
         Logging::print("ICP_Program() - Skipping block    %4.4X-%4.4X\n", addr, addr+dataSize-1);
      }
      data      += dataSize; // update location in buffer
      addr      += dataSize; // update address
      count     -= dataSize; // update count
      doneCount += dataSize;
   }
   return ICP_RC_OK;
}
//! Configures the ICSCG target clock
//!
//! @param busFrequency    - Resulting BDM frequency after clock adjustment
//! @param clockParameters - Describes clock settings to use
//!
//! @return error code, see \ref USBDM_ErrorCode
//!
//! @note Assumes that connection with the target has been established so
//!       reports any errors as PROGRAMMING_RC_ERROR_FAILED_CLOCK indicating
//!       a problem programming the target clock.
//!
USBDM_ErrorCode FlashProgrammer::configureICS_Clock(unsigned long         *busFrequency,
                                                    ICS_ClockParameters_t *clockParameters){
   LOGGING_E;

   const uint32_t ICSC1   = parameters.getClockAddress();
   const uint32_t ICSC2   = parameters.getClockAddress()+1;
   const uint32_t ICSTRIM = parameters.getClockAddress()+2;
   const uint32_t ICSSC   = parameters.getClockAddress()+3;

   unsigned long bdmFrequency;

   Logging::print("ICS Clock: Ad=0x%08X, C1=0x%02X, C2=0x%02X, SC=0x%02X\n",
           parameters.getClockAddress(),
           clockParameters->icsC1,
           clockParameters->icsC2,
           clockParameters->icsSC
           );

   flashReady = FALSE; // Not configured for Flash access

   // ToDo - Review order of writes & need for re-connect()
   if (writeClockRegister(ICSTRIM, clockParameters->icsTrim) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_Connect() != BDM_RC_OK) {// re-connect after possible bus speed change
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(ICSC1, clockParameters->icsC1) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(ICSC2, clockParameters->icsC2) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_Connect() != BDM_RC_OK) { // re-connect after possible bus speed change - no delay
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(ICSSC, clockParameters->icsSC) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   milliSleep(100);
   if (USBDM_Connect() != BDM_RC_OK) { // re-connect after possible FLL change
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_GetSpeed(&bdmFrequency) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   bdmFrequency *= 1000; // Convert to Hz
   *busFrequency = bdmFrequency*parameters.getBDMtoBUSFactor();
   Logging::print("BDM Speed = %ld kHz, Bus Speed = %ld kHz\n",
         bdmFrequency/1000, *busFrequency/1000);
   return PROGRAMMING_RC_OK;
}
Exemplo n.º 9
0
void MyDelay(int ms)
{
#ifdef OSPREY
	if(ms<=0) ms=1;
#endif
#ifdef MDK_AP
	milliSleep(ms);
#elif defined(__APPLE__)
	usleep(ms);
#else
	Sleep(ms);
#endif	
}
static USBDM_ErrorCode gdbLoop(GdbInOut *gdbInOut) {
   LOGGING;
   Logging::print("gdbLoop()...\n");

   const GdbPacket *packet;
   unsigned pollCount = 0;
   GdbTargetStatus targetStatus = T_UNKNOWN;

   serverError = BDM_RC_OK;

   do {
      do {
         // Process packets from GDB until idle
         packet = gdbInOut->getGdbPacket();
         if (packet != NULL) {
            USBDM_ErrorCode rc = doGdbCommand(packet);
            if (rc != BDM_RC_OK) {
               return rc;
            }
         }
      } while (packet != NULL);

      // Get current target status (w/o polling)
      targetStatus = getGdbTargetStatus();
      switch (targetStatus) {
         case T_RUNNING:
         case T_SLEEPING:
            if (pollCount++ >= POLL_INTERVAL) {
               // Actually poll the target
               pollCount = 0;
               targetStatus = gdbPollTarget();
            }
            break;
         case T_NOCONNECTION:
            break;
         case T_UNKNOWN:
         case T_HALT:
            // Don't poll while not running
            milliSleep(1 /* ms */);
            break;
      }

   // Keep going until loose target or GDB
   } while ((targetStatus != T_NOCONNECTION) && (serverError == BDM_RC_OK) && (!gdbInOut->isEOF()));

   Logging::print("gdbLoop() - Exiting GDB Loop\n");
   return BDM_RC_OK;
}
Exemplo n.º 11
0
int main(int argc, char *argv[])
{
    pthread_t display_thread, speed_thread, ant_thread;

    // setup signal handler(s)
    signal(SIGINT, on_sigint);

    // setup hardware
    SetupHardware();

    // start the display thread
    runDisplayThread = 1;
    pthread_create (&display_thread, NULL, Display_Thread, NULL);

    // Start the speed sensor thread
    runSpeedThread = 1;
    pthread_create (&speed_thread, NULL, Speed_Thread, NULL);

    // start the ANT+ thread
    // todo: start broadcasting ANT data when movement sensed, and timeout/stop when idle
    runAntThread = 1;
    pthread_create (&ant_thread, NULL, ANT_Thread, NULL);

    milliSleep(500);

    //unsigned int i;

    // Run until Ctrl-C
    while (is_sigint == 0)
    {
        //sprintf(DisplayMessage, "main thread sleeping... %i", i++);
        sleep(1);
    }

    // wait for threads to finish
    //printf("\nWaiting for threads to finsh..\n");
    runDisplayThread = runSpeedThread = runAntThread = 0;
    pthread_join(display_thread, NULL);
    pthread_join(speed_thread, NULL);
    pthread_join(ant_thread, NULL);

    // cleanup hardware
    CleanupHardware();

    exit(0);
}
Exemplo n.º 12
0
// Input : Maze, debut, A, B
// Output: fin, nb
void trajectoire(Maze& M, Position& debut, int& nb, Position& fin,const Position& A, const Position& B, const bool& with_aff)
{
  debut.bouge(M);
  if (debut==A || debut==B)
    {
      fin=debut;
    }
  else
    {
      if (with_aff)
	{
	  M.aff(true);
	  debut.affiche();
	  milliSleep(200);
	}
      trajectoire(M,debut,++nb,fin,A,B,with_aff);
    }
}
Exemplo n.º 13
0
int scan_print(Ndb * myNdb)
{
// Scan all records exclusive and update
  // them one by one
  int                  retryAttempt = 0;
  const int            retryMax = 10;
  int fetchedRows = 0;
  int check;
  NdbError              err;
  NdbTransaction	*myTrans;
  NdbScanOperation	*myScanOp;
  /* Result of reading attribute value, three columns:
     REG_NO, BRAND, and COLOR
   */
  NdbRecAttr *    	myRecAttr[3];   

  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("api_scan");

  if (myTable == NULL) 
    APIERROR(myDict->getNdbError());

  /**
   * Loop as long as :
   *  retryMax not reached
   *  failed operations due to TEMPORARY erros
   *
   * Exit loop;
   *  retyrMax reached
   *  Permanent error (return -1)
   */
  while (true)
  {

    if (retryAttempt >= retryMax)
    {
      std::cout << "ERROR: has retried this operation " << retryAttempt 
		<< " times, failing!" << std::endl;
      return -1;
    }

    myTrans = myNdb->startTransaction();
    if (myTrans == NULL) 
    {
      const NdbError err = myNdb->getNdbError();

      if (err.status == NdbError::TemporaryError)
      {
	milliSleep(50);
	retryAttempt++;
	continue;
      }
     std::cout << err.message << std::endl;
      return -1;
    }
    /*
     * Define a scan operation. 
     * NDBAPI.
     */
    myScanOp = myTrans->getNdbScanOperation(myTable);	
    if (myScanOp == NULL) 
    {
      std::cout << myTrans->getNdbError().message << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    }

    /**
     * Read without locks, without being placed in lock queue
     */
    if( myScanOp->readTuples(NdbOperation::LM_CommittedRead) == -1)
    {
      std::cout << myTrans->getNdbError().message << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    } 

    /**
     * Define storage for fetched attributes.
     * E.g., the resulting attributes of executing
     * myOp->getValue("REG_NO") is placed in myRecAttr[0].
     * No data exists in myRecAttr until transaction has commited!
     */
    myRecAttr[0] = myScanOp->getValue("REG_NO");
    myRecAttr[1] = myScanOp->getValue("BRAND");
    myRecAttr[2] = myScanOp->getValue("COLOR");
    if(myRecAttr[0] ==NULL || myRecAttr[1] == NULL || myRecAttr[2]==NULL) 
    {
	std::cout << myTrans->getNdbError().message << std::endl;
	myNdb->closeTransaction(myTrans);
	return -1;
    }
    /**
     * Start scan   (NoCommit since we are only reading at this stage);
     */     
    if(myTrans->execute(NdbTransaction::NoCommit) != 0){      
      err = myTrans->getNdbError();    
      if(err.status == NdbError::TemporaryError){
	std::cout << myTrans->getNdbError().message << std::endl;
	myNdb->closeTransaction(myTrans);
	milliSleep(50);
	continue;
      }
      std::cout << err.code << std::endl;
      std::cout << myTrans->getNdbError().code << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    }
    
    /**
     * start of loop: nextResult(true) means that "parallelism" number of
     * rows are fetched from NDB and cached in NDBAPI
     */    
    while((check = myScanOp->nextResult(true)) == 0){
      do {
	
	fetchedRows++;
	/**
	 * print  REG_NO unsigned int
	 */
	std::cout << myRecAttr[0]->u_32_value() << "\t";

	/**
	 * print  BRAND character string
	 */
	std::cout << myRecAttr[1]->aRef() << "\t";

	/**
	 * print  COLOR character string
	 */
	std::cout << myRecAttr[2]->aRef() << std::endl;

	/**
	 * nextResult(false) means that the records 
	 * cached in the NDBAPI are modified before
	 * fetching more rows from NDB.
	 */    
      } while((check = myScanOp->nextResult(false)) == 0);

    }    
    myNdb->closeTransaction(myTrans);
    return 1;
  }
  return -1;

}
Exemplo n.º 14
0
int main(int argc, char** argv)
{
  if (argc != 3)
  {
    std::cout << "Arguments are <socket mysqld> <connect_string cluster>.\n";
    exit(-1);
  }
  char * mysqld_sock  = argv[1];
  const char *connectstring = argv[2];
  ndb_init();
  MYSQL mysql;

  /**************************************************************
   * Connect to mysql server and create table                   *
   **************************************************************/
  {
    if ( !mysql_init(&mysql) ) {
      std::cout << "mysql_init failed\n";
      exit(-1);
    }
    if ( !mysql_real_connect(&mysql, "localhost", "root", "", "",
			     0, mysqld_sock, 0) )
      MYSQLERROR(mysql);

    mysql_query(&mysql, "CREATE DATABASE ndb_examples");
    if (mysql_query(&mysql, "USE ndb_examples") != 0) MYSQLERROR(mysql);

    create_table(mysql);
  }

  /**************************************************************
   * Connect to ndb cluster                                     *
   **************************************************************/
  Ndb_cluster_connection cluster_connection(connectstring);
  if (cluster_connection.connect(4, 5, 1))
  {
    std::cout << "Unable to connect to cluster within 30 secs." << std::endl;
    exit(-1);
  }
  // Optionally connect and wait for the storage nodes (ndbd's)
  if (cluster_connection.wait_until_ready(30,0) < 0)
  {
    std::cout << "Cluster was not ready within 30 secs.\n";
    exit(-1);
  }

  Ndb* myNdb = new Ndb( &cluster_connection,
			"ndb_examples" );  // Object representing the database
  if (myNdb->init(1024) == -1) {      // Set max 1024 parallel transactions
    APIERROR(myNdb->getNdbError());
  }

  /**
   * Initialise transaction array
   */
  for(int i = 0 ; i < 10 ; i++) 
  {
    transaction[i].used = 0;
    transaction[i].conn = 0;
    
  }
  int i=0;
  /**
   * Do 10 insert transactions.
   */
  while(i < 10) 
  {
    while(populate(myNdb,i,0)<0)  // <0, no space on free list. Sleep and try again.
      milliSleep(10);
      
    i++;
  }
  std::cout << "Number of temporary errors: " << tempErrors << std::endl;
  delete myNdb; 
}
Exemplo n.º 15
0
int scan_update(Ndb* myNdb, 
		int update_column,
		const char * before_color,
		const char * after_color)
		
{
  
  // Scan all records exclusive and update
  // them one by one
  int                  retryAttempt = 0;
  const int            retryMax = 10;
  int updatedRows = 0;
  int check;
  NdbError              err;
  NdbTransaction	*myTrans;
  NdbScanOperation	*myScanOp;

  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("api_scan");

  if (myTable == NULL) 
    APIERROR(myDict->getNdbError());

  /**
   * Loop as long as :
   *  retryMax not reached
   *  failed operations due to TEMPORARY erros
   *
   * Exit loop;
   *  retryMax reached
   *  Permanent error (return -1)
   */
  while (true)
  {

    if (retryAttempt >= retryMax)
    {
      std::cout << "ERROR: has retried this operation " << retryAttempt 
		<< " times, failing!" << std::endl;
      return -1;
    }

    myTrans = myNdb->startTransaction();
    if (myTrans == NULL) 
    {
      const NdbError err = myNdb->getNdbError();

      if (err.status == NdbError::TemporaryError)
      {
	milliSleep(50);
	retryAttempt++;
	continue;
      }
      std::cout <<  err.message << std::endl;
      return -1;
    }

   /**
    * Get a scan operation.
    */
    myScanOp = myTrans->getNdbScanOperation(myTable);	
    if (myScanOp == NULL) 
    {
      std::cout << myTrans->getNdbError().message << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    }

    /**
     * Define a result set for the scan.
     */ 
    if( myScanOp->readTuples(NdbOperation::LM_Exclusive) ) 
    {
      std::cout << myTrans->getNdbError().message << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    } 

    /**
     * Use NdbScanFilter to define a search critera
     */ 
    NdbScanFilter filter(myScanOp) ;   
    if(filter.begin(NdbScanFilter::AND) < 0  || 
       filter.cmp(NdbScanFilter::COND_EQ, update_column, before_color, 20) <0||
       filter.end() <0)
    {
      std::cout <<  myTrans->getNdbError().message << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    }    
    
    /**
     * Start scan    (NoCommit since we are only reading at this stage);
     */     
    if(myTrans->execute(NdbTransaction::NoCommit) != 0)
    {      
      err = myTrans->getNdbError();    
      if(err.status == NdbError::TemporaryError){
	std::cout << myTrans->getNdbError().message << std::endl;
	myNdb->closeTransaction(myTrans);
	milliSleep(50);
	continue;
      }
      std::cout << myTrans->getNdbError().code << std::endl;
      myNdb->closeTransaction(myTrans);
      return -1;
    }

    /**
     * start of loop: nextResult(true) means that "parallelism" number of
     * rows are fetched from NDB and cached in NDBAPI
     */    
    while((check = myScanOp->nextResult(true)) == 0){
      do {
	/**
	 * Get update operation
	 */    
	NdbOperation * myUpdateOp = myScanOp->updateCurrentTuple();
	if (myUpdateOp == 0)
	{
	  std::cout << myTrans->getNdbError().message << std::endl;
	  myNdb->closeTransaction(myTrans);
	  return -1;
	}
	updatedRows++;

	/**
	 * do the update
	 */    
	myUpdateOp->setValue(update_column, after_color);
	/**
	 * nextResult(false) means that the records 
	 * cached in the NDBAPI are modified before
	 * fetching more rows from NDB.
	 */    
      } while((check = myScanOp->nextResult(false)) == 0);
      
      /**
       * NoCommit when all cached tuple have been updated
       */    
      if(check != -1)
      {
	check = myTrans->execute(NdbTransaction::NoCommit);   
      }

      /**
       * Check for errors
       */
      err = myTrans->getNdbError();    
      if(check == -1)
      {
	if(err.status == NdbError::TemporaryError){
	  std::cout << myTrans->getNdbError().message << std::endl;
	  myNdb->closeTransaction(myTrans);
	  milliSleep(50);
	  continue;
	}	
      }
      /**
       * End of loop 
       */
    }

    /**
     * Commit all prepared operations
     */
    if(myTrans->execute(NdbTransaction::Commit) == -1)
    {
      if(err.status == NdbError::TemporaryError){
	std::cout << myTrans->getNdbError().message << std::endl;
	myNdb->closeTransaction(myTrans);
	milliSleep(50);
	continue;
      }	
    }

    std::cout << myTrans->getNdbError().message << std::endl;
    myNdb->closeTransaction(myTrans);
    return 0;    
  }


  if(myTrans!=0) 
  {
    std::cout << myTrans->getNdbError().message << std::endl;
    myNdb->closeTransaction(myTrans);
  }
  return -1;
}
Exemplo n.º 16
0
static void *ANT_Thread(void *arg)
{
    struct TimerInfo info;

    uint8_t   power_event_count = 0;
    uint16_t  power_accumulated = 0;
    uint16_t  power_instant = 0;

    double    previous_ke = 0;

    uint8_t   power_accel_index;
    double    power_accel_array[POWER_SAMPLE_DEPTH];
    double    power_accel_filtered;

    // zero out the array of power entries & set index to start
    memset(power_accel_array, 0, sizeof (power_accel_array));
    power_accel_index = 0;

    // USB setup
    if (libusb_init(NULL) != 0)
    {
        //printf("libusb: failed to initialise\n");
        snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "libusb: failed to initialise...");
        return NULL;
    }

    devh = libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);

    if (devh == NULL)
    {
        //printf("libusb: failed to open device 0x%04x:0x%04x\n", vendor_id, product_id);
        snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "libusb: failed to open device 0x%04x:0x%04x\n", vendor_id, product_id);
    }
    else
    {
        // don't really care about the result..
        libusb_detach_kernel_driver(devh, 0);

        if (libusb_claim_interface(devh, 0) != 0)
        {
            //printf("libusb: failed to claim interface");
            snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "libusb: failed to claim interface");

        }
        else
        {
            //printf("libusb: succesfully claimed interface\n");
            snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "libusb: succesfully claimed interface");


            // ANT+ setup

            // reset
            ANTBuildMessage(1, ANT_SYSTEM_RESET, 0, 0, 0, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // ANT docs say wait 500ms after reset before sending any more host commands
            milliSleep(500);

            // set network key
            ANTBuildMessage(9, ANT_SET_NETWORK, ANT_NETWORK_0, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
            ANTTransferMessage();

            // assign channel
            ANTBuildMessage(3, ANT_ASSIGN_CHANNEL, ANT_CHANNEL_1, ANT_CHANNEL_TYPE_TX, ANT_NETWORK_0, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // set channel id
            uint16_t device_id = 0xBEEF;
            ANTBuildMessage(5, ANT_CHANNEL_ID, ANT_CHANNEL_1, device_id&0xff, (device_id>>8)&0xff, ANT_SPORT_POWER_TYPE, ANT_TRANSMISSION_TYPE, 0, 0, 0, 0);
            ANTTransferMessage();

            // set rf frequency
            ANTBuildMessage(2, ANT_CHANNEL_FREQUENCY, ANT_CHANNEL_1, ANT_SPORT_FREQUENCY, 0, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // set channel period
            uint16_t period = ANT_SPORT_POWER_PERIOD;
            ANTBuildMessage(3, ANT_CHANNEL_PERIOD, ANT_CHANNEL_1, period&0xff, (period>>8)&0xff, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // set tx power? (optional)

            // open channel
            ANTBuildMessage(1, ANT_OPEN_CHANNEL, ANT_CHANNEL_1, 0, 0, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // Start the periodic timer @ 250ms
            // todo: use stricter ANT power message interval?
            TimerStart (250000, &info);

            //TESTING!!!
            // ONCE PER SECOND TO MATCH SPEED UPDATES
            //TimerStart (1000000, &info);

            // Run until terminated from main thread
            while (runAntThread)
            {
                // Wait for periodic timer to expire
                TimerWait (&info);

                // Broadcast data
                ////printf("ANT_Thread: timer expired...\n");

                // Data Page 0x10 message format
                // Byte 0 : Data Page Number - 0x10
                // Byte 1 : Update event count
                // Byte 2 : Pedal power - 0xFF
                // Byte 3 : Instantaneous cadence - 0xFF
                // Byte 4 : Accumulated power (LSB)
                // Byte 5 : Accumulated power (MSB)
                // Byte 6 : Instantaneous power (LSB)
                // Byte 7 : Instantaneous power (MSB)

                // #define POWER   150
                // power_instant = POWER;

                double speed = currentSpeed;

                // calculate the static power
                double power_static = (power_curve_a +
                                      (power_curve_b*speed) +
                                      (power_curve_c*speed*speed) +
                                      (power_curve_d*speed*speed*speed));

                // calculate the kinetic energy at this speed
                double speed_ms = speed / 3.6;
                double current_ke = GetKineticEnergy(speed_ms);

                // calculate the acceleration power. This calculation is dependent on the update
                // frequency, as we are looking for the change in stored kinetic energy per second
                //
                double power_accel = (current_ke - previous_ke) * PRU_UPDATE_FREQ;

                // todo: this may need some smoothing as the frequency increases?
                //       - start with a simple moving average of the acceleration power
                power_accel_array[power_accel_index++] = power_accel;
                if (power_accel_index >= POWER_SAMPLE_DEPTH)
                {
                    power_accel_index = 0;
                }

                power_accel_filtered = 0;
                for (int i = 0; i < POWER_SAMPLE_DEPTH; i++)
                {
                    power_accel_filtered += power_accel_array[i];
                }
                power_accel_filtered /= POWER_SAMPLE_DEPTH;

                //snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "current_ke = %lf, previous_ke = %lf", total_kinetic_energy, previous_ke);
                //snprintf(DisplayMessage, DISPLAY_MAX_MSG_SIZE, "power_static = %.0lf, power_accel = %.0lf", power_static, power_accel);

                // Print out the value received from the PRU code
                //printf("%u events, %.0f RPM, %.2f km/h, %.2f watts\r\n", events, rpm, kph, power_static+power_accel);

                previous_ke = current_ke;

                power_event_count++;

                power_instant = power_static + power_accel_filtered;

                currentPower = power_instant;

                power_accumulated += power_instant;

                ANTBuildMessage(9, ANT_BROADCAST_DATA, ANT_CHANNEL_1, ANT_STANDARD_POWER, power_event_count, 0xFF, 0xFF,
                        power_accumulated&0xff, (power_accumulated>>8)&0xff, power_instant&0xff, (power_instant>>8)&0xff);

                ANTTransferMessage();
            }

            // ANT+ cleanup
            //printf("ANT_Thread: cleanup\n");

            // close channel
            ANTBuildMessage(1, ANT_CLOSE_CHANNEL, ANT_CHANNEL_1, 0, 0, 0, 0, 0, 0, 0, 0);
            ANTTransferMessage();

            // USB cleanup
            libusb_release_interface(devh, 0);
        }

        // USB cleanup
        libusb_close(devh);
    }
    libusb_exit(NULL);
    return NULL;
}
Exemplo n.º 17
0
/************************************************************************
 * populate()
 * 1. Prepare 'parallelism' number of insert transactions. 
 * 2. Send transactions to NDB and wait for callbacks to execute
 */
int populate(Ndb * myNdb, int data, async_callback_t * cbData)
{

  NdbOperation*   myNdbOperation;       // For operations
  const NdbDictionary::Dictionary* myDict= myNdb->getDictionary();
  const NdbDictionary::Table *myTable= myDict->getTable("api_async");
  if (myTable == NULL) 
    APIERROR(myDict->getNdbError());

  async_callback_t * cb;
  int retries = 0;
  int current = 0;
  for(int i=0; i<1024; i++)
  {
    if(transaction[i].used == 0)
    {
      current = i;
      if (cbData == 0) 
      {
       /**
        * We already have a callback
	* This is an absolutely new transaction
        */
	cb = new async_callback_t;
	cb->retries = 0;
      }
      else 
      { 
       /**
        * We already have a callback
        */
	cb =cbData;
	retries = cbData->retries;
      }
      /**
       * Set data used by the callback
       */
      cb->ndb = myNdb;  //handle to Ndb object so that we can close transaction
                        // in the callback (alt. make myNdb global).

      cb->data =  data; //this is the data we want to insert
      cb->transaction = current; //This is the number (id)  of this transaction
      transaction[current].used = 1 ; //Mark the transaction as used
      break;
    }
  }
  if(!current)
    return -1;

  while(retries < MAX_RETRIES) 
    {
      transaction[current].conn = myNdb->startTransaction();
      if (transaction[current].conn == NULL) {
	/**
	 * no transaction to close since conn == null
	 */
	milliSleep(10);
	retries++;
	continue;
      }
      myNdbOperation = transaction[current].conn->getNdbOperation(myTable);
      if (myNdbOperation == NULL) 
      {
	if (asynchErrorHandler(transaction[current].conn, myNdb)) 
	{
	  myNdb->closeTransaction(transaction[current].conn);
	  transaction[current].conn = 0;
	  milliSleep(10);
	  retries++;
	  continue;
	}
	asynchExitHandler(myNdb);
      } // if
      if(myNdbOperation->insertTuple() < 0  ||
	 myNdbOperation->equal("REG_NO", data) < 0 ||
	 myNdbOperation->setValue("BRAND", "Mercedes") <0 ||
	 myNdbOperation->setValue("COLOR", "Blue") < 0)
      {
	if (asynchErrorHandler(transaction[current].conn, myNdb)) 
	{
	  myNdb->closeTransaction(transaction[current].conn);
	  transaction[current].conn = 0;
	  retries++;
	  milliSleep(10);
	  continue;
	}
	asynchExitHandler(myNdb);
      }     

      /*Prepare transaction (the transaction is NOT yet sent to NDB)*/
      transaction[current].conn->executeAsynchPrepare(NdbTransaction::Commit, 
						       &callback,
						       cb);
      /**
       * When we have prepared parallelism number of transactions ->
       * send the transaction to ndb. 
       * Next time we will deal with the transactions are in the 
       * callback. There we will see which ones that were successful
       * and which ones to retry.
       */
      if (nPreparedTransactions == parallelism-1) 
      {
	// send-poll all transactions
	// close transaction is done in callback
	myNdb->sendPollNdb(3000, parallelism );
	nPreparedTransactions=0;
      } 
      else
	nPreparedTransactions++;
      return 1;
    }
    std::cout << "Unable to recover from errors. Exiting..." << std::endl;
    asynchExitHandler(myNdb);
    return -1;
}
Exemplo n.º 18
0
static void *Display_Thread(void *arg)
{
    pthread_t spindown_thread;
    int parent_x, parent_y, new_x, new_y;
    int power_speed_height = 5;
    int status_height = 3;

    char DisplayLine[DISPLAY_MAX_MSG_SIZE];
    char DisplayBuffer[DISPLAY_MAX_MSG_LINES][DISPLAY_MAX_MSG_SIZE];

    char StatusLine[DISPLAY_MAX_MSG_SIZE];

    // zero out the display buffer;
    memset(DisplayBuffer, 0, sizeof(DisplayBuffer));

    // Setup ncurses display
    initscr();
    noecho();
    nodelay(stdscr, TRUE);
    cbreak();
    curs_set(FALSE);

    // set up initial windows
    getmaxyx(stdscr, parent_y, parent_x);

    WINDOW *pwr_window = newwin(power_speed_height, parent_x/2, 0, 0);
    WINDOW *spd_window = newwin(power_speed_height, parent_x/2, 0, parent_x - parent_x/2);
    WINDOW *msg_window = newwin(parent_y - power_speed_height - status_height, parent_x, power_speed_height, 0);
    WINDOW *sta_window = newwin(status_height, parent_x, parent_y - status_height, 0);

    box(pwr_window, 0, 0);
    box(spd_window, 0, 0);
    box(msg_window, 0, 0);
    box(sta_window, 0, 0);

    // refresh each window
    wrefresh(pwr_window);
    wrefresh(spd_window);
    wrefresh(msg_window);
    wrefresh(sta_window);

    while (runDisplayThread)
    {
        // use non-blocking ncurses input for control characters
        char ch = getch();

        // 'm' for manual resistance control
        if (ch == 'm')
        {
            currentMode = MODE_MANUAL;
        }

        // 'e' for ergo
        if (ch == 'e')
        {
            currentMode = MODE_ERGO;
        }

        // 's' for slope
        if (ch == 's')
        {
            currentMode = MODE_SLOPE;
        }

        // 'c' for spindown/calibrate - as 's' was already taken ;)
        if (ch == 'c')
        {
            lastMode = currentMode;
            currentMode = MODE_CALIBRATE;
            // todo: make sure we don't try and start more than one spindown thread
            pthread_create (&spindown_thread, NULL, Spindown_Thread, NULL);
        }

        // handle window resize events
        getmaxyx(stdscr, new_y, new_x);

        if (new_y != parent_y || new_x != parent_x)
        {
            parent_x = new_x;
            parent_y = new_y;

            wresize(pwr_window, power_speed_height, new_x/2);
            wresize(spd_window, power_speed_height, parent_x - new_x/2);
            mvwin(spd_window, 0, new_x/2);

            wresize(msg_window, parent_y - power_speed_height - status_height, parent_x);
            mvwin(msg_window, power_speed_height, 0);

            wresize(sta_window, status_height, parent_x);
            mvwin(sta_window, parent_y - status_height, 0);

            // clear the windows if resized
            wclear(stdscr);
            wclear(msg_window);
        }

        // clear the status window regardless
        wclear(sta_window);
        wclear(spd_window);
        wclear(pwr_window);

        // for some reason getch() seems to nuke the borders?
        // easy fix is just to redraw everything regardless..
        box(pwr_window, 0, 0);
        box(spd_window, 0, 0);
        box(msg_window, 0, 0);
        box(sta_window, 0, 0);

        DrawTitle(spd_window, "Speed");
        DrawTitle(pwr_window, "Power");
        DrawTitle(msg_window, "Messages");
        DrawTitle(sta_window, "Status");

        mvwprintw(pwr_window, power_speed_height/2, parent_x/4, "%.0lf", currentPower);
        mvwprintw(spd_window, power_speed_height/2, parent_x/4, "%.1lf", currentSpeed);

        strcpy(DisplayLine, DisplayMessage);

        if (strcmp(DisplayBuffer[0], DisplayLine))
        {
            // clear the previous message window content if we have new messages,
            // so we're not left with artifacts from previous (longer) lines..
            wclear(msg_window);
            box(msg_window, 0, 0);
            DrawTitle(msg_window, "Messages");

            for (int i = DISPLAY_MAX_MSG_LINES-1; i > 0; i--)
            {
                strcpy(DisplayBuffer[i], DisplayBuffer[i-1]);
            }
            strcpy(DisplayBuffer[0], DisplayLine);

            for (int i = 0; i < DISPLAY_MAX_MSG_LINES; i++)
            {
                mvwprintw(msg_window, i+1, 1, "%s",DisplayBuffer[i]);
            }
        }

        switch (currentMode)
        {
            case MODE_MANUAL:
                sprintf(StatusLine, "Freq: %04u - MANUAL MODE", currentFrequency);
                break;

            case MODE_SLOPE:
                sprintf(StatusLine, "Freq: %04u - SLOPE MODE", currentFrequency);
                break;

            case MODE_ERGO:
                sprintf(StatusLine, "Freq: %04u - ERGO MODE", currentFrequency);
                break;

            case MODE_CALIBRATE:
                sprintf(StatusLine, "Freq: %04u - SPINDOWN MODE", currentFrequency);
                break;

        }

        //strcpy(StatusLine, DisplayStatus);
        mvwprintw(sta_window, 1, 1, "%s",StatusLine);

        // refresh each window
        wrefresh(pwr_window);
        wrefresh(spd_window);
        wrefresh(msg_window);
        wrefresh(sta_window);

        milliSleep(100);
    }

    // clean up ncurses display
    endwin();

    return NULL;
}
Exemplo n.º 19
0
int main(int argc, char* argv[])
{
    if (argc < 2)
        return EXIT_FAILURE;
    if (argv[1] == std::string("master"))
    {
        QCoreApplication app(argc, argv);
        QString prog = QCoreApplication::applicationFilePath();
        std::vector<std::unique_ptr<QProcess>> procs;
        QStringList args;
        args << "slave";
        // Start a whole bunch of processes.  Unfortunately QtProcess isn't
        // robust enough to start more than about 100 at once on linux so
        // stress testing more requires a different strategy.
        const int nprocs = 100;
        for (int i = 0; i < nprocs; ++i)
        {
            std::unique_ptr<QProcess> proc(new QProcess());
            proc->start(prog, args);
            procs.push_back(std::move(proc));
        }
        // Wait for them all to finish, accumulating exit status
        int numAcquiredLocks = 0;
        int numBlockedLocks = 0;
        for (int i = 0; i < nprocs; ++i)
        {
            if (!procs[i]->waitForFinished() &&
                procs[i]->exitStatus() != QProcess::NormalExit)
            {
                std::cerr << "Error in waitForFinished()\n";
                return EXIT_FAILURE;
            }
            if (procs[i]->exitCode() == 0)
                ++numAcquiredLocks;
            else if (procs[i]->exitCode() == 1)
                ++numBlockedLocks;
        }
        tfm::printfln("Acquired locks: %d", numAcquiredLocks);
        tfm::printfln("Blocked locks: %d", numBlockedLocks);
        if (numAcquiredLocks != 1)
        {
            std::cerr << "Exactly one process should have got the lock\n";
            return EXIT_FAILURE;
        }
        if (numBlockedLocks != nprocs-1)
        {
            std::cerr << "Should have exactly N-1 blocked locks\n";
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }
    else
    {
        // Slave process.  This is what we're trying to test.
        InterProcessLock lk("InterProcessLock_test");
        if (!lk.tryLock())
            return 1;
        // We have the lock: sleep to let other processes exit
        milliSleep(4000);
        return 0;
    }
}
Exemplo n.º 20
0
//! \brief Receives a response from the USBDM device over the In Bulk Endpoint
//! Responses are retried to allow for target execution
//!
//! @param count = Maximum number of bytes to receive
//!
//! @param data
//!    IN                                       \n
//!    ======================================== \n
//!    data[0]      = error code (= rc)         \n
//!    data[1..N]   = data received             \n
//!
//! @param actualCount = Actual number of bytes received
//!
//! @return                                                       \n
//!    == BDM_RC_OK (0)     => Success, OK response from device   \n
//!    == BDM_RC_USB_ERROR  => USB failure                        \n
//!    == else              => Error code from Device
//!
USBDM_ErrorCode bdm_usb_recv_epIn(unsigned count, unsigned char *data, unsigned *actualCount) {
    int rc;
    int retry = 40; // ~4s of retries
    int transferCount;

    *actualCount = 0; // Assume failure

    if (usbDeviceHandle==NULL) {
        print("bdm_usb_recv_epIn(): device not open\n");
        return BDM_RC_DEVICE_NOT_OPEN;
    }

#ifdef LOG_LOW_LEVEL
    print("bdm_usb_recv_epIn(%d, ...)\n", count);
#endif // LOG_LOW_LEVEL

#if OLD
    do {
        rc = libusb_bulk_transfer(usbDeviceHandle,
                                  EP_IN,                         // Endpoint & direction
                                  (unsigned char *)dummyBuffer,  // ptr to Rx data
                                  sizeof(dummyBuffer)-5,         // number of bytes to Rx
                                  &transferCount,                // number of bytes actually Rx
                                  timeoutValue                   // timeout
                                 );
        if (rc != LIBUSB_SUCCESS) {
            print("bdm_usb_recv_epIn(count=%d) - Transfer timeout (USB error = %s, timeout=%d) - retry\n", count, libusb_strerror((libusb_error)rc), timeoutValue);
            milliSleep(100); // So we don't monopolise the USB
        }
    } while ((rc!=LIBUSB_SUCCESS) && (--retry>0));
#else
    do {
        rc = libusb_bulk_transfer(usbDeviceHandle,
                                  EP_IN,                         // Endpoint & direction
                                  (unsigned char *)dummyBuffer,  // ptr to Rx data
                                  sizeof(dummyBuffer)-5,         // number of bytes to Rx
                                  &transferCount,                // number of bytes actually Rx
                                  timeoutValue                   // timeout
                                 );
        if ((rc == LIBUSB_SUCCESS)  && (dummyBuffer[0] == BDM_RC_BUSY)) {
            // The BDM has indicated it's busy for a while - try again in 1/10 second
            print("bdm_usb_recv_epIn(retry=%d) - BDM Busy - retry\n", retry);
            milliSleep(100); // So we don't monopolise the USB
        }
    } while ((rc == LIBUSB_SUCCESS) && (dummyBuffer[0] == BDM_RC_BUSY)  && (--retry>0));
#endif
    if (rc != LIBUSB_SUCCESS) {
        print("bdm_usb_recv_epIn(count=%d) - Transfer failed (USB error = %s)\n", count, libusb_strerror((libusb_error)rc));
        data[0] = BDM_RC_USB_ERROR;
        memset(&data[1], 0x00, count-1);
        return BDM_RC_USB_ERROR;
    }

    memcpy(data, dummyBuffer, transferCount);
    rc = data[0]&0x7F;

    if (rc != BDM_RC_OK) {
        print("bdm_usb_recv_epIn() - Error Return %d (%s):\n", rc, getErrorName(rc));
        print("bdm_usb_recv_epIn(size = %d, recvd = %d):\n", count, transferCount);
        printDump(data, transferCount);
        memset(&data[1], 0x00, count-1);
    }

#ifdef LOG_LOW_LEVEL
    printDump(data, transferCount);
#endif // LOG_LOW_LEVEL

    *actualCount = transferCount;

    return (USBDM_ErrorCode)(rc);
}
Exemplo n.º 21
0
//! \brief Executes an USB transaction.
//! This consists of a transmission of a command and reception of the response
//! JMxx Version - see \ref bdm_usb_transaction()
//!
static
USBDM_ErrorCode bdmJMxx_usb_transaction( unsigned int   txSize,
        unsigned int   rxSize,
        unsigned char *data,
        unsigned int  *actualRxSize) {
    USBDM_ErrorCode rc;
    const unsigned MaxFirstTransaction = 30;
    static bool commandToggle = 0;
    unsigned retry=6;
    static int sequence = 0;
    bool reportFlag = false;
    uint8_t sendBuffer[txSize];

    if (data[1] == CMD_USBDM_GET_CAPABILITIES) {
//      print("bdmJMxx_usb_transaction() Setting toggle=0\n");
        commandToggle = 0;
        sequence = 0;
    }
    sequence++;
    memcpy(sendBuffer, data, txSize);
    do {
        // An initial transaction of up to MaxFirstTransaction bytes is sent
        // This is guaranteed to fit in a single pkt (<= endpoint MAXPACKETSIZE)
        sendBuffer[0] = txSize;
        if (commandToggle) {
            sendBuffer[1] |= 0x80;
        }
        else {
            sendBuffer[1] &= ~0x80;
        }
        rc = bdm_usb_send_epOut(txSize>MaxFirstTransaction?MaxFirstTransaction:txSize,
                                (const unsigned char *)sendBuffer);

        if (rc != BDM_RC_OK) {
            reportFlag = true;
            print("bdmJMxx_usb_transaction() Tx1 failed\n");
            continue;
        }
        // Remainder of data (if any) is sent as 2nd transaction
        // The size of this transaction is know to the receiver
        // Zero is sent as first byte (size) to allow differentiation from 1st transaction
        if ((rc == BDM_RC_OK) && (txSize>MaxFirstTransaction)) {
            print("bdmJMxx_usb_transaction() Splitting command\n");
            uint8_t saveByte = sendBuffer[MaxFirstTransaction-1];
            sendBuffer[MaxFirstTransaction-1] = 0; // Marker indicating later transaction
            rc = bdm_usb_send_epOut(txSize+1-MaxFirstTransaction,
                                    (const unsigned char *)(sendBuffer+MaxFirstTransaction-1));
            sendBuffer[MaxFirstTransaction-1] = saveByte;
        }
        if (rc != BDM_RC_OK) {
            reportFlag = true;
            print("bdmJMxx_usb_transaction() Tx2 failed\n");
            continue;
        }
        // Get response
        rc = bdm_usb_recv_epIn(rxSize, data, actualRxSize);
        bool receivedCommandToggle = (data[0]&0x80) != 0;

        if ((rc == BDM_RC_USB_ERROR) || (commandToggle != receivedCommandToggle)) {
            // Retry on single USB fail or toggle error
            print("bdmJMxx_usb_transaction() USB or Toggle error, seq = %d, S=%d, R=%d\n", sequence, commandToggle?1:0, receivedCommandToggle?1:0);
            milliSleep(100);
            rc = bdm_usb_recv_epIn(rxSize, data, actualRxSize);
            receivedCommandToggle = (data[0]&0x80) != 0;
            if ((rc == BDM_RC_USB_ERROR) || (commandToggle != receivedCommandToggle)) {
                print("bdmJMxx_usb_transaction() Immediate retry failed, seq = %d, S=%d, R=%d\n", sequence, commandToggle?1:0, receivedCommandToggle?1:0);
            }
            else {
                print("bdmJMxx_usb_transaction() Immediate retry succeeded, seq = %d, S=%d, R=%d\n", sequence, commandToggle?1:0, receivedCommandToggle?1:0);
            }
        }
        // Mask toggle bit out of data
        data[0] &= ~0x80;

        if (rc == BDM_RC_USB_ERROR) {
            // Retry entire command
            reportFlag = true;
            print("bdmJMxx_usb_transaction() USB error, seq = %d, retrying command\n", sequence);
            continue;
        }
        // Don't toggle on busy -
        if (rc == BDM_RC_BUSY) {
            reportFlag = true;
            print("bdmJMxx_usb_transaction() BUSY response, seq = %d\n", sequence);
            continue;
        }
        if (reportFlag) {
            print("bdmJMxx_usb_transaction() Report, seq = %d, S=%d, R=%d\n", sequence, commandToggle?1:0, receivedCommandToggle?1:0);
        }
        commandToggle = !commandToggle;

        if (rc != BDM_RC_OK) {
            data[0] = rc;
            *actualRxSize = 0;
            memset(&data[1], 0x00, rxSize-1);
        }
    } while ((rc == BDM_RC_USB_ERROR) && (retry-->0));

    return rc;
}
//! Configures the MCGCG target clock
//!
//! @param busFrequency    - Resulting BDM frequency after clock adjustment
//! @param clockParameters - Describes clock settings to use
//!
//! @return error code, see \ref USBDM_ErrorCode
//!
//! @note Assumes that connection with the target has been established so
//!       reports any errors as PROGRAMMING_RC_ERROR_FAILED_CLOCK indicating
//!       a problem programming the target clock.
//!
USBDM_ErrorCode FlashProgrammer::configureMCG_Clock(unsigned long         *busFrequency,
                                                    MCG_ClockParameters_t *clockParameters){
   LOGGING_E;

   const uint32_t MCGC1    = parameters.getClockAddress();
   const uint32_t MCGC2    = parameters.getClockAddress()+1;
   const uint32_t MCGTRIM  = parameters.getClockAddress()+2;
   const uint32_t MCGSC    = parameters.getClockAddress()+3;
   const uint32_t MCGC3    = parameters.getClockAddress()+4;
   const uint32_t MCGT     = parameters.getClockAddress()+5;

   unsigned long bdmFrequency;

   Logging::print("MCG Clock: Ad=0x%08X, C1=0x%02X, C2=0x%02X, C3=0x%02X, SC=0x%02X, CT/C4=0x%02X\n",
           parameters.getClockAddress(),
           clockParameters->mcgC1,
           clockParameters->mcgC2,
           clockParameters->mcgC3,
           clockParameters->mcgSC,
           clockParameters->mcgCT
           );

   flashReady = FALSE; // Not configured for Flash access

   // ToDo - Review order of writes & need for re-connect()
   if (writeClockRegister(MCGTRIM, clockParameters->mcgTrim) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_Connect() != BDM_RC_OK) { // re-connect after possible bus speed change
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(MCGC1, clockParameters->mcgC1) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(MCGSC, clockParameters->mcgSC) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(MCGC2, clockParameters->mcgC2) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_Connect() != BDM_RC_OK) { // re-connect after possible bus speed change
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (writeClockRegister(MCGC3, clockParameters->mcgC3) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if ((parameters.getClockType() != S08MCGV1) &&
       (writeClockRegister(MCGT, clockParameters->mcgCT) != BDM_RC_OK)) {
         return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   milliSleep(100);
   if (USBDM_Connect() != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   if (USBDM_GetSpeed(&bdmFrequency) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_FAILED_CLOCK;
   }
   bdmFrequency *= 1000; // Convert to Hz
   *busFrequency = bdmFrequency*parameters.getBDMtoBUSFactor();
   Logging::print("BDM Speed = %ld kHz, Bus Speed = %ld kHz\n",
         bdmFrequency/1000, *busFrequency/1000);
   return PROGRAMMING_RC_OK;
}