Overview

NTIOS can load programs from an SD card and run them, as well as provides an assembler and text editor that allows these programs to be written on the system.  This is done through an emulator, which runs an architecture I designed to run fast on emulators.  It also provides a bunch of useful APIs for the Arduino script that hosts it.  I'm still working on running it outside of Arduino, as a lot of libraries are still used to make it work, but I've made some progress on that front.

NTIOS has a lot of features, some of them are sort of random or niche:

It is generally tailored for portable devices and a lesser extent for robotics.  A lot of this could be bloatware for certain applications, so I think at some point the different parts should be separated into modules that are inserted at compile time, instead of keeping everything loaded at once.  A tablet doesn't need code for PID loops, for example.

This OS was created as a sort of development environment for various ideas.  It's been used in a few portable device prototypes of mine, as well as other random stuff.  That's why it has such diverse and specific features.

Driver List

Here's a list of the drivers I've written or worked on for the system, with notes indicating if it's unfinished:

Progress

I've been working on adding some other features, which do not quite work yet:

I need to make some standard graphical shell for this OS, as of right now there is no good way to use it via touchscreen or keyboard/mouse.  That would need to be a different sort of 'package' from the OS, so there isn't a graphical shell bloating the base OS.

Also, as previously mentioned, I think a separation of the OS into different modules would be useful, so a reduced form of it can easily be compiled.

Supported Devices

I know it works with ESP32, Artemis, and Teensy 4.0.  I would expect that it works with many other devices and architectures on Arduino, I just haven't tried others yet.

Integration with Processors

The OS is a git repo to be inserted in the sketch's 'src' directory.  Since the OS's repo cannot contain drivers for every interface on every processor, it is up to the sketch to extend some of the HAL base classes and add them to the device list.  From there the other drivers can be attached to the base hardware drivers.  For example, on Teensy there is a TeensySPIPort class, which provides the OS with access to the SPI bus.  From here the OS's included drivers can use the bus in a modular way.  The only other required steps are OS initialization, and starting any shell code or intended application code:

/*
 * This function sets up the hardware, then launches the OS.
 * It has been modified to be a minimal initialization of the system.
 */
void setup() {
  Serial.begin(115200);

  // Setup the sketch's hardware code, then launch the OS
  start_hw();

  // Elsewhere in the sketch, we determine which serial port to use.
  UserIO = get_serial_0();

  // Code for TeensyThreads - single-threaded operation can also be done.
  // This starts the shell
  int id = threads.addThread(ntios_shell_wrapper, UserIO, PROGRAM_STACK_SPACE * 2);

  if (id >= 0) {
    on_new_thread(id, "NTIOS Shell");
  } else {
    Serial.println("Problem starting shell thread!");
  }
}

...

void start_hw() {
  bool hassd = false;

  if (sd.cardBegin(SdioConfig(FIFO_SDIO))) {
    Serial.println("Discovered SD Card");
    if (!sd.volumeBegin()) {
      Serial.println("Error setting up SD filesystem.");
      Serial.println("Is the card formatted?");
    } else {
      hassd = true;
    }
  } else {
    Serial.println("No SD Card detected");
  }

  I2CBusDevice* i2c0 = new TeensyI2CPort(0);
  SPIBusDevice* spi = new TeensySPIPort();
  GPIODevice* gpio_dev;

  device_list[0] = serial_0 = new HWSerialDevice(&Serial1);
  device_list[1] = new HWSerialDevice(&Serial2);
  device_list[2] = new HWSerialDevice(&Serial3);
  device_list[3] = new HWSerialDevice(&Serial4);
  device_list[4] = new HWSerialDevice(&Serial5);
  device_list[5] = i2c0;
  device_list[6] = spi;
  device_list[7] = new SDDriver();

  // Initialize the OS
  ntios_init(device_list, 8, serial_0);

  // Example I2C device
  add_virtual_device(builtin_touchpad = new GT911Touch(i2c0, gpio_dev, 0, 1));

  if (hassd) {
    // This mounts device 8 (the SD card) to the system root ("" - ie, no prefix)
    mount(10, "");
    Serial.println("Mounted SD Card.");
  }
}

 This is some template code to show how the OS may be initialized.  There is a base list of devices, then additional devices can be added/removed while the system is running.  This code will start a shell on Serial1, and attempt to mount an SD card.