I have been able to setup a 128 megabyte shared memory block between RT
Tasks and user space that is continuous and DMAable.  It does require some
hacking of main.c but the changes are fairly minor and easy to understand.

  I still use the "Normal High Shared memory area" that you can find on the
FAQ as a command and control buffer to send commands to/from the task and
user space, and use the Large Block to send data back and forth.  I will
write a FAQ at some point for those that need more than 4 Megs and don't
want to use the driver idea that has been posted in the past.  The basic
idea is:

1) Change main.c in the kernel to grab a block of x size before the memory
manager get it.
2) Pass the pointer to your RT Task,  I do this via EXPORTING the vars,
(i.e. mod ksyms.c)
3) Pass the pointer of the bus address of the memory to the user task.
 This I do via the CnC Shared memory, but fifos would also work)
4) mmap the new address and start using it.


The init/main.c mods I have at this time are:

//--------------------------------------------------------------------------
-
// MJ Wyrick
//   Reserve a major chunk of memory for the CEB
//--------------------------------------------------------------------------
-
unsigned long CEB_SHM_Size = (128 * 0x100000);    // Reserve this much
unsigned long CEB_SHM_Start = 0;                  // This is the start of
SHM

...

(around line 1119 in the 2.2.0RTL kernel)
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
        printk(linux_banner);
        setup_arch(&command_line, &memory_start, &memory_end);
        memory_start = paging_init(memory_start,memory_end);

      -- START of MODs --
        //------------------------------------------------------
        // Reserve a Major Block of memory for the CEB
        // MJ Wyrick
        //------------------------------------------------------
        // Lets Allign to the Next Page, Needed if User Space is to map to us
      //  ToDo:
        //    Replace the 4096 with the Page size at some point 99-06-16
      //    Clean up alignment to not waist a page
        memory_start += 4096 - (memory_start % 4096);
        CEB_SHM_Start = memory_start;
        memory_start += CEB_SHM_Size;
        printk("Major Shared Memory Block Version 0.5 by MJ Wyrick\n");
        printk("  CEB_SHM_Start = 0x%08lX\n", CEB_SHM_Start);
        printk("  CEB_SHM_Size  = %lu\n", CEB_SHM_Size);
        //------------------------------------------------------
      -- END of MODs --

        trap_init();
        init_IRQ();
        sched_init();
        time_init();
        parse_options(command_line);

----------------------------------------------------------------------------
---------------------
The kernel/ksyms.c mods:

At the end of the file:
extern unsigned long CEB_SHM_Start;
extern unsigned long CEB_SHM_Size;
EXPORT_SYMBOL(CEB_SHM_Start);
EXPORT_SYMBOL(CEB_SHM_Size);

----------------------------------------------------------------------------
---------------------

To use the Memory:

It the RT task:

// Setup Shared Memory Areas
static SHM_CnC  *shm_cnc = __va(SHM_ADDRESS);   // This is normal High
Shared Memory
static SHM_Data *shm_data;

int init_module(void)
{
  shm_data = (SHM_Data *)CEB_SHM_Start;

  // Tell the user Program how to find the Shared Data Memory
  shm_cnc->CEB_SHM_Start = virt_to_bus((void *)CEB_SHM_Start);   // NOTE:
you must pass the user program a bus address
  shm_cnc->CEB_SHM_Size  = CEB_SHM_Size;

  // Example on using data block; Clear the Number of Interrupts in the Data
Block
  shm_data->numints = 0;

...
}

In User Space:

   ... MAP the shm_cnc using the normal High Shared Memory way (see Shared
Memory FAQ) ...

  int fd;
  if ((fd = open("/dev/mem", O_RDWR)) < 0) {
    printf("Unable to open /dev/mem\n");
  }

  data = (SHM_Data *) mmap(0, cnc->CEB_SHM_Size, PROT_READ | PROT_WRITE,
                           MAP_SHARED, fd, cnc->CEB_SHM_Start);

  if (data == MAP_FAILED) {
    printf(" Unable to map shared memory data. errno = %i;",errno);
    close(fd);
    exit(-1);
  }

  // Example on using data block; Print number of interrupts
  printf(" Num Ints = %i\n", data->numints);

...

----------------------------------------------------------------------------
---------------------------------------

This method seems to work just fine.  The way its done above uses a few byte
of High Shared Memory to pass the pointer but
any means to get the Address to user space should work. (i.e. fifos, dev
reads, proc file system etc.)

******************************************
* Michael J. Wyrick                      *
* Director of Technology Development     *
* Transmitter Location Systems, L.L.C.   *
*========================================*
* E-mail:  [EMAIL PROTECTED]            *
* Phone: 703-227-8434 Fax: 703-968-8808  *
* PGP Key DH/DSS 0xE02104B6              *
*========================================*
*  "TLS - Protecting Satellite Assets"   *
* A subsidiary of Interferometrics, Inc. *
******************************************

--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/

Reply via email to