5 ms·
Choosing between bitfields and masks for register twiddling was something I looked into deeply. Like the article, I wanted the readability of bitfields, but aft
by stevenhuang 8y ago
Choosing between bitfields and masks for register twiddling was something I looked into deeply. Like the article, I wanted the readability of bitfields, but after reading about all the pitfalls and how loosely bitfields specs were defined in the C89 standard, I decided to go with masks instead.
Here was a great summary I found from a comment explaining the dangers of bitfields.
Seeing it spelled out like this made it clear which to choose, lest you're a fan of nasal demons :).
"The royal mistake is to use bit fields in the first place. The following is not specified by the standard:
– whether bit field int is treated as signed or unsigned int
– the bit order (lsb is where?)
– whether the bit field can reach past the memory alignment of the CPU or not
– the alignment of non-bit field members of the struct
– the memory alignment of bit fields (to the left or to the right?)
– the endianess of bit fields larger than one byte
– whether plain int values assigned to them are interpreted as signed or unsigned
– how bit fields are promoted implicitly by the integer promotions
– whether signed bit fields are one’s compliment or two’s compliment
– padding bytes
– padding bits
– values of padding bits.
– and so on."
Source: https://embeddedgurus.com/stack-overflow/2009/10/effective-c-tip-6-creating-a-flags-variable/#comment-2390 https://embeddedgurus.com/stack-overflow/2009/10/effective-c...
- stinos 8y agoSo do I understand it correctly that you are saying the OP's code (or e.g. the one like in AceJohnny2) is not guaranteed to work correctly according to C89? Any idea about C99?
- Gibbon1 8y agoMy thoughts Probably will work with a specific compiler. If it fails it'll likely fall on it's face fail. Which with embedded is the best type of failure. Also you probably can force the behavior you need with pragma's (not portable) Portability is usually completely unimportant in embedded. C89 just don't. C++ in embedded. Lord god no, if you want to do that use rust instead. Or embedded python or lua, anything but C++.
- pjmlp 8y ago> C++ in embedded. Lord god no, if you want to do that use rust instead. Or embedded python or lua, anything but C++. First Rust needs to reach C++'s tooling maturity on embedded space. When there is High Integrity Rust certification, compiler backends for all major CPUs, SDK support on OSes like INTEGRITY or Mbed, UI embedded tooling for IoT displays, maybe we can start seeing production code there.
- Gibbon1 8y ago> First Rust needs to reach C++'s tooling maturity on embedded space. Yeah and that's soon. Anyone starting an embedded project in C++ is making a grave mistake. > Mbed Those guys make a bad mistake and will pay for it.
- pjmlp 8y agoTouching C is an even bigger one. It took C++ about 20 years to reach maturity in this space, with help of several OS and compiler vendors. You might be willing to bet the house on Rust, most business aren't, not in the current state of its toolchain. In 10 years from now, yeah I can clearly see it.
- v_lisivka 8y agoI use Rust for embedded right now. Part of project is in C, part is in C++, part is in Rust. NRF52 and i.MX6. Can you point me to the problem with Rust or toolchain, which I missed, so I will be aware? Thank you in advance.
- pjmlp 8y agoSome ideas: - LLVM backend is limited regarding the supported CPU architectures; - Rust compiler is not certified for high integrity domains, where human lives might be endangered; - Features like SIMD are still nightly - Lack of integration with closed source toolchains from OEMs for mixed debugging and other development workflows, e.g. Keil, Microchip These issues might be complete irrelevant, or showstoppers, depending on the company.
- alxlaz 8y agoEssentially yes. It's the same in C99, too. There's a bit of nuance here though. The function that the author chose to reimplement provides the platform-specific implementation of a function that's actually specified as part of CMSIS (https://developer.arm.com/embedded/cmsis https://developer.arm.com/embedded/cmsis). Its portability across cores and MCUs is not much of an issue, and you're usually tied to the compilers in this sort of projects, too. So it's not necessarily a bad idea from a purely technical standpoint. That being said: - No one who writes embedded software for a living expects to see bitfields in their source tree. In fact, there are standards that this code would break (e.g. in CERT C: https://wiki.sei.cmu.edu/confluence/display/c/EXP11-C.+Do+not+make+assumptions+regarding+the+layout+of+structures+with+bit-fields https://wiki.sei.cmu.edu/confluence/display/c/EXP11-C.+Do+no... ), so it wouldn't even get well through code review. It's a bad idea to surprise your coworkers :-). - Implementation-defined behaviour can sometimes be surprising and non-uniform. More often than not, the distinction between "bug" and "implementation-specific" is very blurry, and the corner cases are very hard to catch. You may think you're OK because your code doesn't need to be portable and it works fine on your device, but then it turns out the memory alignment of bit fields varies with field size because of course it does. - Precisely because of their infrequent use, the implementation of bit fields is one of the things that vendors often get wrong in early versions of a toolchain. At best, it's just a matter of inefficient access. At worst, it's bugs. And if you think that can't possibly go wrong, let me tell you about that time when an early version of msp430-gcc translated access to volatile variables into a NOP. (Disclaimer: that was a long time ago, on an early port. The MSP430 port of GCC is actually very solid.) So basically, just don't. Don't. There are well-known idioms for bit access. They are not readable as in "someone who knows English can read those programs just fine" but it takes like two minutes to understand those idioms. They are very readable, as in "anyone who's ever made a LED blink understands them". Yes, it's domain-specific knowledge, but you're already twiddling bits on tiny machines in a language that's not English. You're already full of domain-specific knowledge. Edit: ah -- just to make sure this doesn't get interpreted the wrong way. IMHO, C++ in embedded systems is not a bad idea. I don't use it because I've never worked on a project where I needed it, and therefore I never got the chance to be proficient with it. But I've seen solid, reliable devices running (what, to my untrained eye, seemed like) very clean, debugable C++ code. Also, "embedded" refers primarily to purpose, not platform capabilities. There are plenty of embedded platforms running on eight-core Xeons and state-of-the-art DSPs and whatnot. It's not all tiny MCUs with 4K of RAM and no MMU.