pru c++ shared mem

any examples of shared memory PRU C++ PWM?

I have one that I used for a PID motor control using PWM and a quadrature encoder on the Beaglebone Black.

Any chance you could share your code? Please?

I found your GitHub repository. I see you use remoteproc. I had issues running remoteproc in the Beaglebone AI. Have you tried it on that platform?

Hi,

AÍ or AI-64?

I have always uses direct memory access and work in both bbb and ai, not tested yet in 64 -
https://beagleboard.org/static/prucookbook/#_building_blocks_applications

Thank you for taking the time to respond. I have used direct memory access on the am3358 and the am5729. I haven’t with the bbai-64 either. I have the used prucookbook extensively and have gotten those example working. But I am interested in getting that same example, but with C++ instead of C. Any ideas?

Have you gotten remoteproc working in the bbai?

No I haven’t working on the AI-64.

Not in the AI but in the AI-64. Has a different device path “/dev/remoteproc/j7-pru0-0” then BBB. I have attached a zip file that toggles __r30 to produce a square wave with 1ms period. I used CCS12.3 to produce the code with the aid of ti’s “pru-software-support-package”. The binary file is uploaded to the BBAI-64, then copied to the /lib/firmware folder. I then echo it to the /dev/remoteproc/j7-pru0_0/firmware. I placed a lot of comments in my source file to remind me of how to do this.
square_wave.zip (6.9 KB)

1 Like

Stuck trying to port to the AI-64 got bit banger __r30 code to work. Next step is to get the PRU_RPMsg_Echo_Interrupt0 found in the “pru-software-support-package” j721e examples to work. I am looking at the am65x//am64x include files to see how port them to the j721e for the PRU_ICSSG. I will post when successful.

PS: You mike like to look in the “pru-software-support-package” under the am572x examples. I don’t use the example Makefile’s but use CCS12.3 exclusively for compile/linking and uploading. I think the AI uses /dev/remoteproc/remoteproc4 and 7
.

Thank you very much for your responses. I just have one more thing. Would you recommend going the rpmsg way to communicate with the PRU? Is it something you would put in a commercial product? How reliable has it been? I am asking because I used to test rpmsg examples, untill I heard Jason Kridner say the best way was with the shared memory. I will try these examples you so kindly provided. Thank you very much

I don’t have an opinion on the reliablility. Although I think it be as reliable as any other linux device. The only shared memory I have used is between PRU0 and PRU1.

The PRU has direct access to all of physical memory. If you are sending data to Linux then you just need to use an unused block, or to be safe allocate a DMA block in the device tree. Just mmap the address and read directly from Linux. RPmsg is great for communicating back and forth to Linux but not really good for moving data/memory.

device tree entry;
// allocate 8mb shred mem for PRU
my_shared_memory_region: pru-shared-memory@90000000 {
compatible = “shared-dma-pool”;
reg = <0x0 0x90000000 0x0 0x800000>;
reusable;
status = “okay”;
};

on Linux user space app just use mmap to map the physical address into user space.
PRU code just needs to keep track of where it is writing and wrap around when you get to the end.
for quick and easy wrap If mem size is power of two, just “And” your byte counter with memsize -1.

e.g.
const uint32_t MEM_SIZE = 0x800000U;
const uint32_t MEM_WRAP = MEM_SIZE -1;

byte_ctr &= MEM_WRAP;

1 Like

Hey. Thank you for your response. Sadly, i am not as advanced as you are. Do you have any examples?

I would appreciate it.

https://markayoder.github.io/PRUCookbook/05blocks/blocks.html#_controlling_the_pwm_frequency

This is for the BBB

Roberts example clearly shows how to write (or read) PRU RAM from Linux. The PRU has direct access to physical memory. Writing Linux RAM is just a memcpy.

using the address I defined in previous post

#define LINUX_SHARED_RAM_ADDRESS 0x90000000

uint8_t volatile __far * const LINUX_SHARED_RAM = (uint8_t*)LINUX_SHARED_RAM_ADDRESS);

your pru_code()
{
uint32_t index = 0;
memcpy((void*)&LINUX_SHARED_RAM[index], local_data, sizeof(local_data);
index+= sizeof(local_data);
}

In Linux just map the memory block into user space with mmap
https://man7.org/linux/man-pages/man2/mmap.2.html

You can utilize the RPMessage protocol to notify Linux when a block of memory has been received.

look at the Rpmessage examples to understand ARM ↔ PRU communication

What LINUX_SHARED_RAM_ADDRESS value should be used with an AI-64? I tried 0x90000000 and it crashed.

IF you get a crash it’s because that address is in use by another device. You will have to look at the BBAI-64 device tree and determine and unused memory space. I do not have an AI-64 so I can’t guide you directly. Search the 64s dts files for “reserved-memory”. Look at the entries for “shared-dma-pool” and use and address that does not conflict with a current device. You can get some info from Linux by using;
sudo cat /proc/iomem. AI64 docs may list a System memory address range
Good Luck