Memory Tests - Regulatory

Sub forums for various specialist XMOS applications. e.g. USB audio, motor control and robotics.
Post Reply
thiago
Junior Member
Posts: 4
Joined: Tue Jun 20, 2017 8:53 am

Memory Tests - Regulatory

Post by thiago »

Hi All,

We are currently working with a Product Development that uses a XCore200 and an external ARM board.

One of the requirements for the regulatory compliance is to be able to do Whole/Full memory tests, such as March-C.

After a brief discussion with Thomas Gmeinder from Xmos, it was suggested to post here on the Forum, so that we could get additional people to join the discussion a bit.

The memory check can be executed when the system is idle.

There are two options to write and read the internal SRAM of the xCORE:
- A program that executes from the same memory.
This program could relocate itself (to a memory area it has already checked) to access the whole memory.
E.g. by forcing the xCORE to boot and execute a self test program.
- Via JTAG.

The initial idea is then to use the external ARM board to trigger the procedure.

It would be interesting to hear if someone had a similar need on the past and how the issue was solved.

Also, would you have any sample source code or guideline to proceed with any of the aforementioned solutions?

Any help is appreciated.

Best Regards,

Thiago


User avatar
data
Active Member
Posts: 43
Joined: Wed Apr 06, 2011 8:02 pm

Post by data »

Could the test be executed from OTP?
thiago
Junior Member
Posts: 4
Joined: Tue Jun 20, 2017 8:53 am

Post by thiago »

@data There is no hard requirement from where the test could be run. I have to admit that I am not familiar with the process of running applications from the OTP. Also, switching between the OTP application to the application on Flash. Could you maybe extend a little bit your idea? Thanks a lot!
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

I'm afraid data's idea, although a nice thought, won't bring any advantage. OTP is mapped to ports. So OTP boot actually copies the values read from the ports into RAM and then branches to that. The only other memory mapped space inside the xcore other than the RAM block is the boot ROM.

Checking memory can be done from any thread (core) on the tile as they share the same space. However you'll need to be careful with sections etc. as stack, heap and code (+ constants) all reside in SRAM.

Code: Select all

xobjdump -t <myfile.xe> 
may be a useful tool for you, or binary viewer in the IDE. JUst double click on the binary to see what's what..

It will be possible to stop all other threads by having them select on an array of channels which is fed from another task. If you use streaming channels, the runtime overhead will be minimal. A thread that is paused waiting on an event will not manipulate the memory at all (unless interrupts are enabled and fire, which is unusual in normal xc code).

The checking thread can use an unsafe pointer to directly read SRAM. Xcores have a fast CRC - see https://github.com/xmos/lib_ethernet/bl ... net_mac.xc for an example.

So in summary, I think
- A program that executes from the same memory.
is the best(and probably only) option..
User avatar
Thomas
Experienced Member
Posts: 66
Joined: Fri Feb 05, 2010 12:34 pm

Post by Thomas »

Hi Thiago
I wrote a function that can test the entire memory of an xCORE Tile.
It works like this:
* Test the upper part of the memory
* Relocate the program to upper part of the memory
* The rest of the program tests the lower (vacated) part of the memory

The function test_whole_memory has to be called on every tile where you want to check the memory.

Here is the code in form of 3 files:

Code: Select all

/*
 * mem_access.c
 *
 */

#include <stdio.h>
#include <platform.h>
#include <relocate.h>

/*! 
 * \brief User defined function to test a memory area
 *
 * \param[in]   base       Pointer to start of memory area
 * \param[in]   byte_size  Size of memory area in bytes
 */
int mem_access(unsigned* base, unsigned byte_size) {

	unsigned word_size = (byte_size + 3)/4; // round to word size
    for(unsigned i=0; i<word_size; ++i) { 
        *(base+i) = i;
        unsigned read_val = *(base+i);
        if(read_val != i) {
            printf("Error: Wrote 0x%x to address 0x%x but read returned 0x%x", i, (unsigned) base+i, read_val);
            return 1; // ERROR
        }
    }
    return 0; // OK
}


/*! 
 * \brief Function to test the whole internal xCORE tile memory 
 *
 * Steps:
 * Test the upper part of the memory
 * Relocate the program to upper part of the memory
 * The rest of the program tests the lower (vacated) part of the memory
 */
int test_whole_memory() {
  int test_result;

  printf("Program to test the whole internal xCORE tile memory of size %d in address range 0x%x..0x%x\n\n", XS1_RAM_SIZE, XS1_RAM_BASE, XS1_RAM_BASE+XS1_RAM_SIZE);

  // Test the part of the RAM above the Program
  unsigned* base = (unsigned*) (XS1_RAM_BASE+PROGRAM_SIZE);
  unsigned  byte_size = XS1_RAM_SIZE-PROGRAM_SIZE-4;
  printf("Testing memory in range 0x%x..0x%x\n", (unsigned) base, (unsigned) base + byte_size+4);
  test_result = mem_access(base, byte_size); // access all memory above the program

  int next_pc;

  /* relocate program memory to the end of RAM and jump to new location */
  /* do not abstract-away - direct manipulation of program flow */

  base = (unsigned*) XS1_RAM_BASE;
  byte_size = PROGRAM_SIZE-4;
  printf("After relocation of the program, the vacated memory are will be tested in range 0x%x..0x%x\n", (unsigned) base, (unsigned) base + byte_size+4);
  //Note: printf has to be executed before relocation !

  RELOCATE(XS1_RAM_BASE, XS1_RAM_BASE + XS1_RAM_SIZE - PROGRAM_SIZE, PROGRAM_SIZE / 4);
  asm("ldap r11, after_relocation");
  asm("mov %0, r11" : "=r"(next_pc) :: "r11");
  asm("bau %0" :: "r"(next_pc + XS1_RAM_SIZE - PROGRAM_SIZE));
  asm("after_relocation:");
  /* syscalls will cease working here */

  // Now test the rest of the RAM. 
  // I.e. the RAM region that was occupied by the program before relocation.
  test_result = mem_access(base, byte_size); 

  return test_result;
}

Code: Select all

/*
 * relocate.h
 */

#include <stdio.h>

#define RELOCATE(from, to, nwords) \
  printf("Relocate memory from 0x%x, to 0x%x, nwords %d\n", from, to, nwords); \
  for (int i = 0; i < nwords; i++) { \
    ((unsigned*)(to))[i] = ((unsigned*)(from))[i]; \
  } \
  printf("Memory relocation successfull\n"); \
  { int dp, cp, sp; \
    asm("ldaw %0, dp[0]" : "=r"(dp)); \
    asm("set dp, %0" :: "r"(dp + (to) - (from))); /* adjust DP */ \
    asm("ldaw r11, cp[0]\nmov %0, r11" : "=r"(cp) :: "r11"); \
    asm("set cp, %0" :: "r"(cp + (to) - (from))); /* adjust CP */ \
    asm("ldaw %0, sp[0]" : "=r"(sp)); \
    asm("set sp, %0" :: "r"(sp + (to) - (from))); /* adjust SP */ \
  } \
  /* syscalls will cease working here! I.e. no print functions can be called anymore */
  
#define PROGRAM_SIZE 0x4000 // 16k

Code: Select all

/*
 * app_write_read_whole_mem.xc
 */

#include <platform.h>

extern int test_whole_memory();

int main(void)
{

  par {
    on tile[0]: test_whole_memory();
    on tile[1]: test_whole_memory();
  }
  return 0;
}
You said that this has to be done regularly. To achieve this you can boot the chip in a special test mode using the mechanism described here:
https://www.xmos.com/support/appnotes/AN00109

I hope this helps.

Regards, /T
thiago
Junior Member
Posts: 4
Joined: Tue Jun 20, 2017 8:53 am

Post by thiago »

@infiniteimprobability: Thanks a lot for the hints! Especially for the unsafe pointer reference.

@Thomas: this is amazing! I will give it a try today(worst case, tomorrow) and give you a feedback, but looks exactly what I needed.
User avatar
data
Active Member
Posts: 43
Joined: Wed Apr 06, 2011 8:02 pm

Post by data »

infiniteimprobability wrote:I'm afraid data's idea, although a nice thought, won't bring any advantage. OTP is mapped to ports.
I'm glad to know this -- I did think it was memory mapped!
thiago
Junior Member
Posts: 4
Joined: Tue Jun 20, 2017 8:53 am

Post by thiago »

Hi Thomas,

I have tested your code. Everything seems to run ok, if I limit the values to:

Code: Select all

#define PROGRAM_SIZE 0x4000 // 16k
#define RAM_SIZE     0x10000 // 64k
#define RAM_BASE     0x10000 // 64k
However, for my platform the values are theoretically:

Code: Select all

#define PROGRAM_SIZE 0x4000 // 16k
#define RAM_SIZE     0x40000 // 256k
#define RAM_BASE     0x40000 // 256k
When executing on those settings, I get the following output:

Code: Select all

After relocation of the program, the vacated memory area will beAfter relocation of the program, the vacated memory area will be tested in range 0x40000..0x48000
 tested in range 0x40000..0x48000
Relocate memory from 0x40000, to 0x78000, nwords 8192
Relocate memory from 0x40000, to 0x78000, nwords 8192
Unhandled exception: LOAD_STORE, data: 0xeb7bc038
I have done some investigations, but could not find a solution to that.

Would you have any hint? Thanks.

Best Regards,

Thiago
Post Reply