//! (HCS12) Writes one word to memory (address must be aligned) //! //! @param address 16-bit memory address //! @param data 16-bit data value //! TBDML_API void _tbdml_write_word(unsigned int address, unsigned int data) { uint8_t buffer[2]; buffer[0] = data>>8; buffer[1] = data; USBDM_WriteMemory( 2, 2, address, buffer); }
//! (CFv1) Memory write //! //! @param addr 24-bit address //! @param count 8-bit block size (in bytes) //! @param elementSize Memory transfer size (1,2 or 4) //! @param data Pointer to buffer containing data //! //! @return TRUE => Success,\n FALSE => Fail //! OSBDM_API BOOL _opensourcebdm_write_mem( unsigned int address, unsigned int count, unsigned int elementSize, unsigned char *data) { return (USBDM_WriteMemory( elementSize, count, address, data) == BDM_RC_OK); }
//! Clock register write with retry //! //! @param addr : clock register address //! @param data : byte to write //! //! @return BDM_RC_OK => success //! //! @note writes are retried after a re-connect to cope //! with a possible clock speed change. //! USBDM_ErrorCode writeClockRegister(uint32_t addr, uint8_t data) { LOGGING_Q; USBDM_ErrorCode rc; rc = USBDM_WriteMemory(1,1,addr,&data); if (rc != BDM_RC_OK) { Logging::print("Failed write 0x%04X <= 0x%02X) - retrying\n", addr, data); rc = USBDM_Connect(); if (rc == BDM_RC_OK) { rc = USBDM_WriteMemory(1,1,addr,&data); if (rc != BDM_RC_OK) { } } } if (rc != BDM_RC_OK) { Logging::print("Failed write 0x%04X <= 0x%02X), rc = %s\n", addr, data, USBDM_GetErrorString(rc)); } return rc; }
//! De-activate breakpoints. \n //! This may involve changing target code for RAM breakpoints or //! modifying target breakpoint hardware. //! void deactivateBreakpoints(void) { print("deactivateBreakpoints()\n"); memoryBreakInfo *bpPtr; if (!breakpointsActive) return; for (bpPtr = memoryBreakpoints; bpPtr < memoryBreakpoints+MAX_MEMORY_BREAKPOINTS; bpPtr++) { if (bpPtr->inUse) { print("deactivateBreakpoints(MEM@%08X)\n", bpPtr->address); USBDM_WriteMemory(2,2,bpPtr->address,bpPtr->opcode); } } USBDM_WriteDReg(CFV1_DRegTDR, TDR_DISABLE); breakpointsActive = false; }
//! De-activate breakpoints. \n //! This may involve changing target code for RAM breakpoints or //! modifying target breakpoint hardware. //! void deactivateBreakpoints(void) { print("deactivateBreakpoints()\n"); memoryBreakInfo *bpPtr; if (!breakpointsActive) return; // Memory breakpoints for (bpPtr = memoryBreakpoints; bpPtr < memoryBreakpoints+MAX_MEMORY_BREAKPOINTS; bpPtr++) { if (bpPtr->inUse) { print("deactivateBreakpoints(MEM@%08X)\n", bpPtr->address); USBDM_WriteMemory(sizeof(haltOpcode),sizeof(haltOpcode),bpPtr->address,bpPtr->opcode); } } // Hardware breakpoints ARM_WriteMemory(4, 4, FP_CTRL, getData4x8Le(FP_CTRL_DISABLE)); breakpointsActive = false; }
//! (HCS12, HC08 & RS08) Writes a block of data to memory //! //! For HCS12 & HC08 this writes to RAM. //! //! @param addr 16-bit memory address //! @param count 8-bit byte count //! @param data Pointer to buffer containing data //! TBDML_API void _tbdml_write_block( unsigned int addr, unsigned int count, unsigned char *data) { USBDM_WriteMemory( 1, count, addr, data); }
TBDML_API void _tbdml_write_byte( unsigned int address, unsigned char data) { USBDM_WriteMemory( 1, 1, address, &data); }
//! 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)); } } }
//! 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); }
USBDM_ErrorCode HCS12Unsecure::programSecurityLocation() { uint8_t unsecureFlashValue[] = {0xFF, 0xFE}; const uint8_t allOnes = 0xFF; const uint8_t allZeroes = 0x00; int timeout; uint8_t statValue; uint8_t Hex_02 = 0x02; uint8_t Hex_30 = 0x30; // Unsecure Chip - re-programming flash NVSEC print( "HCS12Unsecure::programSecurityLocation() - unsecuring target\n"); USBDM_WriteMemory(1, 1, HCS12DeviceData::getCOPCTL(), &COPCTL_value); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &Hex_02); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCLKDIVAddress(), &fcdivValue); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCLKDIVAddress(), &fcdivValue); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFPROTAddress(), &allOnes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &Hex_30); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFTSTMODAddress(), &allZeroes); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &Hex_02); USBDM_WriteMemory(2, 2, HCS12DeviceData::getNVSECAddress()-1, unsecureFlashValue); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCMDAddress(), &mWordProg); USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &startFlashCommand); // Program non-volatile Flash security location // USBDM_WriteMemory(1, 1, HCS12DeviceData::getFPROTAddress(), &allOnes); // USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &HCS12_clearFlashErrors); // USBDM_WriteMemory(2, 2, HCS12DeviceData::getNVSECAddress()-1, unsecureFlashValue); // USBDM_WriteMemory(1, 1, HCS12DeviceData::getFCMDAddress(), &mWordProg); // USBDM_WriteMemory(1, 1, HCS12DeviceData::getFSTATAddress(), &startFlashCommand); // Wait for flash command to complete timeout = 10; do { // Programming should take ??? 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); return BDM_RC_OK; }
//! \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; }
//! (HCS12, HC08 & RS08) Writes a block of data to memory //! //! For HCS12 & HC08 this writes to RAM. //! For RS08 this may write to RAM or Flash if preceded by _opensourcebdm_mem_dlstart(). //! //! @param addr 16-bit memory address //! @param count 8-bit byte count //! @param data Pointer to buffer containing data //! OSBDM_API void _opensourcebdm_write_block( unsigned int addr, unsigned int count, unsigned char *data) { USBDM_WriteMemory( 1, count, addr, data); }
OSBDM_API void _opensourcebdm_write_byte( unsigned int address, unsigned char data) { USBDM_WriteMemory( 1, 1, address, &data); }