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
Memory Tests - Regulatory
-
- Junior Member
- Posts: 4
- Joined: Tue Jun 20, 2017 8:53 am
-
- Active Member
- Posts: 43
- Joined: Wed Apr 06, 2011 8:02 pm
Could the test be executed from OTP?
-
- Junior Member
- Posts: 4
- Joined: Tue Jun 20, 2017 8:53 am
@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!
-
Verified
- XCore Legend
- Posts: 1156
- Joined: Thu May 27, 2010 10:08 am
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.
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
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>
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
is the best(and probably only) option..- A program that executes from the same memory.
Engineer at XMOS
-
- Experienced Member
- Posts: 66
- Joined: Fri Feb 05, 2010 12:34 pm
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:
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
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;
}
https://www.xmos.com/support/appnotes/AN00109
I hope this helps.
Regards, /T
-
- Junior Member
- Posts: 4
- Joined: Tue Jun 20, 2017 8:53 am
@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.
@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.
-
- Active Member
- Posts: 43
- Joined: Wed Apr 06, 2011 8:02 pm
I'm glad to know this -- I did think it was memory mapped!infiniteimprobability wrote:I'm afraid data's idea, although a nice thought, won't bring any advantage. OTP is mapped to ports.
-
- Junior Member
- Posts: 4
- Joined: Tue Jun 20, 2017 8:53 am
Hi Thomas,
I have tested your code. Everything seems to run ok, if I limit the values to:
However, for my platform the values are theoretically:
When executing on those settings, I get the following output:
I have done some investigations, but could not find a solution to that.
Would you have any hint? Thanks.
Best Regards,
Thiago
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
Code: Select all
#define PROGRAM_SIZE 0x4000 // 16k
#define RAM_SIZE 0x40000 // 256k
#define RAM_BASE 0x40000 // 256k
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
Would you have any hint? Thanks.
Best Regards,
Thiago