// Too hard - details depend on target too much // USBDM_ErrorCode HCS12Unsecure::unsecureHCS12Target(void) { unsigned long speed; USBDMStatus_t usbdmStatus; print("HCS12Unsecure::unsecureHCS12Target()\n"); USBDM_GetBDMStatus(&usbdmStatus); USBDM_GetSpeed(&speed); // Confirm speed HCS12Unsecure dialogue(false, speed); dialogue.Create(NULL); int getCancelOK = dialogue.ShowModal(); if (getCancelOK != wxID_OK) return BDM_RC_FAIL; USBDM_SetSpeed(speed); dialogue.bulkEraseMemory(); unsigned long bdmscr; USBDM_ReadStatusReg(&bdmscr); // for debug = UNSEC should be set dialogue.programSecurityLocation(); // closeLogFile(); return BDM_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; }
//! Configures the External target clock //! //! @param busFrequency - Resulting BDM frequency after clock adjustment (Hz) //! //! @return error code, see \ref USBDM_ErrorCode //! USBDM_ErrorCode FlashProgrammer::configureExternal_Clock(unsigned long *busFrequency){ LOGGING_E; unsigned long bdmFrequency; flashReady = FALSE; // Not configured for Flash access // Just connect at whatever speed if (USBDM_Connect() != BDM_RC_OK) { return PROGRAMMING_RC_ERROR_BDM_CONNECT; } if (USBDM_GetSpeed(&bdmFrequency) != BDM_RC_OK) { return PROGRAMMING_RC_ERROR_BDM_CONNECT; } 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; }
//! Determine crystal frequency of the target //! //! @return Crystal Frequency of target in MHz //! TBDML_API float _tbdml_get_speed(void) { unsigned long speed; USBDM_GetSpeed(&speed); // BDM comms speed in kHz return 2*speed/1000.0; // Convert to crystal freq in MHz }
//! 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; }