|
|
View previous topic :: View next topic |
Author |
Message |
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
was “Number of bits out of range” problem fixed? |
Posted: Mon Jul 01, 2013 6:15 pm |
|
|
Colleagues,
This compiler error (or lack of feature) has come up in the past. For example in this thread and this one.
The problem is that the CCS compiler doesn't (or didn't) work with bit fields in a struct bigger than 8 bits.
Code: | typedef union // AD7794 status register (read only) bit fields. See Table 16 in [1]
{
unsigned int8 i8; // content as a byte
struct
{
unsigned int8 Channel : 3;
unsigned int8 : 2; // don't care
unsigned int8 NoExtRef : 1; // no external reference
unsigned int8 Error : 1;
unsigned int8 Ready_n : 1;
}
BitFields;
}
structAD7794StatusRegBits; |
In the above code, the total length is 8 bits. It compiles and runs correctly.
Code: |
typedef union // AD7794 configuration register bits. See Table 20 in [1]
{
unsigned int16 i16;
struct
{
unsigned int16 ChannelSelection : 3; // channel selection bits
unsigned int16 Buffered : 1; // buffered or unbuffered
unsigned int16 RefDetect : 1; // reference detect
unsigned int16 RefSelection : 2; // reference selection
unsigned int16 GainSelection : 3; // gain selection // (!) compile-time error generated here
unsigned int16 Boost : 1; // bias current
unsigned int16 Unipolar : 1; // U/B#
unsigned int16 BurnoutCurrentEn : 1; // burnout current enable
unsigned int16 VBiasSelection : 2; // used in conjunction with Boost bit
}
BitFields;
}
strucrtAD7794ConfigRegBits; |
In the above code, the total length is 16 bits. CCS generates an error “Number of bits out of range”.
I'm still using the old version 4.081. (Primarily because of "don't change it, if it ain't broke" agreement with regulatory people involved.)
Was “Number of bits out of range” problem fixed in the newer version of the compiler
Any suggestion, insight or reference is really appreciated!
Cheers,
- Nick _________________ Read the label, before opening a can of worms. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Mon Jul 01, 2013 7:32 pm |
|
|
Try swapping these two lines:
Code: |
unsigned int16 RefSelection : 2; // reference selection
unsigned int16 GainSelection : 3; // gain selection
|
Quote from TTelmah in one of the posts you listed:
Quote: | In CCS, the default int size, is 8bits, and bit fields in structures have to fit inside this. |
_________________ Google and Forum Search are some of your best tools!!!! |
|
|
kender
Joined: 09 Aug 2004 Posts: 768 Location: Silicon Valley
|
|
Posted: Mon Jul 01, 2013 9:56 pm |
|
|
It had compiled with the change, which you've proposed.
At first, I thought that this change would undermine this use case. The order of the bit fields should corresponds to that in a register of particular external peripheral**. If the order is changed, this would scramble*** the contents from AD7794’s standpoint. The idea behind this union struct is to be able to assign the bit fields using dot notation (convenient), then send them “in bulk” as bytes (convenient).
Code: | strucrtAD7794ConfigRegBits sConfigReg;
sConfigReg.RefSelection = 0b00;
sConfigReg.GainSelection = 0b111;
// … assign more bit fields
spi_xfer( make8(sConfigReg.i16, 1) ); // spi communication code simplified for brevity
spi_xfer( make8(sConfigReg.i16, 0) ); |
At first, I thought that one of the bit fields straddles the boundary between the 2 bytes. But then I've noticed that ChannelSelection bit field is 4 bits instead of 3. After that change, there is not bit field, which straddles.
Other 16-bit registers in AD7794 also don’t have a straddling bit field. Is this luck? Did the designers of AD7794 deliberately (and with foresight) avoid having a bit field, which straddles across the bytes boundary? What if designers of some other hypothetical IC with 16-bit registers didn’t have such foresight?
** AD7794, which is an A/D converter with SPI interface. The register is described in the Table 20 in the datasheet.
*** ever so slightly ;) _________________ Read the label, before opening a can of worms. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Jul 02, 2013 1:05 am |
|
|
I think, it's quite obvious that bitfields over larger entities than a byte are useful in some situations. Bit structures
defined by external hardware are one of several cases where it's not appropriate to reorder the fields.
CCS decided not to supported it with 8-bit compilers, and there's no change in recent V5.
So you need to assemble and decode byte crossing bit fields in your code manually.
The more anoying thing in my view is that altough nominally supported with 16-Bit PCD compiler, they never
worked without some bugs, even up to new V5 versions. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Jul 02, 2013 1:07 am |
|
|
In the example you give there are fifteen bits NOT 16. Depending on endianness and left v right alignment, one field, GainSelection, may straddle the byte boundary. On machines with 16 or more bits this is not a problem, but on 8 bit machines byte straddling is likely to cause trouble.
In the general case, using bit fields to access bits and parts of data is not foolproof not risk free. It may work in C, and if it does that's clearly a good thing, but there is no guarantee.
Instead its generally better to do bit field extraction and manipulation explicitly in code rather than relying on the compiler - any compiler - to always generate correct code for you. These problems most commonly arise when a processor is called on to deal with data streams/structures/packets from other devices. Sometimes the trick of constructing a compatible data structure to cover the data works, sometimes it doesn't. That is was never the intended purpose of bit fields in C - it was to make more efficient use of limited memory at the expense of increased processing speed. When it doesn't you just have to do it by other ways, such as bit masking and shifting.
In this case you are trying to overlay a bit field defined structure over data from/to an ADC. You are dealing with just 15 bits. I'd almost certainly not have even bothered to use bit fields, and simply gone for bit manipulations right from the start. Sure the bit field version looks nice, and gives compact and easy to understand source code which is a clear plus, but its so implementation dependant that there's bound to be trouble at some time or another.
Looking at this, I personally have doubts that there is any actual "problem" to be fixed in the compiler. Rather its an unrealistic expectation on the part of the user: i.e. that all machines and compilers will implement bit fields in the manner the user expects. You don't just have to take my word for it; here is a quote from "The C Book", publications.gbdirect.co.uk/c_book/chapter6/bitfields.html :
"The main use of bitfields is either to allow tight packing of data or to be able to specify the fields within some externally produced data files. C gives no guarantee of the ordering of fields within machine words, so if you do use them for the latter reason, you program will not only be non-portable, it will be compiler-dependent too. The Standard says that fields are packed into ‘storage units’, which are typically machine words. The packing order, and whether or not a bitfield may cross a storage unit boundary, are implementation defined. To force alignment to a storage unit boundary, a zero width field is used before the one that you want to have aligned."
RF Developer |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Jul 02, 2013 2:02 am |
|
|
Bitfields are a standard C element and working flawlessly in most embedded C compilers. Restrictions
are however admitted by the C standard, e.g. not to allow crossing of specific implementation dependent
storage element boundary. K&R, 2. edition states:
Quote: | A bit−field, or field for short, is a set of adjacent bits within a single implementation−defined storage unit that we will call a ``word.''
(...)
Almost everything about fields is implementation−dependent. Whether a field may overlap a word boundary is implementation−defined. Fields need not be names; unnamed fields (a colon and width only) are used for padding. The special width 0 may be used to force alignment at the next word boundary.
Fields are assigned left to right on some machines and right to left on others. This means that although fields are useful for maintaining internally−defined data structures, the question of which end comes first has to be carefully considered when picking apart externally−defined data; programs that depend on such things are not portable. Fields may be declared only as ints; for portability, specify signed or unsigned explicitly. They are not arrays and they do not have addresses, so the & operator cannot be applied on them. |
On a machine with a 16-bit machine word size, e.g. PIC24, correct operation over this size can be
however expected. Needless to say that Microchip C30 or C32 have no problems of this kind. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|