This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

efficient memcpy of far registers

Dear colleagues,

we are using the TINI DS80C400 platform and the KEIL PK51 development tools.
We would like to perform a fast memcpy of some physical CAN registers located in far memory to a buffer also located in far memory.

We use the following code lines:

#pragma moddp2
#include "absacc.h"

unsigned char far *SrcPtr;
unsigned char far *DestPtr;

SrcPtr = &FVAR(unsigned char, 0xFFDBF7);
/* physical register COM15D0 */
/* or alternatively: SrcPtr = (void far*)0xFFDBF7; */
DestPtr = ...;

memcpy(DestPtr, SrcPtr, 8);
/* should copy 8 bytes */

But it does not work!
What's wrong here?

Thanks for any hint.

Raoul

Parents
  • I think you have a problem with your chosen memory map.

    From L51_BANK.A51:

    ; Each function gets as a parameter the memory address with 3 BYTE POINTER    *
    ; representation in the CPU registers R1/R2/R3.  The register R3 holds the    *
    ; memory type.  The C51 compiler uses the following memory types:             *
    ;                                                                             *
    ; R3 Value | Memory Type | Memory Class | Address Range                       *
    ; -----------------------+--------------+--------------------------           *
    ;    00    | data/idata  | DATA/IDATA   | I:0x00     .. I:0xFF                *
    ;    01    | xdata       | XDATA        | X:0x0000   .. X:0xFFFF              *
    ;  02..7F  | far         | HDATA        | X:0x010000 .. X:0x7E0000            *
    ;  80..FD  | far const   | HCONST       | C:0x800000 .. C:0xFD0000 (see note) *
    ;    FE    | pdata       | XDATA        | one 256-byte page in XDATA memory   *
    ;    FF    | code        | CODE         | C:0x0000   .. C:0xFFFF              *
    ;                                                                               *
    

    From absacc.h:
    #define FVAR(object, addr)    (*((object volatile far *) ((addr)+0x10000L)))
    

    Incidentally, you could use FARRAY() to get a pointer rather than &FAR().

    0xFFDBF7 + 0x10000 is going to roll over to 0x00DBF7. A tag byte of 0 indicates data memory, not xdata memory. A tag byte of 0xFF indicates code memory, not far xdata memory. The xdata address space can only go up to 0x7EFFFF (which maps to a tag byte of 0x7F).

    Can you remap your CAN registers to a lower address?


    (I suspect Keil suffers from a backward compatibility problem here. It would have been much cleaner if three-byte xdata addresses started with a tag of 0x00.... for xdata bank 0. That means the data tag would have to move up, say 0x7d. But that would mean changing all the libraries and breaking anyone's assembler code that processes C pointers. So we're probably stuck with this particular inefficiency and wart.)

    While I'm on the subject of far memory:

    There's FCARRAY, which returns a (object const *). FARRAY returns (object volatile *). This causes lint errors ("increase in pointer capability") for assigments such as

    object* o = FARRAY (object, addr);

    because o loses the volatile qualifier. This statement should be pretty innocuous, though. If you want to insert a volatile qualifier, there should be an FVARRAY to parallel FCARRAY. (There should also be FCVARRAY for completeness, if we're going to keep up this naming convention.)

    FARRAY should just return a bare pointer without any qualifers.

Reply
  • I think you have a problem with your chosen memory map.

    From L51_BANK.A51:

    ; Each function gets as a parameter the memory address with 3 BYTE POINTER    *
    ; representation in the CPU registers R1/R2/R3.  The register R3 holds the    *
    ; memory type.  The C51 compiler uses the following memory types:             *
    ;                                                                             *
    ; R3 Value | Memory Type | Memory Class | Address Range                       *
    ; -----------------------+--------------+--------------------------           *
    ;    00    | data/idata  | DATA/IDATA   | I:0x00     .. I:0xFF                *
    ;    01    | xdata       | XDATA        | X:0x0000   .. X:0xFFFF              *
    ;  02..7F  | far         | HDATA        | X:0x010000 .. X:0x7E0000            *
    ;  80..FD  | far const   | HCONST       | C:0x800000 .. C:0xFD0000 (see note) *
    ;    FE    | pdata       | XDATA        | one 256-byte page in XDATA memory   *
    ;    FF    | code        | CODE         | C:0x0000   .. C:0xFFFF              *
    ;                                                                               *
    

    From absacc.h:
    #define FVAR(object, addr)    (*((object volatile far *) ((addr)+0x10000L)))
    

    Incidentally, you could use FARRAY() to get a pointer rather than &FAR().

    0xFFDBF7 + 0x10000 is going to roll over to 0x00DBF7. A tag byte of 0 indicates data memory, not xdata memory. A tag byte of 0xFF indicates code memory, not far xdata memory. The xdata address space can only go up to 0x7EFFFF (which maps to a tag byte of 0x7F).

    Can you remap your CAN registers to a lower address?


    (I suspect Keil suffers from a backward compatibility problem here. It would have been much cleaner if three-byte xdata addresses started with a tag of 0x00.... for xdata bank 0. That means the data tag would have to move up, say 0x7d. But that would mean changing all the libraries and breaking anyone's assembler code that processes C pointers. So we're probably stuck with this particular inefficiency and wart.)

    While I'm on the subject of far memory:

    There's FCARRAY, which returns a (object const *). FARRAY returns (object volatile *). This causes lint errors ("increase in pointer capability") for assigments such as

    object* o = FARRAY (object, addr);

    because o loses the volatile qualifier. This statement should be pretty innocuous, though. If you want to insert a volatile qualifier, there should be an FVARRAY to parallel FCARRAY. (There should also be FCVARRAY for completeness, if we're going to keep up this naming convention.)

    FARRAY should just return a bare pointer without any qualifers.

Children
No data