{"id":16723892,"url":"https://github.com/korken89/crect","last_synced_at":"2025-03-17T01:31:26.869Z","repository":{"id":145373359,"uuid":"85500756","full_name":"korken89/crect","owner":"korken89","description":"A C++, compile-time, reactive RTOS for the Stack Resource Policy based Real-Time For the Masses kernel","archived":false,"fork":false,"pushed_at":"2018-09-07T11:43:47.000Z","size":380,"stargazers_count":192,"open_issues_count":11,"forks_count":21,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-03-16T07:05:02.507Z","etag":null,"topics":["compile-time","cortex-m","deadlock-free","reactive-programming","rtos"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/korken89.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-19T18:57:15.000Z","updated_at":"2025-03-01T14:36:43.000Z","dependencies_parsed_at":"2023-04-17T07:37:37.059Z","dependency_job_id":null,"html_url":"https://github.com/korken89/crect","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korken89%2Fcrect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korken89%2Fcrect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korken89%2Fcrect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/korken89%2Fcrect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/korken89","download_url":"https://codeload.github.com/korken89/crect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243958274,"owners_count":20374834,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compile-time","cortex-m","deadlock-free","reactive-programming","rtos"],"created_at":"2024-10-12T22:39:56.604Z","updated_at":"2025-03-17T01:31:26.857Z","avatar_url":"https://github.com/korken89.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crect: A C++, compile-time, reactive RTOS\n\n**crect** (pronounced _correct_) is a C++ library for generating a\nscheduler (_at compile time_) for Cortex-M series MCUs, which\n**_guarantees_** dead-lock free and data-race free execution.\nIt utilizes the Nested Vector Interrupt Controller (NVIC) in Cortex-M\nprocessors to implement a Stack Resource Policy (SRP) based scheduler.\nThanks to the compile time creation of the scheduler, the resource\nrequirements at run-time are minimal with:\n\n**Initialization:**\n\n* 4-5 instructions / job for initialization of the NVIC.\n* 2-3 instructions / queue element for initializing the `async` queue.\n* The static requirement for `async` is about 400 bytes (the linked list, SysTick and time implementation).\n\n**Compile time:**\n\n* Uses the Kvasir MPL library for metaprogramming.\n\n**Runtime:**\n\n* 3-4 instructions + 4 bytes of stack for a `lock`.\n* 1-3 instructions for an (implicit) unlock.\n* `claim` has zero overhead, it decomposes into a `lock`.\n* 5 instructions for a `unique_lock` (will change).\n* 2 instructions for a `unique_unlock` (will change).\n* 2-4 instructions for `pend` / `clear`.\n* About 20-30 instructions * number of items in queue for `async`.\n\nIn this scheduler, heavy use of C++ metaprogramming and C++14 allows,\namong other things, priority ceilings and interrupt masks to be\nautomatically calculated at compile time, while resource locks are\nhandled through RAII and resource access is handled via a monitor\npattern. This minimizes user error without the need for an external\nextra compile step, as is currently being investigated in the\n[RTFM-core language](http://www.rtfm-lang.org/).\n\n## Videos / tutorials\n\nYouTube video from [embo++ 2018](https://www.embo.io/) describing the inner workings of **crect**: https://www.youtube.com/watch?v=SBij9W9GfBw\n\n## Give it a test\n\nIn the `example` folder a few example projects are setup for the NUCLEO-F411RE board. For example:\n\n* A program that will blink a LED every one seconds using `crect` primitives.\n* An example for how to use `unique_lock` with a data pumping peripheral (for example DMA or a communication interface).\n\nIt also contains examples of `crect_system_config.hpp` and `crect_user_config.hpp`, providing references until a documentation is available.\n\nIf there are any questions on the usage, throw me a message.\n\n_Tested on Ubuntu Linux using GCC 6.3.1 (arm-none-eabi) and a NUCLEO-F411RE for hardware testing. It is currently not working on Cortex-M0 devices._\n\n## License\nBoost Software License - Version 1.0\n\n## Contributors\n\nList of contributors in alphabetical order:\n\n* [Emil Fresk](https://www.github.com/korken89)\n* [Odin Holmes](https://www.github.com/odinthenerd)\n* [Carlos van Rooijen](https://www.github.com/CvRXX)\n\n## References\n\ncrect is based on the following academic papers:\n\n* T.P. Baker, **\"A Stack-Based Resource Allocation Policy for Realtime Processes\"**, (general theory of SRP)\n* Johan Eriksson et. al., **\"Real-Time For the Masses, Step 1: Programming API and Static Priority SRP Kernel Primitives\"**, (SRP primitives)\n* Per Lindgren et. al., **\"Abstract Timers and their Implementation onto the ARM Cortex-M family of MCUs\"**, (async idea)\n\n## Definitions\n**Job:**\n\n* A function that runs to completion in a finite time (no forever loop),\n not as a \"normal\" thread that has a forever loop.\n* Has a settable priority which indicates the urgency of the Job.\n\n**Resource:**\n\n* An entity symbolizing something lockable, _i.e._ any locked Resource may\nonly be accessed by a single Job at a time.\n\n**Lock:**\n\n* A lock on a resource keeps other jobs, that will also take said resource,\nfrom running through manipulation of the systems NVIC/basepri settings. A lock\ncan only be held within a job and must be released before the exit of a job.\n\n---\n\n## Usage\n\nSmall description on how to use this.\n\n#### Resource definition\nA resource definition is as follows:\n```C++\nusing Rled = crect::make_resource\u003c\n    CRECT_OBJECT_LINK(led_resource)  // Link to some object to be protected\n  \u003e;\n```\nCurrently 2 system resources exists:\n\n1. The access to the `async_queue` is protected via `crect::Rasync`.\n2. For getting the current time via `crect::clock::system::now()` is protected\nvia `crect::Rsystem_clock` - see **claim** for example usage.\n\nAny job **using these resources** need to have the corresponding resource **in its resource claim** in `crect_user_config.hpp`.\n\n#### Job definition\nA job definition consists of a few parts:\n  1. The priority of the Job, from 0 meaning low, to max_priority meaning max.\n  2. An ISR the Job is connected to (peripheral ISRs, 0 is the lowest, negative numbers are the system ISRs). If it is not connected to any, take any random ISR number for now, in the future this will be automatic.\n  3. The list of resources that the Job may claim.\n\nThe Job definitions are placed (directly or via include) in `crect_user_config.hpp`.\n```C++\nvoid job1(void);\nusing J1 = crect::job\u003c\n              1,                          // Priority (0 = low)\n              crect::make_isr\u003cjob1, 1\u003e,    // ISR connection and location\n              R1, crect::Rasync            // List of possible resource claims\n            \u003e;\n```\nEach job need to be added to the `user_job_list\u003c Jobs... \u003e` in `crect_user_config.hpp`.\n\n#### ISR definition\nThe ISR definitions available are split in the Peripheral ISRs (I \u003e= 0), and System ISRs (I \u003c 0).\n```C++\n// Peripheral ISR definition (I \u003e= 0)\ntemplate \u003ccrect::details::isr_function_pointer\u003cP, int I\u003e\nusing make_isr = crect::details::isr\u003cP, crect::details::index\u003cI\u003e\u003e;\n\n// System ISR definition (I \u003c 0)\ntemplate \u003cint I\u003e\nusing make_system_isr = crect::details::isr\u003cnullptr, crect::details::index\u003cI\u003e\u003e;\n```\n\n#### lock\nA lock keeps the system from running a job which will lock the same resource.\nThe analysis to determine which job can take which resource is done at\ncompile-time, which makes the lock very cheap to use as indicated at the start\nof this document. Lock should however be **avoided** by the user, use **claim**\nwherever possible.\n\n```C++\n// Lock the resource, remember locks are very cheap -- sprinkle them everywhere!\ncrect::lock\u003c R1 \u003e lock; // Locks are made in the constructor of the lock\n// ...\n// Unlock is automatic in the destructor of lock\n```\n\nThere is no `unlock`, this is by design.\n\n#### claim\nEven with **lock**, it is easy to leak a resource, and to minimize this chance\n`claim` uses a _Monitor Pattern_ to guard the resource. Hence the resource is\nonly available within the lambda of `claim`:\n```C++\n// Access the LED resource through the claim following a monitor pattern (just as cheap as a lock)\ncrect::claim\u003cRled\u003e([](auto \u0026led){\n  led.enable();\n});\n```\n\nTo guarantee the lock for resources with a return works just as good with `claim` (for\nexample when getting the current time, as the system time is a shared resource):\n```C++\n// Resource is handled within the claim, no risk of a data-race.\nauto current_time = crect::claim\u003ccrect::Rsystem_clock\u003e([](auto \u0026now){\n  return now(); // now is a function reference\n});\n```\n\nFor a full example please see `./examples/blinky`.\n\n#### unique_lock\nAdd a unique resource and its corresponding lock is to support lock over job\nboundaries. This allows for\nproducer/consumer patterns as the unique job can work by reading a queue of\nactions. _Ex._ a DMA, where jobs push to a \"DMA transfer queue\",\nand the job which has the unique DMA resource will read this queue and\nperform the desired transactions.\n\nA `unique_lock` effectively decomposes into disabling the interrupt vector of\nthe job, while the `unique_unlock` re-enables the interrupt vector.\n\nFor a full example please see `./examples/unique`.\n\n```C++\n```\n\nThere is no `unlock`, this is by design.\n#### pend / clear\n`pend` directly sets a job for execution and will be as soon as its priority is the highest, while `clear` removes the job for execution.\n```C++\n// Compile time constant pend/clear\ncrect::pend\u003cJobToPend\u003e();\ncrect::clear\u003cJobToPend\u003e();\n\n// Runtime dependent pend/clear\ncrect::pend(JobToPend_ISR_ID);\ncrect::clear(JobToPend_ISR_ID);\n```\n\n#### async\nAsync defers a jobs execution to some specific time.\n```C++\n// Using chrono to relate the system to time, the current max time is somewhere around 1500 years, depending on MCU :)\nusing namespace std::chrono_literals;\n\n// Async in some specific duration using chrono\ncrect::async\u003cJobToPend\u003e(100ms);\n\n// Async in some specific time using a specific time\nauto time_to_execute = some_duration + crect::claim\u003ccrect::Rsystem_clock\u003e([](auto \u0026now){\n  return now();\n});\ncrect::async\u003cJobToPend\u003e(time_to_execute);\n\n// Async can be used as pend for runtime dependent execution\ncrect::async(100ms, JobToPend_ISR_ID);\ncrect::async(time_to_execute, JobToPend_ISR_ID);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkorken89%2Fcrect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkorken89%2Fcrect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkorken89%2Fcrect/lists"}