Communication Between 920 And 940


rixed

Member
Joined
Dec 31, 2005
Messages
206
Age
48
Location
Paris (fr)
Website
happyleptic.org
Im using both the 920 and the 940 (thx dzz and squidge), and Im having problems using a dedicated block of upper memory to pass commands from each others. This buffer is basically a circular buffer with two pointers, begining and end ; one beeing writen by the 920 and the other beeing written by the 940.

Apparently, theses pointers gets periodically crashed.

The 940 should be OK, as this memory region is non-cacheable and it drains the write buffer when it's supposed to.

I suspect the 920 caches this memory, and when its cache writes a line to the buffer it destroys the updated version of the other pointer.

So the question is : how to tell linux on the 920 not to cache this memory region ?
 
As far as I know, the 920T only caches the first 32MB. If you used Dzz's demo tutorial, then only the area between 32Mb and 48MB will be cached by the 940T, leaving the area above 48MB uncached by either CPU. I assume you are using the area of memory between the end of the secondary frame buffer (around 0x03400000) and the MPEG decoder buffers (0x03D00000)? This area should be uncached by both CPUs.
 
slygamer posted on May 9 2006 at 04:24 PM said:
As far as I know, the 920T only caches the first 32MB. If you used Dzz's demo tutorial, then only the area between 32Mb and 48MB will be cached by the 940T, leaving the area above 48MB uncached by either CPU. I assume you are using the area of memory between the end of the secondary frame buffer (around 0x03400000) and the MPEG decoder buffers (0x03D00000)? This area should be uncached by both CPUs.
I agree with this, but I don't have another idea beyond the obvious. You could try posting the relevant data structure and code from both sides and we could try to make some more informed guesses I suppose...
 
Last edited by a moderator:
Linux only thinks there's 32mb of ram, so it only sets up the mmu for the first 32mb. The Last 32mb is left uncached and unbuffered, so that's not your problem. DZZ's startup code splits the upper 16mb into two 8mb chunks, the first cachable and the second non-cachable, so as long as your buffers are in the last 8mb, you should be ok.
 
OK, this is all good news.

Ive spotted a bug in my buffer (yes, Im looking for complex cache behavior while my cyclic buffer was simply bugged. go ahaid and laugh, people).

Anyway, there still is a bug, and it depends on the size and location of my command buffer in the upper 32 Mb.

I will investigate further, and produce a minimal example to produce the problem.

Thank you all for your attention.
 
OK, I found what the problem was, by looking at the assembly code outputed by GCC.
It may interrest others.

The cyclic buffer was packed (attribute packed). Although Im prety sure the begin/end pointers were word aligned, gcc build a code that reads and stores these pointers byte per byte. So, the writes of the pointers were not atomic. from time to time, the other CPU could read an incompletely written address, then kaboum.

Strange things happen.
 
rixed posted on May 11 2006 at 11:35 AM said:
OK, I found what the problem was, by looking at the assembly code outputed by GCC.
It may interrest others.

The cyclic buffer was packed (attribute packed). Although Im prety sure the begin/end pointers were word aligned, gcc build a code that reads and stores these pointers byte per byte. So, the writes of the pointers were not atomic. from time to time, the other CPU could read an incompletely written address, then kaboum.

Strange things happen.
Very interesting! Glad you got it fixed.
 
Last edited by a moderator:
rixed posted on May 11 2006 at 06:35 PM said:
The cyclic buffer was packed (attribute packed). Although Im prety sure the begin/end pointers were word aligned, gcc build a code that reads and stores these pointers byte per byte. So, the writes of the pointers were not atomic. from time to time, the other CPU could read an incompletely written address, then kaboum.

If you use the attribute 'packed', gcc can't assume the pointers are on a word boundary, and so has to use byte access for all reads and writes, as a word access could cause a data abort.

Which brings the question of why you used the 'packed' attribute?
 
Last edited by a moderator:
Squidge posted on May 11 2006 at 09:20 PM said:
If you use the attribute 'packed', gcc can't assume the pointers are on a word boundary, and so has to use byte access for all reads and writes, as a word access could cause a data abort.

Which brings the question of why you used the 'packed' attribute?

I don't think GCC does this systematically, for I have other packed structures that seams to be accessed by words.
In many cases GCC actually knows the start of the structure address, so that he knows if its members are aligned or not.

The case with this particular one was that it's declared extern in the C module that was modifying the pointers. In that case, GCC does not appears to assume that the pointers leads to a word aligned address.

I was expecting GCC to assume all datas are aligned correctly on architectures when it's mandatory.
Too many years on x86 I guess :)

As to why I used packed structures : for the very lame reason that I wanted to have the same member offsets on x86 and on the arm, so that I can generate on the PC while compiling for the GP2X an assembly file countaining these offsets, that are then included and used by the ARM assembly code. I didn't find any other way to access those C structures from assembly.
 
Last edited by a moderator:
Have you thought about instead of using a packed structure, manually padding the structure yourself to ensure everything is aligned?

eg.
char type;
char pad0;
char pad1;
char pad2;
unsigned int length;
unsigned short flags;
unsigned short pad4;

etc... then structure offsets will always be the same regardless of platform.
 
You have a padding byte too much in there :p.

If you can't rely on atomic writes you should probably switch to synchronization primitives. If you're running under Linux, you can probably use a critical section/mutex/semaphore or whatnot.

If not a pair of booleans in shared memory should do the trick (see Dekker's Algorithm).
 
I don't think the 940T can use any Linux system calls, so Linux synchronization routines might not be usable.

One way to get padding to work better is to order members by decreasing size. Have all your ints at the top, followed by the shorts, with chars on the end. If the first int is aligned, then everything following it is guaranteed to be aligned.
 
slygamer posted on May 12 2006 at 05:31 AM said:
I don't think the 940T can use any Linux system calls, so Linux synchronization routines might not be usable.
In the next "demo development" article I'll be giving some code for synchronization primitives...
 
Last edited by a moderator:
Back
Top