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.

Linux/PROCESSOR-SDK-AM335X: PRU debug printout

Part Number: PROCESSOR-SDK-AM335X

Tool/software: Linux

I want to test some mathematical operations of pru. I need to print out the results. What should I do?

Is my debug information written to memory in the pru and then read out of memory?If so, how do I write data in pru to memory and read it in arm?

  • Hello,

    It depends on your hardware and your application.

    Case 1: If 1) you are using a TI EVM or Beaglebone and 2) this firmware is just running on the PRU and will not need to interact with the Linux core, then you can debug in Code Composer Studio using JTAG. Sample instructions are at PRU-ICSS Debug on AM335x wiki. 

    Case 2: If you are using a TI EVM / Beaglebone but the PRU firmware does interact with the Linux core (e.g. through RPMsg), then you need to load the PRU code using RemoteProc (from the Linux core) rather than through Code Composer Studio. I believe there is still a way to debug in Code Composer studio in this case, but it requires some special steps because of issues related to the Linux core interfering with JTAG communication. It's probably easier to use the indirect debug methods in case 3.

    Case 3: every other case. If you have RPMsg running, you can modify the TI echo examples used in the RPMsg Quick Start Guide to send text values from the PRU to the command line. The PRU could load debug values into known parts of memory that you checked from the command line. You could also configure GPOs to toggle LEDs (or just voltages) high or low based on conditions in your code. These ideas are loosely based on the ideas at our outdated PRU Debugging wiki.

    Let me know if you need more information about specific topics.

    Regards, 

    Nick

  • Hi,Nick Saulnier
    Thank you for your reply. I printed out the results using RPMsg after the pru operation floating point.The test found that i can perform floating-point operations in the pru.

    I want to test pru gpio on evm. What should I do?
  • Also, how can I use ARM's gpio to trigger pru run?
  • Hello there,

    You will need to poll the input signal in order to trigger an event in the PRU based on a GPI input.

    The PRU has dedicated GPO pins and GPI pins, so you can use them separately. If you need to have bidirectional GPIO functionality, check out the training section 7.2 mentioned in this post for guidance on tying a GPO and a GPI pin together. You can also use one of the SoC GPIOs, but you won't get the fast reading and writing performance that the PRU has when using its GPO / GPIs.

    To use the GPO or GPI pins, you'll need to pinmux the pins appropriately - note that the PRU itself can't change pinmux settings so you should set them in the device tree. Also note that the output value that is driven to the GPO is nondeterministic (it could be a 1 or a 0) until you initialize R30 to your desired value (i.e., you won't know the value that will get driven on the GPO between when the PRU is initialized during bootup, and when you load your firmware into the PRU). If that is an issue we can talk about workarounds.

    We have a code example for toggling a GPO here or in your Processor SDK: ti-processor-sdk.../example-applications/pru-icss-5.1.0/examples/am335x/PRU_gpioToggle

    Regards, 

    Nick

  • Hi,Nick Saulnier

    Can I use arm's gpio interrupt to control pru execution?For example, the gpio of my arm emits an interrupt event every 50μs to trigger pru to run my function module.

  • Nick Saulnier,I have one more question.

    I would like to ask how I can debug the example of PRU_ARMtoPRU_Interrupt, and the firmware I have compiled successfully, how can I interrupt PRU from arm?
  • Hello,

    The PRU-ICSS does not have a task manager integrated into it, so an external interrupt cannot preempt currently running PRU code. That means the PRU must manually poll to check if it has received events from the ARM or anywhere else in the system.

    I am unclear on your second question. You can use any of the above listed debug methods.

    Regards,
    Nick
  • I want to test pru-icss-5.1.0/examples/am335x/PRU_ARMtoPRU_Interrupt,but I don't know how to do, when testing the example, the arm drive in what to do can let the PRU know driver interrupt event?
  • Hi,Nick Saulnier

    Use of ti-processor-sdk-linux-rt-am335x-evm-03.03.00.04/example-applications/pru-icss-5.1.0/examples/am335x/PRU_ARMtoPRU_Interrupttests, the example code is as follows:

    void main(void)
    {
    uint32_t *pDdr = (uint32_t *) &CT_DDR;
    uint32_t score;

    /* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */ 
    CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

    /* Wait until receipt of interrupt on host 0 */
    while ((__R31 & 0x40000000) == 0) { //How does the arm drive send an event to the pru?Are there any examples?
    }

    /* Clear system event in SECR1 */
    CT_INTC.SECR1 = 0x1;

    /* Clear system event enable in ECR1 */
    CT_INTC.ECR1 = 0x1;

    /* Point C30 (L3) to 0x3000 offset and C31 (DDR) to 0x0 offset */
    PRU0_CTRL.CTPPR1 = 0x00003000;

    /* Load value from DDR, decrement, and store it in L3 */
    score = pDdr[0];
    score--;
    CT_L3 = score;

    /* Halt PRU core */
    __halt();
    }

     

     

    How do I send the arm driver to send an event to pru, which triggers while ((__R31 & 0x40000000) == 0) ??

  • Hello,

    PRU_ARMtoPRU_Interrupt was written several years back when UIO was the way to communicate between ARM and PRU. Nowadays TI supports RemoteProc to communicate between the ARM and the PRU instead of UIO, so I would suggest taking a look at the PRU_RPMsg_Echo_Interrupt examples for interprocessor communication. We have several walkthroughs of using RPMsg, one at the RPMsg Quick Start Guide wiki and one in Lab 5 of the PRU Hands-On Labs. 

    If you want to use UIO, I imagine the PRU_ARMtoPRU_Interrupt example would still work - however, you'd want to check out the beaglebone community since they are the ones supporting UIO nowadays.

    Regards, 

    Nick

  • Thanks, Nick Saulnier.

    How long will it take to send an event from the arm's kernel to pru until the pru receives the event using the RPMsg mode?How to test this time accurately?

  • and,
    I want to communicate with Linux kernel space via RPMsg in pru0. Meanwhile, pru0 also communicates with Linux user space. Is that ok?
  • Hello,

    This post looks like the PRU should be able to receive an event sent from the ARM in less than a millisecond. Note that the PRU polling firmware will affect the time.

    I would expect that the PRU could communicate with both kernel and userspace through RPMsg, but I can check tomorrow and get back to you. 

    Regards, 

    Nick

  • Hey there,

    I'm sorry it took so long to respond. You can have communication with both Linux kernel space and user space. See the below code, which combines PRU_RPMsg_Echo_Interrupt1 from the RPMsg Quick Start Guide and Lab 5 of the PRU Hands-on Labs. I gave each driver its own channel. Modifications to the code are indicated with /* Change{ */ ...code... /* }Change */

    /*
     * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *	* Redistributions of source code must retain the above copyright
     *	  notice, this list of conditions and the following disclaimer.
     *
     *	* Redistributions in binary form must reproduce the above copyright
     *	  notice, this list of conditions and the following disclaimer in the
     *	  documentation and/or other materials provided with the
     *	  distribution.
     *
     *	* Neither the name of Texas Instruments Incorporated nor the names of
     *	  its contributors may be used to endorse or promote products derived
     *	  from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* created April 27, 2018 for e2e post */
    /* e2e.ti.com/.../676165 */
    /* code based on pru-icss-5.1.0/labs/lab_5/solution/PRU_RPMsg_Echo_Interrupt1 */ 
    
    #include <stdint.h>
    #include <stdio.h>
    #include <pru_cfg.h>
    #include <pru_intc.h>
    #include <rsc_types.h>
    #include <pru_rpmsg.h>
    #include "resource_table_1.h"
    
    volatile register uint32_t __R31;
    
    /* Host-1 Interrupt sets bit 31 in register R31 */
    #define HOST_INT			((uint32_t) 1 << 31)	
    
    /* The PRU-ICSS system events used for RPMsg are defined in the Linux device tree
     * PRU0 uses system event 16 (To ARM) and 17 (From ARM)
     * PRU1 uses system event 18 (To ARM) and 19 (From ARM)
     */
    #define TO_ARM_HOST			18	
    #define FROM_ARM_HOST			19
    
    /*
     * Using the name 'rpmsg-client-sample' will probe the RPMsg sample driver
     * found at linux-x.y.z/samples/rpmsg/rpmsg_client_sample.c
     *
     * Using the name 'rpmsg-pru' will probe the rpmsg_pru driver found
     * at linux-x.y.z/drivers/rpmsg/rpmsg_pru.c
     */
    #define CHAN_NAME			"rpmsg-client-sample"
    #define CHAN_DESC			"Channel 31"
    #define CHAN_PORT			31
    
    /* Change{ */
    #define CHAN_NAME2			"rpmsg-pru"
    #define CHAN_DESC2			"Channel 30"
    #define CHAN_PORT2			30
    /* }Change */
    
    /*
     * Used to make sure the Linux drivers are ready for RPMsg communication
     * Found at linux-x.y.z/include/uapi/linux/virtio_config.h
     */
    #define VIRTIO_CONFIG_S_DRIVER_OK	4
    
    uint8_t payload[RPMSG_BUF_SIZE];
    
    /*
     * main.c
     */
    void main(void)
    {
    	struct pru_rpmsg_transport transport;
    	uint16_t src, dst, len;
    	volatile uint8_t *status;
    
    	/* Allow OCP master port access by the PRU so the PRU can read external memories */
    	CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
    
    	/* Clear the status of the PRU-ICSS system event that the ARM will use to 'kick' us */
    	CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST;
    
    	/* Make sure the Linux drivers are ready for RPMsg communication */
    	status = &resourceTable.rpmsg_vdev.status;
    	while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK));
    
    	/* Initialize the RPMsg transport structure */
    	pru_rpmsg_init(&transport, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1, TO_ARM_HOST, FROM_ARM_HOST);
    
    	/* Create the RPMsg channel between the PRU and ARM user space using the transport structure. */
    	while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME, CHAN_DESC, CHAN_PORT) != PRU_RPMSG_SUCCESS);
    
    /* Change{ */
    	/* Create the second RPMsg channel between the PRU and ARM user space using the transport structure. */
    	while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME2, CHAN_DESC2, CHAN_PORT2) != PRU_RPMSG_SUCCESS);
    /* }Change */
    
    	while (1) {
    		/* Check bit 30 of register R31 to see if the ARM has kicked us */
    		if (__R31 & HOST_INT) {
    			/* Clear the event status */
    			CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST;
    			/* Receive all available messages, multiple messages can be sent per kick */
    			while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) {
    				/* Echo the message back to the same address from which we just received */
    				pru_rpmsg_send(&transport, dst, src, payload, len);
    			}
    		}
    	}
    }
    

    Regards, 

    Nick

  • Thanks, Nick Saulnier.
    How do I know which channel in the pru receives the data in this example?
  • Hello there,

    In this example, we are performing the same action (echoing back the character string we received) regardless of which RPMsg channel the RPMsg data came from, so I did not include an IF or CASE statement within the while loop.

    You should be able to check src from pru_rpmsg_receive to see where the message came from.

    Regards,
    Nick
  • Hello,Nick Saulnier
    I checked src from pru_rpmsg_receive to see where the message came from.
    I printed out the src value, 1024 and 1025 respectively.If the kernel sends data first, the value of src is 1024, and after user space, the value of src is 1025. The default value of SRC is 1024. Does it increase the src value by 1?How do I use the src parameter to determine which channel the data is received from?
  • I can know which channel received the data through the DST parameter of the pru_rpmsg_receive function.
  • Hello,Nick Saulnier
    I know which channel in the pru receives the data in this example. and now, how does PRU operate gpio?How do I test the pru operation gpio?
  • Hi there,

    Please see examples/am335x/PRU_gpioToggle/ in the PRU software support package for a starting point with writing to GPO. More information on using the GPI/GPO can be found in the TRM.

    A more complex example of using GPI and GPO is the assembly code here for the TI Design here. I've explained how the application is clocked here, but it is up to you to figure out the rest of the code if you want to use that example as a template.

    Regards, 

    Nick

  • Hello,Nick Saulnier
    I use the am35x evm test to execute the following command on the terminal:
    echo 55 > /sys/class/gpio/export
    echo "out" > /sys/class/gpio/gpio55/direction
    echo 1 > /sys/class/gpio/gpio55/value

    and the buzzer rang.

    Can pru also operate the gpio directly to make the buzzer ring? What am I supposed to do?
  • Hello,

    1) We've let this thread wander over too many subjects, so this is the last question I'll address here. If you have another question, please create a new post. It's easier for us and for future people reading this if we stick to one subject per thread.

    2) Yes, the PRU has the permissions to operate the GPIO. Please note that the PRU has very fast and deterministic access to its own GPO and GPI pins (i.e. we know exactly how many clock cycles communication takes, and the number of clock cycles is very small). The PRU's interactions with GPIO modules will not be as fast, and I'm not sure if they would be deterministic. Note that GPIO0 is the only GPIO module that can send interrupts to the PRU as per the PRU's INTC System Events. We don't have examples of PRU controlling the GPIO, but it should be similar to another core controlling the GPIO.

    Regards,
    Nick