├── requirements.txt ├── LICENSE ├── testMain.py ├── README.md ├── debugger.py └── main.py /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stemnic/pyAVRdbg/HEAD/requirements.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ole Sivert Aarhaug 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /testMain.py: -------------------------------------------------------------------------------- 1 | import debugger 2 | import logging 3 | import time 4 | 5 | dbg = debugger.Debugger("atmega4809") 6 | dbg.stop() 7 | dbg.breakpointSWClearAll() 8 | dbg.breakpointHWClear() 9 | #logging.info(dbg.readRegs()) 10 | #logging.info(dbg.readSRAM(0x00, 1024)) 11 | #logging.info(dbg.readSREG()) 12 | #logging.info(dbg.readStackPointer()) 13 | event = dbg.pollEvent() 14 | while event != None: 15 | event = dbg.pollEvent() 16 | dbg.readRunningState() 17 | print("Started running") 18 | dbg.run() 19 | dbg.readRunningState() 20 | while True: 21 | if dbg.readRunningState() == False: 22 | event = dbg.pollEvent() 23 | while event != None: 24 | event = dbg.pollEvent() 25 | print("Started running") 26 | dbg.run() 27 | time.sleep(1) 28 | #dbg.breakpointSWSet(0x154) 29 | #dbg.pollEvent() 30 | #dbg.pollEvent() 31 | #time.sleep(1) 32 | #dbg.pollEvent() 33 | #dbg.pollEvent() 34 | #dbg.run() 35 | #dbg.pollEvent() 36 | #print(dbg.readProgramCounter()) 37 | #print("\n") 38 | #dbg.step() 39 | #dbg.step() 40 | #dbg.step() 41 | #dbg.pollEvent() 42 | #dbg.pollEvent() 43 | #dbg.pollEvent() 44 | #dbg.pollEvent() 45 | #time.sleep(1) 46 | #dbg.pollEvent() 47 | #dbg.pollEvent() 48 | #dbg.run() 49 | #dbg.pollEvent() 50 | # 51 | #time.sleep(1) 52 | # 53 | #print(dbg.readProgramCounter()) 54 | #print(dbg.readProgramCounter()) 55 | #print("\n") 56 | #dbg.run() 57 | #dbg.pollEvent() 58 | #dbg.pollEvent() 59 | #dbg.pollEvent() 60 | #dbg.pollEvent() 61 | #logging.info(dbg.readRegs()) 62 | 63 | dbg.cleanup() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyAVRdbg 2 | An attempt of making a gdb rsp server for AVR debuggers with [pymcuprog](https://pypi.org/project/pymcuprog/) primarily for the new UPDI devices but other protocols supported by pymcuprog can easily be made to work. 3 | 4 | ## Current Features 5 | - Stepping 6 | - Memory manipulation (viewing and modifying variables) 7 | - Hardware and software breakpoints 8 | - Reading Registers (including SREG, Stack pointer and program counter)* 9 | 10 | *Writing is possible it is just not implemented yet. 11 | 12 | ## Install/Dependencies 13 | 14 | - avr-gdb 15 | - Recommend using the latest version. If you are compiling it I would looking at the arch community repos [buildfile](https://git.archlinux.org/svntogit/community.git/tree/trunk/PKGBUILD?h=packages/avr-gdb) 16 | - Windows users might want to use wsl 17 | - libusb might be required as a seperate install 18 | - pip3 install --user pymcuprog 19 | - Some form for C++ compiler if you are running python versions higher than 3.6 since pymcuprog needs to compile package with Cython 20 | - Windows: 21 | - VC++ 2015.3 v14.00 (v140) installed through [Visual Studio](https://visualstudio.microsoft.com/downloads/) 22 | 23 | ## Usage 24 | 25 | ### Debugger server 26 | 1. Ensure debugger/kit is connected 27 | 2. Modify main.py with device name see [supported devices](#currently-supported-devices) and ip or port defines if applicable 28 | 3. start main.py 29 | 30 | ### GDB 31 | 1. `avr-gdb (wellNamed).elf` 32 | 2. (gdb) `target remote IP:Port` 33 | 34 | ## Currently Supported Devices 35 | These are all the currently supported devices per 03.06.2020. This list is wholly dependent on pymcuprog's device support since this RSP server only uses general library calls in pymcuprog. As mentioned before ISP devices might also be supported in the future. 36 | | Protocol | Device Name | 37 | |:--------:|:-----------:| 38 | | UPDI | atmega4808* | 39 | | | atmega4809 | 40 | | | attiny416* | 41 | | | attiny817* | 42 | | |attiny1607*| 43 | | |attiny1627*| 44 | | |attiny3217*| 45 | | |avr128da28*| 46 | | |avr128da48| 47 | | |avr128db48*| 48 | 49 | *Devices are untested but will most likely work. 50 | 51 | ## Thanks 52 | A huge thanks to Microchip for making pymcuprog available 53 | 54 | ## Some useful links for referance for development 55 | - https://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html#id3033520 56 | - https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_toc.html 57 | - https://onlinedocs.microchip.com/pr/GUID-33422CDF-8B41-417C-9C31-E4521ADAE9B4-en-US-2/index.html 58 | - https://github.com/mbedmicro/pyOCD/tree/master/pyocd 59 | - https://developer.apple.com/library/archive/documentation/DeveloperTools/gdb/gdb/gdb_33.html 60 | - http://ww1.microchip.com/downloads/en/DeviceDoc/50002630A.pdf 61 | -------------------------------------------------------------------------------- /debugger.py: -------------------------------------------------------------------------------- 1 | from pyedbglib.hidtransport.hidtransportfactory import hid_transport 2 | from pyedbglib.protocols import housekeepingprotocol 3 | from pyedbglib.protocols import housekeepingprotocol 4 | from pyedbglib.protocols import avr8protocol 5 | from pyedbglib.protocols import avr8protocolerrors 6 | 7 | # Retrieve device info 8 | from pymcuprog.deviceinfo import deviceinfo 9 | 10 | # Construct an NVM provider 11 | from pymcuprog.nvmupdi import NvmAccessProviderCmsisDapUpdi 12 | 13 | from pyedbglib.protocols.avrcmsisdap import AvrCommand, AvrCommandError 14 | from pyedbglib.protocols.jtagice3protocol import Jtagice3Command 15 | 16 | import logging 17 | import threading 18 | import time 19 | import asyncio 20 | 21 | logging.basicConfig(level=logging.INFO,handlers=[logging.StreamHandler()]) 22 | 23 | 24 | 25 | class Debugger(): 26 | 27 | def __init__(self, DeviceName): 28 | # Make a connection 29 | self.transport = hid_transport() 30 | self.transport.disconnect() 31 | # Connect 32 | self.transport.connect() 33 | self.deviceInf = deviceinfo.getdeviceinfo(DeviceName) 34 | self.memoryinfo = deviceinfo.DeviceMemoryInfo(self.deviceInf) 35 | self.housekeeper = housekeepingprotocol.Jtagice3HousekeepingProtocol(self.transport) 36 | self.housekeeper.start_session() 37 | self.device = NvmAccessProviderCmsisDapUpdi(self.transport, self.deviceInf) 38 | #self.device.avr.deactivate_physical() 39 | self.device.avr.activate_physical() 40 | # Start debug by attaching (live) 41 | self.device.avr.protocol.attach() 42 | #threading.Thread(target=pollingThread, args=(self.eventReciver,)).start() 43 | 44 | def pollEvent(self): 45 | #eventRegister = self.eventReciver.poll_events() 46 | eventRegister = self.device.avr.protocol.poll_events() 47 | #logging.info(eventRegister) 48 | if eventRegister[0] == AvrCommand.AVR_EVENT: # Verifying data is an event 49 | size = int.from_bytes(eventRegister[1:3], byteorder='big') 50 | if size != 0: 51 | #event recived 52 | logging.info("Event recived") 53 | eventarray = eventRegister[3:(size+1+3)] 54 | SOF = eventarray[0] 55 | protocol_version = eventarray[1:2] 56 | sequence_id = eventarray[2:4] 57 | protocol_handler_id = eventarray[4:5] 58 | payload = eventarray[5:] 59 | #logging.info(eventarray) 60 | if payload[0] == avr8protocol.Avr8Protocol.EVT_AVR8_BREAK: 61 | event_id = payload[0] 62 | #event_version = payload[1] 63 | pc = payload[1:5] 64 | break_cause = payload[5] 65 | extended_info = payload[6:] 66 | print("PC: ", end="") 67 | print(int.from_bytes(pc, byteorder='little')) 68 | logging.info("Recived break event") 69 | return (avr8protocol.Avr8Protocol.EVT_AVR8_BREAK, int.from_bytes(pc, byteorder='little'), break_cause) 70 | else: 71 | logging.info("Unknown event: " + payload[0]) 72 | return None 73 | 74 | else: 75 | logging.info("No event") 76 | return None 77 | 78 | # Memory interaction 79 | def writeSRAM(self, address, data): 80 | offset = (self.memoryinfo.memory_info_by_name('internal_sram'))['address'] 81 | return self.device.write(self.memoryinfo.memory_info_by_name('internal_sram'), address-offset, data) 82 | 83 | def readSRAM(self, address, numBytes): 84 | offset = (self.memoryinfo.memory_info_by_name('internal_sram'))['address'] 85 | return self.device.read(self.memoryinfo.memory_info_by_name('internal_sram'), address-offset, numBytes) 86 | 87 | def readFlash(self, address, numBytes): 88 | logging.info("Reading "+str(numBytes)+" bytes from flash at " + str(address)) 89 | offset = (self.memoryinfo.memory_info_by_name('flash'))['address'] 90 | # See programmer.py:265 in pymcuprog, maybe flashread fails due to page alignement? 91 | return self.device.read(self.memoryinfo.memory_info_by_name('flash'), address, numBytes) 92 | 93 | def writeEEPROM(self, address, data): 94 | offset = (self.memoryinfo.memory_info_by_name('eeprom'))['address'] 95 | return self.device.write(self.memoryinfo.memory_info_by_name('eeprom'), address-offset, data) 96 | 97 | def readEEPROM(self, address, numBytes): 98 | offset = (self.memoryinfo.memory_info_by_name('eeprom'))['address'] 99 | return self.device.read(self.memoryinfo.memory_info_by_name('eeprom'), address-offset, numBytes) 100 | 101 | def writeFuse(self, address, data): 102 | offset = (self.memoryinfo.memory_info_by_name('fuses'))['address'] 103 | return self.device.write(self.memoryinfo.memory_info_by_name('fuses'), address-offset, data) 104 | 105 | def readFuse(self, address, numBytes): 106 | offset = (self.memoryinfo.memory_info_by_name('fuses'))['address'] 107 | return self.device.read(self.memoryinfo.memory_info_by_name('fuses'), address-offset, numBytes) 108 | 109 | def writeLock(self, address, data): 110 | offset = (self.memoryinfo.memory_info_by_name('lockbits'))['address'] 111 | return self.device.write(self.memoryinfo.memory_info_by_name('lockbits'), address-offset, data) 112 | 113 | def readLock(self, address, numBytes): 114 | offset = (self.memoryinfo.memory_info_by_name('lockbits'))['address'] 115 | return self.device.read(self.memoryinfo.memory_info_by_name('lockbits'), address-offset, numBytes) 116 | 117 | def writeSignature(self, address, data): 118 | offset = (self.memoryinfo.memory_info_by_name('signatures'))['address'] 119 | return self.device.write(self.memoryinfo.memory_info_by_name('signatures'), address-offset, data) 120 | 121 | def readSignature(self, address, numBytes): 122 | offset = (self.memoryinfo.memory_info_by_name('signatures'))['address'] 123 | return self.device.read(self.memoryinfo.memory_info_by_name('signatures'), address-offset, numBytes) 124 | 125 | def writeUserSignature(self, address, data): 126 | offset = (self.memoryinfo.memory_info_by_name('user_row'))['address'] 127 | return self.device.write(self.memoryinfo.memory_info_by_name('user_row'), address-offset, data) 128 | 129 | def readUserSignature(self, address, numBytes): 130 | offset = (self.memoryinfo.memory_info_by_name('user_row'))['address'] 131 | return self.device.read(self.memoryinfo.memory_info_by_name('user_row'), address-offset, numBytes) 132 | 133 | # General debugging 134 | 135 | def attach(self, do_break=False): 136 | self.device.avr.protocol.attach(do_break) 137 | 138 | def detach(self): 139 | self.device.avr.protocol.detach() 140 | 141 | # Flow controll 142 | def reset(self): 143 | self.device.avr.protocol.reset() 144 | 145 | def step(self): 146 | self.device.avr.protocol.step() 147 | 148 | def stop(self): 149 | self.device.avr.protocol.stop() 150 | 151 | def run(self): 152 | self.device.avr.protocol.run() 153 | 154 | def runTo(self, address): 155 | wordAddress = int(address/2) 156 | self.device.avr.protocol.run_to(wordAddress) 157 | 158 | def readStackPointer(self): 159 | return self.device.avr.stack_pointer_read() 160 | 161 | def readSREG(self): 162 | return self.device.avr.protocol.memory_read(avr8protocol.Avr8Protocol.AVR8_MEMTYPE_OCD, 0x1C, 0x01) 163 | 164 | def readRunningState(self): 165 | # Debug interface to see what state the avr is in. 166 | AVR8_CTXT_TEST = 0x80 167 | AVR8_TEST_TGT_RUNNING = 0x00 168 | running = bool(self.device.avr.protocol.get_byte(AVR8_CTXT_TEST, AVR8_TEST_TGT_RUNNING)) 169 | logging.info("AVR running state " + str(running)) 170 | return running 171 | 172 | 173 | # Register and programcounter 174 | def readRegs(self): 175 | return self.device.avr.protocol.regfile_read() 176 | 177 | def writeRegs(self, regs): 178 | return self.device.avr.protocol.regile_write(regs) 179 | 180 | def readProgramCounter(self): 181 | # Returned as a word not a byte 182 | return self.device.avr.protocol.program_counter_read() 183 | 184 | def writeProgramCounter(self, programCounter): 185 | self.device.avr.protocol.program_counter_write(programCounter) 186 | 187 | # SoftwareBreakpoints EDBG expects these addresses in bytes 188 | # Multiple SW breakpoints can be defined by shifting 4 bytes to the left 189 | def breakpointSWSet(self, address): 190 | self.device.avr.protocol.software_breakpoint_set(address) 191 | 192 | def breakpointSWClear(self, address): 193 | self.device.avr.protocol.software_breakpoint_clear(address) 194 | 195 | def breakpointSWClearAll(self): 196 | self.device.avr.protocol.software_breakpoint_clear_all() 197 | 198 | # HardwareBreakpoints EDBG expects these addresses in words 199 | def breakpointHWSet(self, address): 200 | wordAddress = int(address/2) 201 | self.device.avr.breakpoint_set(wordAddress) 202 | 203 | def breakpointHWClear(self): 204 | self.device.avr.breakpoint_clear() 205 | 206 | # Cleanup code for detatching target 207 | def cleanup(self): 208 | # and end debug 209 | self.device.avr.protocol.stop() 210 | self.device.avr.protocol.software_breakpoint_clear_all() 211 | self.device.avr.breakpoint_clear() 212 | self.device.avr.protocol.detach() 213 | # Stop session 214 | #avr.stop() 215 | self.device.avr.deactivate_physical() 216 | # Unwind the stack 217 | self.housekeeper.end_session() 218 | self.transport.disconnect() 219 | 220 | def __exit__(self, exc_type, exc_value, traceback): 221 | self.cleanup() 222 | 223 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | 2 | import socket 3 | import debugger 4 | from pyedbglib.protocols import avr8protocol 5 | import signal 6 | import sys 7 | import time 8 | import select 9 | 10 | HOST = '127.0.0.1' # Standard loopback interface address (localhost) 11 | PORT = 12555 # Port to listen on (non-privileged ports are > 1023) 12 | 13 | lastPacket = "" 14 | 15 | dbg = debugger.Debugger("atmega4809") 16 | dbg.stop() 17 | dbg.breakpointSWClearAll() 18 | dbg.breakpointHWClear() 19 | pollet_event = dbg.pollEvent() 20 | while pollet_event != None: 21 | pollet_event = dbg.pollEvent() 22 | # dbg.run() 23 | 24 | SIGTRAP = "S05" 25 | last_SIGVAL = "S00" 26 | 27 | def signal_handler(sig, frame): 28 | print('You pressed Ctrl+C!') 29 | dbg.cleanup() 30 | sys.exit(0) 31 | signal.signal(signal.SIGINT, signal_handler) 32 | 33 | def sendPacket(socket, packetData): 34 | lastPacket = packetData 35 | checksum = sum(packetData.encode("ascii")) % 256 36 | message = "$" + packetData + "#" + format(checksum, '02x') 37 | if packetData == "": 38 | message = "$#00" 39 | print("<- " + message) 40 | socket.sendall(message.encode("ascii")) 41 | 42 | def handleCommand(socket, command): 43 | dbg.readRunningState() 44 | # Required support g, G, m, M, c and s 45 | if "?" == command[0]: 46 | global last_SIGVAL 47 | sendPacket(socket, last_SIGVAL) 48 | #elif "Hc-1" in command: 49 | #sendPacket(socket, "OK") 50 | #elif "Hg-1" in command: 51 | #sendPacket(socket, "OK") 52 | #elif "qSymbol" in command: 53 | #sendPacket(socket, "OK") 54 | #elif "qAttached" in command: 55 | #sendPacket(socket, "0") 56 | #elif "qC" in command: 57 | #sendPacket(socket, "") 58 | elif "q" == command[0]: 59 | # Genral query 60 | if len(command) > 1: 61 | query = command[1:] 62 | print(query) 63 | if query == "Attached": 64 | sendPacket(socket, "0") 65 | return 66 | elif "Supported" in query: 67 | # Since we are using a tcp connection we do not want to split up messages into different packets, so packetsize is set absurdly large 68 | sendPacket(socket, "PacketSize=10000000000") 69 | return 70 | elif "Symbol::" in query: 71 | sendPacket(socket, "OK") 72 | return 73 | elif "C" == query[0]: 74 | sendPacket(socket, "") 75 | return 76 | elif "Offsets" in query: 77 | sendPacket(socket, "Text=000;Data=000;Bss=000") 78 | return 79 | sendPacket(socket, "") 80 | elif "s" == command[0]: 81 | # TODO: Make s behavior more in line with GDB docs 82 | # "addr is address to resume. If addr is omitted, resume at same address." 83 | if len(command) > 1: 84 | addr = command[1:] 85 | print(addr) 86 | dbg.step() 87 | sendPacket(socket, SIGTRAP) 88 | last_SIGVAL = SIGTRAP 89 | elif "c" == command[0]: 90 | if len(command) > 1: 91 | addr = command[1:] 92 | print(addr) 93 | 94 | dbg.run() 95 | #polledEvent = dbg.pollEvent() 96 | # Check if its still running, report back SIGTRAP when break. 97 | #while polledEvent == None: 98 | # polledEvent = dbg.pollEvent() 99 | #debug_check_running = dbg.readRunningState() 100 | #while debug_check_running: 101 | # debug_check_running = dbg.readRunningState() 102 | #sendPacket(socket, SIGTRAP) 103 | elif "z" == command[0]: 104 | breakpointType = command[1] 105 | addr = command.split(",")[1] 106 | length = command.split(",")[2] 107 | if breakpointType == "0": 108 | #SW breakpoint 109 | dbg.breakpointSWClear(int(addr, 16)) 110 | sendPacket(socket, "OK") 111 | elif breakpointType == "1": 112 | #HW breakpoint 113 | dbg.breakpointHWClear() 114 | sendPacket(socket, "OK") 115 | else: 116 | #Not Supported 117 | sendPacket(socket, "") 118 | elif "Z" == command[0]: 119 | breakpointType = command[1] 120 | addr = command.split(",")[1] 121 | length = command.split(",")[2] 122 | print(breakpointType) 123 | print(addr) 124 | print(int(addr, 16)) 125 | if breakpointType == "0": 126 | #SW breakpoint 127 | dbg.breakpointSWSet(int(addr, 16)) 128 | sendPacket(socket, "OK") 129 | elif breakpointType == "1": 130 | #HW breakpoint 131 | dbg.breakpointHWSet(int(addr, 16)) 132 | sendPacket(socket, "OK") 133 | else: 134 | #Not Supported 135 | sendPacket(socket, "") 136 | elif "m" == command[0]: 137 | # Assuming read from flash 138 | # ref https://www.nongnu.org/avr-libc/user-manual/mem_sections.html#harvard_arch 139 | # Memory Configuration 140 | # Name Origin Length Attributes 141 | # text 0x00000000 0x0000c000 xr 142 | # data 0x00802800 0x00001800 rw !x 143 | # eeprom 0x00810000 0x00000100 rw !x 144 | # fuse 0x00820000 0x0000000a rw !x 145 | # lock 0x00830000 0x00000400 rw !x 146 | # signature 0x00840000 0x00000400 rw !x 147 | # user_signatures 0x00850000 0x00000400 rw !x 148 | # *default* 0x00000000 0xffffffff 149 | addrSize = command[1:] 150 | addr = addrSize.split(",")[0] 151 | size = addrSize.split(",")[1] 152 | print(addr) 153 | print(size) 154 | addrSection = 00 155 | if len(addr) > 4: 156 | if len(addr) == 6: 157 | addrSection = addr[:2] 158 | addr = addr[2:] 159 | else: 160 | addrSection = "0" + addr[0] 161 | addr = addr[1:] 162 | 163 | data = bytearray() 164 | print(addrSection) 165 | if addrSection == "80": 166 | data = dbg.readSRAM(int(addr, 16), int(size, 16)) 167 | elif addrSection == "81": 168 | data = dbg.readEEPROM(int(addr, 16), int(size, 16)) 169 | elif addrSection == "82": 170 | data = dbg.readFuse(int(addr, 16), int(size, 16)) 171 | elif addrSection == "83": 172 | data = dbg.readLock(int(addr, 16), int(size, 16)) 173 | elif addrSection == "84": 174 | data = dbg.readSignature(int(addr, 16), int(size, 16)) 175 | elif addrSection == "85": 176 | data = dbg.readUserSignature(int(addr, 16), int(size, 16)) 177 | else: 178 | data = dbg.readFlash(int(addr, 16), int(size, 16)) 179 | print(data) 180 | dataString = "" 181 | for byte in data: 182 | dataString = dataString + format(byte, '02x') 183 | print(dataString) 184 | sendPacket(socket, dataString) 185 | elif "M" == command[0]: 186 | # Do mem writing 187 | addrSizeData = command[1:] 188 | addr = addrSizeData.split(",")[0] 189 | size = (addrSizeData.split(",")[1]).split(":")[0] 190 | data = (addrSizeData.split(",")[1]).split(":")[1] 191 | print(addr) 192 | print(size) 193 | print(data) 194 | addrSection = 00 195 | if len(addr) > 4: 196 | if len(addr) == 6: 197 | addrSection = addr[:2] 198 | addr = addr[2:] 199 | else: 200 | addrSection = "0" + addr[0] 201 | addr = addr[1:] 202 | data = int(data, 16) 203 | print(data) 204 | data = data.to_bytes(int(size, 16), byteorder='big') 205 | print(data) 206 | print(addrSection) 207 | if addrSection == "80": 208 | data = dbg.writeSRAM(int(addr, 16), data) 209 | elif addrSection == "81": 210 | data = dbg.writeEEPROM(int(addr, 16), data) 211 | elif addrSection == "82": 212 | data = dbg.writeFuse(int(addr, 16), data) 213 | elif addrSection == "83": 214 | data = dbg.writeLock(int(addr, 16), data) 215 | elif addrSection == "84": 216 | data = dbg.writeSignature(int(addr, 16), data) 217 | elif addrSection == "85": 218 | data = dbg.writeUserSignature(int(addr, 16), data) 219 | else: 220 | # Flash write not supported here 221 | # EACCES 222 | sendPacket(socket, "E13") 223 | sendPacket(socket, "OK") 224 | elif "g" == command: 225 | regs = dbg.readRegs() 226 | sreg = dbg.readSREG() 227 | sp = dbg.readStackPointer() 228 | print([hex(no) for no in regs]) 229 | print([hex(no) for no in sreg]) 230 | print([hex(no) for no in sp]) 231 | regString = "" 232 | for reg in regs: 233 | regString = regString + format(reg, '02x') 234 | sregString = "" 235 | for reg in sreg: 236 | sregString = sregString + format(reg, '02x') 237 | spString = "" 238 | for reg in sp: 239 | spString = spString + format(reg, '02x') 240 | regString = regString + sregString + spString 241 | sendPacket(socket, regString) 242 | elif "G" == command[0]: 243 | newRegData = command[1:] 244 | # Do reg writing 245 | # TODO: Implement 246 | print(newRegData) 247 | sendPacket(socket, "") 248 | elif "k" == command[0]: 249 | dbg.cleanup() 250 | quit() 251 | elif "p" == command[0]: 252 | # Reads register 253 | # TODO: Implement individual register reads 254 | if len(command) > 1: 255 | if command[1:] == "22": 256 | # GDB defines PC register for AVR to be REG34(0x22) 257 | pc = dbg.readProgramCounter() 258 | print(pc) 259 | print(hex(pc)) 260 | pc = pc << 1 261 | print(hex(pc)) 262 | pcString = format(pc, '08x') 263 | print(pcString) 264 | pcByteAr = bytearray.fromhex(pcString.upper()) 265 | pcByteAr.reverse() 266 | pcByteString = ''.join(format(x, '02x') for x in pcByteAr) 267 | #pcString = format(pc, '0<8x') 268 | # $1234abcd#54 => 0xcdab3412 in GDB 269 | # Preforming therefore mirror magic 270 | #pcStringMagicFormat = "" 271 | #for i in range(len(pcString)): 272 | # if i % 2 == 0: 273 | # if i == len(pcString)-1: 274 | # pcStringMagicFormat = pcStringMagicFormat + "0" + pcString[i] 275 | # else: 276 | # pcStringMagicFormat = pcStringMagicFormat + pcString[i] + pcString[i+1] 277 | 278 | #while len(pcStringMagicFormat) < 8: 279 | # pcStringMagicFormat = pcStringMagicFormat + "0" 280 | print(pcByteString) 281 | sendPacket(socket, pcByteString) 282 | else: 283 | sendPacket(socket, "") 284 | 285 | def readRegs(n): 286 | return "0"*2*n 287 | 288 | def handleData(socket, data): 289 | if data.decode("ascii").count("$") > 0: 290 | for n in range(data.decode("ascii").count("$")): 291 | validData = True 292 | data = data.decode("ascii") 293 | #print(data) 294 | checksum = (data.split("#")[1])[:2] 295 | packet_data = (data.split("$")[1]).split("#")[0] 296 | if int(checksum, 16) != sum(packet_data.encode("ascii")) % 256: 297 | print("Checksum Wrong!") 298 | validData = False 299 | commands = [] 300 | if validData: 301 | socket.sendall(b"+") 302 | print("<- +") 303 | else: 304 | socket.sendall(b"-") 305 | print("<- -") 306 | handleCommand(socket, packet_data) 307 | #for command in packet_data.split(";"): 308 | #handleCommand(socket, command) 309 | #commands.append(command.split("+")[0]) 310 | elif data == b"\x03": 311 | dbg.stop() 312 | socket.sendall(b"+") 313 | print("<- +") 314 | #elif data.decode("ascii").count("-") > 0: 315 | #sendPacket(socket, lastPacket) 316 | 317 | 318 | print("Waiting for GDB session " + str(HOST) + ":" + str(PORT)) 319 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 320 | s.bind((HOST, PORT)) 321 | s.listen() 322 | conn, addr = s.accept() 323 | conn.setblocking(0) 324 | with conn: 325 | print('Connected by', addr) 326 | while True: 327 | # Should iterate through buffer and take out commands/escape characters 328 | ready = select.select([conn], [], [], 0.5) 329 | if ready[0]: 330 | data = conn.recv(1024) 331 | if len(data) > 0: 332 | print("-> " + data.decode('ascii')) 333 | handleData(conn, data) 334 | event = dbg.pollEvent() 335 | if event != None: 336 | print(event) 337 | eventType, pc, break_cause = event 338 | if eventType == avr8protocol.Avr8Protocol.EVT_AVR8_BREAK and break_cause == 1: 339 | sendPacket(conn, SIGTRAP) 340 | last_SIGVAL = SIGTRAP 341 | 342 | --------------------------------------------------------------------------------