June 21, 2020

A quick Guide to Shared Memory Space

There are two improtant sub systems in the AM335X the ARM subsystem and the PRU sub system To get the best out of both the worlds one need to setup a communication mechanism between two. There are several memory options which can be used to establish this communication. Basically when establishing communication the ARM side will write to a memory location and then will raise inturrupt so that the PRU knows that its time to read the new data. Similarly when PRU writes something to the memory it tells t the ARM about new data. Apart from intrupts ring buffers can also be used. Now coming to the shared memory options. If you look at the image below there is a shared RAM area of 12KB. This area is accesable by both PRU0 as well as PRU1 as well as by the ARM subsystem. However access to this shared RAM will be faster for both the PRUs but will be slower from the ARM. Apart from this there is Instruction RAM and Data RAM for each PRU.

The access time of these memory locations is as below Memory Access Time Instruction RAM 1 cycle Data RAM 3 cycle Shared DataRam 3 cycle

Apart from this OCMC RAM can also be used for sharing the data. It is of 64KB which is much larger than the 12KB shared RAM inside PRUSS. The base address for this location is 40300000. However the first 8KB is used by Kernal. so effectively we have 56KB of memory that can be used to share data. This memory is much slower for the PRUs to read from but should be faster for the ARM to access. Further there is also a shared memory space below the L3 interconnect that can also be used to share data. to see the memory map one can do cat /proc/iomem There is another important aspect of memories in Linux and that is the fact that On Linux systems, every memory address is virtual. They do not point to any address in the RAM directly. Whenever you access a memory location, a translation mechanism is performed in order to match the corresponding physical memory. On Linux systems, each process owns a virtual address space. It is a kind of memory sandbox during the life of the process. That address space is 4 GB in size on 32-bit systems (even on a system with physical memory less than 4 GB). For each process, that 4 GB address space is split into two parts:
User space virtual addresses
Kernel space virtual addresses
This is called a 3G/1G split, where the user space is given the lower 3 GB of virtual address space, and the kernel uses the upper remaining 1 GB. A typical process's virtual address space layout looks like the following:

There are various functions that one can use while writing drivers that need to access memories like kmalloc, vmalloc and ioremap. Each having their pros and cons and usage senarious. I am also still a begin ner and trying to get my head around all this. However i have figured out some great resourses which should get you going with the detailed understanding and could save you time.

Important References to understand how to access Memory in kernal modules
  • chapter Name: Using I/O Memory: in book titled Linux Device Driver 3rd Edition , page no 249 Onwards
  • Chapter Name: Kernel Memory Managment: in book titled Linux Device Driver Development-John Madieu
  • A kernal Module written by me to read and write to OCMC on beaglebone https://github.com/deebot/Beaglebone-BidirectionBus/tree/master/MEMdriver