GSoC Project Updates, Mid-Term

I have completed work on all the mid-term deliverables that I finalized with my mentors and wanted to make a quick summary of the work done so far in this post.

Here’s the list of deliverables:

The main branch right now is port-files.

Serial Input

This was one of the first things I worked on. We launch the built “test_app” executable using:

qemu-system-i386 \
    --cpu core2duo \
    -append "--console=/dev/com1" \
    -serial stdio \
    -kernel build/test_app.exe

The problem was that fgets or getc wouldn’t block. I looked in the the fileio sample (it takes user input after presenting a menu), and eventually found some termios flags that are set when rtems_shell_wait_for_input is called that set the terminal up for user input. The example application currently just has a call to this RTEMS shell function that properly sets up input for us:

rtems_shell_wait_for_input(STDIN_FILENO, 0, NULL, NULL);

I have identified the termios flags that this function uses but I use this “hack” right now because of the reasons discussed below.

Some more context on this is around the mpremote tool. The tool can be used to interface with MicroPython installations over serial or network. We tried it with the RTEMS Port by redirecting QEMU’s serial device to a new pseudoterminal using -serial chardev:char0 -chardev pty,id=char0 and observed that mpremote sends CTRL+A to make the default “friendly REPL” drop into a “raw REPL”. The CTRL+A (along with other codes) handling is present in MicroPython’s pyexec_friendly_repl implementation that we use. I made some progress with this and identified two sets of termios flags where each lets us use either the friendly REPL or the Raw REPL properly. The goal is to have a set of flags that allow us to easily use both, or just be able to switch to the Raw REPL immediately after sending CTRL+A (which mpremote expects to happen) and the having some logic to change terminal settings. More info on the exact flags I tried can be found in my Week 5 Blog Post.

My mentors decided that getting mpremote to work is not a priority for now so I’ll pick the work-in-progress code up later from the termios_experiments branch. When we have working code for this, I’ll replace the “hack” call to rtems_shell_wait_for_input in the test application’s main function with termios code.

RSB Recipe

As per the discussions with my mentors, I’m only responsible for half of this - a Makefile that can build the port as a library, libmicropython.a and the test application test_app.exe that demonstrates available features. This was decided because my mentors suggested that learning the RSB would take up too much time. Here are the currently defined make targets:

time, random and machine modules

I have been able to get all three modules listed in the last mid-term deliverable working. time and random are fully supported and I’m looking for feedback on their implementation. machine has many classes like Pin, I2S, PWM, etc. that I can’t enable right now because we are using the pc686 BSP with QEMU. So currently the only implemented machine functions are reset and soft_reset (which was the goal) along with 8, 16 or 32 byte read/write access to memory, making up its basic functionality outside of those protocols and GPIO.

Reference for MicroPython libraries can be found here.

Implemented features for each module:

  1. random: all functions available after simply enabling the module
  2. time: all functions implemented
    - sleep(N): sleep for N seconds
    - sleep_ms(N): sleep for N milliseconds
    - sleep_us(N): sleep for N microseconds
    - time(): Returns the number of seconds, as an integer, since the Epoch (defined by the port, boot time here)
    - all “ticks” functions: ticks_cpu(), ticks_ms(), ticks_us(), ticks_add(), ticks_diff(), with RTEMS MICROSECONDS_PER_TICK set to 1000
    - bug: time_ns() leads to an “OverflowError: small int overflow”. Currently looking into this
  3. machine:
    - mem8, mem16, mem32: allow direct memory access
    - reset(): hard resets the machine using bsp_reset()
    - soft_reset(): breaks out of pyexec_friendly_repl (or pyexec_raw_repl in the future), cleans up all the heap objects and runs into a goto that restarts everything

remaining in machine:
- reset_cause(): returns the cause of reset. A list can be found here
- bootloader(): used to put the device in a state where it can be upgraded to a new firmware
- interrupt related and power related functions
- classes for various peripherals like machine.Pin for GPIO, machine.I2C, machine.I2S, etc. Potential candidates for implementation on the current pc686 BSP are Timer and WDT (watchdog timer).

I had to implement the following functions to get these to work:

I also recorded some demos using asciinema:

I started this work in the modules branch and it has been merged into port-files and there have been some rebases related to the time module.

Floating Point

This turned out to be easier than expected. I only had to define MICROPY_FLOAT_IMPL in mpconfigport.h and enable floats on the BSP using CONFIGURE_RTEMS_FLOATING_POINT. I learned that i386 doesn’t have floats by default and needs a separate “i387” chip for floating point functionality. I wrote about this in my week 5 blog post.

An Initial Version of Imports

We now also have an IMFS based imports system. The previously mentioned pytest.c, pytest.h are compiled along with the test application and rtems_tarfs_load is used to load that at “/”. I implemented mp_import_stat as follows:

mp_import_stat_t mp_import_stat(const char *path) {
    char file_path[256] = { 0 };

    sprintf(file_path, "/%s", path);

    struct stat file_info;
    int ret = stat(file_path, &file_info);

    if (ret == -1) {
        return MP_IMPORT_STAT_NO_EXIST;
    }

    if (file_info.st_mode & S_IFDIR) {
        return MP_IMPORT_STAT_DIR;
    }

    if (file_info.st_mode & S_IFREG) {
        return MP_IMPORT_STAT_FILE;
    }
}

I recorded a demo for this too: imports demo. Here’s the related commit.

The Makefile could later be modified to make a tar archive of not just one file, but many in a test/modules directory that we can then import at runtime.

This completes all of the planned mid-term goals. I am currently working on the time_ns() overflow bug and making changes as per my mentors’ feedback, which has so far included:

I will continue to work on these small changes this week and discuss next steps and the post-midterm plan with my mentors. GSoC has been an amazing experience so far and I’m excited for the second phase of this project.

Thank you for your time!