Skip to content

New feature: Serial Terminal #650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from

Conversation

screamerbg
Copy link
Contributor

@screamerbg screamerbg commented Mar 27, 2018

Mbed CLI already has a -f option to automatically flash the program to the connected board after compiling. This PR takes the next natural next step to add serial terminal via -s/--sterm option ("s" for serial) to mbed compile and mbed detect.

Workflow
This PR extends mbed compile and mbed detect by adding -s/--sterm option. The option can be chained with -f/--flash (with mbed compile) or -r/--reset (with mbed detect), meaning that Mbed CLI will first apply the new firmware image, reset the MCU/target/board and then open serial terminal.

The serial terminal offers few commonly used shortcuts:

  • Quit: CTRL+C or CTRL+]
  • Reset: CTRL+B or CTRL+R
  • Echo toggle: CTRL+E
  • Terminal info: TAB or CTRL+I
  • Help: Ctrl+H
  • Menu: Ctrl+T (PySerial)

There are much more options behind the terminal menu (Ctrl+T).

The implementation is based on PySerial, which is one of the fundamental libraries for Mbed Greentea (mbed test). Therefore there are no additional dependencies.

Example usage with mbed compile

$ mbed compile -t GCC_ARM -m NUCLEO_F401RE -f -s
Building project mbed-os-example-blinky (NUCLEO_F401RE, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Compile [100.0%]: main.cpp
Link: mbed-os-example-blinky
Elf2Bin: mbed-os-example-blinky
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |   102 |     7 |   11 |
| [lib]/c.a        | 27166 |  2204 |   56 |
| [lib]/gcc.a      |  3752 |     0 |    0 |
| [lib]/m.a        |    88 |     0 |    0 |
| [lib]/misc       |   236 |    16 |   28 |
| main.o           |   267 |     4 |  276 |
| mbed-os/drivers  |  1301 |     4 |  100 |
| mbed-os/hal      |  1395 |     4 |   66 |
| mbed-os/platform |  3096 |     4 |  354 |
| mbed-os/rtos     |  9114 |   168 | 5989 |
| mbed-os/targets  |  7017 |     5 |  388 |
| Subtotals        | 53534 |  2416 | 7268 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 9684 bytes
Total Flash memory (text + data): 55950 bytes

Image: ./BUILD/NUCLEO_F401RE/GCC_ARM/mbed-os-example-blinky.bin
[mbed] Detected "NUCLEO_F401RE" connected to "/Volumes/NODE_F401RE" and using com port "/dev/tty.usbmodem1413"
[mbed] --- Terminal on /dev/tty.usbmodem1413 - 9600,8,N,1 ---
[mbed] --- Quit: CTRL+C | Reset: CTRL+B | Echo: CTRL+E ---
[mbed] --- Info: TAB    | Help:  Ctrl+H | Menu: Ctrl+T ---
$$$07200221061A657F395EF362start
something 1
something 2
something 3
something 4
something 5
something 6
something 7
something 8
something 9

Example use with mbed detect

$ mbed detect -rs
[mbed] Detected "NUCLEO_F401RE" connected to "/Volumes/NODE_F401RE" and using com port "/dev/tty.usbmodem1413"
[mbed] --- Terminal on /dev/tty.usbmodem1413 - 9600,8,N,1 ---
[mbed] --- Quit: CTRL+C | Reset: CTRL+B | Echo: CTRL+E ---
[mbed] --- Info: TAB    | Help:  Ctrl+H | Menu: Ctrl+T ---
$$$07200221061A657F395EF362start
something 1
something 2
something 3
something 4
something 5
something 6
something 7

Inspired by @yennster's request (#639).

@yennster Do you think you could look into adding help for this feature in the README.md?

Copy link
Contributor

@sg- sg- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems slick. @SenRamakri @deepikabhavnani Have a look and see if there is a natural way to plugin or incorporate the necessary logic for upcoming binary trace expansion.

@theotherjimmy
Copy link
Contributor

It seems odd to me that compile would open a serial terminal. I fear we are turning mbed compile into mbed do. That being said, I can't think of a verb that means build it then run it.

mbed/mbed.py Outdated
@@ -34,6 +34,7 @@
import zipfile
import argparse
import tempfile
from mbed_cdc import mbed_cdc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import should probably be scoped in some way. maybe from mbed.mbed_cdc or from .mbed_cdc. Further, this seems very redundant: from thing import thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a must have, this works in python 2

try:
from mbed_host_tests.host_tests_toolbox import flash_dev
except (IOError, ImportError, OSError):
error("The '-f/--flash' option requires that the 'mbed-greentea' python module is installed.\nYou can install mbed-greentea by running 'pip install mbed-greentea'.", 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not strictly true. The -f/--flash option requires mbed-host-tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather encourage the user to install mbed-greentea which will pull in all the needed modules behind it. In this case, the product is mbed-greentea, not host-tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that works. If mbed-host-tests is not something the user should ever install standalone, I'll merge it with greentea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case this was not clean: this is resolved.

mbed/mbed_cdc.py Outdated
@@ -0,0 +1,111 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

License?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. Thanks

mbed/mbed_cdc.py Outdated
@@ -0,0 +1,111 @@

def mbed_cdc(port, reset=False, sterm=False, baudrate=9600, timeout= 10, print_term_header=True):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we drop mbed from the name of this function? it adds no meaning here. I think this is more a run_serial_term or something similar.

Copy link
Contributor Author

@screamerbg screamerbg Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it's not a standard serial terminal and it's rather for Mbed needs. So I'd rather not use a generic name. Also the whole file would rather go in https://github.com/ARMmbed/mbed-sterm, and this function name will be the contract.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. This is resolved.

mbed/mbed_cdc.py Outdated
except (IOError, ImportError, OSError):
return False

def get_instance(*args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function does not capture any state. Could you move it outside of the body of the mbed_cdc function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does - see port in printed message.

Copy link
Contributor

@theotherjimmy theotherjimmy Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

port is the first parameter. It seems weird to capture it and pass it in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a minor style comment. Not a blocker.

mbed/mbed_cdc.py Outdated
except:
result = False

def cdc_term(serial_instance):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure that this function does not capture any state either. Could you move this function out of mbed_cdc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses other variables from the wrapper function, e.g. imports and cdc_reset()

mbed/mbed_cdc.py Outdated
console_print('[QUIT]')
term.stop()
term.alive = False
break
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This break is not needed; the loop already checks for term.alive

mbed/mbed_cdc.py Outdated
def cdc_reset(serial_instance):
try:
serial_instance.sendBreak()
except:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This except will catch ctrl+c. You probably did not mean to do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep! Just a second.

mbed/mbed_cdc.py Outdated
except:
try:
serial_instance.setBreak(False) # For Linux the following setBreak() is needed to release the reset signal on the target mcu.
except:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This except will catch ctrl+c. You probably did not mean to do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment

mbed/mbed_cdc.py Outdated
serial_port.reset_input_buffer()
if reset:
cdc_reset(serial_port)
result = True
Copy link
Contributor

@theotherjimmy theotherjimmy Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cdc_reset may set result to False. This statement ignores that assignment, effectively throwing away the reset failure.

mbed/mbed_cdc.py Outdated
term.console.write(echo_text)
term.writer = input_handler

if print_term_header:
Copy link
Contributor

@theotherjimmy theotherjimmy Mar 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're referring to this by port, why not just pass it in? Nope something else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you meant. Could you elaborate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ignore, I was mistaken.

@theotherjimmy
Copy link
Contributor

@screamerbg All that remains to be fixed is the two except:s

@cmonr cmonr requested a review from SenRamakri March 27, 2018 16:35
@SenRamakri
Copy link

SenRamakri commented Mar 27, 2018

Why is this only an option to detect/compile? Can we start it by itself? like, "mbed startserial [other options if multiple targets are detected]" OR "mbed sterm".
Also from a developer standpoint, people tend to keep separate terminal to run the builds. So it would be useful if I can do "mbed sterm" separately. And yes, as @sg- mentioned we can potentially expand on this to be used with Binary/ID-based tracing so that it automatically pick the right elf file to do the ID-string mapping.

@theotherjimmy
Copy link
Contributor

@SenRamakri How is mbed sterm different from mbed detect -s? both have to detect attached targets before attaching the terminal.

@SenRamakri
Copy link

If "mbed detect -s" take options in case of multiple targets, then yes, we don't need "mbed sterm".

@theotherjimmy
Copy link
Contributor

@SenRamakri What do you mean by "take options in case of multiple targets"? What options would it take? how do they apply to multiple targets?

@SenRamakri
Copy link

Offline discussion with @theotherjimmy here confirmed that "mbed detect" does pick one of many targets if required. So, "mbed detect -s" does support what I was looking for. Thanks for confirming, @theotherjimmy

@yennster
Copy link
Contributor

So glad this is taking off @screamerbg ! I'll take a look at the README tomorrow 😄

@yennster
Copy link
Contributor

yennster commented Mar 29, 2018

@screamerbg Is there a way to change the baud rate for the serial monitor? Right now it looks like it defaults to 9600 (which is used for a lot of programs, but I vaguely remember needing to use 115200 for various applications, like Mbed Cloud apps)

@jupe
Copy link

jupe commented Mar 30, 2018

Does this feature support terminal codes (ANSI/VT100) ?

@screamerbg
Copy link
Contributor Author

@yennster You can change the baudrate form within the terminal using Ctrl+T + B combo. There's no commandline flag (yet)

@screamerbg
Copy link
Contributor Author

@jupe The implementation invokes PySerial miniterm. This is from miniterm's documentation:

This is a console application that provides a small terminal application.

Miniterm itself does not implement any terminal features such as VT102 compatibility. However it may inherit these features from the terminal it is run. For example on GNU/Linux running from an xterm it will support the escape sequences of the xterm. On Windows the typical console window is dumb and does not support any escapes. When ANSI.sys is loaded it supports some escapes.

http://pyserial.readthedocs.io/en/latest/tools.html#module-serial.tools.miniterm

On Mac terminal it provides a fully featured ANSI support. Had a chance to try it with an ANSI embedded program @stevew817 wrote.

@jupe
Copy link

jupe commented Apr 5, 2018

I tried this with mbed-client-cli which provides ANSI support. Couple comments / proposals:

  • could echo be disabled by default ?
  • could there be cli parameter for baudrate ?
  • When serial port dies it raises SerialException - could it be handled more carefully ?
  • If I press backspace help is printed unexpectedly -> cannot remove characters from cli interface
  • when calling mbed detect -s it prints following logs:
    [mbed] WARNING: The mbed OS tools were not found in "/tmp". 
    [mbed] WARNING: Limited information will be shown about connected mbed targets/boards
    
    What this Limited information means in practice ?
  • CTRL+T CTRL+B causes IOError: [Errno 25] Inappropriate ioctl for device and application stuck (tried with mac)
    This combination is not mentioned in help, but it's easy to do this mistake because CTRL+T b is used to change baudrate.

@screamerbg screamerbg closed this Apr 29, 2018
screamerbg added a commit to screamerbg/neo that referenced this pull request Apr 29, 2018
@screamerbg
Copy link
Contributor Author

Follow up PR #664

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants