|
Thanks for that breakdown, no wonder I was having an issue with the first example Im still pretty bad when it comes to points to pointers and I get lost in whats data and whats an address.
So to access an already initialized piece of memory I use Type *Type *ptr(reinterpret_cast( location )); Creating a double pointer with the first layer being accessible to you but your changes flowing to the bottom layer in the cast? Hopefully thats right.
I have whipped up some code with the union structure (I forgot a unions members occupy the same memory location, duh so that was easy) I have tested it by using the code below and I can use printf to dump the flags and reg and it works perfectly. The problem with this is that I need to initialize every flag manually however the hardware address I am pointing to is all zeros by default so is it safe to ignore this??
#include <stdio.h>
typedef struct
{
unsigned RX0E:1;
unsigned TX0E:1;
unsigned RX1E:1;
unsigned TX1E:1;
unsigned RX2E:1;
unsigned TX2E:1;
unsigned EOFF:1;
unsigned FNEF:1;
} COMM;
typedef union
{
COMM flags;
unsigned reg;
} COMM_FR;
int main()
{
COMM_FR myflags = new( (void *)(0x1400000) ) COMM_FR;
myflags.flags.RX0E = 1;
myflags.reg = 0x2A;
return 0;
}
However when I change things around so the flags are initilized via a union constructor and make the flags a pointer it compiles without error but when run i get exception 6392.
#include <stdio.h>
typedef struct
{
unsigned RX0E:1;
unsigned TX0E:1;
unsigned RX1E:1;
unsigned TX1E:1;
unsigned RX2E:1;
unsigned TX2E:1;
unsigned EOFF:1;
unsigned FNEF:1;
} COMM;
typedef union
{
COMM *flags;
unsigned reg;
void COMM_FR()
{
flags->RX0E = 0;
flags->RX1E = 0;
flags->RX2E = 0;
flags->TX0E = 0;
flags->TX1E = 0;
flags->TX2E = 0;
flags->EOFF = 0;
flags->FNEF = 0;
reg = 0x00;
};
} COMM_FR;
int main()
{
COMM_FR *myflags = new( (void *)(0x1400000) ) COMM_FR;
myflags->flags->RX0E = 1;
myflags->reg = 0x2A;
return 0;
}
I would prefer to use the second example as the rest of my handling is done via -> and with a compiler that does not support auto-complete having combinations of -> and . member access is infuriating.
|
|
|
|
|
Ouch. Neither of your examples are going to work.
The first one won't because of this line...
COMM_FR myflags = new( (void *)(0x1400000) ) COMM_FR;
What this line says is: "Initialise an object of type COMM_FR at the specified location in memory. Create a completely new object of type COMM_FR and initialise it from the object you've just created."
You can see this by taking the address of COMM_FR - it's almost certainly not going to be 0x1400000.
The second won't work Flags is never going to be a pointer. It's a physical lump of memory, not the address of the memory. Here's how I'd have a go at writing the same sort of thing:
struct COMM
{
unsigned RX0E:1;
unsigned TX0E:1;
unsigned RX1E:1;
unsigned TX1E:1;
unsigned RX2E:1;
unsigned TX2E:1;
unsigned EOFF:1;
unsigned FNEF:1;
};
Quick note here: You don't need typedef so much in C++. Generally it's only used to simplify complex types.
union COMM_FR
{
COMM flags;
unsigned reg;
COMM_FR() : reg( 0x00 ) {}
};
You only need to initialise one "view" of the union in it's constructor. Constructors don't have a return type, even void. The comment about typedef applies as before.
Now you've got two ways of setting up access to your device... The first way is if you want to zero the register when you first use it - you have to invoke the constructor:
int main()
{
COMM_FR *myflags = new( (void *)(0x1400000) ) COMM_FR;
myflags->flags.RXOE = 1;
std::cout << std::hex << myflags->reg << std::endl;
}
The placement new invokes the constructor so the register will be written to implicitly before the line setting RXOE.
The second way is if something else has initialised the hardware and you're just using it:
int main()
{
COMM_FR *myflags = reinterpret_cast<COMM_FR *>( (void *)0x1400000 );
myflags->flags.RXOE = 1;
std::cout << std::hex << myflags->reg << std::endl;
}
This one doesn't execute the constructor at all, so the final result depends on what state the register is in before you set RXOE.
PS: Just noticed that Luc makes a good point about volatile. Make sure that anything that touches the bare metal is volatile or your cunning compiler will have a good go at eliminating writes if it doesn't change the visible effects of your program.
|
|
|
|
|
Well that works wonderfully!
I tried bother versions and can access the memory locations just as I wanted. Thanks!
I would really love it if I could access the flag names via a -> though to keep everything the same. I have written plugins for engines before that took several compiles because of variables setup like: Engine->PIO.LPT1->Data.D0 = 1; and when the implementation is hidden from the end uses how the heck are they suppose to know when to use a pointer or the . member of addressing?
|
|
|
|
|
union {
struct bits {
uint8_t b0:1;
uint8_t b1:1;
uint8_t b2:1;
uint8_t b3:1;
}
struct theSameBits {
uint8_t RX0E:1;
uint8_t TX0E:1;
uint8_t RXB0E:1;
uint8_t TXB0E:1;
}
}
would put both sets of bits at the same memory address, after all that is what unions are about.
Read the language specification!
BTW: you "answering" like that, to yourself, causes no signal being sent to whomever you want to read it, only a proper "reply" (not to your own message, hence the warning you've got) would send a mail notification.
|
|
|
|
|
Thanks for the info on the board, I didn't even know I replied to myself.
I only use union every few months and every time I need to google them over again as I forget what they do. I got it working in my latest post so I can access the bit field as a solid byte which is pretty easy when you rtfm lol.
Any ideas on why I am getting runtime errors but not compile time errors on my latest attempt using pointers?
|
|
|
|
|
I'm not following all the details in your thread.
I have two pieces of warning though about code snippets such as:
flags->RX0E = 0;
flags->RX1E = 0;
flags->RX2E = 0;
1.
if the object pointed to isn't marked volatile, the resulting code might not access the register at all until later. (read up on volatile if you're not familiar with it).
2.
assuming volatile got applied, three stores using "flags" would cause either:
- three times a read and a write to the register (read entire byte, adjust one bit, store new byte value);
- three bit operation instructions which some micro-controllers would object to for special registers; I don't know what your target is, nor whether Intel likes them or not.
Whatever is the case, it may turn out not to do what you want it to do.
My advice is:
- read the manual, about what is allowed/defined and what is forbidden/undefined;
- check the assembly instructions your source code results in.
- when those two don't match, adjust your source code.
In general, I tend to use a union with on the one hand the full register, on the other hand the individual bits or bitfields.
|
|
|
|
|
I will remember to mark things as volatile, I have had problems with them in the past when the compiler has optimized a register check right away and boy can they be hard to find sometimes.
I am aware that any change to the bits will require re-writing the whole byte but the processor is geared to handle full register writes in once cycle so I'm not worried. The main reason I am trying to get this set up is to allow a more natural peripheral configuration scheme as currently if you don't have the 1072page manual and the nemonics memorized you will never get anything to work. I wish to re-write things for easier access and properly document the usage.
|
|
|
|
|
I've seen all kinds of peripheral chips; for some, writing a bit causes something to happen, even when the value doesn't change. Others had bits with different semantics on read and write (e.g. on write the bit is an "interrupt enable", while on read it is an "interrupt received"), so you just can't simply write back what you have read before (which is what your flags->b3=0; might do to all 7 bits you think you are not touching).
|
|
|
|
|
True, I know on AVR's you write a 1 to the bit to clear an interrupt and if I read the register before the ISR is called that would be a problem. This could get quite difficult now...
How the heck to the people who write the header files for chips do these things then? For example here is some bus handling setup from an ARM:
RCC->APB1RSTR = 0x00000000;
RCC->APB2RSTR = 0x00000000;
RCC->AHBENR = 0x00000014;
RCC->APB2ENR = 0x00000000;
RCC->APB1ENR = 0x00000000;
RCC->CR |= 0x00000001;
RCC->CFGR &= 0xF8FF0000;
RCC->CR &= 0xFEF6FFFF;
RCC->CR &= 0xFFFBFFFF;
RCC->CFGR &= 0xFF80FFFF;
RCC->CIR = 0x00000000;
They must have a different implementation of how these registers get written as the RCC->CR |= 0x00000001; will cause errors like you say if any bit besides the first one is set. This would be alot easier if their was open source code to walk through and see exactly how changes effect the system.
My goal is to make these register assignments much easier to use. Instead of writing a 32bit value to the entire register or even ORing the bit you want changed in it would be better to have bit level access with the names available to make the code more readable.
For example if you want to enable the clock to timer1 you would write:
<br />
RCC->APB2ENR = 0x00000800<br />
but I want to add access like:
<br />
RCC->APB2ENR->TIM1EN = true;<br />
or better yet:
<br />
HW->Reset_Clock_Control->APB2_Bus_Enables->Timer_1 = true;<br />
I like the functionality in Eclipse IDE that shows the documentation of the thing you have intelisense popping up for you so when you type HW-> you given not only a list of available hardware settings but a description of them. My compiler does not do this but I can at least include documentation in the header and provide an open source file so people know what they heck is going on. as a 1072 page manual is annoying and if you search adobe usually freezes for a few minuets first.
|
|
|
|
|
1.
one can write a header file that contains:
- register addresses (relative to some base address);
- bit numbers, bit masks, bitfield masks
- structs, unions, typedefs
these are pretty much independent of the actual compiler.
2.
you can write executable code that manipulates the registers, based on such header files, AND on some assumptions about the compiler and micro-processor. Most often a vendor offers a free development environment (IDE, compiler, ...), header files and executable code, all working together. There is no guarantee that source code files (other than header files) will work well on another compiler, let alone another micro-processor + compiler combination.
3.
if you're lucky, the peripherals won't have nasty characteristics like the ones I described. Older ones typically do, as they tried to cram all functionality in a small number of (narrow) registers. Newer devices tend to have more registers, wider registers, and several unused bits, alleviating the need for design tricks.
|
|
|
|
|
Hi Trevor,
Trevor Johansen wrote: my GCC compiler does not have STL support only the standard set of c libraries .
The <bitset> header is present in GCC from around 3.0.
Check your '<GCC install>/include/c++/<version number>/bitset'.
cheers,
AR
When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)
|
|
|
|
|
Hi Alan,
Normally I'd say use standard library features but the union of bit fields with an integer of the correct size has some advantages:
- you can name your bits
- you can deal with collections of bits (electronic engineers like packing them it, so you'll often get things like a 4 bit number, a 2 bit number and 2 x 1 bit numbers in one 8 bit register)
Cheers,
Ash
|
|
|
|
|
Hi Ash,
Aescleal wrote: Normally I'd say use standard library features
I have noticed that
Aescleal wrote: the union of bit fields with an integer of the correct size has some advantages:
- you can name your bits
For single bit manipulation you can name your bits and your patterns with enums and std::bitfield makes it simple and easy to maintain:
typedef std::bitset<8> MyBits;
enum e_REG { RX0E, TX0E, RX1E, TX1E, RX2E, TX2E, EOFF, FNEF};
enum e_VAL { val_OK = 0, val_SOMETHING = 0x4A, val_FAILURE = 0x8f, };
MyBits myReg(val_SOMETHING);
myReg[RX2E] = true;
if (myReg == MyBits(val_FAILURE))
{
Aescleal wrote: you can deal with collections of bits (electronic engineers like packing them it, so you'll often get things like a 4 bit number, a 2 bit number and 2 x 1 bit numbers in one 8 bit register)
For that cases the poorly documented std::valarray<bool> is powerful.
With the C++0x lambdas, conversions between bitsets and valarrays become a breeze, so you can benefit of both
cheers,
AR
When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)
|
|
|
|
|
Cool, I'll have to look at them a bit more closely. I've had problems in the past with bitsets mapping to hardware but that was probably some form of muppetry on my part.
Cheers,
Ash
|
|
|
|
|
My target hardware is ARM and my compiler only supports c/c++ standard libraries and not STL. http://www.cplusplus.com/reference/[^] In that link I have all the libraries up to but not including STL.
Gcc version is 4.1.0 Codesorcery ARM however its a branch of that tool chain for Cortex support.
|
|
|
|
|
Just out of interest STL is part of the standard library. A C++ standard library is like a C library without stdlib and string, almost completely useless.
Cheers,
Ash
|
|
|
|
|
I followed a basic DirectX tutorial that displayed a cube, were each of the sides displayed
were not anti aliased, 'I thought that directx would deal with this',
Can anybody tell me why this is so? And:
I used getPixel command in mfc to retrieve the values of a loaded
image in MFC, so I could use these in Directx, when ploting these
in directx, usiung the approbiate draw pixel command,
the overal image size differs from the original, it was shorter!
The ratio of plotting a pixel in MFC comparing to Directx differs
Why so, Please can somebody enlighten me?
Cheeers Simon S
modified on Monday, September 27, 2010 5:43 PM
|
|
|
|
|
Yes I know it is a Database question but I have not had much luck in that forum so I am looking for a fresh perspective.
I am using accessors to perform DB queries which works fine except when I come to do INSERTs.
This is the SQL in the accessor
DEFINE_COMMAND_EX(CDBEvtRawInsert, L" \
INSERT INTO [RawEvent] ([TimeStamp],[Direction],[Hub],[RawEvent]) \
VALUES (GETDATE(),? ,? , ?);")
which works fine with this snippet...
wcscpy_s(rsEvtRawInsert.f_RawEvent, iSize*2, CA2T(pTmp));
rsEvtRawInsert.f_Direction = 1;
rsEvtRawInsert.f_HubID = m_pHubDev->m_iHubID;
hr = rsEvtRawInsert.Open(m_oDB->session);
However in order to retrieve the ID of the record which has just been inserted I need to add SELECT @@IDENTITY AS RecID to the SQL but this makes it a multiple command accessor which is where my problem is.
I have search MSDN and the SDK's but for the life of me I cannot find anything that shows me how to code the accessor properly to deal with the multiple results. I know I can use GetNextResult to move onto the second result set but I cannot get it to work.
It has been suggested using ExecuteScalar would be the solution but as I am going to have multiple threads executing the same code I would prefer to use the @@IDENTITY to avoid any possible collisions between the threads.
The only other solutions I can think of are to either issue a search to find the record I have just created OR maintain a counter which would track the ID field.
Does anyone have any other ideas or point me to a way to get the accessor to process my multiple commands?
Alan
|
|
|
|
|
I have a multidoc app based on CFormView. I have a dialog using CListCtrlEx. Everything works fine. I moved the CListCtrlEx object from the dialog to the view (CFormView). Now it doesn't work. The call to GetHeaderCtrl() for the CListCtrlEx object now returns NULL whereas it didn't when that object was in the dialog. Anyone know why that should be and how I can get the call to GetHeaderCtrl() to return the CHeaderCtrl() when it's in the view instead of the dialog? Thanks in advance.
|
|
|
|
|
As what often happens, I found my problem after posting. In the words of Emily Latella, "never mind" (I think that was Emily, wasn't it?)
|
|
|
|
|
Hi everyone. I have a console application that plays .mp3 and .wav audio files. For .mp3 audio files there is no problem but when playing .wav audio files (PCM), there is always a pop sound at the end of the file. That is, the last bytes that get written to the audio device always produce a pop sound even for different .wav audio files. I tried to change the size of the buffer (4kB, 6KB, 8KB) but I still hear these pop sounds. What I have done is to read a fixed size of wav samples from the file and write them. When the bytes remaining in the file is less than this fixed size, the program reads only the size remaining in the file and writes these wave samples but the last samples read and written to the audio device produce the pop sound. However, when I play these .wav files with other media players, the pop sound is not produced. What am I missing?
|
|
|
|
|
Just a quick idea here since i don't know the wav format but why don't you padd your buffer with zeroes (or whatever will produce silence)?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> "It doesn't work, fix it" does not qualify as a bug report. <
> Amazing what new features none of the programmers working on the project ever heard of you can learn about when reading what the marketing guys wrote about it. <
|
|
|
|
|
I have tried that as well. I had to padd the last 8 bits with zero values as follows:
memset(&samples_buffer[fileBytesRead], 0, 8);
where fileBytesRead has the total size of bytes read from the file but I was still hearing the pop sound.
|
|
|
|
|
Are you sure the pop comes because of those "extra" bytes? As said, i don't know wav but maybe you need something else than simple zeroes to specify silence. Come to think of it, you probably have to "decode" the wav to feed it to the sound driver, so maybe you need to give the "silence" in the end of the sound in a format the sound driver (or hardware?) understands. Am just guessing...
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> "It doesn't work, fix it" does not qualify as a bug report. <
> Amazing what new features none of the programmers working on the project ever heard of you can learn about when reading what the marketing guys wrote about it. <
modified on Friday, September 24, 2010 3:41 PM
|
|
|
|
|
Hi,
If I create a view like
CMyView *pView = new CMyView();
How should I delete it wheather using
pView ->DestroWindow() or
delete pView ;
|
|
|
|
|