where is boolean datatype?

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

how can i create a variable type Boolean in winavr gcc? my main purpose is to save memory. I know i can use integer type but it will take 1 byte where as a boolean type will cosume only 1 bit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#include

but this does NOT pack booleans into single bits

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The way I create BIT_ variables in GCC is:

typedef struct 
{ 
  unsigned char bit0:1; 
  unsigned char bit1:1; 
  unsigned char bit2:1; 
  unsigned char bit3:1; 
  unsigned char bit4:1; 
  unsigned char bit5:1; 
  unsigned char bit6:1; 
  unsigned char bit7:1; 
}io_reg; 

#define BIT_buffer_status		((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit0 
#define BIT_recv_error		((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit1 
#define BIT_active			((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit2 
#define BIT_use_sample1		((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit3 

#define BIT_byte_count		((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit4 
#define BIT_receive_132		((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit5 
#define BIT_wait_uart_low	((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit6 
#define BIT_RS232_calibrated	((volatile io_reg*)_SFR_MEM_ADDR(TWAR))->bit7

and a write of 0/1 to one of these turns into a single CBI or SBI machine instruction.

This only works for r/w 8 bit registers in the 0x00..0x1F range of your AVR. In my one I wasn't using the Two Wire (I2C) interface and TWAR provides a nice bit addressable general purpose 8 bit storage location for eight "booleans".

On more modern AVRs Atmel have thoughfully provided the GPIORn registers in the 0x00..0x1F range for exactly this kind of thing so they should be used in preference to "unsused" control registers for other logic blocks in the AVR if available.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bitfields in C

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> bitfields in C

Which is basically what Cliff suggested. However, there's one distinct
exception: usually, the use of a bitfield is a tradeoff between optimizing
for code size vs. RAM space, as accessing and modifying them can require
more complicated code. Cliff's example does *not* fall into this dilemma
though, as he carefully placed the bitfield into a location where the AVR
can perform actual 1-instruction bit manipulation and testing: the lower
IO registers.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

On more modern AVRs Atmel have thoughfully provided the GPIORn registers in the 0x00..0x1F range for exactly this kind of thing

Well, semi-thoughtfully. Mega88:
Quote:

0x2B (0x4B) GPIOR2 General Purpose I/O Register 2
0x2A (0x4A) GPIOR1 General Purpose I/O Register 1
0x1E (0x3E) GPIOR0 General Purpose I/O Register 0

so I avoid GPIOR1/2 since it is actually >>worse<< than an SRAM location in generated code.

Same with Mega640 family. Same with Mega164 family. Same with Mega325 family. ...

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

so I avoid GPIOR1/2 since it is actually >>worse<< than an SRAM location in generated code.

That statement does not make any sense as the I/O registers are memory mapped, an access to those would be no worse than an access to any other point in SRAM.

In addition, using in & out on those locations would make accessing them even faster than any ram loacation.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch,

I fear you have missed the point. Bits in registers 0x00..0x10 can be changed with the single cycle, single word CBI and SBI opcodes. Between 0x20 and 0x3F once can use IN/modify/OUT and above 0x3F you are left with LDS/modify/STS. So there is a DISTINCT advantage in 0x00..0x1F registers. So it's a bit of a shame if GPIORn registers are provided but they fall outside this range.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler (my low-value, not-for-professional-work brand anyway) will still treat them as I/O registers when in reach of IN/OUT. A bunch "depends"--I can coerce the compiler into using the "T" bit of SREG in some C sequences, for example.

None of the sequences are attractive. CodeVision has the built-in concept of "bit"-type. Basically, you can decide to dedicate low GP registers for variables of type "bit". With the advent of GPIORx, the compiler uses up those first (good idea). Once overflow into GPIOR1/GPIOR2 the code sequences get fat and ugly (thus, IMO a bad idea). So I space out to avoid those and force GPIOR0 for the first 8, 16 dummies for GPIOR1/2 in tight apps where space/time is important, then start using R2/R3/... if more than 8 "bit"-type variables are needed.

IIRC toggling a bit got particularly ugly. Your infinite-value compiler brand may generate much more elegant sequences. Mongo just pawn in game of life. Maybe Cliff can code up a "bit_in_gpior2.bit2 ^= 1;" and see if a few elegant instructions result.

[edit] glitcher--I found one of the versions of my test program with different sequences if you really want the gory details. Summary to set a bit:
GPIOR0: single SBI
R2: SET, BLD (still atomic--don't care if ISR between instructions)
GPIOR1/2: IN, SBR, OUT (not atomic--could kill!!!)

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
glitch,

I fear you have missed the point. Bits in registers 0x00..0x10 can be changed with the single cycle, single word CBI and SBI opcodes. Between 0x20 and 0x3F once can use IN/modify/OUT and above 0x3F you are left with LDS/modify/STS. So there is a DISTINCT advantage in 0x00..0x1F registers. So it's a bit of a shame if GPIORn registers are provided but they fall outside this range.

Cliff

No I didn't miss that.. I was not talking about 00-1F.. I was referring to 20-3F, and Lee's comment on how access to them was WORSE than accessing a variable in SRAM,

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
The compiler (my low-value, not-for-professional-work brand anyway) will still treat them as I/O registers when in reach of IN/OUT. A bunch "depends"--I can coerce the compiler into using the "T" bit of SREG in some C sequences, for example.

None of the sequences are attractive. CodeVision has the built-in concept of "bit"-type. Basically, you can decide to dedicate low GP registers for variables of type "bit". With the advent of GPIORx, the compiler uses up those first (good idea). Once overflow into GPIOR1/GPIOR2 the code sequences get fat and ugly (thus, IMO a bad idea). So I space out to avoid those and force GPIOR0 for the first 8, 16 dummies for GPIOR1/2 in tight apps where space/time is important, then start using R2/R3/... if more than 8 "bit"-type variables are needed.

IIRC toggling a bit got particularly ugly. Your infinite-value compiler brand may generate much more elegant sequences. Mongo just pawn in game of life. Maybe Cliff can code up a "bit_in_gpior2.bit2 ^= 1;" and see if a few elegant instructions result.

[edit] glitcher--I found one of the versions of my test program with different sequences if you really want the gory details. Summary to set a bit:
GPIOR0: single SBI
R2: SET, BLD (still atomic--don't care if ISR between instructions)
GPIOR1/2: IN, SBR, OUT (not atomic--could kill!!!)

Lee

I'm just more curious as to how these sequences are worse than that of a bitfield var stored in normal SRAM? I would think the IN-SBR/CBR-OUT would be faster than the LDS-SBR/CBR-STS for a regular SRAM variable. And carries teh same non-atomic penalties.

I was not keying in on them being worse than the regs in the range 00-1F... that is obvious. It was your comment on how using 20-3F is worse than using SRAM.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, in one way any of the 3-instruction (or more) sequences are unacceptable (to me). It makes me think too hard in ISRs--I cannot just have a single-instruction ISR for my system tick timer "tick = 1;" without thinking of the consequences. The minor consequence is that it is no longer a single-instruction ISR. A register needs to be saved and restored, and maybe SREG saved. The major consequence is that I now have to think about what else (other flags) might be in that byte of flags, 'cause the set is not atomic and would need to be protected.

I'd have to dig back into the backup files to find the "more worser" case. But it doesn't really matter--certain of the sequences to toggle a bit were so ugly (so many instructions) that I "Just say 'No!' " to GPIOR1/2.

Also remember that I'm not really concerned with the SRAM/bitfield stuff much, as CV uses the low registers for the "bit" variables, stealing as many as needed from global register variable space.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So... going back to your original statement:

theusch wrote:

so I avoid GPIOR1/2 since it is actually >>worse<< than an SRAM location in generated code.

which sent us off on this tangent. It seems we're not talking about SRAM at all... but rather CPU registers... in which case I would agree that access to the upper I/O (20-3F) is worse than access to the register'd vars.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, I did in fact run some code using SRAM locations & bit masks ala the GCC politically-correct method. But my aim was to determine for myself which C sequences give me the "best" code for ME and MY COMPILER with "bit" variables located in different memory spaces.

Now, I don't have all of my backup editor files from that test program from a few months back. I distinctly remember the situation I am claiming--but that is probably because of the way MY compiler translates certain sfrb operations into machine code sequences. [I'll post one ugly sequence below.]

So, if I have a CodeVision "bit" variable it could be in GPIOR0, GPIOR1/2, or R2/R3/... . If I want to toggle that bit, I know of 5 ways:

bitvar = !bitvar;
bitvar = ~bitvar;
bitvar ^= 1;
if (bitvar) bitvar=0; else bitvar=1;
bitvar = (bitvar) ? 0 : 1;

So the test, for myself, with my toolchain, was to determine which way I should write this construct, and other similar situations, to give "good" code. The impetus was the discovery that a Mega48 app with lots of "bit" variables bloated on me, and I looked into it.

As promised, a particularly ugly sequence with GPIOR1:

                 ;      58 	gpior10 = !gpior10;
00007d e0e0      	LDI  R30,0
00007e b5fa      	IN   R31,0x2A
00007f fff0      	SBRS R31,0
000080 e0e1      	LDI  R30,1
000081 d044      	RCALL __BSTB1
000082 b5aa      	IN   R26,0x2A
000083 f9a0      	BLD  R26,0
000084 bdaa      	OUT  0x2A,R26
                 ;      59 	gpior10 = ~gpior10;
000085 e0e0      	LDI  R30,0
000086 b5fa      	IN   R31,0x2A
000087 fff0      	SBRS R31,0
000088 e0e1      	LDI  R30,1
000089 d03c      	RCALL __BSTB1
00008a b5aa      	IN   R26,0x2A
00008b f9a0      	BLD  R26,0
00008c bdaa      	OUT  0x2A,R26
                 ;      60 	gpior10 ^= 1;
00008d e0e0      	LDI  R30,0
00008e b5fa      	IN   R31,0x2A
00008f fdf0      	SBRC R31,0
000090 e0e1      	LDI  R30,1
000091 e0a1      	LDI  R26,LOW(1)
000092 27ea      	EOR  R30,R26
000093 d032      	RCALL __BSTB1
000094 b5aa      	IN   R26,0x2A
000095 f9a0      	BLD  R26,0
000096 bdaa      	OUT  0x2A,R26

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thnx everyone for so many replies