Paged ram/ far pointers CW S12X

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Paged ram/ far pointers CW S12X

Jump to solution
4,373 Views
quasio
Contributor I

Hi all,

I'm having trouble understanding and utilising far pointers and various pages of ram. (i'm using chip S12XEP100)

 

I'm trying to make a custom secondary bootloader, and having the program in RAM, with default_ram (variables and that) and large buffer in PAGED ram. 

 

So i've mapped default_rom into ram; (0x2100 to 0x3900) (downloaded from a primary bootloader)

my_data_ram into PAGE_RAM_F0 (F01000 to F01FFF)

my_data into PAGE_RAM_F3 (F31000 to F31FFF)

 

I've then defined all my variables at page F0 using #pragma DATA_SEG __RPAGE_SEG MY_DATA_RAM

Which seems to work fine, and are happy together.

 

Now the issue is i want to copy data using pointers from one page to another, i.e. my_data into my_data_ram but looking at the debugger, it doesn't seem like RPAGE is changing in these conversions.

 

So trying to declare _far  *my_data_ptr doesn't seem to work, it just accesses RPAGE F0 data at the address rather than RPAGE F3

 

i've modified my far pointers to be in RPAGE F3 but that doesn't seem to do anything.

 

(is there a document/tutorial on how to use paged ram properly? am i missing something fundamental? can you copy data from one page to another easily?)

Labels (1)
Tags (1)
0 Kudos
1 Solution
994 Views
CrasyCat
Specialist III

Hello

 

Not sure I understand your issue here, but if you are looking for a way to access paged RAM using RPAGE register you need to define your data as a

    char *__rptr  my_data_ptr;

 

If you want to access you paged RAM using GPAGE register, the pointer should be defined as follows:

    char *__far  my_data_ptr;

 

Attached technical note demonstrate how to use the various pointer types to access data.

 

CrasyCat

 

TN238.pdf

Message Edited by t.dowe on 2009-08-31 11:09 AM

View solution in original post

0 Kudos
8 Replies
995 Views
CrasyCat
Specialist III

Hello

 

Not sure I understand your issue here, but if you are looking for a way to access paged RAM using RPAGE register you need to define your data as a

    char *__rptr  my_data_ptr;

 

If you want to access you paged RAM using GPAGE register, the pointer should be defined as follows:

    char *__far  my_data_ptr;

 

Attached technical note demonstrate how to use the various pointer types to access data.

 

CrasyCat

 

TN238.pdf

Message Edited by t.dowe on 2009-08-31 11:09 AM
0 Kudos
994 Views
jcdammeyer
Contributor III

I'm having trouble declaring a variable larger than one page of RAM.

 

The code is declared as follows but the linker complains that there isn't enough space at FB1000 which makes sense because the array is 5130 bytes in size and that's larger than the 4K page.  What am I doing wrong?  According to TN238 I should be able to declare a gobal larger than a page size.

 

Thanks.

John

 

#pragma DATA_SEG  __GPAGE_SEG PAGED_RAM
TLEDLAMP Rings[RING_COUNT][MAX_LAMP_NUMBER];
#pragma DATA_SEG DEFAULT

 

As per TN238 I have

SEGMENTS

RAM_FB = READ_WRITE 0xFB1000 TO 0xFB1FFF;

RAM_FC = READ_WRITE 0xFC1000 TO 0xFC1FFF;

RAM_FD = READ_WRITE 0xFD1000 TO 0xFD1FFF;

/* Other segment definition here*/

END

PLACEMENT

PAGED_RAM INTO RAM_FB, RAM_FC, RAM_FD;

/* Other placement definition here*/

END

0 Kudos
994 Views
kef
Specialist I

Data has to fit available segment. Since RPAGE page has only 4k, you need to put your data to memory with bigger segments.

 

You can combine several RPAGE pages into contiguous global memory segment like this:

 

SEGMENTS

/*

RAM_FB = READ_WRITE 0xFB1000 TO 0xFB1FFF;

RAM_FC = READ_WRITE 0xFC1000 TO 0xFC1FFF;

RAM_FD = READ_WRITE 0xFD1000 TO 0xFD1FFF;

*/

RAM_FBFD = READ_WRITE 0x0FB000'G TO 0x0FDFFF'G;

 

.....

 

PLACEMENT

PAGED_RAM INTO RAM_FBFD/*RAM_FB, RAM_FC, RAM_FD*/;

 

 

Also, you need to add to compiler settings -D__FAR_DATA.

 

Seems to work for me.

 

0 Kudos
994 Views
CompilerGuru
NXP Employee
NXP Employee

As work of warning, only use global/gpage/far accesses when using global segments which cross a logical page boundary,

don't use the more efficient RPAGE accesses.

 

I would only use global addresses for 2 cases, for large objects bigger than the page boundary (as it is the case here) or for accesses to the external area not mapped in the logical address space. For everything else, I'm recommending paged addresses.

 

Daniel

0 Kudos
994 Views
kef
Specialist I

Daniel,

 

Yes, your warning is important. Array or wider than 1 byte variable allocated in single G-segment may get allocated in two R-pages. RPAGE accesses may fail in this case. Also, if using PAGED_RAM variables from ISR, one should save/restore GPAGE or RPAGE or even both paging registers.

 

But your words about more efficient RPAGE accesses dragged my attention. Yes, I agree, Gxxx instructions cost extra byte, extra CPU cycle, also not all instructions (like BSET) are available for global addressing. But 64k big G-page in contrast to 4k R-page should allow to reduce page register switching, isn’t it? Single G-page covers all available internal S12X RAM. In case paged flash and external bus accesses are not necessary, it is physically possible to setup GPAGE register once and not touch it any more. Global accesses could be more effective in this case, right? But I wondered how CW compiler deals with paging registers and found something bad.

 

I tried to put 3 variables into PAGED_RAM and initialized them from main(). PRM file is project wizard default and not touched. I disassembled C file and noticed that RPAGE register is set up once. That’s weird. How does compiler recognize that paged variables are linked to the same R-segment? Maybe compiler/linker force all paged data from same *.c file to single R-segment? I tried to move data definitions to another *.c module and declaring data in main.c between DATA_SEG pragmas. It didn’t change anything. I also tried to allocate more than 4k in DATA_SEG. Disassemble didn’t changed, also I didn't get single warning.

 

#pragma DATA_SEG __RPAGE_SEG PAGED_RAM

char a[4096-4]; // code works only if all three a, b and c fit single 4k R-segment.

short b,c;

#pragma DATA_SEG DEFAULT

 

void main(void) {

  /* put your own code here */

 

   a[100] = 123;

   b = 456;

   c = 789;

 

Disassemble:

 

   28:     a[100] = 123;

  0000 c600         [1]     LDAB  #PAGE(a)

  0002 5b16         [2]     STAB  /*RPAGE*/22

  0004 c67b         [1]     LDAB  #123

  0006 7b0000       [3]     STAB  a:100

   29:     b = 456;

  0009 cc01c8       [2]     LDD   #456

  000c 7c0000       [3]     STD   b

   30:     c = 789;

  000f ce0315       [2]     LDX   #789

  0012 7e0000       [3]     STX   c

 

Of course this fails if I define a as char a[4096];. a and b are placed in different R-segments, but RPAGE is not switched when accessing a and b.

 

Am I missing something? I guess I should make service request for this.

0 Kudos
994 Views
CompilerGuru
NXP Employee
NXP Employee

There is a compiler option to configure that, not sure about the name out of memory.

 

By default the compiler assumes that user defined sections as PAGED_RAM are placed into a single PAGE only, that's why there is only a single RPAGE write.

This setup will need a new entry in the prm which maps PAGED_RAM to single paged segment only.

 

With the option this behavior can be changed so that the compiler will set RPAGE for each different variable it accesses.

 

About the efficiency of GPAGE. I think the limited set of instructions available is more severe than the additional byte per GPAGE access instruction, well the effect of both parts just add up. The optimization with fixing GPAGE is a good idea, but it can only be used if GPAGE is used for no other purpose.

And for accessing constants in paged flash (PPAGE area), using GPAGE is the only real option. So it can only be done in special setups and I also would consider it a quite advanced (and fragile?) configuration. Basically there are many such optimized setups, another one which comes to mind is to fix RPAGE to get a 12k unpaged area (and then for example using the rest of the RAM if there is any via GPAGE). For beginners I would however recommend to stick with the simple setups.

 

Daniel

 

BTW, the compiler does not directly support fixing GPAGE to a value. No 16 bit gpage using pointers.

 

 

0 Kudos
994 Views
kef
Specialist I

Thanks. I found that option. -PSegObj. It's in Code Generation tab, "Assume object is in same page for=never for different objects"

 

As I understand it now, safe RPAGE addressing requires either 1) -PSegObj option be on or 2) PAGED_RAM divided into R-page sized segments, so that required RPAGE update is never missing. -PSegObj is easy to use but costs extra code space, since RPAGE is updated on every data access. Dividing PAGED_RAM into 4k segments needs less code space, but then one has to care about filling different pages with data, more work. 

Using global addressing with PAGED_RAM doesn't require -PSegObj, also doesn't require user filling pages manually!

 

0 Kudos
994 Views
quasio
Contributor I

I was declaring my far pointers incorrectly,

 

I started using  char *__far24  my_data_ptr; to access the far paged ram properly and that seems to work.

 

0 Kudos