[Home]Shared Memory

Last edit: Peter Favrholdt on July 2, 2006 18:10 (4157 days, 21 hours and 54 minutes ago) (diff)
Rtai.Dk | RecentChanges | Preferences | DIAPM RTAI

Q: I'm using rtai_shm between LXRT and a rtai-module and its fine: A rtai-task in the module can read and write data from/to a LXRT-task.

Using the same shm in a rtai IRQ-handler (rt_request_global_irq) is not possible (as stated on the mailing list).

Is there a workaround or hint I don't know ?

A: ?


Q: Any examples?

A: ftp://ftp.denx.de/pub/RTAI/contrib/ex_shm.tar.bz2


"I have also use shared memory and real-time FIFO's in the same system. Shared
memory I use for large blocks of data between hardware that has DMA capabilities
and conventional Linux. I don't use any of the mbuff modules or anything like
that, I just hide some memory from Linux at boot time (I am still using lilo)
with something like:

append = "debug=2 noapic nosmp mem=61M"

Since I have 64MB of memory, the upper 3 MB are available to be mapped into my
conventional Linux process like this:

	/* Shared memory */
	int mem_fd = 0;
	mem_fd = open("/dev/mem", O_RDWR);
	if(mem_fd < 0){
	        cout<<"Failed to get mem_fd"<<endl;
		perror("open perror");
		exit( 1 );
	}
	pmem_base =  (void *) mmap(  /* map the following into this process' memory map
*/
			      (void *)(PHYS_BUF_BASE),/* suggested map address */
			      PHYS_BUF_SIZE,          /* size of map           */
			      PROT_READ | PROT_WRITE, /* flags */
			      MAP_FILE  | MAP_SHARED,
			      mem_fd,
			      PHYS_BUF_BASE );        /* physical address      */
	close(mem_fd); 
	if( (int)pmem_base == -1){
		perror("mmap error");
		exit( 1 );
	}

I have not been successful at getting access to /dev/mem without having to run
my Linux process at root. If anyone can give me help there... I would much
rather run this as a conventional user level process. I am using rtl 3.0 and the
pre patched 2.2.18 kernel.


In my rtl init_module(), I do:


	pmem_base = ioremap(PHYS_BUF_BASE, PHYS_BUF_SIZE );
	if(!pmem_base){
		printk("<0>rt_task: ioremap(PHYS_BUF_BASE, PHYS_BUF_SIZE ) failed.."
		       "pmem_base = %x \n", (unsigned )pmem_base );
		cleanup_module();
	}
		
Both sides now (rtl and conventional Linux) have pointers to the upper 3MB of
memory and due to the "mem=61M" directive, Linux memory management will not use
it. 

I have a simple system of semaphores / progress markers between rtl and the
conventional Linux process whereby my conventional Linux process knows when the
next fragment (1/8 of a field) of data is fresh. Since I am thresholding and
processing pixels from 4 frame grabbers, I felt it was important to get started
as soon as a reasonable amount of data was available and overlap processing and
acquisition.

The general control decisions of starting and stopping the data capture is
passed through the real time FIFOs from conventional Linux to rtl. 

Rtl then programs the DMA controllers (frame grabbers in my case), places
markers in the shared memory that allow the Linux process to start processing
fragments of data as they arrive and sends a confirming message back via
RT-FIFO. "


Q: Is memcpy() atomic or do I need to protect memcpy() by spinlocks in order to protect reading/writing from different RT tasks?

A: Generally, it is not. Exception: reading or writing a 32 bit value on a 32 bit platform is typically atomic, but the combination of both may only be atomic again on a single processor system (although it is a single instruction), SMP requires some locks.

So, it's better to put your memcpy in some spinlock with disabled IRQs or, if there is a significant number of bytes to be transfered, use a mutex or semaphore to allow handling interrupts and switching to high priority tasks while moving the bytes.


Edit text of this page | View other revisions | Download Rtai.dk
Search: