| Index: emcore/trunk/tools/emcore.py | 
| — | — | @@ -464,23 +464,23 @@ | 
| 465 | 465 | self.logger.info("Thread dump:\n") | 
| 466 | 466 | for thread in threads: | 
| 467 | 467 | self.logger.info(thread.name+":\n", 2) | 
| 468 |  | -            self.logger.info("Thread id: "      + str(thread.id)+"\n", 4)
 | 
| 469 |  | -            self.logger.info("Thread type: "    + thread.type+"\n", 4)
 | 
| 470 |  | -            self.logger.info("Thread state: "   + thread.state+"\n", 4)
 | 
| 471 |  | -            self.logger.info("Block type: "     + thread.block_type+"\n", 4)
 | 
| 472 |  | -            self.logger.info("Blocked by: "     + self._hex(thread.blocked_by_ptr)+"\n", 4)
 | 
|  | 468 | +            self.logger.info("Threadstruct address: " + self._hex(thread.addr)+"\n", 4) | 
|  | 469 | +            self.logger.info("Thread type: "    + str(thread.thread_type)+"\n", 4) | 
|  | 470 | +            self.logger.info("Thread state: "   + str(thread.state)+"\n", 4) | 
|  | 471 | +            self.logger.info("Block type: "     + str(thread.block_type)+"\n", 4) | 
|  | 472 | +            self.logger.info("Blocked by: "     + self._hex(thread.blocked_by)+"\n", 4) | 
| 473 | 473 | self.logger.info("Priority: "       + str(thread.priority)+"/255\n", 4) | 
| 474 | 474 | self.logger.info("Current CPU load: %.1f%%\n" % ((thread.cpuload * 100) / 255.), 4) | 
| 475 | 475 | self.logger.info("CPU time (total): "+str(datetime.timedelta(microseconds = thread.cputime_total))+"\n", 4) | 
| 476 |  | -            self.logger.info("Stack address: "  + self._hex(thread.stackaddr)+"\n", 4)
 | 
|  | 476 | +            self.logger.info("Stack address: "  + self._hex(thread.stack)+"\n", 4) | 
| 477 | 477 | self.logger.info("Registers:\n", 4) | 
| 478 | 478 | for registerrange in range(4): | 
| 479 | 479 | self.logger.info("      ") | 
| 480 | 480 | for register in range(registerrange, 16, 4): | 
| 481 | 481 | registerrepr = "r"+str(register) | 
| 482 |  | -                    self.logger.info("{0:3s}: 0x{1:08X}   ".format(registerrepr, thread.regs["r"+str(register)]))
 | 
|  | 482 | +                    self.logger.info("{0:3s}: 0x{1:08X}   ".format(registerrepr, thread.regs[register])) | 
| 483 | 483 | self.logger.info("\n") | 
| 484 |  | -            self.logger.info("cpsr: 0x{0:08X}".format(thread.regs.cpsr), 6)
 | 
|  | 484 | +            self.logger.info("cpsr: 0x{0:08X}".format(thread.cpsr), 6) | 
| 485 | 485 | self.logger.info("\n") | 
| 486 | 486 |  | 
| 487 | 487 | @command | 
| Index: emcore/trunk/tools/libemcoredata.py | 
| — | — | @@ -21,39 +21,63 @@ | 
| 22 | 22 | # | 
| 23 | 23 | # | 
| 24 | 24 |  | 
| 25 |  | -thread_state = (
 | 
| 26 |  | -    "THREAD_FREE",
 | 
| 27 |  | -    "THREAD_SUSPENDED",
 | 
| 28 |  | -    "THREAD_READY",
 | 
| 29 |  | -    "THREAD_RUNNING",
 | 
| 30 |  | -    "THREAD_BLOCKED",
 | 
| 31 |  | -    "THREAD_DEFUNCT",
 | 
| 32 |  | -    "THREAD_DEFUNCT_ACK"
 | 
| 33 |  | -)
 | 
|  | 25 | +from ctypes import * | 
|  | 26 | +from misc import ExtendedCStruct, c_enum | 
| 34 | 27 |  | 
| 35 |  | -thread_block = (
 | 
| 36 |  | -    "THREAD_NOT_BLOCKED",
 | 
| 37 |  | -    "THREAD_BLOCK_SLEEP",
 | 
| 38 |  | -    "THREAD_BLOCK_MUTEX",
 | 
| 39 |  | -    "THREAD_BLOCK_WAKEUP",
 | 
| 40 |  | -    "THREAD_DEFUNCT_STKOV",
 | 
| 41 |  | -    "THREAD_DEFUNCT_PANIC"
 | 
| 42 |  | -)
 | 
| 43 | 28 |  | 
| 44 |  | -thread_type = (
 | 
| 45 |  | -    "USER_THREAD",
 | 
| 46 |  | -    "OS_THREAD",
 | 
| 47 |  | -    "CORE_THREAD"
 | 
| 48 |  | -)
 | 
|  | 29 | +class thread_type(c_enum): | 
|  | 30 | +    _fields_ = ["USER_THREAD", | 
|  | 31 | +                "OS_THREAD", | 
|  | 32 | +                "CORE_THREAD", | 
|  | 33 | +               ] | 
| 49 | 34 |  | 
| 50 |  | -hwtypes = {
 | 
| 51 |  | -    0: "invalid",
 | 
| 52 |  | -    0x47324e49: "iPod nano 2g",
 | 
| 53 |  | -    0x47334e49: "iPod nano 3g",
 | 
| 54 |  | -    0x47344e49: "iPod nano 4g",
 | 
| 55 |  | -    0x4c435049: "iPod classic"
 | 
| 56 |  | -}
 | 
|  | 35 | +class thread_state(c_enum): | 
|  | 36 | +    _fields_ = ["THREAD_FREE", | 
|  | 37 | +                "THREAD_SUSPENDED", | 
|  | 38 | +                "THREAD_READY", | 
|  | 39 | +                "THREAD_RUNNING", | 
|  | 40 | +                "THREAD_BLOCKED", | 
|  | 41 | +                "THREAD_DEFUNCT", | 
|  | 42 | +                "THREAD_DEFUNCT_ACK", | 
|  | 43 | +               ] | 
| 57 | 44 |  | 
|  | 45 | +class thread_block(c_enum): | 
|  | 46 | +    _fields_ = ["THREAD_NOT_BLOCKED", | 
|  | 47 | +                "THREAD_BLOCK_SLEEP", | 
|  | 48 | +                "THREAD_BLOCK_MUTEX", | 
|  | 49 | +                "THREAD_BLOCK_WAKEUP", | 
|  | 50 | +                "THREAD_DEFUNCT_STKOV", | 
|  | 51 | +                "THREAD_DEFUNCT_PANIC" | 
|  | 52 | +               ] | 
|  | 53 | + | 
|  | 54 | +class responsecode(c_enum): | 
|  | 55 | +    _fields_ = ["INVALID", | 
|  | 56 | +                "OK", | 
|  | 57 | +                "UNSUPPORTED", | 
|  | 58 | +                "BUSY" | 
|  | 59 | +               ] | 
|  | 60 | + | 
|  | 61 | +class scheduler_thread(ExtendedCStruct): | 
|  | 62 | +    _fields_ = [("regs", c_uint32 * 16), | 
|  | 63 | +                ("cpsr", c_uint32), | 
|  | 64 | +                ("state", c_uint32), | 
|  | 65 | +                ("name", c_uint32), | 
|  | 66 | +                ("cputime_current", c_uint32), | 
|  | 67 | +                ("cputime_total", c_uint64), | 
|  | 68 | +                ("startusec", c_uint32), | 
|  | 69 | +                ("thread_next", c_uint32), | 
|  | 70 | +                ("queue_next", c_uint32), | 
|  | 71 | +                ("timeout", c_uint32), | 
|  | 72 | +                ("blocked_since", c_uint32), | 
|  | 73 | +                ("blocked_by", c_uint32), | 
|  | 74 | +                ("stack", c_uint32), | 
|  | 75 | +                ("err_no", c_int32), | 
|  | 76 | +                ("block_type", thread_block), | 
|  | 77 | +                ("thread_type", thread_type), | 
|  | 78 | +                ("priority", c_uint8), | 
|  | 79 | +                ("cpuload", c_uint8), | 
|  | 80 | +               ] | 
|  | 81 | + | 
| 58 | 82 | swtypes = { | 
| 59 | 83 | 0: "invalid", | 
| 60 | 84 | 1: "emBIOS Debugger", | 
| — | — | @@ -60,9 +84,10 @@ | 
| 61 | 85 | 2: "emCORE Debugger" | 
| 62 | 86 | } | 
| 63 | 87 |  | 
| 64 |  | -responsecodes = {
 | 
|  | 88 | +hwtypes = { | 
| 65 | 89 | 0: "invalid", | 
| 66 |  | -    1: "ok",
 | 
| 67 |  | -    2: "unsupported",
 | 
| 68 |  | -    3: "busy"
 | 
|  | 90 | +    0x47324e49: "iPod nano 2g", | 
|  | 91 | +    0x47334e49: "iPod nano 3g", | 
|  | 92 | +    0x47344e49: "iPod nano 4g", | 
|  | 93 | +    0x4c435049: "iPod classic" | 
| 69 | 94 | } | 
| Index: emcore/trunk/tools/libemcore.py | 
| — | — | @@ -28,9 +28,10 @@ | 
| 29 | 29 |  | 
| 30 | 30 | import sys | 
| 31 | 31 | import struct | 
|  | 32 | +import ctypes | 
| 32 | 33 | import usb.core | 
| 33 |  | -import libemcoredata
 | 
| 34 | 34 |  | 
|  | 35 | +from libemcoredata import * | 
| 35 | 36 | from misc import Logger, Bunch, Error, gethwname | 
| 36 | 37 | from functools import wraps | 
| 37 | 38 |  | 
| — | — | @@ -369,66 +370,27 @@ | 
| 370 | 371 | @command() | 
| 371 | 372 | def getprocinfo(self): | 
| 372 | 373 | """ Gets current state of the scheduler """ | 
| 373 |  | -        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
 | 
| 374 |  | -        # Get the size
 | 
| 375 | 374 | schedulerstate = self.lockscheduler() | 
| 376 |  | -        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
 | 
| 377 |  | -        tablesize = resp.tablesize
 | 
| 378 |  | -        size = tablesize
 | 
| 379 |  | -        structver = resp.structver
 | 
| 380 |  | -        offset = 0
 | 
| 381 |  | -        data = ""
 | 
| 382 |  | -        while size > 0:
 | 
| 383 |  | -            if size > cin_maxsize:
 | 
| 384 |  | -                readsize = cin_maxsize
 | 
| 385 |  | -            else:
 | 
| 386 |  | -                readsize = size
 | 
| 387 |  | -            resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
 | 
| 388 |  | -            data += resp.data
 | 
| 389 |  | -            offset += readsize
 | 
| 390 |  | -            size -= readsize
 | 
| 391 |  | -        self.lockscheduler(schedulerstate)
 | 
| 392 |  | -        threadstructsize = 120
 | 
| 393 |  | -        registersize = 32
 | 
| 394 |  | -        if len(data) % threadstructsize != 0:
 | 
| 395 |  | -            raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
 | 
| 396 |  | -        threadcount = len(data) / threadstructsize
 | 
|  | 375 | +        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "structptr", None)) | 
|  | 376 | +        if resp.structver != 2: | 
|  | 377 | +            raise DeviceError("Unsupported thread struct version!") | 
|  | 378 | + | 
| 397 | 379 | threads = [] | 
|  | 380 | +        structptr = resp.structptr | 
| 398 | 381 | id = 0 | 
| 399 |  | -        for thread in range(threadcount):
 | 
| 400 |  | -            offset = threadstructsize * thread
 | 
| 401 |  | -            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
 | 
| 402 |  | -            info = Bunch()
 | 
| 403 |  | -            info.id = id
 | 
| 404 |  | -            state = threaddata[17]
 | 
| 405 |  | -            info.state = libemcoredata.thread_state[state]
 | 
| 406 |  | -            if info.state == "THREAD_FREE":
 | 
| 407 |  | -                id += 1
 | 
| 408 |  | -                continue
 | 
| 409 |  | -            info.regs = Bunch()
 | 
| 410 |  | -            for register in range(16):
 | 
| 411 |  | -                info.regs["r"+str(register)] = threaddata[register]
 | 
| 412 |  | -            info.regs.cpsr = threaddata[16]
 | 
| 413 |  | -            info.nameptr = threaddata[18]
 | 
| 414 |  | -            if info.nameptr == 0:
 | 
| 415 |  | -                info.name = "Thread %d" % info.id
 | 
| 416 |  | -            else:
 | 
| 417 |  | -                info.name = self.readstring(info.nameptr)
 | 
| 418 |  | -            info.cputime_current = threaddata[19]
 | 
| 419 |  | -            info.cputime_total = threaddata[20]
 | 
| 420 |  | -            info.startusec = threaddata[21]
 | 
| 421 |  | -            info.queue_next_ptr = threaddata[22]
 | 
| 422 |  | -            info.timeout = threaddata[23]
 | 
| 423 |  | -            info.blocked_since = threaddata[24]
 | 
| 424 |  | -            info.blocked_by_ptr = threaddata[25]
 | 
| 425 |  | -            info.stackaddr = threaddata[26]
 | 
| 426 |  | -            info.err_no = threaddata[27]
 | 
| 427 |  | -            info.block_type = libemcoredata.thread_block[threaddata[28]]
 | 
| 428 |  | -            info.type = libemcoredata.thread_type[threaddata[29]]
 | 
| 429 |  | -            info.priority = threaddata[30]
 | 
| 430 |  | -            info.cpuload = threaddata[31]
 | 
| 431 |  | -            threads.append(info)
 | 
|  | 382 | +        while structptr != 0: | 
|  | 383 | +            threadstruct = scheduler_thread() | 
|  | 384 | +            self.logger.debug("Reading thread struct of thread at 0x%x\n" % structptr) | 
|  | 385 | +            threaddata = self.read(structptr, ctypes.sizeof(scheduler_thread)) | 
|  | 386 | +            threadstruct._from_string(threaddata) | 
|  | 387 | +            threadstruct = threadstruct._to_bunch() | 
|  | 388 | +            threadstruct.id = id # only for the purpose of detecting the idle thread as it is always the first one | 
|  | 389 | +            threadstruct.addr = structptr | 
|  | 390 | +            threadstruct.name = self.readstring(threadstruct.name) | 
|  | 391 | +            threadstruct.state = thread_state(threadstruct.state) | 
|  | 392 | +            threads.append(threadstruct) | 
| 432 | 393 | id += 1 | 
|  | 394 | +            structptr = threadstruct.thread_next | 
| 433 | 395 | return threads | 
| 434 | 396 |  | 
| 435 | 397 | @command() | 
| — | — | @@ -963,8 +925,12 @@ | 
| 964 | 926 | rcvdatatypes = "I" + rcvdatatypes # add the response | 
| 965 | 927 | data = self.dev.cin(struct.calcsize(rcvdatatypes)) | 
| 966 | 928 | data = struct.unpack(rcvdatatypes, data) | 
| 967 |  | -            response = data[0]
 | 
| 968 |  | -            if libemcoredata.responsecodes[response] == "ok":
 | 
|  | 929 | +            try: | 
|  | 930 | +                response = responsecode(data[0]) | 
|  | 931 | +            except IndexError: | 
|  | 932 | +                self.logger.debug("Response: UNKOWN\n") | 
|  | 933 | +                raise DeviceError("Invalid response! This should NOT happen!") | 
|  | 934 | +            if response == "OK": | 
| 969 | 935 | self.logger.debug("Response: OK\n") | 
| 970 | 936 | if rcvstruct: | 
| 971 | 937 | datadict = Bunch() | 
| — | — | @@ -976,18 +942,15 @@ | 
| 977 | 943 | return datadict | 
| 978 | 944 | else: | 
| 979 | 945 | return data | 
| 980 |  | -            elif libemcoredata.responsecodes[response] == "unsupported":
 | 
|  | 946 | +            elif response == "UNSUPPORTED": | 
| 981 | 947 | self.logger.debug("Response: UNSUPPORTED\n") | 
| 982 | 948 | raise DeviceError("The device does not support this command.") | 
| 983 |  | -            elif libemcoredata.responsecodes[response] == "invalid":
 | 
|  | 949 | +            elif response == "INVALID": | 
| 984 | 950 | self.logger.debug("Response: INVALID\n") | 
| 985 | 951 | raise DeviceError("Invalid command! This should NOT happen!") | 
| 986 |  | -            elif libemcoredata.responsecodes[response] == "busy":
 | 
|  | 952 | +            elif response == "BUSY": | 
| 987 | 953 | self.logger.debug("Response: BUSY\n") | 
| 988 | 954 | raise DeviceError("Device busy") | 
| 989 |  | -            else:
 | 
| 990 |  | -                self.logger.debug("Response: UNKOWN\n")
 | 
| 991 |  | -                raise DeviceError("Invalid response! This should NOT happen!")
 | 
| 992 | 955 | else: | 
| 993 | 956 | return writelen | 
| 994 | 957 |  |