Example #1
0
def run_tests(elf, comment):
    mark = 0
    comment("Starting to run prac 3 tests")
    ii = InterrogatorInterface()
    comment(ii.comms_test())
    ii.reset(0) # pull line low. This does a reset
    with OpenOCD(comment) as openocd:
        time.sleep(0.2)
        ii.reset(1) # release line. Allows code to run.
        with GDBInterface(elf, comment) as gdb:
            gdb.open_file()
            gdb.connect()
            gdb.erase()
            gdb.load()
            gdb.send_continue()
            # assert no button, ensure that AA->55->AA timing is 0.47-0.53 2/2
            comment("=== Part 1 ===")
            mark += part1_tests(ii, comment)

            comment("===Part 2 ===")
            mark += part2_tests(ii, comment)
            
            comment("=== Part 3 ===")
            mark += part3_tests(ii, comment)

            ii.highz_pin(0)
            ii.highz_pin(1)
    
    comment("All tests complete. Mark: {m}".format(m=mark))
    return mark
Example #2
0
    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 5 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                for test in [self.part1_tests, self.part2_tests, self.part3_tests, self.part4_tests]:
                    mark += test()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)

                size_of_text = elf_parser.get_text_size(self.full_path_to_elf)
                if size_of_text > 272:
                    print("======Size of TEXT suspiciously large==========")

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark
Example #3
0
    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 6 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.gdb.send_continue()
                time.sleep(3)

                for test in [self.part1_tests, self.part2_tests, self.part3_tests]:
                    mark += test()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark
Example #4
0
    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 7 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()

                for test in [self.part1_tests]:
                    try:
                        mark += test()
                    except Exception as e:
                        self.comment("Unrecoverable exception while running test. Aborting")
                        self.comment(str(e))
                        break

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark
Example #5
0
def run_tests(elf, comment):
    mark = 0
    comment("Starting to run prac 1 tests")
    ii = InterrogatorInterface()
    comment(ii.comms_test())
    ii.reset(0) # pull line low. This does a reset
    with OpenOCD(comment) as openocd:
        time.sleep(0.2)
        ii.reset(1) # release line. Allows code to run.
        with GDBInterface(elf, comment) as gdb:
            gdb.open_file()
            gdb.connect()
            gdb.erase()
            gdb.load()
            # run to copy_to_RAM_complete
            if gdb.run_to_label("copy_to_RAM_complete") == False: # could not find label
                comment("Mark = 0")
                return mark
            comment("Now verifying the first four words in RAM")
            # verify the 4 words, awarding a mark for each
            mark += verify_word(gdb, comment, 0x20000000, 0xAABBCCDD)
            mark += verify_word(gdb, comment, 0x20000004, 0x00001122)
            mark += verify_word(gdb, comment, 0x20000008, 0x00002233)
            mark += verify_word(gdb, comment, 0x2000000c, 0x55555555)
            # modify the 4 words
            comment("Modifying 0x20000000 to be 0xCC0000BB")
            gdb.write_word(0x20000000, 0xCC0000BB)
            comment("Modifying 0x20000004 to be 0xAA")
            gdb.write_word(0x20000004, 0xAA)
            comment("Modifying 0x20000008 to be 0x42")
            gdb.write_word(0x20000008, 0x42)
            comment("Modifying 0x2000000c to be 0x69")
            gdb.write_word(0x2000000c, 0x69)
            # move data into 0x20000020, same data as 0x20000010
            gdb.write_word(0x20000020, 0xCC000011)
            # run to infinite_loop
            if gdb.run_to_label("infinite_loop") == False:
                comment("Aborting.")
                return mark
            # verify the 4 words
            mark += verify_word(gdb, comment, 0x20000010, 0xCC000011)
            mark += verify_word(gdb, comment, 0x20000014, 0xCC0001A7)
            mark += verify_word(gdb, comment, 0x20000018, 0xE8)
            mark += verify_word(gdb, comment, 0x2000001c, 0x2bd4)
            # query pattern on LEDs
            led_data = ii.read_port(0)
            comment("Bonus: data read from LEDs as: {a:#x}, and should be 0x11".format(a = led_data))
            if led_data == 0x11:
                comment("Bonus correct! :-). 2/0")
                mark += 2
            else:
                comment("Bonus not done. 0/0")

    comment("All tests complete. Mark: {m}".format(m=mark))
    return mark
Example #6
0
    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 4 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.comment("=== Part 1 ===")
                mark += self.part1_tests()

                self.comment("===Part 2 ===")
                mark += self.part2_tests()

                self.comment("Sending 'continue' to allow code to free-run")
                self.gdb.send_continue()
                
                self.comment("=== Part 3 ===")
                mark += self.part3_tests()

                self.comment("=== Part 4 ===")
                mark += self.part4_tests()

                self.comment("=== Part 5 ===")
                mark += self.part5_tests()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark
Example #7
0
def run_tests(elf, comment):
    mark = 0
    comment("Starting to run prac 2 tests")
    ii = InterrogatorInterface()
    comment(ii.comms_test())
    ii.reset(0) # pull line low. This does a reset
    with OpenOCD(comment) as openocd:
        time.sleep(0.2)
        ii.reset(1) # release line. Allows code to run.
        with GDBInterface(elf, comment) as gdb:
            gdb.open_file()
            gdb.connect()
            gdb.erase()
            gdb.load()

            if gdb.run_to_label("all_off") == False:
                comment("Could not hit label 'all off'. Aborting")
                return mark
            # ensure that only the correct pins are set as outputs:
            if gdb.read_word(0x48000400) <= 0x5555:
                comment("Only the lower byte of port B set to outputs. 1/1")
                mark += 1
            else:
                comment("More than the lower byte of port B set to outputs. 0/1") 

            for label, expected in [["display_AA", 0x00], ["all_on", 0xAA], ["bonus", 0xFF]]:
                if gdb.run_to_label(label) == False:
                    comment("Could not hit label '{l}'. Aborting".format(l=label))
                    return mark
                led_data = ii.read_port(0)
                if led_data == expected:
                    mark_to_add = 2
                else:
                    mark_to_add = 0
                comment("LED data should be {exp:#X} and is {led:#X}: {toadd}/2".format(exp = expected, led=led_data, toadd=mark_to_add))
                mark += mark_to_add

            comment("Attempting bonus")    
            gdb.delete_all_breakpoints()
            bonus_correct = True
            for i in range(0, 7): # checking the bonus 7 times.
                if [0, 1, 1, 1, 0, 0, 1][i] == 1: # sequence of button pushes and not pushes
                    ii.highz_pin(0) # simulate a button release
                    comment("Simulating not pushing SW0")
                    if gdb.run_to_label("all_off") == False:
                        comment("Could not hit label 'all_off' implying that you don't have a loop. Aborting")
                        return mark
                    if ii.read_port(0) != 0xFF: # should be all on when not pushing button
                        comment("Excpected 0xFF on the LEDs but got {led:#X}".format(led = ii.read_port(0)))
                        bonus_correct = False
                        break
                    comment("Expected 0xFF on LEDs and got it")
                else:
                    ii.clear_pin(0) # simulate a button push
                    comment("Simulating pushing SW0")
                    if gdb.run_to_label("all_off") == False:
                        comment("Could not hit label 'all_off' implying that you don't have a loop. Aborting")
                        return mark
                    if ii.read_port(0) != 0x55:
                        comment("Excpected 0x55 on the LEDs but got {led:#X}".format(led = ii.read_port(0)))
                        bonus_correct = False
                        break
                    comment("Expected 0x55 on LEDs and got it")


            if bonus_correct == True:
                comment("Bonus correct! :-). 2/0")
                mark += 2
            else:
                comment("Bonus not done. 0/0")

    comment("All tests complete. Mark: {m}".format(m=mark))
    return mark
Example #8
0
class Prac5Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        as_proc = subprocess.Popen(["arm-none-eabi-as", \
                "-mcpu=cortex-m0", "-mthumb", "-g", \
                "-o", self.submission_dir + "/main.o", \
                self.submission_dir + "/" + self.src_name], \
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if (as_proc.wait() != 0):
            error_message = as_proc.communicate()
            self.comment("Compile failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Compile succeeded. Attempting to link.")
        ld_proc = subprocess.Popen(["arm-none-eabi-ld", \
                "-Ttext=0x08000000", \
                "-o", self.submission_dir + "/main.elf", \
                self.submission_dir + "/main.o"], \
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if (ld_proc.wait() != 0):
            error_message = ld_proc.communicate()
            self.comment("Link failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.full_path_to_elf = self.submission_dir + "/main.elf"
        self.comment("Link succeeded")
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 5 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                for test in [self.part1_tests, self.part2_tests, self.part3_tests, self.part4_tests]:
                    mark += test()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)

                size_of_text = elf_parser.get_text_size(self.full_path_to_elf)
                if size_of_text > 272:
                    print("======Size of TEXT suspiciously large==========")

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def scale_mark(self):
        self.comment("Scaling PRAC5 mark by factor dependant on submission time")
        self.comment("No scale factor implemented for this prac.")
        return mark

    def part1_tests(self):
        self.comment("=== Part 1 ===")
        # run to initialisations_complete 
        if self.gdb.run_to_label("initialisations_complete") == False:
            return 0
        # set start of ram to some sensible value
        self.comment("Setting 0x20000000 to {sa:#x}".format(sa = SPECIAL_ADDRESS))
        self.gdb.write_word(0x20000000, SPECIAL_ADDRESS)
        # run to fib_calc_complete and verify fibs
        if self.gdb.run_to_label("fib_calc_complete") == False:
            self.comment("Could not hit label 'fib_calc_complete'. Aborting")
            return 0
        self.comment("Verifying array of fib numbers")
        for idx, val in enumerate(FIB_NUMBERS):
            address = 0x20002000 - 0x4 - (4 * idx)
            if self.gdb.read_word(address) != val:
                self.comment("Words at address {addr:#x} should be {exp} but is {act}".format(\
                        addr = address, exp = val, act = self.gdb.read_word(address)))
                self.comment("Aborting")
                return 0
        self.comment("Verification completed successfully. 2/2")
        return 2

    def part2_tests(self):
        self.comment("=== Part 2 ===")
        # run to cycle_patterns
        if self.gdb.run_to_label("cycle_patterns") == False:
            return 0
        # validate sensible values
        data_at_special_address = self.gdb.read_word(SPECIAL_ADDRESS)
        self.comment("Data at {sa:#x} should be {max_fib:#x}. Found to be {found:#x}".format( \
                    sa = SPECIAL_ADDRESS, max_fib = FIB_NUMBERS[-1], found = data_at_special_address))
        if  data_at_special_address != FIB_NUMBERS[-1]:
            self.comment("Incorrect. 0/2")
            return 0
        else:
            self.comment("Correct. 2/2")
            return 2

    def part3_tests(self):
        self.comment("=== Part 3 ===")
        self.gdb.soft_reset()
        # run to initialisations_complete
        if self.gdb.run_to_label("initialisations_complete") == False:
            return 0
        # set illegal value in start of RAM
        self.comment("Setting 0x20000000 to {sa:#x}".format(sa = ILLEGAL_ADDRESS))
        self.gdb.write_word(0x20000000, ILLEGAL_ADDRESS)
        # continue and verify that pattern is 0xAA
        if self.gdb.run_to_label("HardFault_Handler") == False:
            return 0
        self.gdb.send_continue()
        time.sleep(0.5)
        pattern_on_leds =  self.ii.read_port(0) 
        if pattern_on_leds != 0xAA:
            self.comment("HardFault handler expected to produce pattern 0xAA but instead got {p:#x}".format(\
                        p = pattern_on_leds))
            return 0
        self.comment("HardFault handler hit on illegal value and displaying 0xAA. 1/1")
        return 1
        
    def part4_tests(self):
        self.comment("=== Part 4 ===")
        # reset
        self.gdb.send_control_c()
        self.gdb.soft_reset()
        if self.gdb.run_to_label("initialisations_complete") == False:
            return 0
        # run to initialisations_complete 
        # set start of ram to some sensible value
        self.comment("Setting 0x20000000 to {sa:#x}".format(sa = SPECIAL_ADDRESS))
        self.gdb.write_word(0x20000000, SPECIAL_ADDRESS)
        # set breakpoint on  delay_routine
        # run to breakpoint in a loop until pattern 0x81 is found.
        #self.comment("Running to 'delay_routine' in a loop until pattern 0x81 found")
        #pattern_found = False
        #for i in range(0, 10):
        #    self.gdb.run_to_label("delay_routine")
        #    if self.ii.read_port(0) == 0x81:
        #        pattern_found = True
        #        break
        #if pattern_found == False:
        #    self.comment("Could not find 0x81 on LEDs after 10 loop itterations. Aborting")
        #    return 0
        #self.comment("Found 0x81. Now checking the rest of the patterns by running to 'delay_routine'.")
        # run to delay_routine again. Verify that next pattern until all patterns
        pattern_array = [0xC3, 0xE7, 0xFF, 0x7E, 0x3C, 0x18]
        #for idx, val in enumerate(pattern_array):
        #    self.gdb.run_to_label("delay_routine")
        #    pattern_on_leds = self.ii.read_port(0)
        #    if pattern_on_leds != pattern_array[idx]:
        #        self.comment("On loop iteration number {lp} the pattern {found:#x} was found but should be {exp:#x}".format(
        #                    lp = idx, found = pattern_on_leds, exp = val))
        #    return 0
        # continue
        #self.comment("All patterns found to use 'delay_routine'")
        self.comment("Testing time between patterns")
        self.gdb.send_continue()
        # verify all patterns with 0.5 delay between.
        for i in range(0, len(pattern_array) - 1):
            delay = self.ii.transition_timing(pattern_array[i], pattern_array[i+1])
            self.comment("Delay between {p1:#x} and {p2:#x} found to be {d}".format(
                        p1 = pattern_array[i], p2 = pattern_array[i+1], d = round(delay,2)))
            if delay > 0.53 or delay < 0.47:
                self.comment("Incorrect. 0/2")
                return 0

        self.comment("Delays found to be correct. 2/2")
        return 2
Example #9
0
class Prac6Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        self.comment("Changing dir to submission dir")
        os.chdir(self.submission_dir)
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 0:
            self.comment("Elf files exist before make run: {e}".format(e = all_files))
            self.comment("Aborting")
            return False
        self.comment("Running 'make'")
        make_proc = subprocess.Popen(["make"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            return_code = make_proc.wait(timeout = 5)
        except subprocess.TimeoutExpired:
            make_proc.kill()
            self.comment("Make did not complete after 5 seconds. Aborting")
            return False
        if (return_code != 0):
            error_message = make_proc.communicate()
            self.comment("Make failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Make succeeded. Attempting to link.")
        self.comment("Searching submission directory for .elf files")
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 1:
            self.comment("Too many elf files out of {e}".format(e = all_files))
            return False
        if len(elf_files) == 0:
            self.comment("No elf files out of: {e}".format(e = all_files))
            return False
        self.comment("One elf file produced: {e}".format(e = elf_files[0]))
        self.full_path_to_elf = self.submission_dir + "/" + elf_files[0]
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 6 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.gdb.send_continue()
                time.sleep(3)

                for test in [self.part1_tests, self.part2_tests, self.part3_tests]:
                    mark += test()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def part1_tests(self):
        self.comment("=== Part 1 ===")
        self.comment("Releasing both SW2 and SW3")
        self.ii.highz_pin(2)
        self.ii.highz_pin(3)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern + 3, current_pattern + 4)
        self.comment("Timing between an increment expected to be 0.5 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.47 or timing > 0.53:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Correct. 4/4")
        return 4

    def part2_tests(self):
        self.comment("=== Part 2 ===")
        self.comment("Releasing SW2 and pressing SW3")
        self.ii.highz_pin(2)
        self.ii.clear_pin(3)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern - 3, current_pattern - 4)
        self.comment("Timing between a decrement expected to be 0.5 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.47 or timing > 0.53:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Correct. 1/1")
        self.ii.highz_pin(2)
        self.ii.highz_pin(3)
        return 1

    def part3_tests(self):
        self.comment("=== Part 3 ===")
        self.comment("Pressing SW2 and releasing SW3")
        self.ii.clear_pin(2)
        self.ii.highz_pin(3)
        self.comment("Asserting 0.54 V on port A5. Period should become 0.17 seconds.")
        self.ii.write_dac(42)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern + 4, current_pattern + 5)
        self.comment("Timing between an increment expected to be 0.17 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.14 or timing > 0.20:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Pressing SW2 and pressing SW3")
        self.ii.clear_pin(2)
        self.ii.clear_pin(3)
        self.comment("Asserting 2.59 V on port A5. Period should become 0.41 seconds.")
        self.ii.write_dac(200)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern - 3, current_pattern - 4)
        self.comment("Timing between an increment expected to be 0.41 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.37 or timing > 0.45:
            self.comment("Timing out. Awarding 0")
            return 0
        return 3
Example #10
0
class Prac7Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        self.comment("Changing dir to submission dir")
        os.chdir(self.submission_dir)
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 0:
            self.comment("Elf files exist before make run: {e}".format(e = all_files))
            self.comment("Aborting")
            return False
        self.comment("Running 'make'")
        make_proc = subprocess.Popen(["make"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            return_code = make_proc.wait(timeout = 5)
        except subprocess.TimeoutExpired:
            make_proc.kill()
            self.comment("Make did not complete after 5 seconds. Aborting")
            return False
        if (return_code != 0):
            error_message = make_proc.communicate()
            self.comment("Make failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Searching submission directory for .elf files")
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 1:
            self.comment("Too many elf files out of {e}".format(e = all_files))
            return False
        if len(elf_files) == 0:
            self.comment("No elf files out of: {e}".format(e = all_files))
            return False
        self.comment("One elf file produced: {e}".format(e = elf_files[0]))
        self.full_path_to_elf = self.submission_dir + "/" + elf_files[0]
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 7 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()

                for test in [self.part1_tests]:
                    try:
                        mark += test()
                    except Exception as e:
                        self.comment("Unrecoverable exception while running test. Aborting")
                        self.comment(str(e))
                        break

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def part1_tests(self):
        self.comment("=== Part 1 ===")
        self.comment("Running to main")
        self.gdb.run_to_function("main")
        self.comment("Allowing code to free run")
        self.gdb.send_continue()
        self.comment("Reading value displayed on LED")
        time.sleep(1)
        leds = self.ii.read_port(0)
        self.comment("Pattern expected to be 0xAA, and found to be {l:#x}.".format(l=leds))
        if leds == 0xAA:
            self.comment("Correct. 3/3")
            return 3
        else:
            self.comment("Incorrect. 0/3")
            return 0
Example #11
0
class Prac10Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        self.comment("Changing dir to submission dir")
        os.chdir(self.submission_dir)
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 0:
            self.comment("Elf files exist before make run: {e}".format(e = all_files))
            self.comment("Aborting")
            return False
        self.comment("Running 'make'")
        make_proc = subprocess.Popen(["make"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            return_code = make_proc.wait(timeout = 5)
        except subprocess.TimeoutExpired:
            make_proc.kill()
            self.comment("Make did not complete after 5 seconds. Aborting")
            return False
        if (return_code != 0):
            error_message = make_proc.communicate()
            self.comment("Make failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Make succeeded. Attempting to link.")
        self.comment("Searching submission directory for .elf files")
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 1:
            self.comment("Too many elf files out of {e}".format(e = all_files))
            return False
        if len(elf_files) == 0:
            self.comment("No elf files out of: {e}".format(e = all_files))
            return False
        self.comment("One elf file produced: {e}".format(e = elf_files[0]))
        self.full_path_to_elf = self.submission_dir + "/" + elf_files[0]
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 10 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.gdb.send_continue()

                for test in [self.part1_tests, self.part2_tests, self.part3_tests, self.part4_tests, self.part5_tests]:
                    try:
                        mark += test()
                    except Exception as e:
                        self.comment("Unrecoverable exception while running test. Aborting")
                        self.comment(str(e))
                        self.comment(type(e))
                        break

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def part1_tests(self):
        self.comment("=== Part 1 ===")
        self.comment("Verifying timing between all patterns. Should be 1 second +-6%.")
        pattern_array = [0x01, 0x02, 0x04, 0x08, 0x88, 0x48, 0x28, 0x18]
        for i in range(1, len(pattern_array)+3, 2):
            pat0 = pattern_array[i % len(pattern_array)]
            pat1 = pattern_array[(i+1) % len(pattern_array)]
            timing = round(self.ii.transition_timing(pat0, pat1), 3)
            self.comment("Timing between {p0:#x} and {p1:#x} found to be: {t}".format(p0 = pat0, p1 = pat1, t = timing))
            if timing < 1.0*0.88 or timing > 1*1.12:
                self.comment("Timing out. Awarding 0.")
                return 0
            elif timing < 1.0*0.94 or timing > 1*1.06:
                self.comment("Timing somewhat out. Awarding 1.")
                return 1
        self.comment("Correct. 2/2")
        return 2

    def part2_tests(self):
        mark = 1
        self.comment("=== Part 2 ===")
        self.comment("Waiting until pattern 0x48 is displayed.")
        t0 = time.time()
        leds = self.ii.read_port(0)
        while( (time.time() - t0 < 10.0) and leds != 0x48):
            leds = self.ii.read_port(0)
        if leds != 0x48:
            self.comment("Could not find 0x48 after 10 seconds. Timeout. 0/2")
            return 0
        self.comment("Pattern 0x48 is now on LEDs. Asserting a 100 ms pulse on SW0")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        pattern = self.ii.read_port(0)
        self.comment("Pattern should now be 0x01 and is {p:#x}.".format(p = pattern))
        if pattern != 0x01:
            self.comment("Incorrect. 0/2")
            return 0
        self.comment("Correct. 1/2")
        self.comment("Now holding SW0 down and ensuring that transitions occur.")
        self.ii.clear_pin(0)
        timing = round(self.ii.transition_timing(0x02, 0x04), 3)
        self.ii.highz_pin(0)
        if timing != -1:
            self.comment("Transition successfully found with SW0 held. 2/2")
            return 2
        self.comment("No transition found with SW0 held. 1/2")
        return 1

    def part3_tests(self):
        self.comment("=== Part 3 ===")
        self.comment("Pulsing SW0 again to reset pattern to start.")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        self.comment("Pulsing SW1 to change frequency to 2 Hz.")
        self.ii.clear_pin(1)
        time.sleep(0.1)
        self.ii.highz_pin(1)
        time.sleep(0.1)
        self.comment("Now looking for transition from 0x04 to 0x08. Should be 0.5 seconds +- 6%")
        timing = round(self.ii.transition_timing(0x04, 0x08), 3)
        self.comment("Timing found to be: {t}".format(t = timing))
        if timing < 0.5 * 0.9 or timing > 0.5 * 1.1:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Timing good. 2/2")
        return 2

    def part4_tests(self):
        self.comment("=== Part 4 ===")
        self.comment("Pulsing SW0 again to reset pattern to start.")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        self.comment("Pulsing SW2 to change frequency to 5 Hz.")
        self.ii.clear_pin(2)
        time.sleep(0.1)
        self.ii.highz_pin(2)
        time.sleep(0.1)
        self.comment("Now looking for transition from 0x04 to 0x08. Should be 0.2 seconds +- 6%")
        timing = round(self.ii.transition_timing(0x04, 0x08), 3)
        self.comment("Timing found to be: {t}".format(t = timing))
        if timing < 0.2 * 0.9 or timing > 0.2 * 1.1:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Timing good. Now checking that Part 3 tests still work.")
        if self.part3_tests() != 0:
            self.comment("Part 3 tests still good, awarding part 4. 1/1")
            return 1
        self.comment("Part 3 tests seem broken. Awarding 0")
        return 0


    def part5_tests(self):
        self.comment("=== Part 5 ===")
        self.comment("Asserting SW3.")
        self.ii.clear_pin(3)
        self.comment("Applying 0V to both pot0 and pot1. Frequency should be 1 Hz.")
        self.ii.write_dac(0)
        self.ii.configure_dac_channel(0, 0)
        self.ii.configure_dac_channel(1, 0)
        self.comment("Pulsing SW0 and looking for timing from 0x02 to 0x04.")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        timing = round(self.ii.transition_timing(0x02, 0x04), 3)
        self.comment("Timing found to be: {t}".format(t = timing))
        if timing < 1 * 0.9 or timing > 1 * 1.1:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Timing good.")
        self.ii.write_dac(50) # v = 50/256 * 3.3 = 0.645 V
        self.ii.configure_dac_channel(0, 1)
        self.ii.configure_dac_channel(1, 0)
        time.sleep(2)
        self.comment("Asserting 0.65 V on pot0 and 0 V on pot 1. Timing should be 0.814 seconds")
        self.comment("Pulsing SW0 and looking for timing from 0x02 to 0x04.")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        timing = round(self.ii.transition_timing(0x02, 0x04), 3)
        self.comment("Timing found to be: {t}".format(t = timing))
        if timing < 0.814 * 0.9 or timing > 0.814 * 1.1:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Timing good.")
        self.ii.write_dac(200) # v = 200/255 * 3.3 = 2.589 V
        self.ii.configure_dac_channel(0, 0)
        self.ii.configure_dac_channel(1, 1)
        time.sleep(2)
        self.comment("Asserting 2.589 V on pot1 and 0 V on pot 0. Timing should be 0.255 seconds")
        self.comment("Pulsing SW0 and looking for timing from 0x02 to 0x04.")
        self.ii.clear_pin(0)
        time.sleep(0.1)
        self.ii.highz_pin(0)
        time.sleep(0.1)
        timing = round(self.ii.transition_timing(0x02, 0x04), 3)
        self.comment("Timing found to be: {t}".format(t = timing))
        if timing < 0.255 * 0.9 or timing > 0.255 * 1.1:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("All timing good. 3/3")
        return 3
Example #12
0
class Prac4Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        print("building {f} in dir: {d}".format(f= self.src_name, d=self.submission_dir))
        as_proc = subprocess.Popen(["arm-none-eabi-as", \
                "-mcpu=cortex-m0", "-mthumb", "-g", \
                "-o", self.submission_dir + "/main.o", \
                self.submission_dir + "/" + self.src_name], \
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if (as_proc.wait() != 0):
            error_message = as_proc.communicate()
            self.comment("Compile failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Compile succeeded. Attempting to link.")
        ld_proc = subprocess.Popen(["arm-none-eabi-ld", \
                "-Ttext=0x08000000", \
                "-o", self.submission_dir + "/main.elf", \
                self.submission_dir + "/main.o"], \
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if (ld_proc.wait() != 0):
            error_message = ld_proc.communicate()
            self.comment("Link failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.full_path_to_elf = self.submission_dir + "/main.elf"
        self.comment("Link succeeded")
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 4 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.comment("=== Part 1 ===")
                mark += self.part1_tests()

                self.comment("===Part 2 ===")
                mark += self.part2_tests()

                self.comment("Sending 'continue' to allow code to free-run")
                self.gdb.send_continue()
                
                self.comment("=== Part 3 ===")
                mark += self.part3_tests()

                self.comment("=== Part 4 ===")
                mark += self.part4_tests()

                self.comment("=== Part 5 ===")
                mark += self.part5_tests()

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def part1_tests(self):
        if self.gdb.run_to_label("copy_to_RAM_complete") == False:
            self.comment("Could not hit label 'copy_to_RAM_complete'. Aborting")
            return 0
        self.comment("Verifying array in RAM")
        for idx, val in enumerate(data_array):
            address = 0x20000000 + (4*idx)
            data_in_RAM = self.gdb.read_word(address)
            if data_in_RAM != val:
                self.comment("Data at address {addr:#x} should be {v:#x} but is {d:#x}".format(addr = address, v = val, d = data_in_RAM))
                return 0
        self.comment("Data correct in RAM. 3/3")
        return 3

    def part2_tests(self):
        if self.gdb.run_to_label("increment_of_bytes_complete") == False:
            self.comment("Could not hit label 'increment_of_bytes_complete'. Aborting")
            return 0
        self.comment("Verifying incremented array in RAM")
        mark_to_return = 2
        for idx, val in enumerate(data_array):
            address = 0x20000000 + (4*idx)
            data_in_RAM = self.gdb.read_word(address)
            for byte_offset in range(0, 3):
                # add one at the correct place, then shift the byte of interest down to LSB and select with mask
                val_byte = ((val + (1 << (byte_offset * 8))) >> (byte_offset * 8)) & 0xFF
                data_byte = ((data_in_RAM ) >> (byte_offset * 8)) & 0xFF
            if val_byte != data_byte:
                self.comment("Data at address {addr:#x} should be {v:#x} but is {d:#x}".format( \
                        addr = address + byte_offset, v = val_byte, d = data_byte))
                self.comment("Aborting verification phase. 0/2")
                mark_to_return = 0
                break
        if mark_to_return == 2:
            self.comment("Data correct in RAM. 2/2")
        self.comment("Now modifying data in RAM. Setting all words to 0x88888888")
        for word_offset in range(0, len(data_array)):
            word_addr = 0x20000000 + (word_offset*4)
            self.gdb.write_word(word_addr, 0x88888888)
        self.comment("Setting address 0x2000000C0 to 0x8870FA05")
        self.comment("This implies a max unsigned of 0xFA, min unsigned of 0x05 and max signed of 0x70")
        self.gdb.write_word(0x20000008, 0x8870FA05)
        return mark_to_return

    def part3_tests(self):
        # simulate SW1 and not SW0. Should be flashing AA,55 at 0.25 seconds
        self.ii.highz_pin(0)
        self.ii.highz_pin(1)
        time.sleep(0.5)
        self.comment("Releasing both SW0 and SW1")
        led_data = self.ii.read_port(0)
        self.comment("Data on LEDs should be max unsigned (0xFA), and found to be {d:#X}".format(d=led_data))
        if led_data != 0xFA:
            self.comment("Incorrect. 0/3")
            return 0
        self.comment("Part 3 correct. 3/3")
        return 3

    def part4_tests(self):
        # simulate SW1 and not SW0. Should be flashing AA,55 at 0.25 seconds
        self.ii.clear_pin(0)
        self.ii.highz_pin(1)
        time.sleep(0.5)
        self.comment("Pressing SW0 and releasing SW1")
        led_data = self.ii.read_port(0)
        self.comment("Data on LEDs should be min unsigned (0x05), and found to be {d:#X}".format(d=led_data))
        if led_data != 0x05:
            self.comment("Incorrect. 0/2")
            return 0
        self.comment("Part 4 correct. 2/2")
        return 2

    def part5_tests(self):
        # simulate SW1 and not SW0. Should be flashing AA,55 at 0.25 seconds
        self.ii.highz_pin(0)
        self.ii.clear_pin(1)
        time.sleep(0.5)
        self.comment("Releasing SW0 and pressing SW1")
        led_data = self.ii.read_port(0)
        self.comment("Data on LEDs should be max signed (0x70), and found to be {d:#X}".format(d=led_data))
        if led_data != 0x70:
            self.comment("Incorrect. 0/1")
            return 0
        self.comment("Part 5 correct. 1/1")
        return 1
Example #13
0
class Prac9Tests:
    def __init__(self, comment, submission_dir, src_name):
        self.comment = comment
        self.src_name = src_name
        self.full_path_to_elf = None
        self.submission_dir = submission_dir

    def build(self):
        self.comment("Changing dir to submission dir")
        os.chdir(self.submission_dir)
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 0:
            self.comment("Elf files exist before make run: {e}".format(e = all_files))
            self.comment("Aborting")
            return False
        self.comment("Running 'make'")
        make_proc = subprocess.Popen(["make"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        try:
            return_code = make_proc.wait(timeout = 5)
        except subprocess.TimeoutExpired:
            make_proc.kill()
            self.comment("Make did not complete after 5 seconds. Aborting")
            return False
        if (return_code != 0):
            error_message = make_proc.communicate()
            self.comment("Make failed. Awarding 0. Error message:")
            self.comment(error_message[0].decode())
            self.comment(error_message[1].decode())
            return False
        self.comment("Make succeeded. Attempting to link.")
        self.comment("Searching submission directory for .elf files")
        all_files = os.listdir()
        elf_files = [fi for fi in all_files if fi.endswith(".elf")]
        if len(elf_files) > 1:
            self.comment("Too many elf files out of {e}".format(e = all_files))
            return False
        if len(elf_files) == 0:
            self.comment("No elf files out of: {e}".format(e = all_files))
            return False
        self.comment("One elf file produced: {e}".format(e = elf_files[0]))
        self.full_path_to_elf = self.submission_dir + "/" + elf_files[0]
        return True

    def run_tests(self):
        mark = 0
        self.comment("Starting to run prac 9 tests")
        self.ii = InterrogatorInterface()
        self.comment(self.ii.comms_test())
        self.ii.reset(0) # pull line low. This does a reset
        with OpenOCD(self.comment) as self.openocd:
            time.sleep(0.2)
            self.ii.reset(1) # release line. Allows OpenOCD to establish connection to core.
            with GDBInterface(self.full_path_to_elf, self.comment) as self.gdb:
                self.gdb.open_file()
                self.gdb.connect()
                self.gdb.erase()
                self.gdb.load()
                self.gdb.send_continue()

                for test in [self.part1_tests, self.part2_tests, self.part3_tests]:
                    try:
                        mark += test()
                    except Exception as e:
                        self.comment("Unrecoverable exception while running test. Aborting")
                        self.comment(str(e))
                        break

                if mark == 7:
                    mark += self.bonus_tests()
                else:
                    self.comment("Not attempting bonus due to previous errors")

                self.ii.highz_pin(0)
                self.ii.highz_pin(1)
                self.ii.highz_pin(2)
                self.ii.highz_pin(3)

        self.comment("All tests complete. Mark: {m}".format(m=mark))
        return mark

    def part1_tests(self):
        self.comment("=== Part 1 ===")
        self.comment("Releasing both SW2 and SW3")
        self.ii.highz_pin(2)
        self.ii.highz_pin(3)
        time.sleep(2)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern + 2, current_pattern + 3)
        self.comment("Timing between an increment expected to be 0.5 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.46 or timing > 0.54:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Correct. 2/2")
        return 2

    def part2_tests(self):
        self.comment("=== Part 2 ===")
        self.comment("Releasing SW2 and pressing SW3")
        self.ii.highz_pin(2)
        self.ii.clear_pin(3)
        time.sleep(0.6)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern - 2, current_pattern - 3)
        self.comment("Timing between a decrement expected to be 0.5 and found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.47 or timing > 0.53:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Correct. 1/1")
        self.ii.highz_pin(2)
        self.ii.highz_pin(3)
        return 2

    def part3_tests(self):
        self.comment("=== Part 3 ===")
        self.comment("Pressing SW2 and releasing SW3")
        self.ii.clear_pin(2)
        self.ii.highz_pin(3)
        self.comment("Asserting 0.52 V on port A6. Period should become 0.16 seconds.")
        self.ii.write_dac(40)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern + 4, current_pattern + 5)
        self.comment("Timing between an increment found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.14 or timing > 0.18:
            self.comment("Timing out. Awarding 0")
            return 0
        self.comment("Pressing SW2 and pressing SW3")
        self.ii.clear_pin(2)
        self.ii.clear_pin(3)
        self.comment("Asserting 1.93 V on port A6. Period should become 0.33 seconds.")
        self.ii.write_dac(150)
        time.sleep(1)
        current_pattern = self.ii.read_port(0)
        timing = self.ii.transition_timing(current_pattern - 4, current_pattern - 5)
        self.comment("Timing between an decrement found to be: {t}".format(t = round(timing, 2)))
        if timing < 0.30 or timing > 0.36:
            self.comment("Timing out. Awarding 0")
            return 0
        return 3


    def bonus_tests(self):
        self.comment("=== Bonus ===")
        self.comment("Releasing SW2 and SW3.")
        self.ii.highz_pin(2)
        self.ii.highz_pin(3)
        time.sleep(1)
        value_before_rst = self.ii.read_port(0)
        self.ii.reset(0)
        self.comment("Value on LEDs before reset: {leds:#x}".format(leds = value_before_rst))
        self.comment("Pulling NRST line low and sleeping for 2 seconds.")
        time.sleep(2)
        self.comment("Releasing NSRT line and sleeping for 100 ms")
        self.ii.reset(1)
        time.sleep(0.1)
        value_after_rst = self.ii.read_port(0)
        self.comment("Value on LEDs after reset: {leds:#x}".format(leds = value_after_rst))
        if value_before_rst != value_after_rst:
            self.comment("Values different. 0/0")
            return 0
        self.comment("Bonus correct! 1/0")
        return 1