scientifichackers / ampy

MicroPython Tool - Utility to interact with a MicroPython board over a serial connection.
MIT License
718 stars 156 forks source link

ampy commands are pending on windows 10 #71

Open youngsu999 opened 5 years ago

youngsu999 commented 5 years ago

I want to share my experience how I (may be temporary) solve the ampy command pending issue.

Here is my problem and temporary solution for ampy command pending issue.

My environment

SW:

HW:

Problem

Finding the issue

I checkout the source and add the print on library and searched for the point where code was pending. I Found that the code is pending at the line 189 of pyboard.py. The code is data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>').

    def enter_raw_repl(self):
        # Brief delay before sending RAW MODE char if requests
        if _rawdelay > 0:
            time.sleep(_rawdelay)

        self.serial.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program

        # flush input (without relying on serial.flushInput())
        n = self.serial.inWaiting()
        while n > 0:
            self.serial.read(n)
            n = self.serial.inWaiting()

        self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL
        data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>')  # line 189
        if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'):
            print(data)
            raise PyboardError('could not enter raw repl')

        self.serial.write(b'\x04') # ctrl-D: soft reset
        data = self.read_until(1, b'soft reboot\r\n')
        if not data.endswith(b'soft reboot\r\n'):
            print(data)
            raise PyboardError('could not enter raw repl')
        # By splitting this into 2 reads, it allows boot.py to print stuff,
        # which will show up after the soft reboot and before the raw REPL.
        # Modification from original pyboard.py below:
        #   Add a small delay and send Ctrl-C twice after soft reboot to ensure
        #   any main program loop in main.py is interrupted.
        time.sleep(0.5)
        self.serial.write(b'\x03')
        time.sleep(0.1)           # (slight delay before second interrupt
        self.serial.write(b'\x03')
        # End modification above.
        data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n')
        if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'):
            print(data)
            raise PyboardError('could not enter raw repl')

I also inspected the inside of self.read_util function but the most suspicious line was a line before. (self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL). I think For some reason, The develop board missed Ctl-A character and it may fail to enter raw repl mode.

So I modified the function as follows:

    def enter_raw_repl(self):
        # Brief delay before sending RAW MODE char if requests
        if _rawdelay > 0:
            time.sleep(_rawdelay)
        self.serial.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program
        # flush input (without relying on serial.flushInput())
        n = self.serial.inWaiting()
        while n > 0:
            self.serial.read(n)
            n = self.serial.inWaiting()
->      time.sleep(0.5)
        self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL
->      for i in range(4):
->          time.sleep(0.1)
->          self.serial.write(b'\x01') # send ctl-A for several times
->      self.serial.flushOutput()
        data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n>')
        # data = self.read_until(1, b'raw REPL; CTRL-B to exit\n>')
        if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'):
            print(data)
            raise PyboardError('could not enter raw repl')
->      self.serial.flushInput()
        self.serial.write(b'\x04') # ctrl-D: soft reset
        data = self.read_until(1, b'soft reboot\r\n')

        if not data.endswith(b'soft reboot\r\n'):
            print(data)
            raise PyboardError('could not enter raw repl')

        # By splitting this into 2 reads, it allows boot.py to print stuff,
        # which will show up after the soft reboot and before the raw REPL.
        # Modification from original pyboard.py below:
        #   Add a small delay and send Ctrl-C twice after soft reboot to ensure
        #   any main program loop in main.py is interrupted.
        time.sleep(0.5)
        self.serial.write(b'\x03')
        time.sleep(0.1)           # (slight delay before second interrupt
        self.serial.write(b'\x03')
        # End modification above.
        data = self.read_until(1, b'raw REPL; CTRL-B to exit\r\n')
        if not data.endswith(b'raw REPL; CTRL-B to exit\r\n'):
            print(data)
            raise PyboardError('could not enter raw repl')

And the commands works well. My opinion is that many pending issues are came from failing to enter the raw_repl mode.

It is just temporal patch and until now i have no idea more proper way to solve it.

youngsu999 commented 5 years ago

I found issues such as #19 #41 #43 and #69 seems to be related. Especially for #19, it is same issue except board model.

ladyada commented 5 years ago

Hiya! We are discontinuing support for ampy, and will no longer be maintaining it. We are leaving this repository available for continued use. If you would like to take over supporting it, please contact us on the Adafruit Discord server and we can transfer the repository to you. If you wish to continue developing it on your own, please fork the repository.