DSPRelated.com
Forums

Using bitfields

Started by Bende Georg February 7, 2005
Hi CodeWarriors,

I'm using bit fields very extensively in my software. Recently I had a
very strange bug: the values of these bit fields were corrupted if there
were a lot of interrupts in the same time in the system. It didn't
happen at once - sometimes the system worked OK for 10 minutes,
sometimes for an hour, but it came over the time for sure. The temporary
workaround was that I converted the bitfields into 16-bit variables.
It smells like some stack corruption caused by improper register
pushing. The question is, why 16-bit variables make a difference? Where
sould I look for the bug?
I'm using compiler CW5.0 @ DSP56F803; the tests with CW7.0 had the same
result. The assembler dump seems to be correct.
Any hints, suggestions or your own experiences on bitfields are welcome.

BR,
Georg Bende



This is a common problem that occurs with multiple processes in an RTOS and in code that uses ISRs.
 
If a background application wants to update a bit field, it operates by reading, modifying, and writing the new value.
If the ISR routine (or other thread in an RTOS) starts in between the read and write operations, the ISR's change will be lost
when the write of the background application occurs.
 
Possible solutions include:
1. Don't use bit fields (which required read modify write), which you already have found out.
2. Disable interrupts before the read and re-enable after the write.
3. Keep separate variables for bit fields in the application and ISR.
 
Another similar problem can occur if variables used by ISRs are not declared as volatile. This paricularly includes memory mapped I/O registers.
This can manifest itself when polling a status register and never seeing it change because a compiler optimized the read of the I/O register and replaced it with an infinite loop.
 
Howard
-----Original Message-----
From: Bende Georg [mailto:g...@faulhaber.de]
Sent: Monday, February 07, 2005 10:32 AM
To: m...@yahoogroups.com
Subject: [motoroladsp] Using bitfields

Hi CodeWarriors,

I'm using bit fields very extensively in my software. Recently I had a
very strange bug: the values of these bit fields were corrupted if there
were a lot of interrupts in the same time in the system. It didn't
happen at once - sometimes the system worked OK for 10 minutes,
sometimes for an hour, but it came over the time for sure. The temporary
workaround was that I converted the bitfields into 16-bit variables.
It smells like some stack corruption caused by improper register
pushing. The question is, why 16-bit variables make a difference? Where
sould I look for the bug?
I'm using compiler CW5.0 @ DSP56F803; the tests with CW7.0 had the same
result. The assembler dump seems to be correct.
Any hints, suggestions or your own experiences on bitfields are welcome.

BR,
Georg Bende


NEW!  You can now post a message or access and search the archives of this group on DSPRelated.com:
http://www.dsprelated.com/groups/motoroladsp/1.php

_____________________________________
Note: If you do a simple "reply" with your email client, only the author of this message will receive your answer.  You need to do a "reply all" if you want your answer to be distributed to the entire group.

_____________________________________
About this discussion group:

Archives:  http://www.dsprelated.com/groups/motoroladsp/1.php

To Post:  Send an email to m...@yahoogroups.com

Other DSP Related Groups: http://www.dsprelated.com/groups.php

Hi Georg

Have you tried wrapping "interrupt-disable" and "restore interrupt level"
around the at-risk code? (Just to prove that interrupts are breaking it.)

A co-worker also used to use bitfields with CW 5 on DSP56F803 (I think the
CW version was 5.1.2). We used it to poke bitfields registers with
more-easily-read C code. It was "pretty" code, though very inefficient.

When we moved that same code to 56F8357s and CW 6.0, some of the bitfields
broke - I forget whether it was Optimization Level 0 or 1.

Writing to single-bit-bitfields seemed to be OK.

One bitfield was 3bits wide, however, and the 21 lines of ASM generated for
that assignment was strange - it set those 3bits wrong and altered other
bits than just those 3. We probably had a pointer to a structure to access
the register.

I tore out the bitfield code, since it behaved differently from one rev of
the compiler to the next.

My experience was not like yours - mine worked wrong every time it ran, with
the CW6 compiler and the 56F8357. It wasn't intermittent, and I had no
reason to think it was Interrupt-related. It occurred at setup time when (I
think) no interrupts should have been running (but I did not disable
interrupts during the setup). I never used the CW6 compiler on the 56F803,
or CW5 on the 56F8357.

I'm going to wait before moving to CW 7 ... perhaps indefinitely. I don't
want to be the one to discover new bugs. I think this is a sample of the code that broke, but it was months ago:

//Timer A0 Control Register bit wise structure
union TMRACtrlReg0Union
{
volatile unsigned short *RegAddressVar;

struct CtrlReg0Struct {
unsigned OutPutMode : 3; /*LSb */
unsigned CoInit : 1;
unsigned CounterDir : 1;
unsigned CountLengh : 1;
unsigned CountOnce : 1;
unsigned SecondaryCountSource : 2;
unsigned PrimaryCountSource : 4;
unsigned CountMode : 3; /*MSb */
}*TMRACtrlReg0Struct;

}TMRAcontrolReg0Int; // GatedCount: enum, 011=3 turns TACH PULSE counter ON
TMRAcontrolReg0Int.TMRACtrlReg0Struct->CountMode = GatedCount;
Rick Corey -----Original Message-----
From: Bende Georg [mailto:]
Sent: Monday, February 07, 2005 10:32 AM
To:
Subject: [motoroladsp] Using bitfields
Hi CodeWarriors,

I'm using bit fields very extensively in my software. Recently I had a
very strange bug: the values of these bit fields were corrupted if there
were a lot of interrupts in the same time in the system. It didn't
happen at once - sometimes the system worked OK for 10 minutes,
sometimes for an hour, but it came over the time for sure. The temporary
workaround was that I converted the bitfields into 16-bit variables.
It smells like some stack corruption caused by improper register
pushing. The question is, why 16-bit variables make a difference? Where
sould I look for the bug?
I'm using compiler CW5.0 @ DSP56F803; the tests with CW7.0 had the same
result. The assembler dump seems to be correct.
Any hints, suggestions or your own experiences on bitfields are welcome.

BR,
Georg Bende


Hi Georg

>> Sad that these DSPs don't support bit fields like microcontrollers do -
the generated code is inefficient and slow. <<

I don't blame the chip, I blame the compiler. I was baffled when I looked
at generated ASM code for bitfields (CW6). The chip has BFSET and BFCLR.

How about creating a lot of macros, using constants, that just set one bit?
The amount of code that is in danger of being stepped on by an ISR is much
less. And you could build the interrupt-disable-restore into the macro.
Just remember to allow 6 NOPs for the interrupt-disable to take effect. I got this one from some Moto or Metro file, I like their name:
#define setRegBits(reg, mask) reg |= mask

then I use it:

#define SET_GPIO_D( WhichBit ) setRegBits( *GPIO_D_DR, (1<<WhichBit)
);

#define LED1_On() (setRegBits( *GPIO_E_DR, 0x0080)) It seems to generate reasonable code for register-poking after the
pre-processor digests everything:

OFF_USER_LED;
P:00040722: E418F3310000 move.l #0xf331,R0
P:00040725: 80400080 bfclr #0x80,X:(R0) SET_GPIO_D( 3 );
P:000480DD: E418F3210000 move.l #0xf321,R0
P:000480E0: 82400008 bfset #8,X:(R0)
// D0, D1, D2 and D3 => WhichBits_D_IO == 0x0F - a variable
setRegBits(*GPIO_D_PPMODE, WhichBits_D_IO ); // set for 1=OpenDrain
(0=PushPullMode)
P:00040727: E418F3290000 move.l #0xf329,R0
P:0004072A: F114 move.w X:(R0),B
P:0004072B: F01F move.w X:(SP),A // WhichBits comes
from the stack
P:0004072C: 7819 or.w B,A
P:0004072D: D014 move.w A1,X:(R0) Rick Corey -----Original Message-----
From: Bende Georg [mailto:]
Sent: Monday, February 07, 2005 12:08 PM
To: Corey, Rick
Cc:
Subject: AW: [motoroladsp] Using bitfields Hello,

> Have you tried wrapping "interrupt-disable" and "restore interrupt level"
> around the at-risk code? (Just to prove that interrupts are breaking
it.)

I'm not able to do this, since the affected bit fields are referred over 200
times in the software. I did it for the first variable that seemed to be
buggy, the problem appeared at the next one, so I gave up this way of
troubleshooting quickly.
The bitfield referencing on peripheral structures you have mentioned works
for me reliable on both CW5.0 and CW7.0. (6.x versions were not tested.) The
only thing that broke CW5.0 was when I tried to put these variables in a
"while" cycle - in this case the compiled smashed the following error in my
face:
Error : internal compiler error: File: 'IroNonRegLoopAccesses.c' Line:
559
main.c line 101 }

I'll try to isolate the problem more clearly, but right now it appears to be
somewhat "mystic" for me. Sad that these DSPs don't support bit fields like
microcontrollers do - the generated code is inefficient and slow.

Thanks,
Georg Bende > -----Ursprgliche Nachricht-----
> Von: Corey, Rick [mailto:]
> Gesendet: Montag, 7. Februar 2005 17:40
> An: Bende Georg;
> Betreff: RE: [motoroladsp] Using bitfields > Hi Georg
>
> Have you tried wrapping "interrupt-disable" and "restore
> interrupt level"
> around the at-risk code? (Just to prove that interrupts are
> breaking it.)
>
> A co-worker also used to use bitfields with CW 5 on DSP56F803
> (I think the
> CW version was 5.1.2). We used it to poke bitfields registers with
> more-easily-read C code. It was "pretty" code, though very
> inefficient.
>
> When we moved that same code to 56F8357s and CW 6.0, some of
> the bitfields
> broke - I forget whether it was Optimization Level 0 or 1.
>
> Writing to single-bit-bitfields seemed to be OK.
>
> One bitfield was 3bits wide, however, and the 21 lines of ASM
> generated for
> that assignment was strange - it set those 3bits wrong and
> altered other
> bits than just those 3. We probably had a pointer to a
> structure to access
> the register.
>
> I tore out the bitfield code, since it behaved differently
> from one rev of
> the compiler to the next.
>
> My experience was not like yours - mine worked wrong every
> time it ran, with
> the CW6 compiler and the 56F8357. It wasn't intermittent,
> and I had no
> reason to think it was Interrupt-related. It occurred at
> setup time when (I
> think) no interrupts should have been running (but I did not disable
> interrupts during the setup). I never used the CW6 compiler
> on the 56F803,
> or CW5 on the 56F8357.
>
> I'm going to wait before moving to CW 7 ... perhaps
> indefinitely. I don't
> want to be the one to discover new bugs. > I think this is a sample of the code that broke, but it was
> months ago:
>
> //Timer A0 Control Register bit wise structure
> union TMRACtrlReg0Union
> {
> volatile unsigned short *RegAddressVar;
>
> struct CtrlReg0Struct {
> unsigned OutPutMode : 3; /*LSb */
> unsigned CoInit : 1;
> unsigned CounterDir : 1;
> unsigned CountLengh : 1;
> unsigned CountOnce : 1;
> unsigned SecondaryCountSource : 2;
> unsigned PrimaryCountSource : 4;
> unsigned CountMode : 3; /*MSb */
> }*TMRACtrlReg0Struct;
>
> }TMRAcontrolReg0Int; > // GatedCount: enum, 011=3 turns TACH PULSE counter ON
> TMRAcontrolReg0Int.TMRACtrlReg0Struct->CountMode = GatedCount; >
> Rick Corey > -----Original Message-----
> From: Bende Georg [mailto:]
> Sent: Monday, February 07, 2005 10:32 AM
> To:
> Subject: [motoroladsp] Using bitfields >
> Hi CodeWarriors,
>
> I'm using bit fields very extensively in my software. Recently I had a
> very strange bug: the values of these bit fields were
> corrupted if there
> were a lot of interrupts in the same time in the system. It didn't
> happen at once - sometimes the system worked OK for 10 minutes,
> sometimes for an hour, but it came over the time for sure.
> The temporary
> workaround was that I converted the bitfields into 16-bit variables.
> It smells like some stack corruption caused by improper register
> pushing. The question is, why 16-bit variables make a
> difference? Where
> sould I look for the bug?
> I'm using compiler CW5.0 @ DSP56F803; the tests with CW7.0
> had the same
> result. The assembler dump seems to be correct.
> Any hints, suggestions or your own experiences on bitfields
> are welcome.
>
> BR,
> Georg Bende > ------------------------ Yahoo! Groups Sponsor
> --------------------~-->
> In low income neighborhoods, 84% do not own computers.
> At Network for Good, help bridge the Digital Divide!
> http://us.click.yahoo.com/EpW3eD/3MnJAA/cosFAA/PNArlB/TM
> --------------------------
> ------~- >