Home > On-Demand Archives > Q&A Sessions >
Live Q&A - The Quest for Simplicity
Henk Muller - XMOS - Watch Now - EOC 2022 - Duration: 20:24
Henk - your ideas about simplicity are a really important contribution to the embedded embedded community - they still keep me thinking days after the talk. Proper SW-Engineering is in everybody's focus and the various talks in this conference provide ample reasons. BUT, as you point out - those benefits are not for free (technically speaking)! Thanks for taking position and advocating this! And I really like the challenging stile - it creates a nice contrast to "that's just the way it proper SW-Engineering tells us things to do". Engineering is about finding the sweet spot of making the "right" compromises to meet the project target within the given constraints - sticking dogmatically to best practice might not always lead us to the best path. You are providing a further Thought-Tool to challenging those on the hunt for the appropriate technical solution! Really looking forward to more of your ideas! Thanks a lot! Andreas
Thanks for the kind words - glad it made you think. Discussions like this provide food for thought for me as well - both when creating the talk and in the discussions afterwards. I appreciate your and other people's feedback
@Max: The book "Hacker's delight" is a very interesting tipp regarding this topic - I had a brief look at it and ordered it right away. I just add it in the comment to make it easy accessible - Link to a wikipedia page: https://en.wikipedia.org/w/index.php?title=Hacker%27s_Delight&oldid=1063402410
It reminds me of code I found in the Linux Kernel - Another good inspirational source for efficient code ! Just the last couple days I needed a circular buffer and found interesting, efficient, code in the kernel sources: Here an example ...
/ Return space available, 0..size-1. We always leave one free char
as a completely full buffer has head == tail, which is the same as
empty. /
define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size))
/ Return count up to the end of the buffer. Carefully avoid
accessing head and tail more than once, so they can change
underneath us without returning inconsistent results. /
define CIRC_CNT_TO_END(head,tail,size) \
({int end = (size) - (tail); \
int n = ((head) + end) & ((size)-1); \
n < end ? n : end;})
...
- Source: https://github.com/torvalds/linux/blob/master/include/linux/circ_buf.h
- Documentation: https://www.kernel.org/doc/html/latest/core-api/circular-buffers.html
Another interesting thing to look at is the Linux-Scheduler source ... since those lines are being executed a bit more often per second :-)
What's your view on the future of new programming languages like Rust, which have been designed with a focus on safety, in solving the issues you just pointed out in C and C++ in the embedded field? (In particular the lack of constraint in what you can do)
I think rust is a great development and looking actively into it. The big question is whether everybody else will think so too - the strength of C and C++ is the vast number of people who use it, not the "quality" of the language (I accept that this is a very wooly statement). If rust gets critical mass that would be seismic in a positive way.
Noobie Question: Does working with Ada bypass all the problems mentioned in the session?
Hah! That takes us back a while. It does resolve some of the problems, but ADA, if I remember correctly, has a rather baroque exception handling mechanism so that may add a large chunk to your memory footprint
Thanks for the talk Henk. The most important phrase for me --> Making small programs is hard... I fight with it all the time... FLASH or SRAM restrictions using FreeRTOS and TI-RTOS... And sometimes solve that is very complicated... and the time to market press on the developer... I always build generic C functions... however your advise to create specialization code version is more appropriate in many cases... interesting ideas to think about exceptions too.... Thanks
Building generic C functions is definitely the answer to fast time to market; but as you say it may blow your budget!
You're right... Thanks for all advises
Henk,
Thanks for the insightful presentation.
Would you have any recommendations when it comes to quantifying the memory requirements for a system that is at an early stage of design? Would all the software dependencies and build tools have be known with relatively high accuracy at that point to ascertain a good enough estimate?
In the slide of specialisation as an answer to generic code, is the specialisation achieved solely by the compiler? Could you expand briefly on how the specialisation approach would look in practical terms, e.g. the library implementation leveraging a polymorphic interface (?).
Indeed, you will have to have a reasonable grasp of all the bits that you are going to need for the design. Indeed, I find this a valuable first stage of the design:what bits are there and what resources do they need? Accuracy is not an enormous issue typically, with the proviso that if you don't know how much data, for example, a filter needs that that unknown will persist all the way.
About specialisation: it is typically compiler and linker; I often, incorrectly, label the whole tool-chain a compiler, but you have to build a full call-graph before you can specialise efficiently. Some toolchains choose to only specialise if the number of specialisations created is small (eg, never more than 2), other toolchains can be more brutal.
Specialisation can help get rid of polymorphism, but polymorphism is not a requirement for specialisation.
Thanks for this very informative summary on the problems you have to deal with on emedded systems.
You mentioned that it's a good idea to deal with errors an not to pass the bug. But isn't this (especially for libraries) not always a problem to decide?
I think of a current problem I'm facing with a communication protocol implementation (written as a library) which is used on many differnt devices from very small embedded processors up to powerful processors running an embedded Linux. On a Linux machine the communication protocol runs as a user process which you can safely terminate and restart on an error without affecting the rest of the system. On the embedded component the only possible way to handle the same error could be to do a reset which will break all the other functionalities the component does beside communication.
I mean that in such cases it's up to the application that uses the library to know what the "correct" error handling would be and therefore the library must pass the bug to give the user the ability to decide?
Or did I misunderstood something?
Hi Erwin - you are absolutely right. It will matter very much in what sort of company you work, whether you got to pass the buck or whether the library can deal with the error.
If the company delivers Linux device drivers as a product, then there is no way that you can deal with the error other than reporting it to the caller; you cannot second guess what the caller is going to do.
However, if you work in a company where you are making a communication driver and one of your colleagues is writing the software that deals with the error (maybe in another building), then it may be worthwhile to shortcut the spec, and still create a generic library that is useful for different cars, but it is going to report a communication error at a low level in a more direct manner.