//! Activate breakpoints. \n //! This may involve changing target code for RAM breakpoints or //! modifying target breakpoint hardware //! void activateBreakpoints(void) { print("activateBreakpoints()\n"); memoryBreakInfo *bpPtr; if (breakpointsActive) return; // Memory breakpoints for (bpPtr = memoryBreakpoints; bpPtr < memoryBreakpoints+MAX_MEMORY_BREAKPOINTS; bpPtr++) { if (bpPtr->inUse) { print("activateBreakpoints(%s@%08X)\n", getBreakpointName(memoryBreak), bpPtr->address); USBDM_ReadMemory(sizeof(haltOpcode),sizeof(haltOpcode),bpPtr->address,bpPtr->opcode); USBDM_WriteMemory(sizeof(haltOpcode),sizeof(haltOpcode),bpPtr->address,haltOpcode); breakpointsActive = true; } } // Hardware breakpoints uint32_t fp_ctrl = FP_CTRL_DISABLE; for (int breakPtNum=0; breakPtNum<MAX_HARDWARE_BREAKPOINTS; breakPtNum++) { if (hardwareBreakpoints[breakPtNum].inUse) { print("activateBreakpoints(%s@%08X)\n", getBreakpointName(hardBreak), hardwareBreakpoints[breakPtNum].address&~0x1); fp_ctrl = FP_CTRL_ENABLE; ARM_WriteMemory(4, 4, FP_COMP0+4*breakPtNum, getFpCompAddress(hardwareBreakpoints[breakPtNum].address)); breakpointsActive = true; } else { ARM_WriteMemory(4, 4, FP_COMP0+4*breakPtNum, getData4x8Le(FP_COMP_DISABLE)); } } ARM_WriteMemory(4, 4, FP_CTRL, getData4x8Le(fp_ctrl)); // Hardware watches for (int watchPtNum=0; watchPtNum<MAX_DATA_WATCHES; watchPtNum++) { if (dataWatchPoints[watchPtNum].inUse) { unsigned size = dataWatchPoints[watchPtNum].size; unsigned bpSize = 1; unsigned sizeValue = 0; while ((bpSize<size) && (sizeValue<15)) { sizeValue++; bpSize <<= 1; } int mode = DWT_FUNCTION_READ_WATCH; switch (dataWatchPoints[watchPtNum].type) { case readWatch: mode = DWT_FUNCTION_READ_WATCH; break; case writeWatch: mode = DWT_FUNCTION_WRITE_WATCH; break; case accessWatch: mode = DWT_FUNCTION_RW_WATCH; break; default : break; } print("activateBreakpoints(%s@%08X)\n", getBreakpointName(dataWatchPoints[watchPtNum].type), dataWatchPoints[watchPtNum].address); print("activateBreakpoints(%s@%08X, bpSize=%d, sizeValue=%d)\n", getBreakpointName(dataWatchPoints[watchPtNum].type), dataWatchPoints[watchPtNum].address&(~(bpSize-1)), bpSize, sizeValue ); ARM_WriteMemory(4, 4, DWT_COMP0+16*watchPtNum, getData4x8Le(dataWatchPoints[watchPtNum].address)); ARM_WriteMemory(4, 4, DWT_MASK0+16*watchPtNum, getData4x8Le(sizeValue)); ARM_WriteMemory(4, 4, DWT_FUNCTION0+16*watchPtNum, getData4x8Le(mode)); breakpointsActive = true; } else { ARM_WriteMemory(4, 4, DWT_FUNCTION0+16*watchPtNum, getData4x8Le(DWT_FUNCTION_NONE)); } } }
//! 2.2.8.2 Execute a Single Step //! //! @param dnNrInstructions //! USBDM_GDI_DECLSPEC DiReturnT DiExecSingleStep ( DiUInt32T dnNrInstructions ) { LOGGING_Q; log.print("(%d)\n", dnNrInstructions); USBDM_ErrorCode BDMrc; long unsigned ccrValue; long unsigned pcValue; unsigned char currentOpcode; const int interruptMask = (1<<3); const int tapOpcode = 0x84; const int tpaOpcode = 0x85; const int seiOpcode = 0x9B; const int cliOpcode = 0x9A; const int waitOpcode = 0x8F; const int rtiOpcode = 0x80; const int swiOpcode = 0x83; const int stopOpcode = 0x8E; CHECK_ERROR_STATE(); #if (TARGET == MC56F80xx) BDMrc = DSC_TargetStepN(dnNrInstructions); #else if (dnNrInstructions>1) { log.print("DiExecSingleStep() - Only a single step is supported!\n"); return setErrorState(DI_ERR_PARAM, ("Only a single step is allowed")); } /* * Cases to consider when masking interrupts during step * * +--------+-----------+---------+-----------------------------------------------------+ * | Opcode | Initial I | Final I | Problem - action | * +--------+-----------+---------+-----------------------------------------------------+ * | --- | 1 | X | None - no action (interrupts already masked) | * +--------+-----------+---------+-----------------------------------------------------+ * | CLI | 0 | ? | It may be possible for an interrupt to occur, | * | WAIT | | | setting I-flag which is then incorrectly cleared. | * | STOP | | | (I don't think it applies to CLI but be safe.) | * | SWI | | | - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | RTI | 0 | 1 | Contrived but possible situation. I flag | * | | | | incorrectly cleared - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | SEI | 0 | 1 | The instruction may set I-flag which is then | * | TAP | 0 | 1 | incorrectly cleared - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | TPA | 0 | X | The wrong value is transferred to A - fix A | * +--------+-----------+---------+-----------------------------------------------------+ * | --- | 0 | 0 | CCR change - clear I-flag in new CCR | * +--------+-----------+---------+-----------------------------------------------------+ */ if (bdmOptions.maskInterrupts) { log.print("DiExecSingleStep() - checking if interrupt masking needed\n"); USBDM_ReadReg(HCS08_RegCCR, &ccrValue); if ((ccrValue&interruptMask) != 0) { // Interrupts already masked - just step BDMrc = USBDM_TargetStep(); } else { // Mask interrupts log.print("DiExecSingleStep() - masking interrupts\n"); USBDM_WriteReg(HCS08_RegCCR, ccrValue|interruptMask); // Get current instruction opcode USBDM_ReadReg(HCS08_RegPC, &pcValue); USBDM_ReadMemory(1,1,pcValue,¤tOpcode); // Do a step BDMrc = USBDM_TargetStep(); switch(currentOpcode) { case cliOpcode : case waitOpcode : case seiOpcode : case tapOpcode : case rtiOpcode : case swiOpcode : // Not ever stepped - treated as subroutine? case stopOpcode : log.print("DiExecSingleStep() - skipping CCR restore\n"); // Don't 'fix' CCR as updated by instruction or int ack break; case tpaOpcode : // Fix A & CCR (clear I flag) log.print("DiExecSingleStep() - fixing A & CCR reg\n"); USBDM_WriteReg(HCS08_RegA, ccrValue&~interruptMask); USBDM_WriteReg(HCS08_RegCCR, ccrValue&~interruptMask); break; default : // Fix CCR (clear I flag) // Unmask interrupts log.print("DiExecSingleStep() - fixing CCR reg\n"); USBDM_ReadReg(HCS08_RegCCR, &ccrValue); USBDM_WriteReg(HCS08_RegCCR, ccrValue&~interruptMask); break; } } } else BDMrc = USBDM_TargetStep(); #endif if (BDMrc != BDM_RC_OK) { return setErrorState(DI_ERR_NONFATAL, BDMrc); } return setErrorState(DI_OK); }
//! Activate breakpoints. \n //! This may involve changing target code for RAM breakpoints or //! modifying target breakpoint hardware //! void activateBreakpoints(void) { print("activateBreakpoints()\n"); static const uint8_t haltOpcode[] = {0x4a, 0xc8}; memoryBreakInfo *bpPtr; if (breakpointsActive) return; for (bpPtr = memoryBreakpoints; bpPtr < memoryBreakpoints+MAX_MEMORY_BREAKPOINTS; bpPtr++) { if (bpPtr->inUse) { print("activateBreakpoints(%s@%08X)\n", getBreakpointName(memoryBreak), bpPtr->address); USBDM_ReadMemory(2,2,bpPtr->address,bpPtr->opcode); USBDM_WriteMemory(2,2,bpPtr->address,haltOpcode); breakpointsActive = true; } } uint32_t tdrValue = TDR_DISABLE; if (hardwareBreakpoints[0].inUse) { tdrValue |= TDR_TRC_HALT|TDR_L1T|TDR_L1EBL|TDR_L1EPC; USBDM_WriteDReg(CFVx_DRegPBR0, hardwareBreakpoints[0].address&~0x1); USBDM_WriteDReg(CFVx_DRegPBMR, 0x00000000); breakpointsActive = true; print("activateBreakpoints(%s@%08X)\n", getBreakpointName(hardBreak), hardwareBreakpoints[0].address&~0x1); } if (hardwareBreakpoints[1].inUse) { tdrValue |= TDR_TRC_HALT|TDR_L1T|TDR_L1EBL|TDR_L1EPC; USBDM_WriteDReg(CFVx_DRegPBR1, hardwareBreakpoints[1].address|0x1); breakpointsActive = true; print("activateBreakpoints(%s@%08X)\n", getBreakpointName(hardBreak), hardwareBreakpoints[1].address&~0x1); } else { USBDM_WriteDReg(CFVx_DRegPBR1,0); } if (hardwareBreakpoints[2].inUse) { tdrValue |= TDR_TRC_HALT|TDR_L1T|TDR_L1EBL|TDR_L1EPC; USBDM_WriteDReg(CFVx_DRegPBR2, hardwareBreakpoints[2].address|0x1); breakpointsActive = true; print("activateBreakpoints(%s@%08X)\n", getBreakpointName(hardBreak), hardwareBreakpoints[2].address&~0x1); } else { USBDM_WriteDReg(CFVx_DRegPBR2,0); } if (hardwareBreakpoints[3].inUse) { tdrValue |= TDR_TRC_HALT|TDR_L1T|TDR_L1EBL|TDR_L1EPC; USBDM_WriteDReg(CFVx_DRegPBR3, hardwareBreakpoints[3].address|0x1); breakpointsActive = true; print("activateBreakpoints(%s@%08X)\n", getBreakpointName(hardBreak), hardwareBreakpoints[3].address&~0x1); } else { USBDM_WriteDReg(CFV1_DRegPBR3,0); } if (dataWatchPoints[0].inUse) { tdrValue |= TDR_TRC_HALT|TDR_L1T|TDR_L1EBL|TDR_L1EA_INC; USBDM_WriteDReg(CFVx_DRegABLR, dataWatchPoints[0].address); USBDM_WriteDReg(CFVx_DRegABHR, dataWatchPoints[0].address+dataWatchPoints[0].size-1); breakpointsActive = true; } USBDM_WriteDReg(CFVx_DRegTDR, tdrValue); }
//! \brief Does Bulk Erase of Target Flash. //! //! @return error code, see \ref FlashError_t //! //! @note The target is not reset so current security state persists after erase. //! USBDM_ErrorCode HCS12Unsecure::bulkEraseMemory() { const uint8_t allOnes = 0xFF; const uint8_t allZeroes = 0x00; uint8_t dummyFlashAddress[] = {0xFF, 0xFE}; uint8_t dummyEepromAddress[] = {0x0C, 0x00}; uint8_t dummyFlashData[] = {0xFF, 0xFF}; int timeout; uint8_t statValue; USBDM_ErrorCode rc; print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target...\n"); // Erase chip //============================= // Set up flash & eeprom rc = initialiseTargetFlash(); if (rc != BDM_RC_OK) { print("HCS12Unsecure::bulkEraseMemory(): initialiseTargetFlash() failed, reason=%s\n", USBDM_GetErrorString(rc)); return rc; } print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target Flash...\n"); // Apply Bulk Erase operation to all Flash banks USBDM_WriteMemory(1, 1, HCS12DeviceData::getFPROTAddress(), &allOnes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &HCS12_clearFlashErrors); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &HCS12_clearFlashErrors); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &HCS12_FTSTMOD_WRALL); USBDM_WriteMemory(2, 2, HCS12DeviceData::getFADDRAddress(), dummyFlashAddress); USBDM_WriteMemory(2, 2, HCS12DeviceData::getFDATAAddress(), dummyFlashData); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCMDAddress(), &mMassErase); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &startFlashCommand); // Wait for flash command to complete timeout = 10; do { // Mass erase should take ~100ms wxMilliSleep(100); if (USBDM_ReadMemory(1,1,HCS12DeviceData::getFSTATAddress(),&statValue) != BDM_RC_OK) return BDM_RC_FAIL; if (timeout-- == 0) return BDM_RC_FAIL; } while ((statValue & 0xC0) != 0xC0); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes); if (hasEEPROM) { print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target EEPROM...\n"); // Apply Bulk Erase operation to EEPROM USBDM_WriteMemory(1, 1, HCS12DeviceData::getEPROTAddress(), &allOnes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getESTATAddress(), &HCS12_clearFlashErrors); USBDM_WriteMemory(2, 2, HCS12DeviceData::getEADDRAddress(), dummyEepromAddress); USBDM_WriteMemory(2, 2, HCS12DeviceData::getEDATAAddress(), dummyFlashData); USBDM_WriteMemory(1, 1, HCS12DeviceData::getECMDAddress(), &mMassErase); USBDM_WriteMemory(1, 1, HCS12DeviceData::getESTATAddress(), &startFlashCommand); // Wait for flash command to complete timeout = 10; do { // Mass erase should take ~100ms wxMilliSleep(100); if (USBDM_ReadMemory(1,1,HCS12DeviceData::getESTATAddress(),&statValue) != BDM_RC_OK) return BDM_RC_FAIL; if (timeout-- == 0) return BDM_RC_FAIL; } while ((statValue & 0xC0) != 0xC0); } USBDM_TargetReset((TargetMode_t)(RESET_HARDWARE|RESET_SPECIAL)); unsigned long usbdmStatus; USBDM_ReadStatusReg(&usbdmStatus); if ((usbdmStatus & HC12_BDMSTS_UNSEC) != 0) { print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target memory...Complete\n"); return BDM_RC_OK; } else { print("HCS12Unsecure::bulkEraseMemory():Bulk erasing target memory...Failed!\n"); return BDM_RC_FAIL; } }
//! \brief Sets the FCLKDIV/ECLKDIV register value based on //! the BDM communication speed. //! //! Prepares the target for Flash and eeprom operations. \n //! - Unprotects flash & eeprom [FPROT/EPROT registers] //! - Set Flash clock divider [FCLKDIV/ECLKDIV registers] based busFrequency //! - Clear flash & eeprom errors [FSTAT/ESTAT registers] //! - Unprotects flash (FPROT) //! - Set Flash clock divider (FCDIV) //! - Disable COP //! //! @return error code, see \ref FlashError_t //! //! @note Assumes target has been reset & connected //! USBDM_ErrorCode HCS12Unsecure::initialiseTargetFlash() { uint8_t fcdivCheckValue; static const unsigned char allOnes = 0xFF; static const unsigned char allZeroes = 0x00; USBDM_ErrorCode rc; print("HCS12Unsecure::initialiseTargetFlash()\n"); // Determine the FCLKDIV/ECLKDIV value //========================================= // Set user supplied speed rc = USBDM_SetSpeed(busFrequency); if ((rc != BDM_RC_OK) && (rc != BDM_RC_BDM_EN_FAILED)) return rc; // Calculate the required FCDIV value fcdivValue = findFlashDividerValue((long)round(busFrequency), 150, 200); print("HCS12Unsecure::initialiseTargetFlash(): fBus = %ld kHz, FCDIV=0x%2.2X (%d)\n", (long)round(busFrequency/1000.0), fcdivValue, fcdivValue); if (fcdivValue == 0xFF) return BDM_RC_UNKNOWN_SPEED; // Disable COP if (USBDM_WriteMemory(1, 1, HCS12DeviceData::getCOPCTL(), &COPCTL_value) != BDM_RC_OK) return BDM_RC_FAIL; // fcdivValue |= 0x80; // Unprotect the Flash if (USBDM_WriteMemory(1,1,HCS12DeviceData::getFPROTAddress(),&allOnes) != BDM_RC_OK) return BDM_RC_FAIL; // Clear any Flash errors (set FTSTMOD_WALL so all banks are affected) if (USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &HCS12_FTSTMOD_WRALL) != BDM_RC_OK) return BDM_RC_FAIL; if (USBDM_WriteMemory(1,1,HCS12DeviceData::getFSTATAddress(),&HCS12_clearFlashErrors) != BDM_RC_OK) return BDM_RC_FAIL; if (USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes) != BDM_RC_OK) return BDM_RC_FAIL; // Set FCLKDIV value & verify if (USBDM_WriteMemory(1,1,HCS12DeviceData::getFCLKDIVAddress(),&fcdivValue) != BDM_RC_OK) return BDM_RC_FAIL; if (USBDM_ReadMemory(1,1,HCS12DeviceData::getFCLKDIVAddress(),&fcdivCheckValue) != BDM_RC_OK) return BDM_RC_FAIL; if (fcdivCheckValue != (fcdivValue|FCLKDIV_FDIVLD)) return BDM_RC_FAIL; if (hasEEPROM) { // Set up the eeprom //==================================== // Assume errors here mean there isn't actually any EEPROM // Unprotect the eeprom if (USBDM_WriteMemory(1,1,HCS12DeviceData::getEPROTAddress(),&allOnes) != BDM_RC_OK) hasEEPROM = false; // Clear any eeprom errors if (USBDM_WriteMemory(1,1,HCS12DeviceData::getESTATAddress(),&HCS12_clearFlashErrors) != BDM_RC_OK) hasEEPROM = false; // Set ECLKDIV value & verify if (USBDM_WriteMemory(1,1,HCS12DeviceData::getECLKDIVAddress(),&fcdivValue) != BDM_RC_OK) hasEEPROM = false; if (USBDM_ReadMemory(1,1,HCS12DeviceData::getECLKDIVAddress(),&fcdivCheckValue) != BDM_RC_OK) hasEEPROM = false; if (fcdivCheckValue != (fcdivValue|ECLKDIV_EDIVLD)) hasEEPROM = false; } return BDM_RC_OK; }
//! 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; }
//! (HCS12, HC08 & RS08) Reads block from memory //! //! @param addr 16-bit memory address //! @param count 8-bit byte count //! @param data Pointer to buffer to contain data //! OSBDM_API void _opensourcebdm_read_block( unsigned int addr, unsigned int count, unsigned char *data) { USBDM_ReadMemory( 1, count, addr, data); }
//! (HCS12, HC08 & RS08) Reads one byte from memory //! //! @param address 16-bit memory address //! //! @return 8-bit value //! OSBDM_API unsigned char _opensourcebdm_read_byte(unsigned int address) { U8 value; USBDM_ReadMemory( 1, 1, address, &value); return value; }