This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3358: PRU Access

Part Number: AM3358
Other Parts Discussed in Thread: TIDA-01555

Hi Team,

I am currently working with the BeagleBone Black (AM3358) board and I am using version 6.00.00.07 of the SDK for this processor. I have two questions . First, I would like to confirm my understanding of a post that I found on E2E. The post can be found here:
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/725531/am3358-ddr-access-from-pru

It states that the PRU has limited access to just the first 16 MB of DDR memory. Does this mean that by default I can set DDR in the cmd file with len= FFFF00 to allow the PRU to have access to 16Mb of memory by storing data sections in this memory block? I wanted to use the method laid out in lab 3 of the PRU training labs. They use the DATA_SECTION pragma to store variables into shared ram but instead in my case I will be storing my variables in DDR memory on the ARM side.

My second question is on how can I access the same memory location from the ARM side to acquire the data that the PRU stored into the DDR?|

Thanks in advance!


Kind Regards,

Jejomar

  • Hello Jejomar,

    PRU ACCESSING SYSTEM MEMORY

    That understanding is incorrect. The PRU can read any part of the address space, and it can write to any part of the address space that does not require elevated privileges to modify (e.g., PRU cannot be used to set the pinmux register settings).

    If you want to use the constant table specifically to refer to an area of DDR memory, then you would be limited to that range. But take another look at part 2 of my response https://e2e.ti.com/support/processors-group/processors/f/processors-forum/725531/am3358-ddr-access-from-pru/2677232#2677232 for an example of accessing DDR without using a constant table address.

    ARM ACCESSING SYSTEM MEMORY 

    I assume you are trying to access the memory from Linux userspace on the ARM core?

    If your system has elevated permissions, then it is pretty easy to expose memory to userspace with mmap. See TIDA-01555 documentation and code:
    http://www.ti.com/tool/TIDA-01555 
    in your AM335x SDK at example/applications/pru-adc-x.x/, or at the git repo https://git.ti.com/cgit/apps/tida01555

    Note that accessing dev/mem requires sudo permissions. If your userspace application does not have elevated permissions, then you would probably need something like a custom UIO or character driver to expose that memory up to userspace.

    Regards,

    Nick

  • Hi Nick,

    Apologies for the delay. I want to make sure I understand what ranges of memory I can read and write to cause I am having a bit of trouble writing to certain ranges with the constant table method. Based on the link and info you provided in your previous post, am I correct to say that the PRU can read from 0x80000000 to 0x80FFFF00 but it can only read/write from ranges 0x80000000 to 0x8000FFFF which means there is only about 64kb of useable ddr? In the other post you stated that with SBCO, you can write to addresses with an offset of 0x0 from the programmed base address up to an offset of 0xFFFF so I assume the same goes for the constant table method.

    I attempted to write 3 integer values to the first several of bytes of ddr from the pru and was successful with reading them with mmap on the arm side. However, if it’s true that I do only have 64kb of useable ddr to write to, I thought I could test to see if I could write to the last 4kb of writable ddr memory by creating a new memory section in the .cmd linker file as DDR_BUF : org=8000EFFF len=0x00001000 and that would make DDR become org=0x80000000 len=0x0000EFFF. I then created a new data section called .DATA_BUF and stored it into DDR_BUF on page 2. However, when I try to load my pru program into the pru, which stores data into the DATA_BUF section, I get an error which i have attached to the post. Do you have any idea what might be causing the error? Can I not create separate memory sections from DDR? I can do so with the 12kb shared ram so I figured it could work with DDR. I have also attached my code if that helps. Thank you


    Kind Regards,

    Jejomar



    sharing_ddr.tar

  • Hello Jejomar,

    To clarify: the PRU can read any address in the ENTIRE PROCESSOR (I realize I left that vague in my prior response). However, it can only write to memory addresses that do not require elevated permissions to edit. e.g., you can check pinmuxing settings from PRU, but you can't change them. You are NOT limited to 64kb of DDR.

    For future reference I am pointing you to the AM64x Linux SDK 8.1 (i.e., Linux kernel 5.10) documentation for PRU, where you can find a bunch of PRU resources. I pushed the same PRU information to the AM335x Linux SDK 7.3 (i.e., Linux kernel 5.4) docs, but there has been a bug that is preventing my updates from going live in that document for the past couple of months. Just keep in mind that AM335x is using PRU-ICSS (not PRU_ICSSG) and that the AM335x Linux 5.10 release won't come out for another month or so, and you'll be fine:
    https://software-dl.ti.com/processor-sdk-linux/esd/AM64X/08_01_00_39/exports/docs/common/PRU-ICSS/Overview.html 

    Take a look at Overview of PRU-ICSS and PRU_ICSSG > Development Tools > PRU Assembly Instruction Guide. Do you see the assembly commands LBBO/SBBO and LBCO/SBCO? If you use the constant table to access a memory location, the assembler uses LBCO/SBCO. If you do NOT use the constant table to access a memory location, the assembler uses LBBO/SBBO.

    So unless there is a specific reason that you don't want your code using LBBO/SBBO, let's keep it simple. Ignore the constant table. Use the default linker command file. Do something like this in your PRU firmware:

    #define DDR_8000_0000 (*((volatile unsigned int *)0x80000000))
     
    main(void){
    	/* 
    	 * Allow OCP master port access by the PRU so the PRU can read 
    	 * external memories 
    	 */
    	CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
    	
    	DDR_8000_0000 = 0xDEADBEEF;
    }

    Regards,

    Nick

  • Hello Nick,

    I understand that the pru can read any memory location and can only write to memory addresses that do not require elevated permissions to edit. I would like a region of memory that is contiguous and can be written/read to store data. Instead of having to read the TRM to find out what regions of memory are writable I decided it may be better to have the ARM allocate contiguous memory with CMEM. The beaglebone black is advertised as have 512MB of ddr, I wanted to allocate a buffer of 100MB with CMEM so I did the following:

    modprobe cmemk phys_start=0xa0000000 phys_end=0xa6400000 pools=1x104857600 allowOverlap=1

    on the pru side I write a integer value of 35 to DDR_a000_00000 with the method you described in your previous post. On the ARM side I do an fopen to /dev/mem and read the value at the address 0xa0000000 with mmap however I read a value of 33188 instead of 35. I’m I using CMEM incorrectly? I got no errors and can see that the kernel module cmemk has been installed with lsmod.


    Kind Regards,

    Jejomar

  • Hi Nick,

    May I ask for a follow-up? Thank you!


    Kind Regards,

    Jejomar

  • Hello Jejomar,

    Example shared memory solution

    Please take a look at this ARM <--> PRU shared memory example.

    Linux devicetree: board-support/linux-x.x.x/arch/arm/boot/dts/am335x-pru-adc.dtsi (includes the memory allocation)

    Userspace code and PRU code: example-applications/pru-adc-x.x.

    The TI design: www.ti.com/.../TIDA-01555

    If that does not work

    If that does not work, I would need to see what you are doing. 

    1) Please post the PRU code snippet where you are writing to the memory location. Include the part where you enable the OCP master port access.

    2) Show me the terminal commands you are using, and your Linux devicetree settings.

    Regards,

    Nick

  • Hi Nick,

    Thanks for the update. But I can’t seem to compile the .dtsi file you mentioned. I tried to compile it with the following command:
    dtc -W no-unit_address_vs_reg -O dtb -o am335x-pru-adc.dtbo -b 0 -@ am335x-pru-adc.dtsi
    However, I get the following error:



    I tried isolating the portion of the device dtsi file that handles the memory allocation into a dts file to be used as an overlay but I when I compiled it with the command below, I received the following warnings:
    dtc -W no-unit_address_vs_reg -O dtb -o am335x-ddr.dtbo -b 0 -@ am335x-ddr.dts



    I included the modified device tree am335x-ddr.dts in the post as a text file. Despite the warnings above, it does produce a dtbo file although I don’t think its working. Also I have not modified the main device tree for the beaglebone black.


    Kind Regards,

    Jejomar

  • Hi Nick,

    +Adding the text file am335x-ddr for your reference.


    Kind Regards,

    Jejomar

    /dts-v1/;
    /plugin/;
    
    /* Reserve 256kB DDR memory for the ping/pong buffers */
    /{
        __overlay__ {
            reserved-memory {
                    #address-cells = <1>;
                    #size-cells = <1>;
                    ranges;
    
                    pruadc_reserved: pruadc_reserved@0x9ffc0000 {
                            reg = <0x9ffc0000 0x00040000>;
                            no-map;
                            status = "okay";
                    };
                };
            };
    
    };

  • Hi Nick,

    May I ask for a follow-up on this please? Thank you!


    Kind Regards,

    Jejomar

  • Hi Nick,

    I am not sure why my previous method for compiling my dts file did not work, however I did get the dtsi file to work my including it at the bottom of the am335x-boneblack.dts file and compiling it with the command: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am335x-boneblack.dtb
    With the dtb loaded in with uEnv.txt file, the board boots up fine and I can see that’s its using the new dtb file from looking at the booting messages. Everything seems to be working but I have a question:

    Regardless of whether or not I am using the new dtb file with the included am335x-pru-adc.dtsi file, I can still write/read to the memory ranges 0x9ffc0000 to 0x00040000. So what exactly is the reserved-memory node in the dtsi file doing?

    Thanks again in advance!


    Kind Regards,

    Jejomar

  • Hello Jejomar,

    dts file basics

    dtsi files are basically include files for dts files. So when doing the "make dtb" command, you would want to include the dtsi file in whichever dts board file you are using, and then make the board dts file. Note that device trees apply settings from the top of the file down. So if you include a dtsi file at the top of the dts file, and then set something different in the device nodes lower down in the dts file, then the settings in the dts file will override the settings in the dtsi file. On the other hand, if the dtsi file include is placed at the bottom of the dts file, then information in the dtsi file will override conflicting settings higher up in the dts file.

    what does the reserved-memory node do? 

    From the PRU side, it can read/write to any place in DDR. As long as userspace has sudo permissions, it can use mmap to expose any part of DDR memory for read & write. So what is the reserved-memory node doing?

    The Linux OS decides where it will put all the information it needs to run during boot/runtime. In other words, we cannot guarantee before Linux starts up that application X will be allocated memory in address range X, application Y will be allocated memory in address range Y, etc.

    If we do not reserve the shared memory location in the device tree file, then Linux may decide to use that chunk of memory for something other than our shared memory task. That would lead to all kinds of issues, since we would have no idea if or when Linux could come in and rewrite all the memory in that region. By reserving the memory region, Linux knows to leave that range of address space alone.

    Regards,

    NIck

  • Hi Nick,

    Thank you for your response. The TRM states that the sdram has a size of 1GB with a range from 0x80000000 to 0Xbfffffff. I was wondering if there are sections that I cannot reserve memory for my uses? Is there anywhere in the technical references manual that tells you which sections I can reserve? I am pretty sure I can’t reserve all of it right? What's the limit that I can reserve?


    Kind Regards,

    Jejomar

  • Hello Jejomar,

    What is your usecase? Typically when I see people setting aside shared memory between ARM and PRU they are using it to pass information back and forth (i.e., usecases that don't usually require reserved memory that is hundreds of MBs or a GB)

    I am double checking on the "are specific sections of DDR reserved for Linux" question.

    Regards,

    Nick

  • Hello Nick,

    For the most part I asked out of curiosity, since I did hear that the beaglebone black has 512MB of ddr. However, my goal is to store large amounts of sensor data and you are right I don’t need a lot of ddr since I could just use small section of it to act as a data buffer and store the data into a sd card from the ARM side. Seeing as how I am sure I can work with the 256 KB of reserved memory from the dtsi, I say that we can close this thread.

    Thank you very much for all the help!


    Kind Regards,

    Jejomar

  • Hello Jejomar,

    Got it. I've got a meeting to discuss the "does Linux use specific DDR addresses" question with a team member next week, I won't worry about trying to accelerate that discussion since it's not needed for your immediate design.

    Regards,

    Nick