We partner with companies to create embedded systems of outstanding quality, reliability, and maintainabilty. Our engineering approach gives our clients complete transparency and high levels of confidence in the code, and on progress.
We work test-driven at all times, and in small increments. This cycle gives us feedback on the design, lets us safely refactor code as we go along. A typical development involves multiple forms of test-driven activity:
Behaviour-Driven Development specifications are the driver that lets us capture requirements with clients, and agree the specifications and scenarios. These tests runs on the target device on evaluation hardware.
Classic “Red-Green-Refactor” TDD gives us feedback on design, and builds a suite of fine-grained, highly-specific unit tests.
Integration tests run on the target device for scenarios where interaction with peripheral hardware is needed.
Along with tests focused on requirements and design, and depending on the nature of the requirements, we also write fuzz tests to help verify security at trust boundaries, and benchmarks of performance-critical code sections.
We leverage the investment we’ve made in the tests to run instrumentation on the build, further building confidence in the code correctness.
With our CI build pipelines, you see everything that we do - the CI build is the exact same configuration we run on our own workstations as we code. We also share with clients all of the CI build and container configuration, and help them to set up the build locally or on their own cloud infrastructure for independent verification.
We run every commit though our CI build. This runs on developer workstations as well as in a shared cloud-based build, and gives us a high level of confidence of the code quality. Configuration varies for the needs of the project, but a typical setup is shown above. You can read more about our approach in our blog series on CI for C++.
With the CI build doing the heavy lifting for us, we also test, profile, and capture instrumentation telemetry on the target device, typically on evaluation boards or custom-designed hardware test harnesses. This isn’t a “quality phase”, but an activity that’s baked-in as part of every increment.
Our experience has shown that this blend of micro-incremental TDD test idioms, dynamic instrumentation, quality checks, and profile/telemetry goes a long way to minimising the technical risks to successful delivery of complex embedded systems requirements.
We focus exclusively on languages, platforms and technical domains where were can add the most value. For embedded systems development, our “happy zone” is development in modern, idiomatic C++ on:
We also undertake any any general GNU/Linux C++ development work in on AMD64 or other processor architectures. We have recent experience also of developing cross-platform C++ libraries for integration to Android and iOS applications.
You can reach us via email or phone, and we're always happy to meet in person to talk through any ideas or requirements you have:
Unit 8 Deer Park
Fairways Business Park Livingston EH54 8GA
+ 44 (0)1506 343015