How would I locate a structure to coincide with the beginning of SFR space for the 8051? address 0x80 of directly assessible data memory.
We are using a core8051 (inside an FPGA), and the core8051 lets us map external events to SFR space. So it would be very convienent to define a structure which allows us to more easily access all of SFR space. (we take care not to "stomp" on already defined SFR registers.
How can I do that?
Thanks
You can't. SFRs live in a completely separate address space. The 8051's machine language only lets you get at this memory space via direct addressing. But direct addressing is quite useless for aggregate data structures. There are no pointers to SFRs, and no structs in SFR space. Basically SFRs can only be used to store individual bytes or bits.
Hmmm. but I think you can declare a struct in the SFR space. I found this
http://www.keil.com/support/docs/2998.htm
that seems to do the trick for me.
Hopefully I don't hit too many roadblocks (everything compiles and seems to work so far).
Why do you want to overlay SFR space with a structure?
The usual reason for declaring a structure to overlap registers is to access multiple instances of a piece of hardware via a base pointer. That is, the code looks something like:
instance1->intMask |= myInt; instance2->intMask |= MyInt;
The 8051 architecture isn't well suited to pointers, so this coding style wouldn't be very efficient.
Even if you locate a single copy of the structure at a fixed memory location
struct { ... } SFR _at_ 0x80; SFR.P0 |= 1;
you're going to run into the 8051 quirk that the addressing mode interacts with the address to determine what address space you actually wind up seeing.
There are two of each address 80H through 0FFH. Direct addressing reaches an SFR. Indirect addressing reaches a byte of RAM (for variants with 256 bytes of RAM intead of 128). If you try to make SFR space look like a variable in data space, you're going to run the risk of confusing the code generator and having it generate an indirect access to a location, which won't do what you want.
The sfr keyword is in C51 for a reason. SFRs are not like just another byte of data space. The 8051 is a peculiar architecture with concepts that C, with its CPUs-have-exactly-one-address-space assumption, doesn't quite match.
You might want to consider sticking with the definitions in the REG.h files and the coding style that just treats SFRs as independent variables.
EA = 0; P0 &= 0x0f;
We are using a core8051 (inside an FPGA), and the core8051 lets us map external events to SFR space.
There is a '51 standard and all I can suggest is "deviate at your own risk"
That some nonstandard practice is possible with a version of the compiler would, by many, be considered an error and thus you could find it fixed in the next release.
My suggestion would be to limit the 'expanded possibilities' of the core8051 to what you see as 'normal differences' between derivatives of the '51 (added SFRs) - why do you need to I locate a structure to coincide with the beginning of SFR space why not just define whatever you have there as SFRs.
erik
Hopefully
That's exactly the problem, in a single word. You're relying on hope to resolve a technical problem. That cannot ever, possibly, be a good idea.
That link you dug up doesn't actually define the struct in C --- it declares it in C, then defines the address (but not the size) in assembly. The C compiler doesn't even know this structure is in SFR space. That opens a can of worms like you wouldn't believe. E.g. if you were to use struct assignment on such a struct, the compiler would almost certainly use its internal equivalent of memcpy() to do that --- but that uses pointers, and there is no such thing as a pointer to an SFR. Madness will ensue.
Basically none of the things for which a struct offers any actual advantage over individual variables can really work if the struct is in SFR space. The net gain between
sfr foo_a; sfr foo_b; sfr foo_c;
and what you want to do:
sfr struct { u8 a; u8 b; u8 c; } foo;
is, for practical purposes, zero.
"map external events to SFR space"
What does that actually mean?
All standard 8051s access their peripherals via SFRs (or memory-mapping), so I don't see how this differs from a standard 8051 chip - except that you are defining the SFRs yourself.
Thus, I don't see how this struct idea will help - and others have already pointed out serious flaws!
I have a guess
In 'big time computing' you typically describe a device as a struct such as
typedef struct { u32 counter u32 reload u16 control u16 status } TIMER
I guess the OP is trying to apply 'big time computing' philosophy to the poor little '51 as so many have done before with disastrous results.
I can see the thinking "since this is a 'core51' there is no need to read "the bible" that can not possibly apply"
Maybe I'm wrong, maybe I'm right as said "I have a guess"
Erik
Thanks for your replies everyone. Your comments are well noted, and I will re-write everything using SFR terminology. Everything actually works fine in the simulator so far as is, but I admit, I am a bit scared of the "pointer to SFR" stuff, so I absolutely agree with yall about that.
A little more insight as to why I was trying to do what I was. We have used an 8051 several times previously, and the 8051 essentially only interacts with an FPGA, which in turn interacts with the rest of the system. So we basically mapped all kinds of system status and such to xdata space for the 8051. We then defined a struct for all of the FPGA registers (did we have to--no, is that big time programming? -to each his own I guess).
Well, this project began using the core8051, and we initally treated it the same, i.e. mapping all the FPGA to xdata space, and we again created a struct (~70bytes large) to simplify downstream programming. Well, because of some performance requirements on our instrument, we were looking for ways to speed up tasks. And we decided, since the core8051 allows you to directly modify unused SFR registers using external sources (say a buffer read from our detector. The FPGA can modify the SFR space on its own) that we could save quite a few instructions by accessing the FPGA registers as unused SFR, as opposed to xdata space.
So we modified the FPGA to do just that, and in an attempt to salvage the already written code, it seemed reasonable to redefine our struct, as most code using it would not have to be changed, as the struct name and fields would remain the same.
It sounds that it is prudent to invest in the work to use the SFR context and change the code.
Lastly, all of your comments were useful, although I really don't understand the value of the last comment. Not using structs because your are using an 8051? I guess to each his own.
Not using structs because your are using an 8051? I guess to each his own.
Of course not. If you heard what i thought I said it is: "Not using structs to describe I/O because your are using an 8051".
There is nothing against using structs (I do) but for I/O where time often is an issue (pointers to) structs can really slow you down.
And we decided, since the core8051 allows you to directly modify unused SFR registers using external sources (say a buffer read from our detector. The FPGA can modify the SFR space on its own) that we could save quite a few instructions by accessing the FPGA registers as unused SFR, as opposed to xdata space.
One more thing to consider here is that you use up a lot of SFR space.
If you need access to a buffer of data (rather than individual status bytes) you could implement a FIFO using SFRs. When you need to read the buffer, you simply initialize the FIFO and read. The FIFO pointer could be designed to automatically increment. Similar techniques have been used by some of the early 8051-based USB devices rather than a large memory-mapped block.
Jon
Jon-
Yes, indeed that is exactly what we are doing. it is an 8k buffer, but the 8051 only sees a byte, and we read that byte as fast as we can.
Erik-
Sorry, I apologize, I misread what you were saying. Thanks for the clarification.
Eddie
fast as we can Eddie, now you are talking my language. I have, since - due to what I make - "speed is my game" developed tricks galore and maybe, just maybe, I have a trick to speed up what you do.
If you want to, you can post your 'fast code snippet' and if I see any way to speed it up, I'll happily let you know what it is.
If confidentiality is an issue and you still want my comment(s) e-mail me. BTW confidentiality is the only reason I find acceptable for communication outside the forum if the issue belong in a forum.
Excellent! Thanks. I will post some, but it will be a few days, as I have some other project bs to clean up right now.
"for I/O where time often is an issue (pointers to) structs can really slow you down"
One more time:
accessing a structure field as, eg, a.b.c has no more run time overhead than a direct variable access.
The runtime overhead only comes when you start using pointers; eg, pA->pB->pC