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:
- Getting Serial input to work
- Working on an RSB Recipe
- Implementing
time,randomandmachineto be able to get uptime, reset the machine - Getting floating point values to work on the pc686 BSP
- Working on an initial version of Imports (.py files mounted in QEMU)
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:
- (default): builds libmicropython.a
- build/pytest.tar: archives
test/test.pyintobuild/pytest.tar - build/pytest.c: converts
build/pytest.tartobuild/pytest.candbuild/pytest.h, allowing thetestmodule to be imported at runtime using MicroPython - test_app: builds
test_app.exeusinglibmicropython.a,test/init.candtest/main.c
I’m waiting for Chris, one of my mentors, to write an RSB Recipe using this, so we should have one soon. I talked about the build system progress in my week 4 and week 5 blog posts.
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:
random: all functions available after simply enabling the moduletime: all functions implemented
-sleep(N): sleep forNseconds
-sleep_ms(N): sleep forNmilliseconds
-sleep_us(N): sleep forNmicroseconds
-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 thismachine:
-mem8,mem16,mem32: allow direct memory access
-reset(): hard resets the machine usingbsp_reset()
-soft_reset(): breaks out ofpyexec_friendly_repl(orpyexec_raw_replin the future), cleans up all the heap objects and runs into agotothat 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:
mp_obj_t mp_time_time_get(void)uint64_t mp_hal_time_ns(void)void mp_hal_delay_ms(uint64_t delay)void mp_hal_delay_us(uint64_t delay)uint64_t mp_hal_ticks_cpu(void)uint64_t mp_hal_ticks_ms(void)uint64_t mp_hal_ticks_us(void)
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:
- moving the
mp_hal_delay_msimplementation away fromrtems_task_wake_after, tonanosleep(by switching the example from classic RTEMS Tasks to POSIX) - using
bsp_resetinmachine.resetinstead of the call tortems_shutdown_executiveI was using earlier
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!