{"id":15136990,"url":"https://github.com/m-spiessens/flow","last_synced_at":"2025-09-29T06:31:04.523Z","repository":{"id":144186668,"uuid":"76965390","full_name":"m-spiessens/Flow","owner":"m-spiessens","description":"Cooperative scheduler for low-power, reactive applications using the \"pipes and filters\" pattern on ARM Cortex-M microcontrollers.","archived":true,"fork":false,"pushed_at":"2021-02-12T20:24:46.000Z","size":392,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"dev","last_synced_at":"2024-09-27T06:42:29.363Z","etag":null,"topics":["arm","conan","cooperative","cortex-m","cpp","filter","flow","low-power","microcontroller","pipe","reactive","scheduler","tests"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m-spiessens.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2016-12-20T14:54:59.000Z","updated_at":"2023-01-28T09:59:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"7c7c9e35-6370-4572-b34a-8df505f6d810","html_url":"https://github.com/m-spiessens/Flow","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-spiessens%2FFlow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-spiessens%2FFlow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-spiessens%2FFlow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m-spiessens%2FFlow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m-spiessens","download_url":"https://codeload.github.com/m-spiessens/Flow/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234597573,"owners_count":18857980,"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":["arm","conan","cooperative","cortex-m","cpp","filter","flow","low-power","microcontroller","pipe","reactive","scheduler","tests"],"created_at":"2024-09-26T06:42:31.435Z","updated_at":"2025-09-29T06:30:59.175Z","avatar_url":"https://github.com/m-spiessens.png","language":"C++","readme":"# MIGRATION NOTICE\n\n[2021-02-12 Flow moved to GitLab!](https://gitlab.com/m-spiessens/Flow)\n\n# Flow {#mainpage}\n\n[![Build Status](https://travis-ci.com/CynaraKrewe/Flow.svg?branch=master)](https://travis-ci.com/CynaraKrewe/Flow)\n[![Coverage Status](https://coveralls.io/repos/github/CynaraKrewe/Flow/badge.svg?branch=master)](https://coveralls.io/github/CynaraKrewe/Flow?branch=master)\n\n[We have conan packages!](https://gitlab.com/m-spiessens/spiessensm/-/packages)\n\nFlow is a pipes and filters implementation tailored for (but not exclusive to) ARM Cortex-M microcontrollers. It provides 3 concepts: component, port and connection.\nA minimal cooperative scheduler helps you build low-power, reactive applications with ease.\n\n## Concepts\n\n### Component\n\nA component provides application functionality, it is a filter from the pipes and filters design pattern. A component implements the ```Flow::Component``` interface and the resulting ```void run()``` method defines it's complete behavior.\n\n### Port\n\nA component can have in- and/or output port(s). A typical component will receive data from its input port(s), process data and send data to its output port(s). Flow provides ```Flow::InPort\u003cDataType\u003e``` and ```Flow::OutPort\u003cDataType\u003e``` templates to support every possible datatype.\n\n### Connection\n\nConnections are pipes from the pipes and filters design pattern. An output port can be connected to an input port. A connection can behave as a queue, allowing multiple data element to be buffered. One output port can be connected to one input port, one-to-many or many-to-one connections are not supported. One-to-many or many-to-one can achieved by using components that implement split/tee or zip/combine behavior for example. Connections are perfectly safe from race conditions when the connected components run concurrently.\n\n## Reactive\n\nSystems using microcontrollers are typically reactive systems, they respond to events.\nThat is were the Flow::Reactor comes in to play.\nThe idea is to define a reaction to an event by making a pipeline of multiple Flow::Component.\nThe head (first Flow::Component) of the pipeline will run in interrupt context (an event).\nThe head sends data to the second component in the pipeline over a (concurrency safe) Flow::Connection.\nWhich will schedule the second component to be run by the Flow::Reactor when possible.\nAll components except for the head will be handled by the Flow::Reactor and be executed in main() context, keeping the interrupt service routines short.\n\nAfter the complete pipeline was run and no other events need to be serviced, the Flow::Reactor will execute the Flow::Platform::waitForEvent() function.\nThe implementation of this function can be freely defined.\nOn low power Cortex-M3 or -M4 based system the WFE (wait for event) instruction can be executed.\nDepending on the configuration the microcontroller will go into sleep mode untill it is woken up by the next event (interrupt) to which it will respond.\n\n### Conclusion\n\nGiven that all pipelines are triggered by events (head component in interrupt service routine), the Flow::Reactor provides a convenient mechanism to build a low power enabled, reactive system.\n\n### Scheduling\n\nThe Flow::Reactor is a cooperative scheduler. Except for the head component of a pipeline, which runs in interrupt context, there is no preemption.\n\nThe current scheduling strategy is a simple round robin. \n\nPriority could be introduced by changing the Flow::Reactor::run() implementation. After finding a Flow::Component that had to be run (and running it) the reactor continues in the list. If the reactor would start from the start of the list after running a component, the order in which Flow::Components are created will define their priority for scheduling. This way different data paths could have different priorities. \n\nA few different strategies might be a future extension.\n\n## Example\n\n### Blinky\n\nBlinky is a minimal example application that performs blinking of a LED. It runs on a [EK-TM4CEXL launchpad](http://www.ti.com/tool/EK-TM4C129EXL) with cooperative scheduling.\n\nBlinky is composed of 3 components: a timer, toggling and a digital output. The timer will generate a tick every configured period. The toggling will consume the tick and invert an internal boolean value. The boolean value is sent to the digital output, which has a LED attached.\n\nFirst of all the three components are created (these implement the ```Flow::Component``` interface):\n\n```cpp\n// Create the components of the application.\nTimer timer{100 /*ms*/};\nToggle toggle;\nDigital::Output led{Pin::Port::N, 1, Digital::Polarity::Normal};\n\n```\n\nThe components (actually the ports of the components) are connected so they can interact:\n\n```cpp\n// Connect the components of the application.\nFlow::connect(timer.outTick, toggle.tick);\nFlow::connect(toggle.out, led.inState);\n```\n\nStart the Flow::Reactor and have it schedule the components: \n\n```cpp\nFlow::Reactor::start();\n\n// Run the application.\nwhile(true)\n{\n\tFlow::Reactor::run();\n}\n```\nThe full example can be found at [FlowBlinky](https://github.com/CynaraKrewe/FlowBlinky).\nA more complex example with PWM, UART, USB and ADC can be found at [FlowTM4C](https://github.com/CynaraKrewe/FlowTM4C).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-spiessens%2Fflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm-spiessens%2Fflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm-spiessens%2Fflow/lists"}