A quick c programming survey question

I never use a) for memorymapped I/O since I discovered that GCC-ARM in that case tries to do a byte-access on a 32-bit register (not byte-addressable). The rest of the register of course got thrashed.

But I still use a) for variables in memory, since the compiler (at least GCC) nicely realigns things when a field size has to be changed. Just changing one field in an structure and recompiling is mucht nicer than searching all the code. And I'm not so fond of macros.

Regards, Arie de Muynck

Reply to
Arie de Muynck
Loading thread data ...

Reply to
Grant Edwards

I hope I never have to work with you. Absolute rules like that are a sure way to produce bad results.

--
Grant Edwards                   grante             Yow!  My mind is making
                                  at               ashtrays in Dayton...
                               visi.com
Reply to
Grant Edwards

Because I find that the forms

port |= whateverBit;

and port &= ~whateverBit;

to be the most clear and readible.

However, if setting a multi-bit field, then the struct bit-field approach or the macro approach is often more readble:

value.clockSel = 2 or SetBitField(value,ClockSel,2)

rather than

value &= ~(7

Reply to
Grant Edwards

If you had said that portability was important, then you get different answers. A piece of code that is only going to run on a single processor model is written differently than one that has to run on multiple architectures. A lot of embedded code doesn't need to be portable. There absolutely no point trying to port code that sets up times on an Hitachi H8/3062B microctonroller to a VAX.

Beacause the vendor provided all the structure bitfield header files and none of the code is going to be portable anyway?

Asking somebody whether A or B is better without stating all the requirements, is deluded.

--
Grant Edwards                   grante             Yow!  Alright,
                                  at               you!! Imitate a WOUNDED
                               visi.com            SEAL pleading for a PARKING
                                                   SPACE!!
Reply to
Grant Edwards

"> Do you (your company) prefer to:

b)

Reply to
Mark

I have to admit, I am a little lost at the whole point you are trying to make ?

Shame that was not specified in the original question, then ?

3) It can provide a uniform interface with reading

Still not easy to find the point...

BOOLEAN BITS, by their nature are not portable. In embedded systems, they most commonly apply to hardware flags. Someone who thinks that a change in SW style can somehow create 'more portable bits' probably should not be let near low level code!

The embedded systems I work on have never had to change HW targets, so I code for best maintainance/interrupt integrity.

-jg

Reply to
Jim Granville
[snip...snip...]

No, I prefer to be honest and to the question:

"Do you (your company) prefer to:

a) Create a 'bits' structure for each register and access using the dot or arrow operator.

b) Create a set of bit access functions (or perhaps macros) and access using those?"

I would have answered "neither" as I did in my original reply, since I feel that both methods tend to obfuscate rather than clarify.

There's nothing about which to argue, is there, as the question is what my preference is?

No, they answered a rote question. I suspect (as Grant has also implied) that most working embedded programmers prefer the "|=" and "^= ~" constructs. I've used the other techniques when doing maintenance programming (Rule #1 of maintenance programming: Don't change the existing style.) but really don't "prefer" either 'a' or 'b'.

[snip...snip...]

What nonsense. If this is something that the interviewer actually believes that the candidate pool may be unsure of, then perhaps he's fishing in the bottom of the pool and deserves what he pulls out.

--
Rich Webb   Norfolk, VA
Reply to
Rich Webb

Untrue. I suspect most employers want to hire people that can think for themselves. I certainly would give more weight to candidates that could argue their points intelligently and disagree with me.

No, it's a filter to weed out independent thinkers. This is the classic Microsoft interview question "why are manhole covers round" where they accepted only one possible answer as "correct".

Your colleague should be happy, since now he doesn't have to work with people like that.

--
Darin Johnson
    Gravity is a harsh mistress -- The Tick
Reply to
Darin Johnson

I agree, but I think you'd also agree there is a point at which that alone isn't worthwhile.

For example, we had an interviewee who thought that "Getting code to market fastest" was the way to do it, and forget about any processes, reusability or maintainability of the code. He argued tooth and nail for it. We didn't hire him.

That would be fine, unless their points are asinine.

I don't think that's what the original poster meant. It's more of a field question of "is this guy aware of the pitfalls of a common construct and does he know when and when not to use them"?

I personally don't mind independent thinking or using the bitfield construct, provided it's knowingly applied, rather than haphazardly by the ignorant.

-->Neil

Reply to
Neil Bradley

On Mon, 17 May 2004 09:31:37 +1200, Jim Granville wrote:

FWIW, not only have I never used the built-in "bits" facility in C (answer a) in the original thread), I forgot it was in the language. I don't recall seeing any code that uses it (outside of k&r).

Now I at least see the 'agenda' that prompted the original question. The answers were either a) or not a). I definitely do bit manipulation by bitwise anding, oring, shifting and complementing, either directly in the 'main' code or in functions or macros as I see fit. This generally works (until changing to a processor with a differen word size, then there are usually other considerations as well) and is about as portable as can be expected.

I recall an interview I had maybe ten years ago. The company had the same C code running on two different 8-bit microcontrollers, one was, IIRC, an 8051, and the other was some other unrelated (non-compatible) architecture. They were asking me questions to see how much I knew about writing "portable" C code. I gave what answers I could, about isolating I/O operations to separate functions that are different for each chip and the main "portable" code calls those functions to do I/O. I didn't get a job offer, and looking back it's just as well (I vaguely recall the products were related to "home networking" for appliances like washer/dryers and refrigerators, so they could be controlled remotely to do things like reduce peak power consumption - this was hot at the time but I haven't heard anything about such applications in years). It seemed to me at the time (though I could be wrong, I can't think of another reason to do this) that they did this for manufacturer/vendor independence - so that in case one chip maker went out of business, they would have the code and hardware designed with the other chip ready to manufacture. Perhaps they also played the manufacturers and vendors against each other, saying "We've got the code running on your compettitor's chip right here, and we're going with the lowest priced solution at a few million units/year" in an effort to negotiate lower prices. But it seemed like they were going to great expense to be able to say they had "portable code" running on both these chips.

-----

formatting link

Reply to
Ben Bradley

In situations when you have to deal with "write only" hardware registers, it would be a good idea to use both methods :-).

You have to use a separate memory location to store the value most recently written to the hardware register. To change the register, the appropriate bit in the memory location has to be changed first and the whole byte/word/longword is written with a single MOVE byte/word/long instruction into the hardware register.

In this situation, the memory location could be a bit field structure, which can then be written into the hardware register as a single byte/word/long.

Although different compilers arrange the bit fields differently into the byte or if you have to switch from big endian to little endian processors using the same 16 or 32 bit peripheral register, you only have to rearrange the fields in the struct definition. Bit fields larger than 1 bit which are contained within the same byte, can also be handled nicely with bit fields in big/little endian situations.

If the compiler is not capable of generating the correct size of the structure (say 8, 16 or 32 bit) as required for the hardware access, use a union parallel with the structure.

While this is quite readable on its own, two assignments are required, one to change the memory bit field and an other to transfer the entire structure value to the hardware register.

Of course, you can hide this into an access macro. This access macro would be identical on all hardware platforms and only the struct definition (in a header file) needs to be changed.

If method B) is solely used, you may have to change a lot of access macro changes if the peripheral hardware register requires 16 bit access and you are changing between big/little endian processors.

Paul

Reply to
Paul Keinanen

One factor that folk seem to have forgotton, not known, or neglected to mention: In ANSI C bitfields are *only* defined over "unsigned int". not any other data type or size. That plays havoc with their usefulness to access hardware registers. The other factors already mentioned are the lack of any control over bit ordering (no, it's *not* dependent on the endian-ness of your CPU), and the fact that you don't know when you'll get an unwanted read-modify-write, or how many bytes or words will be read.

When I can, I use C++ (as a better C) with inline methods, often even with inline assembly code. Second preference is or inline C functions. If no inlining is available, I simulate the inline C using macros, and only fall back to static methods when it's worth the procedure call overhead.

I *never* use inline bit manipulation on registers outside the code which has direct and sole charge of managing those registers. It's much better to have even a macro with an API-like name to produce even a single statement, even if it's only used in one place, as the code documents itself that way.

Reply to
Clifford Heath

No, they're only defined as fields in structures. The fields themselves have a special declaration syntax that only accepts "_Bool", "[signed] int" or "unsigned [int]". But the size of the memory allocated is up to the implementation. To quote the standard:

"An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified."

IOW, an implementation is _allowed_ to be space-efficient.

This is true.

[...]

And it makes it possible (if not trivial) to port code. Perhaps my experience is unique, but I very often have to port my code to new processors. Isolating I/O manipulation behind macros and functions means I only have to re-write those macros and functions. Everything else works the way it should (providing, of course, a suitible compiler exists for the new platform...).

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

While the standard doesn't require it, all of the C compilers I've used in the past 15 years for embedded work _did_ provide the user with control over allocation order. IMO, the old "bit order is undefined" cry is pretty much bogus in practice.

In my experience, the only real problem with using bitfields that remains is controlling the width of the read/modify/write operation.

I've never suffered from lack of control over bit ordering. You need to use better C compilers.

Sorry, I don't know what that means.

That's is still an issue. If they're to be used for accessing hardware registers, it would help if there was a way to group bit-fields together into access units.

The vast majority of the bit-manipulation I do is manipulating peripheral registers. Trying to port code like that to a new architecture with a different set of peripherals is usually pointless.

--
Grant Edwards                   grante             Yow!  Is this my STOP??
                                  at               
                               visi.com
Reply to
Grant Edwards

"It works on _my_ system" isn't the best argument.

[...atribution lost...]

That's my point. Application code invokes Set_Led_On(), Transmit_Buffer(), Set_Baud_Rate(BAUD), whatever. "Driver" code implements these macros.

Regards,

-=Dave

--
Change is inevitable, progress is not.
Reply to
Dave Hansen

C was designed primarily as a systems programming language, I believe. It was also implemented at a time that memory was much more scarce, so that it was important to be able to use single bits for storing boolean variables. The C bitfields are a reasonable syntax for doing this.

As far as portability, bitfields per se are not, in my opinion, "highly non-portable". You simply need to know the limitations that are given by the standard: no specification of ordering of bit fields within a word, no specification of the size of the word, no specification of whether a bitfield can overlap words, no specification for the minimum size of the word in which bitfields are stored, no specification of whether a "plain int" bitfield (not explicitly signed or unsigned) is signed or unsigned. As long as you use each bitfield separately, you shouldn't have much problem.

I think that bitfields are a benefit to the language. Also, for target-dependent code, you can take advantage of the implementation-defined aspects of bitfields.

Bitfields are used in a lot of applications, I think, and rewriting them to remove bitfields would be a lot of work with very little profit.

Thad

Reply to
Thad Smith

In my experience, embedded systems code is only meant to work on one system.

Right. But there's no point it trying to write that driver code in a "portable style" since the hardware being manipulated isn't portable.

--
Grant Edwards                   grante             Yow!  I'm in ATLANTIC CITY
                                  at               riding in a comfortable
                               visi.com            ROLLING CHAIR...
Reply to
Grant Edwards

Sometimes perhaps, but in this case I think it justified. It isn't just the portability of absolute code that is important. It is the portability of the ideas across a department. If the team of people working on one processor use a different method to the team working on a different processor it makes it much harder for individuals to review code across projects

tim

Reply to
tim

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.