• AVR Freaks

Hot!Bitfields: To Use Or Not To Use. That is the question.

Page: 12 > Showing page 1 of 2
Author
acharnley
Super Member
  • Total Posts : 315
  • Reward points : 0
  • Joined: 2016/05/01 06:51:28
  • Location: 0
  • Status: offline
2019/04/13 02:14:22 (permalink)
0

Bitfields: To Use Or Not To Use. That is the question.

I like the idea of bitfields, it looks efficient and encapsulated. I ran a small test to see what improvement would yield...


 
volatile static struct {
uint8_t futureLED: 3;
uint8_t activeLED: 3;
} flags;
 
#define futureLED flags.futureLED
#define activeLED flags.activeLED
 

 
-vs-
 

volatile static uint8_t futureLED;
volatile static uint8_t activeLED;
 

 
As expected I save one byte of data (a 0.16% improvement), but program logic increased by 54 bytes (a 0.33% decrement). I assume that's in masking out the value so the more times the value is used the more program usage will take a hit.

Therefore if data isn't a problem (I'm at 59% data and 76% program) is it wise to give the CPU less work and only introduce bitfields when one believes, or knows, that they're running short on data space?
#1

26 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 02:38:17 (permalink)
    +1 (1)
    acharnley
    Therefore if data isn't a problem (I'm at 59% data and 76% program) is it wise to give the CPU less work and only introduce bitfields when one believes, or knows, that they're running short on data space?

    If your only aim was to reduce storage space, I think your summary is good.
     

    Nearly there...
    #2
    Mysil
    Super Member
    • Total Posts : 3326
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 03:25:43 (permalink)
    +2 (2)
    Hi,
    Bitfields are used a lot by the device support header file <xc.h>, to pick apart and combine SFR register fields.
     
    8 bit PIC devices have efficient instructions to handle single bit operations,
    and XC8 is usually clever in using bit instructions for single bit fields.
    3 bit fields and larger, require more work to load a mask and perform a logic operation to isolate the field value. 
    The mask may typically be loaded as a immediate value in the instruction stream,
    and will be at least one additional instruction to test a bitfield value that is not a single bit.
     
    You may define a struct having both bitfields, and whole byte and larger variables or arrays.
    Code using the struct may be the same, even if you change a variable from a bitfield to a whole byte, or opposite.
     
        Mysil
    #3
    radikn
    Starting Member
    • Total Posts : 22
    • Reward points : 0
    • Joined: 2015/07/31 23:58:01
    • Location: Czech Republic
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 05:17:15 (permalink)
    0
    It's hard to say. It depends on CPU and whether the bitfields are one bit wide or more.

    8bit and 16bit CPUs have instructions for one bit manipulation (bset, bclr, btg, and more) whereas 32bit CPU hasn't. 32bit CPUs have special registers (SET, CLR, INV). So with 8bit and 16 bit CPU's is fine to use one bit wide bitfields. The line LATBbits.LATB3 = 1 is translated as one instruction. Because PIC32 doesn't have instruction for bit manipulation, the line mentioned above would be translated as four instructions (load, and, or, store ... perhaps may be ... load value, load a constant, INS, store). In this case it is better to use special SET, CLR or INV registers, which are translated as load a constant and store instructions. If bitfield is wider than one bit, I thing that use of separated variable is safer. Imagine the situation, you have two bitfields wider than one bit in one variable. You changing one bitfield somewhere in main loop and another in interrupt service routine. Because changing bitfield wider that one bit cannot be atomic operation, there may be following situation:

    main loop                                                isr
    changing one                              changing another
        bitfield                                              bitfiend
    ======================================
    load variable
                             ---- interupt --->  
                                                          load the same variable
                                                          and                                                       
                                                          or
                                                          store
                             <- ret from isr --
    and
    or
    store  !!!!!!  previously loaded value was changed in isr and
                      this instruction rewrite a value saved in isr.

    To avoid this dangerous situation, it is better to use two separate variables. Of course, you can disable the interrupts, but to me it is not the best way.
    post edited by radikn - 2019/04/13 07:13:32
    #4
    crosland
    Super Member
    • Total Posts : 1586
    • Reward points : 0
    • Joined: 2005/05/10 10:55:05
    • Location: Bucks, UK
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 07:13:34 (permalink)
    +1 (1)
    radikn
    It's hard to say. It depends on CPU and whether the bitfields are one bit wide or more.

    8bit and 16bit CPUs have instructions for one bit manipulation (bset, bclr, btg, and more) whereas 32bit CPU hasn't. 32bit CPUs have special registers (SET, CLR, INV). So with 8bit and 16 bit CPU's is fine to use one bit wide bitfields. The line LATBbits.LATB3 = 1 is translated as one instruction. Because PIC32 doesn't have instruction for bit manipulation, the line mentioned above would be translated as four instructions (load, and, or, store ... perhaps may be ... load value, load konstant, INS, store). 



    Your example of setting a bit does not require an AND, only three instructions load, OR (set the bit), store.
     
    If the compiler is any good it will automatically translate that to a single access to the SET register.
     
    The SET, CLR and INV registers in 32 bit PICs can target multiple bits. Again, if the compiler is any good, assignments to multi-bit bit fields can be quite efficient, especially if assigning ones or zeros to each bit.
     
     
    #5
    NKurzman
    A Guy on the Net
    • Total Posts : 17610
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 09:20:22 (permalink)
    0
    You know the PIC10-18 compiler supports bit variables? That should be the smallest for bot RAM and Flash.
    #6
    NorthGuy
    Super Member
    • Total Posts : 5543
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 15:38:34 (permalink)
    +1 (1)
    PIC32 has SET, CLR and INV only for SFRs (not even for all of SFRs). There's nothing similar for general memory. There are "ins" and "ext" instructions to manipulate bitfields, so it's more or less load/set/store.
     
    The other PICs can set/clear single bits in general memory, but if you want to assign an unknown value to a single-bit field, you still need 3 instructions. Multi-bit manipulations are way too inefficient to consider.
     
    So, it all depends on what you do with bitfields and what PIC you use. In general case, they're inefficient.
    #7
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11246
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/13 16:35:23 (permalink)
    +2 (2)
    If you ever plan to move your code to a different family of processor, be aware that the behavior of bit-fields is very non-portable.
    #8
    mlp
    boots too small
    • Total Posts : 776
    • Reward points : 0
    • Joined: 2012/09/10 15:12:07
    • Location: previously Microchip XC8 team
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 08:34:38 (permalink)
    +2 (2)
    jtemples
    If you ever plan to move your code to a different family of processor, be aware that the behavior of bit-fields is very non-portable.

    Some specific behaviour is very non-portable, e.g.
    • maximum width of a bitfield
    • physical layout of bitfields within RAM
    • what happens with padding
    • efficiency of generated code
     
    General behaviour is very portable e.g. struct { unsigned foo:3; unsigned bar:4; } will always give you a .foo which can hold 0..7 and a .bar which can hold 0..15, whether you compile it for a PIC10F200 or a Cray X/MP.

    Mark (this opinion available for hire)
    #9
    KTrenholm
    Super Member
    • Total Posts : 710
    • Reward points : 0
    • Joined: 2012/08/08 14:04:23
    • Location: Connecticut, USA
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 10:00:55 (permalink)
    0
    Since we're talking about bitfields, couldn't you force the RAM layout via a union?

    typedef union{
        struct {
            uint8_t l_ctrl  :1;
            uint8_t l_shift :1;
            uint8_t l_alt   :1;
            uint8_t l_gui   :1;
            uint8_t r_ctrl  :1;
            uint8_t r_shift :1;
            uint8_t r_alt   :1;
            uint8_t r_gui   :1;
        };
        uint8_t modbyte;
    } modifier_keys_t;
     

     
    Wouldn't this "enforce" how the bitfield is laid out in RAM by laying it out into an 8-bit unsigned int?  I would assume endianness would still matter going from MCU to MCU but the bits would be laid out in sequence in RAM yes?  Or am I misunderstanding?
    post edited by KTrenholm - 2019/04/15 10:02:23
    #10
    cobusve
    Super Member
    • Total Posts : 493
    • Reward points : 0
    • Joined: 2012/04/02 16:15:40
    • Location: Chandler
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 10:05:00 (permalink)
    +2 (2)
    No this does not enforce the ram layout. E.g. the standard does not specify where is the MSB and the LSB, so in your example one compiler could start at l_ctrl and the other could start at r_gui and they would both be doing the right thing ...

    Also take a look at https://www.microforum.cc/ - a great resource for information on PIC and AVR microcontrollers and embedded programming in general. You can also post questions to the experts there.
    #11
    KTrenholm
    Super Member
    • Total Posts : 710
    • Reward points : 0
    • Joined: 2012/08/08 14:04:23
    • Location: Connecticut, USA
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 10:24:03 (permalink)
    +2 (2)
    cobusve
    No this does not enforce the ram layout. E.g. the standard does not specify where is the MSB and the LSB, so in your example one compiler could start at l_ctrl and the other could start at r_gui and they would both be doing the right thing ...

     
    So basically make sure to look at the compiler docs before assuming any bit positions...
    Luckily the compiler I'm using for that code does specify.
    #12
    Jim Nickerson
    User 452
    • Total Posts : 6123
    • Reward points : 0
    • Joined: 2003/11/07 12:35:10
    • Location: San Diego, CA
    • Status: online
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 10:28:58 (permalink)
    +2 (2)
    As does the compiler I use XC32
     
    edit add and in XC8
     
    post edited by Jim Nickerson - 2019/04/15 10:35:24

    Attached Image(s)

    #13
    nice
    Super Member
    • Total Posts : 1080
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 14:14:42 (permalink)
    +1 (1)
    NorthGuyMulti-bit manipulations are way too inefficient to consider.



    Definitely not true for dsPIC33CH/CK, e.g.

    ADTRIG0Hbits.TRGSRC3  = 0b10100; 
    000CBC  200142     MOV #0x14, W2
    000CBE  0A22C8     BFINS #0x8, #0x5, W2, ADTRIG0H
    000CC0  000B82     NOP

    #14
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3146
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 14:56:49 (permalink)
    -3 (3)
    The CH chips do contain a good set of bitfield instructions however they could do with some improvement - literal values only although not a problem if they are constant values.
     
    This is just one platform with a subset of instructions meaning MC will never use it in their C Compiler produced code.  Why bother to make extra code if it already works.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #15
    nice
    Super Member
    • Total Posts : 1080
    • Reward points : 0
    • Joined: 2004/09/18 11:42:25
    • Location: Germany
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 15:11:47 (permalink)
    +2 (2)
    Gort2015
    This is just one platform with a subset of instructions meaning MC will never use it in their C Compiler produced code.  Why bother to make extra code if it already works.



    Before making such a statement, you should have tested the compiler’s behaviour. The example I've posted is compiler generated code. In German I'd tend to say: "Wenn man keine Ahnung hat, einfach mal die Fresse halten".
    #16
    Mysil
    Super Member
    • Total Posts : 3326
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 17:56:14 (permalink)
    0
    Hi,
    It may seem that the XC32 compiler have not read the XC32 manual referred to in message #13.
    I have successfully used 10 bit bitfield both in XC16 and XC32 for a long time.
     
    Note the conditional to divide the 10 bit field for XC8 only.
    /** ****************************************************************************
      I2C Master Driver Task Queue Entry Type

      @Summary
        Defines the object used for an entry in the I2C queue.

      @Description
        This type defines the object in the i2c queue.
       Each entry is a self-contained transaction,
       with possibility to link tasks together to be performed without releasing the bus.
     * Mysil    2016-04-19
     */
    typedef union                    /* Task queue transfer request entry */
    {    struct
        {    uint16_t    Address;        /* Bits <10:1> are the 10 bit address.    */
                                        /* Bits <7:1> are the 7 bit address        */
                                        /* Bit  <0> is R/W (1 for read)            */
                                        /* Bits <15:11> are used for options.   */
            uint8_t        Length;            /* Number of bytes to be transferred  . */
            uint8_t        count;            // a count of trb's in the trb list,
                                        // maybe change to option,
                                        // queue entries linked together
            I2C_MESSAGE_STATUS    *pStatus;    /* Pointer to User Status word */
                                        /* set with the status of the current task. */
                                        /* When last transfer is successfull,
                                         * this is I2C_MESSAGE_COMPLETE. */
            uint8_t    *pBuffer;        // pointer to buffer of length bytes
        };
        struct
        {    unsigned    :1;                /* R/W bit is here. */
      #ifdef    __XC8
            unsigned    :7;                /* Bitfield crossing byte boundary not allowed. */
            unsigned    :3;
      #else
            unsigned    Address10:10;    /* Bits <10:1> are the 10 bit address. */
      #endif
            unsigned    Options:5;        /* Option Flags, when task is complete, these are cleared. */
            uint16_t    Size;            /* 16 bit Length field overwriting count. */
            uintptr_t    uStatusPtr;        /* placeholder, Pointer to User Status word */

          #if (I2C_TASK_QUEUE_LENGTH > 1)
            uint8_t     Data[4];        /* Immediate storage for up to 4 bytes. */
          #endif
        };
        struct
        {    unsigned    R_W:1;            /* Bit <0> is R/W bit (1 for read) */
            unsigned    Address7:7;        /* Bits <7:1> are the 7 bit address */
            unsigned    Address3:3;        /* Bits <10:8> 3 high bits of 10 bit address. */
            unsigned    Aflag:1;        /* Bit <11> =1 Master send 10 bit address.*/
            unsigned    Lflag:1;        /* Bit <12> =1 Request is Linked. */
            unsigned    Eflag:1;        /* Bit <13> =1 Big end of Command first. */
            unsigned    Iflag:1;        /* Bit <14> =1 Immediate Data[4] mode */
            unsigned    Bflag:1;        /* Bit <15> =1 Buffer mode flag. */
            uint16_t    L;
            uintptr_t    uStatusPtr2;        /* Dummy, Pointer to User Status word */
          #if (I2C_TASK_QUEUE_LENGTH > 1)
            uint32_t    Command;        /* Up to 32 bits to be transmitted. */
          #endif
        };
    } I2C_TASK;  

    There have been no problems with alignment or padding caused by the union of bitfields.
    Structure is not used for transfer of data between platforms,
    so total size of the structure is not a concern.
    Instead, the aim is for minimum size, especially on 8 bit processors.
    On XC32, total size of the structure is 12 bytes.
    On XC16, total size may be 10 bytes on processors that have 16 bit pointers.
    The last item in the union is an overlay of either a pointer to a data array, or a 4 byte array of immediate values.
     
        Mysil
    #17
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3146
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 19:19:17 (permalink)
    -2 (2)
    "This is just one platform with a subset of instructions meaning MC will never use it in their C Compiler produced code.  Why bother to make extra code if it already works.


    Before making such a statement, you should have tested the compiler’s behaviour. The example I've posted is compiler generated code. In German I'd tend to say: "Wenn man keine Ahnung hat, einfach mal die Fresse halten". 
    I stand corrected.  In English I'd say, "Don't be a dick, I didn't read your post fully, I scanned the page but you could have been polite about it and just said read the post again"




    post edited by Gort2015 - 2019/04/15 19:25:49

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #18
    NKurzman
    A Guy on the Net
    • Total Posts : 17610
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 19:37:58 (permalink)
    +1 (1)
    So Gort Expectations Exceeded.
    #19
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3146
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Bitfields: To Use Or Not To Use. That is the question. 2019/04/15 20:25:51 (permalink)
    -1 (1)
    I do use the bit field instructions in assembly code but I was surprised at how quick MC supported that in compiler produced code.
     
    Shame they could not get PK4 fully operational for the CK/CH chips. (Should be June, Over a Year later)  Got an SD-Card slot that does Jack.
     
    Expectations Exceeded:  Would be if PK4 wasn't used to keep my door open.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5