Execute code using external RAM on MC9S12XEP100

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

Execute code using external RAM on MC9S12XEP100

Jump to solution
1,128 Views
ElMaia
Contributor I

Hi.

I'm working in a personal project using uC MC9S12XEP100 and external RAM CY7C1041GN.

I think I setup up all registers correctly because I can read from and write to the memory correctly.

Here a brief of my hardware:

  • uC: MC9S12XEP100 144-LQFB
  • Ext. RAM: CY7C1041GN  Static RAM 4Mb / 512KB
    • ADDR [18:1] / !UDS
    • !CS1 as Enable Signal

My registers' values:

 

  // EBICTL0
  EBICTL0_ASIZ  = 0b10011;   // External Address Bus Size : 10011 -> ADDR[18:1], UDS'
  EBICTL0_HDBE  = 1;         // High Data Byte Enable - UDS' e LDS' signals : 0 Disabled / 1 Enabled
  EBICTL0_ITHRS = 0;         // Reduced Input Threshold : 0 5V / 1 3V3

  // EBICTL1
  EBICTL1_EXSTR0    = 0b000; // External Access Stretch Option 0 
  EBICTL1_EXSTR_10  = 0b000; // External Access Stretch Option 1 
  
  // MMCCTL0
  MMCCTL0_CS0E = 0b00;       // Chip Select 0 Enables : 00 -> Disabled / 01, 10 or 11 -> Enabled
  MMCCTL0_CS1E = 0b01;       // Chip Select 1 Enables : 00 -> Disabled / 01, 10 or 11 -> Enabled
  MMCCTL0_CS2E = 0b00;       // Chip Select 2 Enables : 00 -> Disabled / 01, 10 or 11 -> Enabled
  MMCCTL0_CS3E = 0b00;       // Chip Select 3 Enables : 00 -> Disabled / 01, 10 or 11 -> Enabled
  
  // MMCCTL1
  MMCCTL1_ROMON    = 0b1;    // Enable FLASH or ROM in the memory map
  MMCCTL1_ROMHM    = 0b0;    // FLASH or ROM only in higher Half of Memory Map : 1 -> Accesses to 0x4000-0x7FFF will be mapped to 0x14_4000-0x14_7FFF in the global memory space (external access).
  MMCCTL1_EROMON   = 0b1;    // Enables emulated Flash or ROM memory in the memory map : 0 - Disable / 1 - Enable
  MMCCTL1_RAMHM    = 0b0;    // RAM only in higher Half of the memory map : 1 Accesses to $4000-$7FFF will be mapped to $0F_C000-$0F_FFFF in the global memory space (RAM area)
  MMCCTL1_PGMIFRON = 0b0;    // Program IFR visible in the memory map : 0 Not Visible / 1 Visible 
  MMCCTL1_EEEIFRON = 0b0;    // EEE IFR visible in the memory map : 0 Not Visible / 1 Visible 
  MMCCTL1_TGMRAMON = 0b0;    // EEE Tag RAM and FTM SCRATCH RAM visible in the memory map : 0 Not Visible / 1 Visible
  
  // MODE
  MODE_MODx = 0b101; // MODC MODB MODA : 101 -> Normal Expanded

 

To read/write the memory, I made something like that:

 

// Byte access
byte *far externalAddress  = (byte *far)0x200000;
externalAddress[0] = value;
value = externalAddress[0];
// as well as word access
word *far externalAddress  = (word *far)0x200000;
externalAddress[0] = value;
value = externalAddress[0];

 

 

The image below show a log of access to some addresses in the external memory. 

Access to External RAMAccess to External RAM

However, I can't execute code which I stored in the external memory.

I wrote "by hand" this assembly code and opcode values which oscillate the PTH0 pin.

 

/*
  1C 02 62 01 BSET  _DDRH,#1
  1C 02 60 01 BSET  _PTH,#1
  1D 02 60 01 BCLR  _PTH,#1
  20 F6       BRA   *-8 ;abs = 0004 
*/
externalRAM[0]  = 0x1C;
externalRAM[1]  = 0x02;
externalRAM[2]  = 0x62;
externalRAM[3]  = 0x01;
externalRAM[4]  = 0x1C;
externalRAM[5]  = 0x02;
externalRAM[6]  = 0x60;
externalRAM[7]  = 0x01;
externalRAM[8]  = 0x1D;
externalRAM[9]  = 0x02;
externalRAM[10] = 0x60;
externalRAM[11] = 0x01;
externalRAM[12] = 0x20;
externalRAM[13] = 0xF6;

 

 So, I created a function pointer type in order to try calling this "function" and tried many ways to go there:

 

// Function pointer type
typedef void (*far funcVoid)(void);
// Global address
funcVoid funcOsc @ 0x200000L;
// Local address
funcVoid addrFunc  = (funcVoid)0x200000;

// ... and these calls (one at a time)
asm {
  call 0, $20
}
((funcaoVoid)externalRAM)();
addrFunc();
funcOsc();

 

But all these call interrupt the execution and no access to external RAM appears in the oscilloscope lines.

I made the it a time in the past using 9S12DP512, but there the external RAM wasn't paged and a simple call to any address from 0x4000-7FFF generated access to it.

How can execute code in the external RAM with paged memory?

I noticed that @lama answer many questions about external memory. Can you or anyone help me with this problem?

Thanks in advance.

0 Kudos
1 Solution
1,111 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

I have just finished my vacation and try to answer. I am sorry I do not have a board at home to test so I'll try to describe the solution without example.
Moreover. I have not played with exbus for a long time so I hope...

If I manage it I'll take my MRAM board from the office tomorrow but I think you will understand.
First of all check the data access and correctness of your setup on the basis of answer I provided for:
https://community.nxp.com/t5/S12-MagniV-Microcontrollers/S12XE-XEBI-error-while-addressing-over-64KB...

Next...

The PPAGE or near address can be used in the address of the function but there is a condition for used CSx\.

If the code is required to be executed out of the paged exmem then the address space controlled by CS0\ must be used. The space corresponds to PPAGE 00~BF.

See attached memory map.

Of course there is also possibility to use near address for external space from the range 4000~7FFF but in this case you have to set ROMHM to 1 and RAMHM to 0. Moreover the space uses CS2\.

Lets continue with CS0\.
Next condition is that pointers to the functions have different structure. I hope I'll do no mistake or forget anything.

For example, I want to have a function prepared automaticall after start of the code. The note about EXbus initialization placement bellow must be fulfilled.:
//-----------------------------------------------------------------------------
*.prm file
SECTION
MY_EX_RAM_PG01 = READ_ONLY DATA_FAR IBCC_FAR 0x018000 TO 0x01BFFF;
PLACEMENT
MY_EX_RAM_PG01 INTO MY_EX_RAM_PG01;

If everything is done by SW then no external space definitions in the prm file are needed.

*.c file

#pragma DATA_SEG __PPAGE_SEG MY_EX_RAM_PG01 // see prm file

volatile unsigned char far code01_02[] @ 0x018000L =
{0x04,0x4A,0x80,0x09,0x04,0x20,0x0A };

#pragma DATA_SEG __PPAGE_SEG DEFAULT

//definition of the pointer to a function
void (*far f1)(void);

// filling pointer to the function by address of data representing a code.
f1=(void(*far)()) (0x800001); // see different order of the page and offset in comparison to data pointers.

// calling the function
f1();

Moreover, you can copy the function to the exram automatically by placement of the function to the exmem in the prm file (as presented above). In this case, it is necessary to enable exbus in the start12.c file sooner than copy down function (which copies function stored in flash to the ram). I use it in examples for exram data access because I have initialized variables in in their definitions. Another approach is to copy data to the exram by own code.

Best regards,
Ladislav

View solution in original post

0 Kudos
2 Replies
1,112 Views
lama
NXP TechSupport
NXP TechSupport

Hi,

I have just finished my vacation and try to answer. I am sorry I do not have a board at home to test so I'll try to describe the solution without example.
Moreover. I have not played with exbus for a long time so I hope...

If I manage it I'll take my MRAM board from the office tomorrow but I think you will understand.
First of all check the data access and correctness of your setup on the basis of answer I provided for:
https://community.nxp.com/t5/S12-MagniV-Microcontrollers/S12XE-XEBI-error-while-addressing-over-64KB...

Next...

The PPAGE or near address can be used in the address of the function but there is a condition for used CSx\.

If the code is required to be executed out of the paged exmem then the address space controlled by CS0\ must be used. The space corresponds to PPAGE 00~BF.

See attached memory map.

Of course there is also possibility to use near address for external space from the range 4000~7FFF but in this case you have to set ROMHM to 1 and RAMHM to 0. Moreover the space uses CS2\.

Lets continue with CS0\.
Next condition is that pointers to the functions have different structure. I hope I'll do no mistake or forget anything.

For example, I want to have a function prepared automaticall after start of the code. The note about EXbus initialization placement bellow must be fulfilled.:
//-----------------------------------------------------------------------------
*.prm file
SECTION
MY_EX_RAM_PG01 = READ_ONLY DATA_FAR IBCC_FAR 0x018000 TO 0x01BFFF;
PLACEMENT
MY_EX_RAM_PG01 INTO MY_EX_RAM_PG01;

If everything is done by SW then no external space definitions in the prm file are needed.

*.c file

#pragma DATA_SEG __PPAGE_SEG MY_EX_RAM_PG01 // see prm file

volatile unsigned char far code01_02[] @ 0x018000L =
{0x04,0x4A,0x80,0x09,0x04,0x20,0x0A };

#pragma DATA_SEG __PPAGE_SEG DEFAULT

//definition of the pointer to a function
void (*far f1)(void);

// filling pointer to the function by address of data representing a code.
f1=(void(*far)()) (0x800001); // see different order of the page and offset in comparison to data pointers.

// calling the function
f1();

Moreover, you can copy the function to the exram automatically by placement of the function to the exmem in the prm file (as presented above). In this case, it is necessary to enable exbus in the start12.c file sooner than copy down function (which copies function stored in flash to the ram). I use it in examples for exram data access because I have initialized variables in in their definitions. Another approach is to copy data to the exram by own code.

Best regards,
Ladislav

0 Kudos
1,084 Views
ElMaia
Contributor I

Thanks @lama .

The key point of your answer was "If the code is required to be executed out of the paged exmem then the address space controlled by CS0\ must be used. The space corresponds to PPAGE 00~BF."

The .xls file was also very important to confirm some information.

I changed the hardware to use CS0 as "Chip Enable" in the memory and set up the register to correspond the new hardware.

// Use CS0, not CS1 anymore
MMCCTL0_CS0E = 0b01;
MMCCTL0_CS1E = 0b00;

// New absolute address: 0x40_0000

// Byte access
byte *far externalAddress  = (byte *far)0x400000;
externalAddress[0] = value;
value = externalAddress[0];
// as well as word access
word *far externalAddress  = (word *far)0x400000;
externalAddress[0] = value;
value = externalAddress[0];

// A call to an equivalent mapped address to 0x40_0000
asm {
  call $8000, $40 ; I don't remember right now if 40 or 0
                  ; I think is $0.
}

 

Now everything is working like a charm. Thanks a lot.

0 Kudos