Are bit-variables in PICC a good idea

Hi!

I had a discussion in the other day about the usefullness and validity of the following (non-std) C extension in PICC:

static bit BitVar @ 0x20*8+0;

This would mean that a static variable, named BitVar will be located in the memory at address 0x20 at bit 0. (Note, that this C compiler is for an 8-bit microcontroller and this construct should provide a means to define HW-related functions in C.)

With this declaration the following program would set bit 0 of address 0x20 to 0 and bit 1 to 1:

static bit BitVar1 @ 0x20*8+0; static bit BitVar2 @ 0x20*8+1;

void main() { BitVar1 = 0; BitVar2 = 1; }

The discussion was about two things:

- Since there are other (though more complex) constructs in standard C to achieve the same effect, is it a good idea to add a new built-in type (without the __ prefix) and an address-binding syntax (with the @ operator) to the language?

- Since all operations on all modern CPUs are work on at least 8-bits of data at once, is it even possible to compile such a source program into a valid executable (in a sense that it accesses only memory that's defined in the source)?

We couldn't on our own reach an agreement so I seek the opinions of a wider audience.

-- Thanks, Andras Tantos

Reply to
Andras Tantos
Loading thread data ...

I'm not sure it matters a lot how you specify bit addresses for hardware. You generally don't change CPU architectures for a product a whole lot. There's no way you could change from a PIC to an AVR and simply recompile your C code and expect it to run. You would have to change all your bit addresses as I doubt if different architectures from different companies would keep bits in the same positions.

Now, for bit positions in something that is fixed (like in some standard communications protocol), you'd probably want to use C as it is independent of the actual hardware used, so you could in theory re-use such code on different hardware.

Reply to
Gary Kato

It really depends on whether your priority is efficiency or portability (or a compromise between these) A good technique is to use a typedef based on the platform, something like :

#if __TARGET__ == __SOME_TARGET_WHOSE_COMPILER_SUPPORTS_BITS__ #else typedef int bit ; /* or is it bit int - I can't remember */ #endif

You can then use the C convention that 0 is false and anything else is true to make your code portable.

It is almost always a bad idea to define absolute addresses as "magic numbers" in source code. The link process should give you a much more maintainable and portable way to do this

the

8-bit
0x20

operator)

in

wider

Reply to
Gary Pace

The syntax for typedef declarations is the same as for "normal" declarations. The "typedef" keyword is placed where you might otherwise place a storage-class specifier such as "static" or "extern". So,

/* declare an variable `a' of type int */ static int a;

/* declare a type alias `b' for type int */ typedef int b; /* declare a function `f', which returns a pointer to a function which returns a pointer to char */ extern char *(*f())();

/* declare a type alias `f' for a function which returns a pointer to a function which returns a pointer to char */ typedef char *(*f())();

Jeremy.

Reply to
Jeremy Yallop
[...]
[...]

These are two separate issues:

1) Double-underbar prefix. Keep it. If you (or your user) wants to hide the "ugliness", use a macro defined in a header a la _Bool and bool in stdbool.h

2) The only real feature this provides over _Bool is the ability to specify the location of the bit in memory. And the only reasons to do this (that I can imagine) are to specify control and status bits in hardware registers, or to assemble bit masks into bytes or words in order to handle packages of bits. For both these operations I prefer masking and shifting operations because the actual operations used and the order they are taken can be (must be) specified in the code, so (for example) possible interactions with interrupt service routines are more visible.

FWIW, I generally avoid bitfield structures except when 1) the compiler doesn't support a native bit type like _Bool, and 2) I have several boolean variables I need to define that are not necessarily related to one another. Something like the following:

struct bits { unsigned b0 :1; unsigned b1 :1; unsigned b2 :1; unsigned b3 :1; unsigned b4 :1; unsigned b5 :1; unsigned b6 :1; unsigned b7 :1; } my_status_bits;

#define boost_switch_position my_status_bits.b0 #define is_warmup_mode my_status_bits.b1 /*etc.*/

But even then, you have to be careful about using these in ISRs. Something like

is_warmup_mode = TRUE;

isn't generally atomic.

What's a "modern CPU?"

For the PIC or an 8051, with memory-mapped registers, it makes sense. For a Pentium running Windoze, it doesn't.

HTH,

-=Dave

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

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.