//! 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;
}
Beispiel #2
0
void AD770X::init(byte channel, byte clkDivider, byte polarity, byte gain, byte updRate) {
    setNextOperation(REG_CLOCK, channel, 0);
    writeClockRegister(0, clkDivider, updRate);

    setNextOperation(REG_SETUP, channel, 0);
    writeSetupRegister(MODE_SELF_CAL, gain, polarity, 0, 0);

    while (!dataReady(channel)) {
    };
}
//!  Determines the trim value for the target internal clock.
//!  The target clock is left trimmed for a bus freq. of targetBusFrequency.
//!
//!     Target clock has been suitably configured.
//!
//!  @param      trimAddress           Address of trim register.
//!  @param      targetBusFrequency    Target Bus Frequency to trim to.
//!  @param      returnTrimValue       Resulting trim value (9-bit number)
//!  @param      measuredBusFrequency  Resulting Bus Frequency
//!  @param      do9BitTrim            True to do 9-bit trim (rather than 8-bit)
//!
//!  @return
//!   == \ref PROGRAMMING_RC_OK  => Success \n
//!   != \ref PROGRAMMING_RC_OK  => Various errors
//!
USBDM_ErrorCode FlashProgrammer::trimTargetClock(uint32_t       trimAddress,
                                                 unsigned long  targetBusFrequency,
                                                 uint16_t      *returnTrimValue,
                                                 unsigned long *measuredBusFrequency,
                                                 int            do9BitTrim){
   LOGGING;
   uint8_t          mask;
   uint8_t          trimMSB, trimLSB, trimCheck;
   int              trimValue;
   int              maxRange;
   int              minRange;
   unsigned         long bdmSpeed;
   int              index;
   USBDM_ErrorCode  rc = PROGRAMMING_RC_OK;

#if TARGET == RS08
   mask = RS08_BDCSCR_CLKSW;
#elif TARGET == HCS08
   mask = HC08_BDCSCR_CLKSW;
#elif TARGET == HCS12
   mask = HC12_BDMSTS_CLKSW;
#elif TARGET == CFV1
   mask = CFV1_XCSR_CLKSW;
#endif

   unsigned long BDMStatusReg;
   rc = USBDM_ReadStatusReg(&BDMStatusReg);
   if ((BDMStatusReg&mask) == 0) {
      Logging::print("Setting CLKSW\n");
      BDMStatusReg |= mask;
#if TARGET == CFV1
      // Make sure we don't accidently do a mass erase
      mask &= ~CFV1_XCSR_ERASE;
#endif
      rc = USBDM_WriteControlReg(BDMStatusReg);
      rc = USBDM_Connect();
   }
   static const int maxTrim        = 505;   // Maximum acceptable trim value
   static const int minTrim        =   5;   // Minimum acceptable trim value
   static const int SearchOffset   =   8;   // Linear sweep range is +/- this value
   static const unsigned char zero =   0;
   const unsigned long targetBDMFrequency = targetBusFrequency/parameters.getBDMtoBUSFactor();
   int numAverage;     // Number of times to repeat measurements

   double sumX          = 0.0;
   double sumY          = 0.0;
   double sumXX         = 0.0;
   double sumYY         = 0.0;
   double sumXY         = 0.0;
   double num           = 0.0;
   double alpha, beta;
   double trimValueF;

   Logging::print("targetBusFrequency=%ld, targetBDMFrequency=%ld)\n", targetBusFrequency, targetBDMFrequency);

   flashReady = FALSE; // Not configured for Flash access

   // Set safe defaults
   *returnTrimValue      = 256;
   *measuredBusFrequency = 10000;
   trimMSB               = 0;

   // Set LSB trim value = 0
   if (writeClockRegister(trimAddress+1, zero) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_BDM_WRITE;
   }
   // Initial binary search (MSB only)
   for (mask = 0x80; mask > 0x0; mask>>=1) {
      trimMSB |= mask;
      // Set trim value (MSB only)
      if (writeClockRegister(trimAddress, trimMSB) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      // Check target speed
      if (USBDM_Connect() != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_CONNECT;
      }
      if (USBDM_GetSpeed(&bdmSpeed) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      bdmSpeed *= 1000; // convert to Hz

    Logging::print("Binary search: trimMSB=0x%02X (%d), bdmSpeed=%ld%c\n",
            trimMSB, trimMSB, bdmSpeed, (bdmSpeed<targetBDMFrequency)?'-':'+');

      // Adjust trim value
      if (bdmSpeed<targetBDMFrequency) {
         trimMSB &= ~mask; // too slow
      }
      if (trimMSB > maxTrim/2) {
         trimMSB = maxTrim/2;
      }
      if (trimMSB < minTrim/2) {
         trimMSB = minTrim/2;
      }
   }

   // Binary search value is middle of range to sweep

   trimValue = trimMSB<<1;  // Convert to 9-bit value

   // Linear sweep +/-SEARCH_OFFSET, starting at higher freq (smaller Trim)
   // Range is constrained to [minTrim..maxTrim]

   maxRange = trimValue + SearchOffset;
   if (maxRange > maxTrim) {
      maxRange = maxTrim;
   }
   minRange = trimValue - SearchOffset;
   if (minRange < minTrim) {
      minRange = minTrim;
   }
//   Logging::print("trimTargetClock(): Linear sweep, f=%6ld    \n"
//                   "trimTargetClock():    Trim       frequency \n"
//                   "========================================== \n",
//                   targetBDMFrequency/1000);

   if (do9BitTrim) {
      numAverage = 2;
   }
   else {
      numAverage = 4;
   }
   for(trimValue=maxRange; trimValue>=minRange; trimValue--) {
      trimLSB = trimValue&0x01;
      trimMSB = (uint8_t)(trimValue>>1);
      if (do9BitTrim) {
         // Write trim LSB
         if (writeClockRegister(trimAddress+1, trimLSB) != BDM_RC_OK)
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
         if (USBDM_ReadMemory(1, 1, trimAddress+1,   &trimCheck) != BDM_RC_OK)
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
         if ((trimCheck&0x01) != trimLSB)
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      else if (trimValue&0x01) {
         // skip odd trim values if 8-bit trim
         continue;
      }
      // Write trim MSB
      if (writeClockRegister(trimAddress,  trimMSB) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      if (USBDM_ReadMemory(1, 1, trimAddress,   &trimCheck) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      if (trimCheck != trimMSB) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      //milliSleep(100);
      // Measure sync multiple times
      for(index=numAverage; index>0; index--) {
         // Check target speed
         if (USBDM_Connect() != BDM_RC_OK)
            return PROGRAMMING_RC_ERROR_BDM_CONNECT;
         if (USBDM_GetSpeedHz(&bdmSpeed) != BDM_RC_OK)
            return PROGRAMMING_RC_ERROR_BDM_CONNECT;
         sumX  += trimValue;
         sumY  += bdmSpeed;
         sumXX += trimValue*trimValue;
         sumYY += bdmSpeed*bdmSpeed;
         sumXY += bdmSpeed*trimValue;
         num   += 1.0;
//         Logging::print("trimTargetClock(): %6d    %10ld %10ld\n", trimValue, bdmSpeed, targetBDMFrequency-bdmSpeed);
      }
   }
   for(trimValue=minRange; trimValue<=maxRange; trimValue++) {
      trimLSB = trimValue&0x01;
      trimMSB = (uint8_t)(trimValue>>1);
      if (do9BitTrim) {
         // Write trim LSB
         if (writeClockRegister(trimAddress+1, trimLSB) != BDM_RC_OK) {
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
         }
         if (USBDM_ReadMemory(1, 1, trimAddress+1,   &trimCheck) != BDM_RC_OK) {
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
         }
         if ((trimCheck&0x01) != trimLSB) {
            return PROGRAMMING_RC_ERROR_BDM_WRITE;
         }
      }
      else if (trimValue&0x01) {
         // skip odd trim values if 8-bit trim
         continue;
      }
      // Write trim MSB
      if (writeClockRegister(trimAddress, trimMSB) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      if (USBDM_ReadMemory(1, 1, trimAddress,   &trimCheck) != BDM_RC_OK) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      if (trimCheck != trimMSB) {
         return PROGRAMMING_RC_ERROR_BDM_WRITE;
      }
      //milliSleep(100);
      // Measure sync multiple times
      for(index=numAverage; index>0; index--) {
         // Check target speed
         if (USBDM_Connect() != BDM_RC_OK) {
            return PROGRAMMING_RC_ERROR_BDM_CONNECT;
         }
         if (USBDM_GetSpeedHz(&bdmSpeed) != BDM_RC_OK) {
            return PROGRAMMING_RC_ERROR_BDM_CONNECT;
         }
         sumX  += trimValue;
         sumY  += bdmSpeed;
         sumXX += trimValue*trimValue;
         sumYY += bdmSpeed*bdmSpeed;
         sumXY += bdmSpeed*trimValue;
         num   += 1.0;
//         Logging::print("trimTargetClock(): %6d    %10ld %10ld\n", trimValue, bdmSpeed, targetBDMFrequency-bdmSpeed);
      }
   }

//   Logging::print("N=%f, sumX=%f, sumXX=%f, sumY=%f, sumYY=%f, sumXY=%f\n",
//                    num, sumX, sumXX, sumY, sumYY, sumXY);

   // Calculate linear regression co-efficients
   beta  = (num*sumXY-sumX*sumY)/(num*sumXX-sumX*sumX);
   alpha = (sumY-beta*sumX)/num;

   // Estimate required trim value
   trimValueF = ((targetBDMFrequency-alpha)/beta);

   if ((trimValueF <= 5.0) || (trimValue >= 505.0)) { // resulted in extreme value
      trimValueF = 256.0;                             // replace with 'Safe' trim value
      rc = PROGRAMMING_RC_ERROR_TRIM;
   }

   trimValue = (int)round(trimValueF);
   trimMSB   = trimValue>>1;
   trimLSB   = trimValue&0x01;

//   Logging::print("alpha= %f, beta= %f, trimF= %f, trimMSB= %d (0x%02X), trimLSB= %d\n",
//           alpha, beta, trimValueF, trimMSB, trimMSB, trimLSB);

//   Logging::print("trimTargetClock() Result: trim=0x%3.3x (%d), measured bdmSpeed=%ld\n",
//           savedTrimValue, savedTrimValue, bestFrequency);

   *returnTrimValue  = trimValue;

   // Set trim value (LSB first)
   if ((do9BitTrim && (writeClockRegister(trimAddress+1, trimLSB) != BDM_RC_OK)) ||
       (writeClockRegister(trimAddress, trimMSB) != BDM_RC_OK)) {
      return PROGRAMMING_RC_ERROR_BDM_WRITE;
   }
   // Check connection at that speed
   if (USBDM_Connect() != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_BDM_CONNECT;
   }
   if (USBDM_GetSpeedHz(&bdmSpeed) != BDM_RC_OK) {
      return PROGRAMMING_RC_ERROR_BDM_CONNECT;
   }
   *measuredBusFrequency = bdmSpeed*parameters.getBDMtoBUSFactor();

   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;
}