Keil Logo

PDATA question

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Read-Only
Author
Eddie Weigle
Posted
14-Jan-2004 00:04 GMT
Toolset
C51
New! PDATA question
I have not used PDATA before, so this may be a silly question. Can I set up PDATA dynamically (within the code) to any 256-byte chunk of xdata? So I can change where the PDATA is "looking" in xdata on the fly, and subsequently have byte addressing (and hopefully faster writes within a loop) for any 256-byte section of xdata at a time?
Read-Only
Author
Drew Davis
Posted
14-Jan-2004 00:54 GMT
Toolset
C51
New! RE: PDATA question
The upper half of the address for pdata is taken from port 2 (usually; your particular variant may have a different SFR for this purpose).

You'll want to be sure to restore P2 if you have declared pdata variables. The linker will expect them to live in a particular page (see the PPAGE directive, and PPAGEENABLE / PPAGE_SFR defines in STARTUP.A51).

I don't think the C compiler and linker support a "banked pdata" mode, where you can declare more than 256 bytes of pdata that live in different pages, and have the compiler automatically generate the correct values to write to P2.
Read-Only
Author
Andrew Neil
Posted
14-Jan-2004 09:51 GMT
Toolset
C51
New! RE: PDATA question
"see the PPAGE directive, and PPAGEENABLE / PPAGE_SFR defines in STARTUP.A51"

Can't see a PPAGE directive in the manuals - just a PPAGE define in STARTUP.A51

"I don't think the C compiler and linker support a 'banked pdata' mode, where you can declare more than 256 bytes of pdata that live in different pages, and have the compiler automatically generate the correct values to write to P2."

That's the way I understand it, too.

But I don't know if you could "roll your own" using the "XDATA Banking" features in the latest versions?
(similar to the way you can give direct 'C' variable access to serial memories)
Maybe Jon Ward could suggest...?
Read-Only
Author
Graham Cole
Posted
14-Jan-2004 10:51 GMT
Toolset
C51
New! RE: PDATA question
It has always seemed to me that it is a pity that it is not possible to take advantage of banking xdata by manipulating P2.

The most obvious way to use P2 would be to have versions of library functions such memcpy() that could take advantage of P2 to be almost as fast as the dual data pointer versions.

Another way might be to be able to define a function as being compact and then specify a page number in a similary way that using specifies a register bank. Of course, this would cause all sorts of potential complications....
Read-Only
Author
Jon Ward
Posted
14-Jan-2004 17:03 GMT
Toolset
C51
New! RE: PDATA question
PDATA is strange. And, it is inconsistently implemented.

In the Intel 8051, you could use R0/R1 to access 256 bytes of a page that was identified with the port value of P2. Thus, Paged XData or PDATA was born.

Then, devices like the Philips 750/751/752 came along with no LCALL/LJMP instructions and no XDATA (and no PDATA either).

Then, devices came along with no external memory (so P2 was available as a General Purpose Port) but with 2K or 4K of on-chip XDATA. But what about PDATA? Well, PDATA was either fixed at page 0, or there was an SFR that set the PDATA page.

The Keil linker has an associated SIZE with each memory type. So, DATA is 128, IDATA is 256, XDATA is 64K, CODE is 64K, PDATA is 256, and so on. If you try to put more stuff than will fit in a memory are, the linker complains.

There is currently no support for PDATA banking to get the compiler to handle more than 256 bytes of PDATA for you.

Using PDATA requires several steps:

  • Copy the startup code to your project directory, modify it for PDATA access, and add it to the project.

  • In the startup code, you must set PPAGEENABLE EQU 1 and PPAGE EQU 0??h (the page to write into P2). There is also a PPAGE_SFR DATA 0B0h. It contains the SFR address for the SFR that contains the PDATA page. Typically, this is the address of P2 but may change depending on the device you use.

  • In the BL51 Linker options, you must specify the starting address for the PDATA memory. Use 0x??00 where ?? is the same thing specified in the startup file for PPAGE. In uVision, enter 0x??00 under Options for Target - BL51 Locate - Pdata.

  • In the Lx51 Linker options, you must specify the range of PDATA memory. Options for Target - LX51 Locate - User Class: PDATA(X:0x??00-X:0x??FF).


Now for responses:

Can't see a PPAGE directive in the manuals - just a PPAGE define in STARTUP.A51

PPAGE and PPAGEENABLE are constants in the startup file (STARTUP.A51). I think they are pretty well described there.

In the uVision Debugger, PPAGE is used to specify the PDATA page for derivatives that don't use P2. See http://www.keil.com/support/docs/2394.htm for more details on that.

You could easily roll your own PDATA banking to access a large buffer. For example:

unsigned char xdata bigbuf [256*40] _at_ 0x0100;

unsigned int index;
unsigned char pdata *p;

.
.
.
P2 = index >> 8;
p = index & 0xFF;
.
.
.

I'm not sure it is as simple for multiple variable types, but I think you could handle things with structs by putting a new struct in each page.

As Graham pointed out, there are lots of clever ways to use PDATA.

...P2 to be almost as fast as the dual data pointer versions

Actually, PDATA access is lots faster than dual data pointers. However, you start running into the same kinds of problems that you do with dual data pointers. Do we save and restore P2 in an interrupt? Do we need a shadow P2 register (since reading P2 on some devices returns the pins and not the port value)? Do we need a P2 and a shadow P2 for both R0 and R1?

For lack of a better term, I'll call this hunk of goo PDATA Banking.

We have not implemented PDATA banking for a number of reasons.

  1. There is always something more important.

  2. Do you know how many support phone calls we get about standard PDATA?

  3. There are only 4 developers in the world who understand and get benefit from PDATA (Andrew, Graham, Drew, and Eric) :-)

Remember that C51 does overlay PDATA variables. So what may appear to be efficient (like assigning a different PDATA bank to each function) or having a banked PDATA area only maximizes the amount of RAM used or minimizes the efficiency of PDATA (since P2 must be reloaded for each access).

Jon
Read-Only
Author
Andy Neil
Posted
15-Jan-2004 00:40 GMT
Toolset
C51
New! RE: PDATA question
Ho-hum.

What it is to be world-famous...




(or is that infamous...?)
Read-Only
Author
Graham Cole
Posted
10-Feb-2004 10:42 GMT
Toolset
C51
New! RE: PDATA question
I took some time out to explore the benefits of using P2 in memcpy() and sure enough, in cases of a copy from CODE to XDATA or XDATA to XDATA there is a very significant speed bonus.

Futhermore, looking through my recent applications, I see that these transfers are very common. Also, the compiler frequently calls memcpy() even when it is not explicitly mentioned in the source. For example, memcpy() is used to copy or initialise structures.

It seems to me that a byte to save a shadow of P2 and a couple of exta instructions in an interrupt such as:
        PUSH    P2_shadow
        ...
        POP     P2
would be a small price to pay for the extra performance.

The version of memcpy() and its siblings that use P2 could be made a compiler option as a tick box on the target tab.

Next Thread | Thread List | Previous Thread Start a Thread | Settings

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.