Skip to main content

Native (C++) Application

Native Application System Overview​

In Matrix OS, native (C++) applications will be running on the device as it's own thread in the OS and have access to System API, device level low level API, and any third party library. This is great for performance but not great for portability and sharing. (hint hint)

The application code will be similar to the Arduino, which you will have an user defined Setup() for the initialization of your application, a user defined Loop() as infinite loop for your application code. Additionally, you will have a user defined End() for end of your application and a Exit() function that you can call to exit the application.

Available API​

  • Matrix OS C++ API - Matrix OS provided APIs, they are the easiest to use, provides the best portability, and memory safe (supposedly).
  • Device Layer API - Device layer provided API. Matrix OS API are largely a wrapper over those and you should be using them instead. There might be some non standard API for some special device features that have not been added into the Matrix OS API.
  • Core Layer API - Provided by the SoC SDK of the device, in the case of Mystrix, the ESP-IDF SDK. They provides a lot of features that are not device specific but chip specific. You can for example, build an WiFi enabled Matrix OS application for Mystirx, even though the Matrix OS API isn't available yet. See example
  • FreeRTOS API - Matrix OS runs on FreeRTOS and you can use FreeRTOS API as well to create threads and cross thread communication.
  • Any third party C/C++ library you wish to use - You should be able to include them inside your application folder and use them.
Non Stable API & Build system

As this project is still evolving, I can not promise APIs will stay the same. There are constantly a lot of new usages that requires new API and changes of existing API. Your code will break, but I don't know when and how. I do try to maintain backward compatibility as much as possible but I won't try to save an obviously bad design.

Matrix OS build system might be receiving an overhaul soon so it will be smarter to know what to compile and what not to. Your code might need to change a bit to adapt to it, but it shouldn't be very hard and there will be migration guide.

Example App​

We use the example App in the Matrix OS the example to explain how the application works. You can find the source code at the Matrix OS repo

Header File​

1
2#pragma once
3
4#include "MatrixOS.h"
5#include "applications/Application.h"
6#include "applications/BrightnessControl/BrightnessControl.h" 
7
8class ExampleAPP : public Application {
9public:
10static Application_Info info;
11
12void Setup() override;
13void Loop() override;
14void End() override;
15
16
17
18// Wanna make your number and color saves between restarts? Comment out the define below. 
19// This macro change the code that will the color variable to a saved variable
20// And replace part of the code to support it
21
22// #define EXAMPLEAPP_SAVED_VAR
23
24#ifndef EXAMPLEAPP_SAVED_VAR
25uint8_t number = 0;
26Color color = Color(0xFFFFFF);
27#else
28CreateSavedVar("Example", number, uint8_t, 0);
29CreateSavedVar("Example", color, Color, Color(0xFFFFFF));
30
31// Namespace (This namespace only applies to this application. So even if two different applications have the same variable name, they won't conflict), variable name (no ""), variable type, default value
32// And then just use the variable as a normal variable. The value will be saved & loaded automatically!
33// However, not all variable type and operator is supported. If that is the case, you have to get the variable via .Get() and .Set()
34// For more, see /os/framework/SavedVariable.h
35#endif
36
37void UIMenu();
38void KeyEventHandler(uint16_t KeyID, KeyInfo* keyInfo);
39void MidiEventHandler(MidiPacket midiPacket);
40};
41
42// Meta data about this application
43inline Application_Info ExampleAPP::info = {
44  .name = "Example",
45  .author = "203 Systems",
46  .color = Color(0xFFFFFF),
47  .version = 1,
48  .visibility = true,
49};
50
51// Register this Application to the OS (Use the class name of your application as the variable)
52REGISTER_APPLICATION(ExampleAPP);
53

Break Down​


#include "MatrixOS.h"

This includes the MatrixOS.h file, which includes all the framework, type, and APIs provided by the Matrix OS.


#include "applications/Application.h"" 

This include the Application.h file, which is the base class for all applications. It provides the basic structure for the application.


#include "applications/BrightnessControl/BrightnessControl.h" 

This include the BrightnessControl.h file, which is an external UI for brightness control. This shows that you can include UI or UI elements from other applications. (Although it's not recommended)


class ExampleAPP : public Application {
public:
static Application_Info info;

void Setup() override;
void Loop() override;
void End() override;

This is the class definition of the ExampleAPP class. It inherits from the Application class, which is the base class for all applications. The Application_Info info is a static variable that contains the meta data of the application. It includes the name, author, color, version, and visibility of the application. (See below for more info)

It also defines the override of Setup(), Loop(), and End() functions from the Application class. (If you don't need them, you can remove them and not override them. They will do nothing by default)


uint8_t number = 0;
Color color = Color(0xFFFFFF);

This is the variable definition of the number and color variable. They are used by the application to store the number and color at run time.

Local variable only

Make sure all your variables are within the class. If you define them outside of the class, they will be global variables and the memory will not be managed by the OS. This will cause memory to be taken even if the application is not running.


CreateSavedVar("Example", number, uint8_t, 0);
CreateSavedVar("Example", color, Color, Color(0xFFFFFF))

If you want to save your variable between restarts, you can use the CreateSavedVar() macro. This is the saved variable definition of the number and color variable. They are used by the application to store the number and color between restarts.

The macro is defined as CreateSavedVar(namespace string, variable name, variable type, default value).

  • Namespace string is the name of the application. It is used to separate the saved variables between different applications. (You can technically use the same namespace to access the saved variables of another application, but it's not recommended)
  • Variable name is the name of the variable. It is used to identify the variable in the saved variables. You also use this name to access the variable in the code.
  • Variable type is the type of the variable. It is used to determine the size of the variable and how to save/load it.
  • Default value is the default value of the variable. It is used to initialize the variable if it is not saved yet.

In most case when you are access the variable, you can just use the variable name as if it's a normal variable. The value will be saved & loaded automatically! For primitive types, you also will be able to use it in arithmetic operations. If you have a complex variable, you might need to use .Get() to get a pointer to the variable, modifiy it, and then use .Save() to save it.

I know the macro is not very intuitive and it's not following C's syntex on varible creation. If you have a better idea, please let me know.

For more info on saved variable, see Saved Variable


void UIMenu();
void KeyEventHandler(uint16_t KeyID, KeyInfo* keyInfo);
void MidiEventHandler(MidiPacket midiPacket);

This is the function definition of the UIMenu(), KeyEventHandler(), and MidiEventHandler() functions. They are used by the application to handle UI, key, and MIDI events. We will explain them in the source file section.


inline Application_Info ExampleAPP::info = {
  .name = "Example",
  .author = "203 Systems",
  .color = Color(0xFFFFFF),
  .version = 1,
  .visibility = true,
};

This is the meta data of the application. It is used by the OS to display information about the application. It includes the name, author, color, version, and visibility of the application.

  • Name - The name of the application. It is used to identify the application in the OS. (System will refer to the application by this name)
  • Author - The author of the application. It is used to create namespaced between different authors. (So two applications with the same name but different authors won't conflict)
  • Color - The color of the application. It is used to identify the application in the UI. (The color will be used in the UI to represent the application)
  • Version - The version of the application. It is used to identify the version of the application. (The OS does not make use of this yet, but it will be helpful for APPs to keep track of their version and update it's NVS)
  • Visibility - The visibility of the application. It is used to determine if the application is visible in the UI. (If the application is not visible, it will not be shown in the UI, but they can still be launched by ExecuteAPP() function.)

REGISTER_APPLICATION(ExampleAPP);

Registrating the application to the OS. (The OS will know about the application and will be able to launch it)

Source File​

1
2#include "Example.h"
3#include "ui/UI.h" // Include the UI Framework
4
5// Run once
6void ExampleAPP::Setup() {
7MLOGI("Example", "Example Started");
8}
9
10// Run in a loop after Setup()
11void ExampleAPP::Loop() {
12// Set up key event handler
13struct KeyEvent keyEvent; // Variable for the latest key event to be stored at
14while (MatrixOS::KEYPAD::Get(&keyEvent)) // While there is still keyEvent in the queue
15{ KeyEventHandler(keyEvent.id, &keyEvent.info); } // Handle them
16
17struct MidiPacket midiPacket; // Variable for the latest midi packet to be stored at
18while (MatrixOS::MIDI::Get(&midiPacket)) // While there is still midi packet in the queue
19{ MidiEventHandler(midiPacket); } // Handle them
20}
21
22// Handle the key event from the OS
23void ExampleAPP::KeyEventHandler(uint16_t keyID, KeyInfo* keyInfo) {
24Point xy = MatrixOS::KEYPAD::ID2XY(keyID);  // Trying to get the XY coordination of the KeyID
25if (xy)                                     // IF XY is valid, means it is a key on the grid
26{
27  MLOGD("Example", "Key %d %d %d", xy.x, xy.y, keyInfo->state); // Print the key event to the debug log
28  if (keyInfo->state == PRESSED)            // Key is pressed
29  {
30    MatrixOS::LED::SetColor(xy, color, 0);      // Set the LED color to a color. Last 0 means writes to the active layer (255 writes to the active layer as well but do not trigger auto update.)
31  }
32  else if (keyInfo->state == RELEASED)
33  {
34    MatrixOS::LED::SetColor(xy, 0x000000, 0);  // Set the LED to off
35  }
36}
37else                          // XY Not valid,
38{
39  if (keyID == FUNCTION_KEY)  // FUNCTION_KEY is pre defined by the device, as the keyID for the system function key
40  {
41    UIMenu();                 // Open UI Menu
42  }
43}
44}
45
46void ExampleAPP::MidiEventHandler(MidiPacket midiPacket) {
47// Echo back the midi packet to the source
48MatrixOS::MIDI::Send(midiPacket);
49
50//Midi Packet has port, status, and data
51// Port shows where this midi signal is from (USB, Bluetooth, RTPMIDI, HWPort, etc)
52// When sending midi packets. This is also where the midi signal will be sent to
53// See EMidiStatus enum in /os/framework/midiPacket.h for all the midi status
54// 0x0 sends to all first of available ports
55// Status is the midi status (NoteOn, NoteOff, ControlChange, etc)
56// See EMidiStatus enum in /os/framework/midiPacket.h for all the midi status
57
58// Wanna do more with the packet? Here's a example parser
59
60/*
61switch (midiPacket.status)
62{
63  case NoteOn:
64  case ControlChange:
65    NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity());
66    break;
67  case NoteOff:
68    NoteHandler(midiPacket.channel(), midiPacket.note(), 0);
69    break;
70  case SysExData:
71  case SysExEnd:
72    SysExHandler(midiPacket);
73    break;
74  default:
75    break;
76}
77*/
78}
79
80void ExampleAPP::UIMenu() {
81// Matrix OS Debug Log, sent to hardware UART and USB CDC
82MLOGI("Example", "Enter UI Menu");
83
84// Create a UI Object
85// UI Name, Color (as the text scroll color). and new led layer (Set as true, the UI will render on a new led layer. Persevere what was rendered before after UI exits)
86UI menu("UI Menu", Color(0x00FFFF), true);
87
88// Create an UI element
89UIButton numberSelector;
90numberSelector.SetName("Number Selector");  // Name of this UI element
91numberSelector.SetColor(Color(0xFF0000));  // Color of the UI element
92numberSelector.OnPress([&]() -> void {     // Callback function when the button is pressed
93  number = MatrixOS::UIInterface::NumberSelector8x8(number, 0xFF0000, "Number", 0, 100);  // Current Number, color, low range, high range
94  // EXAMPLEAPP_SAVED_VAR does not affect this code
95  // For most value types, the saved variable wrapper library requires no changes to code!
96});
97// Add the UI element to the UI object to top left conner
98menu.AddUIComponent(numberSelector, Point(0, 0));
99
100// Create an dynamic colored button
101UIButton colorSelector;
102colorSelector.SetName("Color Selector");  // Name of this UI element
103colorSelector.SetColorFunc([&]() -> Color { return color; });  // Use the color variable as the color of this UI element
104colorSelector.OnPress([&]() -> void {  // Callback function when the button is pressed
105  #ifndef EXAMPLEAPP_SAVED_VAR
106  MatrixOS::UIInterface::ColorPicker(color);  // References to the color variable. The color variable will be updated by the ColorPicker function. Return true if color is changed, false if not.
107  #else
108  MatrixOS::UIInterface::ColorPicker(color.value);  // Get the actual value from the saved variable wrapper library
109  color.Set(color.value);  // Save the new variable
110  // The saved variable wrapper doesn't implicitly convert to the references type.
111  // This way you know you have to get the references manually and set the value back to the saved variable manually.
112  #endif
113});
114colorSelector.OnHold([&]() -> void {  // Optional Callback function for hold down. Reset color to default white.
115  color = 0xFFFFFF;
116});
117
118// Add the UI element to the UI object to top right conner
119menu.AddUIComponent(colorSelector, Point(Device::x_size - 1, 0));
120
121// A large button that cycles though the brightness of the device
122UIButton brightnessBtn;
123brightnessBtn.SetName("Brightness"); // Name
124brightnessBtn.SetColor(Color(0xFFFFFF)); // Color
125brightnessBtn.SetSize(Dimension(2, 2)); // Size of the button
126brightnessBtn.OnPress([&]() -> void { MatrixOS::LED::NextBrightness(); }); // Function to call when the button is pressed
127brightnessBtn.OnHold([&]() -> void {BrightnessControl().Start(); }); // Function to call when the button is hold down
128
129// Place this button in the center of the device
130menu.AddUIComponent(brightnessBtn, Point((Device::x_size - 1) / 2, (Device::y_size - 1) / 2));
131
132// Set a key event handler for the UI object
133// By default, the UI exits after the function key is PRESSED.
134// Since this is the main UI for this application. 
135// We want to exit the application when the function key is hold down,
136// and exit the UI is released (but before the hold down time threshold)
137
138// First, disable the default exit behavior 
139menu.AllowExit(false);
140
141// Second, set the key event handler to match the intended behavior
142menu.SetKeyEventHandler([&](KeyEvent* keyEvent) -> bool {
143  // If function key is hold down. Exit the application
144  if (keyEvent->id == FUNCTION_KEY)
145  {
146      if(keyEvent->info.state == HOLD)
147      {
148          Exit();  // Exit the application.
149
150          return true;  // Block UI from to do anything with FN, basically this function control the life cycle of the UI. This is not really needed as the application exits after
151                          // Exit();
152      }
153      else if(keyEvent->info.state == RELEASED)
154      {
155          menu.Exit(); // Exit the UI
156          return true; // Block UI from to do anything with FN, basically this function control the life cycle of the UI
157      }
158  }
159  return false; // Nothing happened. Let the UI handle the key event
160});
161
162// The UI object is now fully set up. Let the UI runtime to start and take over.
163menu.Start();
164// Once the UI is exited (Not the application exit!), the code will continue here.
165// If Exit() is called in UI. The code will start in the End() of this application and then exit.
166
167// See /os/framework/ui/UI.h for more UI Framework API
168// See /os/framework/ui/UIComponents.h for more UI Components
169// See /os/framework/ui/UIInterface.h for more UI built in UI Interface
170
171// You can also create your own UI Components and UI Interfaces for your own application.
172// You can see the Note application for an example of how to do that. (Note Pad. Octave Shifter. Scales, ScaleVisualizer...)
173
174
175MLOGI("Example", "Exited UI Menu");
176}
177
178void ExampleAPP::End() {
179MLOGI("Example", "Example Exited");
180}
181

Break Down​


#include "Example.h"
#include "ui/UI.h" // Include the UI Framework

This includes the Example.h file, which includes the header file of the application. It also includes the UI.h file, which includes the Matrix OS UI framework. (Why does it need to include the UI framework separately? The default UI framework is not a part of the Matrix OS kernal but it's separate, built in library. You are welcome to make your own UI framework or use a third party one if there is one)


void ExampleAPP::Setup() {
  MLOGI("Example", "Example Started");
}

This is the Setup() function of the application. It is called once when the application is launched. It is used to initialize the application.


void ExampleAPP::Loop() {
  // Set up key event handler
  struct KeyEvent keyEvent; // Variable for the latest key event to be stored at
  while (MatrixOS::KEYPAD::Get(&keyEvent)) // While there is still keyEvent in the queue
  { KeyEventHandler(keyEvent.id, &keyEvent.info); } // Handle them

  struct MidiPacket midiPacket; // Variable for the latest midi packet to be stored at

  while (MatrixOS::MIDI::Get(&midiPacket)) // While there is still midi packet in the queue
  { MidiEventHandler(midiPacket); } // Handle them
}

This is the Loop() function of the application. It is called in a loop after the Setup() function. It is used to run the main logic of the application. In this case, it is looping to check if there is any key or MIDI event in the queue and handle them until the queue is empty.


void ExampleAPP::KeyEventHandler(uint16_t keyID, KeyInfo* keyInfo) {
  Point xy = MatrixOS::KEYPAD::ID2XY(keyID);  // Trying to get the XY coordination of the KeyID
  if (xy)                                     // IF XY is valid, means it is a key on the grid
  {
    MLOGD("Example", "Key %d %d %d", xy.x, xy.y, keyInfo->state); // Print the key event to the debug log
    if (keyInfo->state == PRESSED)            // Key is pressed
    {
      MatrixOS::LED::SetColor(xy, color, 0);      // Set the LED color to a color. Last 0 means writes to the active layer (255 writes to the active layer as well but do not trigger auto update.)
    }
    else if (keyInfo->state == RELEASED)
    {
      MatrixOS::LED::SetColor(xy, 0x000000, 0);  // Set the LED to off
    }
  }
  else                          // XY Not valid,
  {
    if (keyID == FUNCTION_KEY)  // FUNCTION_KEY is pre defined by the device, as the keyID for the system function key
    {
      UIMenu();                 // Open UI Menu
    }
  }
}

This is the KeyEventHandler() function of the application. It is called when there is a key event. It is used to handle the key event.

It sets the LED color of the key to the color variable when the key is pressed. It sets the LED color of the key to off when the key is released. It opens the UI menu when the function key is pressed.

You will get a keyID as the id of the key of the event, and a KeyInfo struct as the information of the key event. The KeyInfo struct contains the state of the key event (PRESSED, HOLD, AFTERTOUCH, RELEASED) and the value of the key event.

You can use the MatrixOS API KEYPAD::ID2XY(id) to get the XY coordination of the keyID. If the bool(xy) == false or xy == Point.Invalid(), then the keyID is not a key on the grid. (It's a key with ID only).

FUNCTION_KEY is an function key ID provided by device layer. In the case of Mystrix, it is the center key. All Mystrix OS device are required to have a FUNCTION_KEY or equivalent method of evoking it.


void ExampleAPP::MidiEventHandler(MidiPacket midiPacket) {
  MatrixOS::MIDI::Send(midiPacket);

  switch (midiPacket.status)
  {
    case NoteOn:
    case ControlChange:
      NoteHandler(midiPacket.channel(), midiPacket.note(), midiPacket.velocity());
      break;
    case NoteOff:
      NoteHandler(midiPacket.channel(), midiPacket.note(), 0);
      break;
    case SysExData:
    case SysExEnd:
      SysExHandler(midiPacket);
      break;
    default:
      break;
  }
}

This is the MidiEventHandler() function of the application. It is called when there is a MIDI event. It is used to handle the MIDI event.

First, it sends the MIDI packet back to the source. Then, it parses the MIDI packet and calls the corresponding handler function based on the status of the MIDI packet.

Each midi packet consists of:

  • port - Where the MIDI signal is from (See EMidiPortID in MidiPacket.h). It indicates where the MIDI signal is from (USB, Bluetooth, RTPMIDI, HWPort, etc). When sending MIDI packets, this is also where the MIDI signal will be sent to. In this case, if a midi is coming from USB and it will be send back to USB. If a midi is coming from Bluetooth, it will be send back to Bluetooth. You can also send to multiple source by setting the port to EMidiPortID::MIDI_PORT_EACH_CLASS (send to first of each port type) or EMidiPortID::MIDI_PORT_ALL (send to all ports).
  • status - The MIDI status (See EMidiStatus in MidiPacket.h). It indicates the type of the MIDI signal. In this case, it will call the NoteHandler() function if the status is NoteOn or ControlChange, and call the SysExHandler() function if the status is SysExData or SysExEnd.
  • data - 3 byte of data. Contents of this data depends on the status. For example, if the status is NoteOn, the first byte is the channel, the second byte is the note, and the third byte is the velocity.

There are also alternative names for each data bytes for different status type. Like channel, note, velocity, etc. You can access them by calling the function of the same name. See

The Matrix OS midi system is complex & powerful but very intuitive. You can read more details of Matrix OS midi system in Matrix OS MIDI API


void ExampleAPP::UIMenu() {
MLOGI("Example", "Enter UI Menu");

UI menu("UI Menu", Color(0x00FFFF), true);

UIButton numberSelector;
numberSelector.SetName("Number Selector");
numberSelector.SetColor(Color(0xFF0000));
numberSelector.OnPress([&]() -> void {
  number = MatrixOS::UIInterface::NumberSelector8x8(number, 0xFF0000, "Number", 0, 100);
});

menu.AddUIComponent(numberSelector, Point(0, 0));

UIButton colorSelector;
colorSelector.SetName("Color Selector");
colorSelector.SetColorFunc([&]() -> Color { return color; });
colorSelector.OnPress([&]() -> void {
  #ifndef EXAMPLEAPP_SAVED_VAR
  MatrixOS::UIInterface::ColorPicker(color);
  #else
  MatrixOS::UIInterface::ColorPicker(color.value);
  color.Set(color.value);
  #endif
});
colorSelector.OnHold([&]() -> void {
  color = 0xFFFFFF;
});

menu.AddUIComponent(colorSelector, Point(Device::x_size - 1, 0));

UIButton brightnessBtn;
brightnessBtn.SetName("Brightness");
brightnessBtn.SetColor(Color(0xFFFFFF));
brightnessBtn.SetSize(Dimension(2, 2));
brightnessBtn.OnPress([&]() -> void { MatrixOS::LED::NextBrightness(); });
brightnessBtn.OnHold([&]() -> void {BrightnessControl().Start(); });

menu.AllowExit(false);

menu.SetKeyEventHandler([&](KeyEvent* keyEvent) -> bool {
  if (keyEvent->id == FUNCTION_KEY)
  {
      if(keyEvent->info.state == HOLD)
      {
          Exit();
          return true;
      }
      else if(keyEvent->info.state == RELEASED)
      {
          menu.Exit();
          return true;
      }
  }
  return false;
});

menu.Start();

MLOGI("Example", "Exited UI Menu");
}

This is the UIMenu() function of the application. It is called when the function key is pressed. It is used to open the UI menu of the application.

It creates a UI object with the name "UI Menu" and the color 0x00FFFF. It creates a number selector button, a color selector button, and a brightness button. It sets the callback functions for the buttons and adds them to the UI object.

Finally after the UI object is fully set up, it starts the UI runtime to take over. The code will continue after the UI is exited. If the Exit() function is called in the UI, the code will start in the End() function of the application and then exit.

See the Matrix OS UI Framework for more details on how to create UIs and use the UI interface and elements.


void ExampleAPP::End() {
MLOGI("Example", "Example Exited");
}

This is the End() function of the application. It is called when the application is exited. It is used to clean up the application.

Add the Application to the OS​

To add the application to the OS, you need to add the application to the applications list in your device layer files. For Mystrix, the application list is the /devices/MatrixBlock6/Applications.h file.


#pragma once

// SYSTEM_APPLICATION
#include "applications/Shell/Shell.h"
#include "applications/Performance/Performance.h"
#include "applications/Note/Note.h"
#include "applications/REDACTED/REDACTED.h"
#include "applications/Companion/Companion.h"

// USER APPLICATION
#include "applications/Lighting/Lighting.h"
#include "applications/Dice/Dice.h"
#include "applications/Gamepad/Gamepad.h"
#include "applications/Example/Example.h" // <- Add your application here
#include "applications/Reversi/Reversi.h"

// BOOT ANIMATION
#include "applications/Mystrix/MystrixBoot/MystrixBoot.h"

// DEVICE APPLICATION
#include "applications/Mystrix/FactoryMenu/FactoryMenu.h"
#include "applications/Mystrix/ForceCalibration/ForceCalibration.h"

#define OS_SHELL APPID("203 Systems", "Shell")
#define DEFAULT_BOOTANIMATION APPID("203 Systems", "Mystrix Boot")

Add your application to the USER APPLICATION section of the file. Simply include the header file of your application. (In this case, it is "applications/Example/Example.h")

In the Matrix OS application launcher, the order of the applications in the list is the order they will be displayed in the UI. You can change the order of the applications by changing the order of the applications in the file.

Your Application as Submodule​

You can create your Application in it's own repository and include it as a submodule in the Matrix OS repository. This way, you can develop your application separately and different builds can include it as external module.

We are also working on standardized this process so you can easily include your application in the Matrix OS build system. We might also release an webapp that can help you create a Matrix OS build with different applications you want to include!

Things to Note​

  • Make sure all your variables are within the class. If you define them outside of the class, they will be global variables and the memory will not be managed by the OS. This will cause memory to be taken even if the application is not running.
  • If you use dynamic memory allocation, make sure to free the memory when the application is exiting. The OS can only recycle the static memory in the application stack, not the dynamic memory that you or your variables allocated.
  • If you used anything advanced, like threads, mutex, etc or hardware changes like peripheral configuration and start up. Make sure to clean them up or undo them when the application is exiting.

Comments