User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
user:embedded_c_code_doesn_t_have_to_be_ugly [2020/05/11 16:41] – [1. Use *YOUR* favorite IDE] Igor Yefmovuser:embedded_c_code_doesn_t_have_to_be_ugly [2020/05/11 17:18] – [4. Bit manipulations vs. structured data] Igor Yefmov
Line 98: Line 98:
  
 ==== 4. Bit manipulations vs. structured data ==== ==== 4. Bit manipulations vs. structured data ====
 +Working with the low-level code((which is, basically, pretty much all the embedded code)) quite often requires direct bit manipulation. And as much as every ''C'' programmer is familiar and is comfortable with bit operations in the language, using those results in the ugliest code - it is unnecessarily verbose, prone to errors((operator precedence is often to blame)), makes the code that much harder to port((little- vs. big-endian porting, anyone?)).
 +
 +Here's a more concrete example: working with 16/32 bit integers, where depending on the context it is either a CPU-addressable word, or a stream of bytes on the wire (be it USB or I²C). Traditionally that would result in the 1970's style code like this:
 +<code C>uint32_t = pageAddress * glSpiPageSize;
 +uint8_t location[4];
 +location[1] = (byteAddress >> 16) & 0xFF; /* MS byte */
 +location[2] = (byteAddress >> 8) & 0xFF;
 +location[3] = byteAddress & 0xFF; /* LS byte */
 +</code>
 +
 +Do you see an **obvious bug** in that code((yes, this is what was in the code! An uninitialized first byte of the ''location'' buffer))?
 +
 +Here's a much more modernized version of this, which also (automagically!!!) takes care of that idiotic bug:
 +<code C>typedef union PackedUint16{
 +    uint16_t v;
 +    struct{ uint8_t l, h; };
 +    uint8_t a[2];
 +} PackedUint16;
 +typedef union PackedInt16{
 +    int16_t v;
 +    struct{ uint8_t l, h; };
 +    uint8_t a[2];
 +} PackedInt16;
 +typedef union PackedUint32{
 +    uint32_t v;
 +    struct{ PackedUint16 l, h; };
 +    uint8_t a[4];
 +} PackedUint32;
 +
 +///////////////////////////////////
 +
 +PackedUint32 byteAddress = {pageAddress * glSpiPageSize};
 +uint8_t location[4] = {};      /* uninitialized memory is evil */
 +location[1] = byteAddress.h.l; /* compiler error, of course - must be PackedUint32, not 16 */
 +location[2] = byteAddress.l.h;
 +location[3] = byteAddress.l.l; /* LS byte */
 +
 +/* alternatively the code above can be written much more to-the-point, clearly expressing the intent  */
 +const uint8_t * const location_arr = pageAddress.a;</code>
 +
  
 ==== 5. Globals ==== ==== 5. Globals ====

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information