Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

problem with mutex core

Altera_Forum
Honored Contributor II
1,437 Views

Dear all, 

 

I've created a qsys system composed of two NIOS, each one attached to its on-chip memory that contains its program. 

the two processors are connected to a shared RAM protected via a HW mutex core. I need that the first NIOS writes a data in the shared memory to be read by the second processor. 

I write the following code for the first NIOS: 

altera_avalon_mutex_lock( mutex, 1 ); 

if(altera_avalon_mutex_is_mine(mutex)) 

IOWR_32DIRECT(SHM,0x4,0x3); 

altera_avalon_mutex_unlock( mutex ); 

 

And for the second NIOS: 

altera_avalon_mutex_lock( mutex, 1 ); 

if(altera_avalon_mutex_is_mine(mutex)) 

{ data = IORD_32DIRECT(SHM,0x4); 

printf ("data = %x \n",data);} 

altera_avalon_mutex_unlock( mutex ); 

 

 

However, the NIOS2 always read a strange value (different from 0x3) 

 

Please could anyone help me to solve the problem? 

Thanks in advance,
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
466 Views

please any one could answer??

0 Kudos
Altera_Forum
Honored Contributor II
466 Views

Did the mutex device open correctly? (i.e. is mutex not NULL) 

Can you ensure that the lock on the first CPU was successful, for example by writing something from inside the if ? 

Are you sure the second CPU is reading the value after the first one set it?
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

I've added this code at teh beginning of the program to test if teh mutex is not NULL: 

 

mutex = altera_avalon_mutex_open(MUTEX_NAME); 

 

 

if (mutex == NULL) /* for testing only */ 

error_code = ERROR_OPENED_INVALID_MUTEX;  

printf("error \n"); 

goto error;  

 

 

The two cpu do not access to this if, this means that the mutex is not NULL, 

 

I also added a printf inside the if of cpu1 after wrinting data, which displays hello in console and it's OK 

However the data read by cpu2 is fault 

 

How to be sure that the second CPU is reading the value after the first one set it? 

 

Please help me
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

Firstly make sure that the memory area you are using for SHM isn't also used by some other part of the system. 

I'd then use a sequence something like: 

1) CPUB: write C0 to SHM(0) 

2) CPUB: wait for SHM(1) to be C1 

3) CPUA: wait for SHM(0) to be C0 

4) CPUA: Acquire mutex 

5) A: write SMH(1) C1 

6) B: Acquire mutex (should spin) 

7) A: Loop for a moderate fraction of a second 

8) A: Write SMH(0) C2 

9) A: Release mutex - B should run 

10) B: Check SHM(1) is C1 and SMH(0) C2 

11) B: release mutex 

 

I've not used the Altera mutex functions, and I wouldn't consider using and of the IOWR_32DIRECT() family of functions in any code I ever wrote - they are far, far, far, far too error prone. 

You really need to use C pointers and structures (but not bit fields of enums) to map hardware registers. You might need access functions (to do cache bypass, or because the 'pointer' actually references a different memory space), but you need the verificatiion that the offsets match the device pointer.
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

 

--- Quote Start ---  

Firstly make sure that the memory area you are using for SHM isn't also used by some other part of the system. 

I'd then use a sequence something like: 

1) CPUB: write C0 to SHM(0) 

2) CPUB: wait for SHM(1) to be C1 

3) CPUA: wait for SHM(0) to be C0 

4) CPUA: Acquire mutex 

5) A: write SMH(1) C1 

6) B: Acquire mutex (should spin) 

7) A: Loop for a moderate fraction of a second 

8) A: Write SMH(0) C2 

9) A: Release mutex - B should run 

10) B: Check SHM(1) is C1 and SMH(0) C2 

11) B: release mutex 

 

I've not used the Altera mutex functions, and I wouldn't consider using and of the IOWR_32DIRECT() family of functions in any code I ever wrote - they are far, far, far, far too error prone. 

You really need to use C pointers and structures (but not bit fields of enums) to map hardware registers. You might need access functions (to do cache bypass, or because the 'pointer' actually references a different memory space), but you need the verificatiion that the offsets match the device pointer. 

--- Quote End ---  

 

 

 

 

Please could you tell me how to make CPUB waiting for SHM(1) to be C1?? isn't this guaranteed by the mutex?? 

if one processor acquires the mutex, it doesn't mean that the other can't acquire it?? 

 

if you can provide me an example of code, I'll be very thankful,
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

while (IORD_32DIRECT(SHM,0x4) != C1) continue; Without the mutex held. 

 

You need to use mutex to make sure nothing happens between two separate actions (eg reading 2 variables, or a read-modify-write sequence), you don't need one to just read a variable - since you can't care whether you get the old or new value. 

Note that the loop above relies on the compiler not moving the memory read outside the loop. IORD_32DIRECT() is (hopefully) 'asm volatile' so can't be moved, if you are reading a normal C variable (accessed uncached) you need to declare the variable volatile (eg: volatile int x;)
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

 

--- Quote Start ---  

while (IORD_32DIRECT(SHM,0x4) != C1) continue; Without the mutex held. 

 

You need to use mutex to make sure nothing happens between two separate actions (eg reading 2 variables, or a read-modify-write sequence), you don't need one to just read a variable - since you can't care whether you get the old or new value. 

Note that the loop above relies on the compiler not moving the memory read outside the loop. IORD_32DIRECT() is (hopefully) 'asm volatile' so can't be moved, if you are reading a normal C variable (accessed uncached) you need to declare the variable volatile (eg: volatile int x;) 

--- Quote End ---  

 

 

 

 

Hi, 

 

I can't solve the problem 

the first cpu writes 4 in @ 0x0 

in the second cpu: 

while (IORD_32DIRECT(SHM,0x0) != 4) {printf("waiting \n");} printf("data read = %d \n",IORD_32DIRECT(SHM,0x0) ); 

 

 

The cpu2 display a series of waiting in the console, this means that it doexn't read the right value written by cpu1 

 

So , please what can i do?
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

Are you sure that both CPU are connected to the same shared memory, that SHM is the correct address, and that this memory isn't used for anything else? (including the text, ro, rw, bss, stack and head sections) 

I'd suggest to put SignalTap probes on the shared memory control signals to verify that the first CPU is correctly writing the value and see what the second one is reading.
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

 

--- Quote Start ---  

Are you sure that both CPU are connected to the same shared memory, that SHM is the correct address, and that this memory isn't used for anything else? (including the text, ro, rw, bss, stack and head sections) 

I'd suggest to put SignalTap probes on the shared memory control signals to verify that the first CPU is correctly writing the value and see what the second one is reading. 

--- Quote End ---  

 

 

 

Yes I'm sure that both CPU are connected to the shared RAM, this memory is only connected to cpu data masters, to clk and reset signals 

Could you please tell how use and put SignalTap probes on the shared mem? what are signal tap probes? is there any tutorial??
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

See this manual for SignalTap: 

 

http://www.altera.com/literature/hb/qts/qts_qii53009.pdf 

 

In addition to the suggestions to Daixiwen, I would also suggest double checking that the memory contents are consistent from perspective of CPUA, and then as a small step forward, use the system-console to come in separately and dump the memory contents. I guess you could also use the memory window in Eclipse but system-console is more direct.
0 Kudos
Altera_Forum
Honored Contributor II
466 Views

The SignalTap section of the Quartus manual is well written: http://www.altera.com/literature/hb/qts/qts_qii53009.pdf 

You will need to find the control signals to your memory block, and monitor the address, read, write, read_data and write_data signals. Then you can trigger on either the read or the write signal to see what is happening.
0 Kudos
Reply