/* 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; }
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()); }
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 }
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; } }
//! \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; }
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; }
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); }
// 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); } }
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; }
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; }
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; }
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; }
/************************************************************************ * 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; }
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; }
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; } }
//! \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); }
//! \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; }