This operating system is designed for SINGLE CORE microcontrollers and uses the fixed-priority preemptive scheduling algorithm. Stated briefly as follows,
- The scheduler (tries to) makes sure that it runs the highest priority ready thread.
- A higher priority thread will always preempt one with a lower priority outside a critical section.
- If multiple highest-priority threads with the same priority exist, the CPU time will be shared between them.
- If a higher priority thread is waiting for a resource that is currently unavailable, the operating system will put it to sleep and run other threads until the resource becomes available or specified time-out has been reached. In both cases the thread will be readied and a reschedule will be triggered immediately.
This RTOS has not been fully evaluated for performance and reliability. It is licensed under MIT license which is free for commercial and open/private uses and does not require source code disclosure (under certain conditions stated in LICENSE). Before planning to use it, please see LICENSE.
If you believe you have found a bug, please consider reporting it in ISSUES so that a fix can be worked out and the software can be made more robust, although this is not required. If you decided to, include the following information as much as possible, after making sure to protect your private code and information:
- How to replicate the bug/how it is discovered
- Version affected (tag, git-describe, or commit ID)
- Version or versions known to be good (tag, git-describe, or commit ID)
- Dynamic thread creation and deletion
- Static thread creation and deletion using existing buffer (as RTOS module)
- Thread suspend/resume
- Dynamic priority
- Sleeping
- Yielding
- Critical section
- Dynamic memory allocation/deallocation using Next Fit
- Block/Pool/Thread memory statistics
- Dynamic creation and deletion
- Static creation and deletion using existing buffer (as RTOS module)
- Buffer reset (clear all data)
- Peek/Nonblocking peek (reading data without affecting the queue )
- Receive/Nonblocking receive (reading data)
- Send/Nonblocking send
- Send ahead/Nonblocking send ahead (sending high priority messages)
- Dynamic creation and deletion
- Static creation and deletion using existing buffer (as RTOS module)
- Peek mutex without affecting the lock status
- Lock/Nonblocking lock
- Unlock
- Lock status
- Dynamic creation and deletion
- Static creation and deletion using existing buffer (as RTOS module)
- Counter reset
- Post operation
- Wait/Nonblocking wait operations
- Peek/Nonbloking peek without affecting semaphore status
If you are using one of the following platforms, clone the corresponding repository
into a folder called mrtos-portable
, under the same directory as mrtos
, using the command
git clone <repository> mrtos-portable
Don't forget to add path mrtos-portable
to the compiler search path -Imrtos-portable
so that mRTOS can find the portable header file.
Supported platforms:
Clone the mrtos source code under your project using
git@github.com:jdoe95/mrtos.git
Create another folder under the project named mrtos-portable
, and then create the following files
under that folder
rtos_portable.h
rtos_portable.c
where rtos_portable.h
should contain the configurations and function prototypes and rtos_portable.c
will contain function bodies. It is important that you add the path to folder mrtos_portable
to the compiler include directory '-Imrtos_portable
', so that the RTOS source code can find the portable header.
Define the following macros in rtos_portable.h
-
OSPORT_BYTE_T
the byte type of the platform, usuallyuint8_t
instdint.h
-
OSPORT_UINT_T
an unsigned integer type, used for array indexing, timestamp, and priority. Usuallyuint16_t
oruint32_t
instdint.h
-
OSPORT_UINTPTR_T
an unsigned integer type, guaranteed to be able to hold an address, used foros_handle_t
, usually uintptr_t instdint.h
-
OSPORT_BOOL_T
a boolean type, usuallybool
instdbool.h
-
OSPORT_IDLE_STACK_SIZE
the stack size of the idle thread, usually the size of exactly one full stack frame. -
OSPORT_NUM_PRIOS
number of prorities. Use as few as possible. Usually 8. Prioirty 0 will be the highest priority and 6 will be the lowest priority. Priority 7 will be reserved for the idle thread. Do not create anything on this priority. -
OSPORT_MEM_ALIGN
the largest memory pool alignment requirement. On some platforms, it is required for certain data types to be aligned to a certain memory address, and unaligned access can generate faults in the CPU or cause performance issues. For example, some platforms require that 8-byte data to be aligned to a 1-byte address boundary, 16-bit data and 32-bit data to be aligned to a 4-byte boundary. For this case, the value will be 4, because it will be the largest alignment requirement. The memory pool is also used to allocate process stacks. -
OSPORT_MEM_SMALLEST
The smallest memory (number of bytes) allocated to a thread at a time. To minimize fragmentation, the OS will always allocate more memory than this value to a thread. -
OSPORT_ENABLE_DEBUG
Use 1 to enable the assertion macros. If you believe there's a bug in the operating system, turn this on to allow the OS to capture the bug before it causes a chain of errors. -
OSPORT_IDLE_FUNC
The function name of the idle function. It will be created as an idle thread. On most platforms this is simply a function that executes an empty, dead loop. Sometimes, it is desirable to put the CPU to sleep in the IDLE function, done by using platform-dependent methods. -
OSPORT_START()
The function that clears the main stack context and sets up the CPU in a certain mode and loads the first thread. -
OSPORT_INIT_STACK()
The function that initializes the process stack so that it contain the initial stack frame (called a fake context) to be loaded onto the CPU. -
OSPORT_BREAKPOINT()
The breakpoint function that halts the debugger. Only used whenOSPORT_ENABLE_DEBUG
. If not defined, it will be replaced by a dead loop. -
OSPORT_DISABLE_INT()
The function that disables the interrupt. -
OSPORT_ENABLE_INT()
The function that enables the interrupt. -
OSPORT_CONTEXTSW_REQ()
The function that generates a context switch request. Usually the context switcher is implemented as the lowest priority interrupt.
In rtos_portable.c
you should have
- Functions declared in
rtos_portable.h
- A context switcher implemented as the lowest priority interrupt.
- A timer interrupt that calls
os_handle_heartbeat()
periodically after the operating system starts.