//! Insert breakpoint //! //! @param type one of memoryBreak, hardBreak, writeWatch, readWatch, accessWatch //! @param address address for breakpoint/watchpoint //! @param size range to watch (watchpoint only) //! //! @return true => OK\n //! false => error //! //! @note writeWatch, readWatch, accessWatch not currently working //! int GdbBreakpoints::insertBreakpoint(BreakType type, uint32_t address, unsigned size) { LOGGING_Q; log.print("(%s, a=%08X, s=%d)\n", getBreakpointName(type), address, size); switch (type) { case memoryBreak: { if (findMemoryBreakpoint(address)) { log.print("- already set - ignored\n"); return true; // Already set - ignore } MemoryBreakInfo *bpPtr = findFreeMemoryBreakpoint(); if (bpPtr == NULL) { return false; // Too many breakpoints } bpPtr->address = address; bpPtr->inUse = true; return true; // Done } break; case hardBreak: { if (findHardwareBreakpoint(address)) { log.print("- already set - ignored\n"); return true; // Already set - ignore } HardwareBreakInfo *bpPtr = findFreeHardwareBreakpoint(); if (bpPtr == NULL) { return false; // Too many breakpoints } bpPtr->address = address; bpPtr->inUse = true; return true; // Done } break; case writeWatch: case readWatch: case accessWatch: { DataBreakInfo *bpPtr = findDataWatchPoint(address); if (bpPtr != NULL) { if (size > bpPtr->size) bpPtr->size = size; if (type != bpPtr->type) bpPtr->type = accessWatch; return true; // Already set - update } bpPtr = findFreeDataWatchPoint(); if (bpPtr == NULL) { return false; // Too many breakpoints } bpPtr->address = address; bpPtr->size = size; bpPtr->type = (BreakType)type; bpPtr->inUse = true; return true; // Done } break; default: return false; // Unknown type } }
//! Remove breakpoint //! //! @param type one of memoryBreak, hardBreak, writeWatch, readWatch, accessWatch //! @param address address for breakpoint/watchpoint //! @param size not used //! int GdbBreakpoints::removeBreakpoint(BreakType type, uint32_t address, unsigned size) { LOGGING_Q; log.print("(%s, a=%08X, s=%d)\n", getBreakpointName(type), address, size); switch (type) { case memoryBreak: { MemoryBreakInfo *bpPtr = findMemoryBreakpoint(address); if (bpPtr == NULL) { return false; // Non-existent breakpoint } bpPtr->inUse = false; bpPtr->address = 0; bpPtr->opcode[0] = 0; bpPtr->opcode[1] = 0; log.print("(t=MEM, a=%08X, s=%d) - done\n", address, size); return true; // Done } break; case hardBreak: { HardwareBreakInfo *bpPtr = findHardwareBreakpoint(address); if (bpPtr == NULL) { return false; // Non-existent breakpoint } bpPtr->inUse = false; log.print("(t=HW, a=%08X, s=%d) - done\n", address, size); return true; // Done } break; case writeWatch: case readWatch: case accessWatch: { DataBreakInfo *bpPtr = findDataWatchPoint(address); if (bpPtr == NULL) { return false; // Non-existent breakpoint } bpPtr->inUse = false; return true; // Done } break; default: return false; // Unknown type } }
//! 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); }