//! (HCS12) Writes one byte to the BDM address space //! //! @param address 16-bit memory address //! @param data 8-bit data value //! //! @return 0 => Success,\n !=0 => Fail //! //! @note Access to Control register addres is mapped to USBDM_WriteControlReg() //! TBDML_API unsigned char _tbdml_write_bd(unsigned int address, unsigned char data) { if (address == HC12_BDMSTS) return USBDM_WriteControlReg(data); else return USBDM_WriteDReg(address, data); }
//! 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; }
//! 2.2.6.1 Write Value to Register //! //! @param dnRegNumber //! @param drvValue //! USBDM_GDI_DECLSPEC DiReturnT DiRegisterWrite ( DiUInt32T dnRegNumber, DiRegisterValueT drvValue ) { LOGGING; U32c value(drvValue); USBDM_ErrorCode rc = BDM_RC_OK; log.print("(0x%X(%d) <= 0x%08X)\n", dnRegNumber, dnRegNumber, (uint32_t)value); CHECK_ERROR_STATE(); if (dnRegNumber>cfv1regID_FIRST_DEBUG_regID_BYTE) { switch (dnRegNumber) { case cfv1regID_xcsr_byte : rc = USBDM_WriteControlReg(value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", "XCSR.byte", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } break; case cfv1regID_csr2_byte : rc = USBDM_WriteDReg(CFV1_DRegCSR2byte,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", "CSR2.byte", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } break; case cfv1regID_csr3_byte : rc = USBDM_WriteDReg(CFV1_DRegCSR3byte,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", "CSR3.byte", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } break; default : log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber); rc = BDM_RC_ILLEGAL_PARAMS; break; } } else if (dnRegNumber>cfv1regID_FIRST_DEBUG_REG) { int regNum = dnRegNumber-cfv1regID_FIRST_DEBUG_REG; rc = USBDM_WriteDReg(regNum,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", getCFV1DebugRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } } else if (dnRegNumber > cfv1regID_FIRST_CONTROL_REG) { int regNum = dnRegNumber-cfv1regID_FIRST_CONTROL_REG; rc = USBDM_WriteCReg(regNum,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", getCFV1ControlRegName(regNum), dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } } else { switch (dnRegNumber) { case cfv1regID_pc : /* PC */ if (!pcWritten) { log.print("Saving initial PC write = 0x%08X)\n", (uint32_t)value); pcWritten = true; pcResetValue = value; } rc = USBDM_WriteCReg(CFV1_CRegPC,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", "PC", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } break; case cfv1regID_sr : rc = USBDM_WriteCReg(CFV1_CRegSR,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", "SR", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } break; default : // D0-7, A0-7 if (dnRegNumber>15) { log.print("DiRegisterWrite(Illegal Reg# 0x%X(%d)\n", dnRegNumber, dnRegNumber); rc = BDM_RC_ILLEGAL_PARAMS; } else { rc = USBDM_WriteReg(dnRegNumber,value); if (rc != BDM_RC_OK) { log.print("DiRegisterWrite(%s(0x%X)) Failed, reason= %s\n", getCFV1RegName(dnRegNumber), dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } } break; } } if (rc != BDM_RC_OK) { log.error("0x%X Failed, reason= %s\n", dnRegNumber, USBDM_GetErrorString(rc)); return setErrorState(DI_ERR_NONFATAL, rc); } return setErrorState(DI_OK); }
//========================================================= //========================================================= //========================================================= // CFV1 // //! (CFv1) Write XCSR.msb //! //! @param value 8-bit number //! OSBDM_API void _opensourcebdm_write_xcsr_byte(unsigned char value) { USBDM_WriteControlReg(value); }