473,408 Members | 1,702 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,408 software developers and data experts.

Forcing compiler to access bitfields as 32-bits instead of bytes.

In my code, I have bit fields in structures to access hw registers. I tested my compiler to see how it reads/writes to the registers and noticed that the compiler is trying to access the registers by bytes. The HW registers only allow 32-bit "words" to be written or read, otherwise it will give a "bus error".

Is there a way to force the compiler to produce WORD (32bit) accesses for bitfields instead of byte??
Dec 4 '08 #1
5 2286
donbock
2,426 Expert 2GB
Don't use bit fields; instead access each register as an unsigned long and do your own bit manipulations.

Actually, you don't have a firm guarantee that unsigned long will give you precisely 32-bit accesses. Ideally you would use uint32_t from C99. If that isn't an option for you, then create your own typedef. This typedef may need to be changed whenever you port your code to a different compiler.

You need to worry about endianness. The 32-bit words may be written out in a different bit order than the logical values you're manipulating in your program. My suggestion is to use access functions to do all reads and writes. These access functions can include conditionally-compiled code to make endian adjustments for you. You either need to provide your own endian-control macro or use one that your compiler already provides. To prevent anybody from cheating, make sure the register pointers are hidden from the rest of your software.

Don't forget that I/O registers are "volatile".
Dec 4 '08 #2
@donbock

Like this?? :

Expand|Select|Wrap|Line Numbers
  1. typedef struct {
  2.  
  3.   uint32_t reg1 : 25;
  4.   uint32_t reg2 : 5;
  5.   uint32_t reg3 : 2;
  6.  
  7. } volatile RegStruct;
  8.  
Right now I have the same, but the reg types are 'unsigned' instead of 'uint32_t'
Will that make it access the registers by words not bytes?
Dec 5 '08 #3
Banfa
9,065 Expert Mod 8TB
No, Don means do not use bit fields at all.

Read your register into a 32 bit unsigned int and then manipulate that copy that exists in the RAM rather than attempting to access

Expand|Select|Wrap|Line Numbers
  1. uint32_t reg = *((volatile uint32_t *)REGISTER_ADDRESS);
  2.  
  3. uint32_t reg3 = (reg & 0xC0000000) >> 30;
  4.  
  5. // etc
  6.  
Do not make bit accesses to registers, it can produce unpredictable results.

I fixed this exact problem in project I work on 2 weeks ago. Accessing an analogue-digital converter the original code ready the ready bit until it was set and then read the data bits. But these bits were all part of the same register and reading it clears the ready bit and starts the next conversion so by reading the ready bit the data bits become invalid.

I changed the code to read the register into a local variable, test the ready bit in that variable and if set extract the data bits from that variable.

The difference? Before the change for a given input the readings averaged 85 with a standard deviation of 110 after the change for the same input the reading averaged 137 with a standard deviation of 3.

Not reading the register correctly and in a single access really messed things up.
Dec 5 '08 #4
donbock
2,426 Expert 2GB
However, instead of sprinkling references to REGISTER_ADDRESS throughout your code, I suggest you provide two access functions:

unsigned long readRegister(void);
void writeRegister(unsigned long value);

These functions dereference the REGISTER_ADDRESS, but everybody else calls these functions. That way, any endian conversions that become necessary are localized to these two functions.

Notice that I'm suggesting the prototypes for these functions use 'unsigned long' rather than uint32_t. That's my own personal preference -- I like to minimize the scope of specific-width types. The access functions would have to cast to and from uint32_t. Unsigned long is guaranteed to be at least 32 bits wide, so it would work everywhere except possibly where the register accesses take place.

Suppose you want to set one bit in a register. The following snippet looks correct:
Expand|Select|Wrap|Line Numbers
  1. unsigned long value;
  2. value = readRegister();
  3. writeRegister(value | BIT_MASK);
A not uncommon headache for device driver writers is that some hardware provides write-only registers. If that were true here then the preceding code probably corrupts part of the register because readRegister() returned garbage.

The way to deal with that problem is to maintain a "ram image" of the register. The writeRegister() function writes its argument value to this local static variable and also to the register. The readRegister() function returns the value of the ram image instead of vainly trying to read the register itself. There are a couple of limitations to this strategy:

1. The ram image is not initialized until after you call writeRegister(), therefore you want to be sure you don't call readRegister() first.

2. writeRegister() isn't thread safe: if another thread calls readRegister() between the time the ram image is written and the time the register is written then it will not get the correct value for the contents of the register.
Dec 5 '08 #5
Thanks guys!! We are convinced of moving away from bit fields - and I will work on your suggestions now...
Dec 5 '08 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

8
by: Michael Gaab | last post by:
How would I force the compiler to throw an error for the following: function signature - void foo(short); function call - foo('d'); My compiler does not complain when I call foo() with a...
43
by: Mr.Tickle | last post by:
// Run this code and look for his obvious error by the compiler namespace FlagCheck { using System; enum SomeFlags {
6
by: tmartsum | last post by:
I have a discussion in comp.std.c++ After a (bit stupid) suggestion on representing a fixed 'big' length int I moderated it to "Bitfields-ints should be allowed to have any fixed length" I...
8
by: Régis Troadec | last post by:
Hi all, I follow c.l.c. for only a short time and I would like to know why there isn't anything concerning bitfields among the FAQs. Is it because ... 1. of portability issues? 2. bitfields...
2
by: Mary | last post by:
Hello, I am having a problem with the cl compiler. I have written a C class (RegConnect.c) which uses Win32 API functions such as RegOpenKey, RegCloseKey etc. Initially when I was trying to...
40
by: Neo The One | last post by:
I think C# is forcing us to write more code by enforcing a rule that can be summarized as 'A local variable must be assgined *explicitly* before reading its value.' If you are interested in what...
7
by: gert.vierman | last post by:
Hello, Here is some code mixing bitfields and longs in an union. Any comments on the validity and portability of this program ? Thank you very much. #include <stdio.h> union msg_t {
18
by: richard_l | last post by:
Hello All, I am writing an application which receives a word which is a bitmap. I have created a word typedef which contains a bitfield defining each bit. however, I was wondering however if it...
8
by: Gerhard Fiedler | last post by:
Hello, I'm not sure whether this is a problem or not, or how to determine whether it is one. Say memory access (read and write) happens in 64-bit chunks, and I'm looking at 32-bit variables....
5
by: David Thielen | last post by:
Hi; We keep having to restart IIS after ASP.NET kills it. Below is what we have in the event log. Any idea what the problem is? thanks - dave Event code: 3003 Event message: A validation...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.