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: Can't clear PRU interrupt from host

Part Number: AM3358
Hi,

I´m starting to learn about using the PRUs of my BBG. My goal is to drive some Adafruit NeoPixels by the PRU and control them by writing instructions from the host to the shared memory.
First I tried to toggle some GPOs with the PRU. I followed this istructions: https://elinux.org/EBC_Exercise_30_PRU_via_remoteproc_and_RPMsg. To configure the GPO I wrote a DTO (see below) and
activated it in the uEnv.txt file (also see below).

Here are some information about my system:

root@Linux:~# uname -r
4.4.91-ti-r133


root@Linux:~# lsmod
Module                  Size  Used by
arc4                    2339  2
mt7601u                93718  0
mac80211              630543  1 mt7601u
cfg80211              535245  2 mac80211,mt7601u
rfkill                 22142  2 cfg80211
evdev                  14151  1
uio_pdrv_genirq         4243  0
uio                    11100  1 uio_pdrv_genirq
iptable_nat             2336  0
nf_conntrack_ipv4      18312  1
nf_defrag_ipv4          2016  1 nf_conntrack_ipv4
nf_nat_ipv4             6966  1 iptable_nat
nf_nat                 18857  1 nf_nat_ipv4
nf_conntrack          118311  3 nf_nat,nf_nat_ipv4,nf_conntrack_ipv4
iptable_mangle          2060  0
iptable_filter          2061  0
spidev                  9289  0
tieqep                 10422  0
ip_tables              15525  3 iptable_filter,iptable_mangle,iptable_nat
x_tables               21069  3 ip_tables,iptable_filter,iptable_mangle
pru_rproc              15879  2
pruss_intc              9009  1 pru_rproc
pruss                  12346  1 pru_rproc


uname_r=4.4.91-ti-r133 #uuid= #dtb= ###U-Boot Overlays### ###Documentation: elinux.org/Beagleboard:BeagleBoneBlack_Debian ###Master Enable enable_uboot_overlays=1 ### ###Overide capes with eeprom uboot_overlay_addr0=/lib/firmware/bspm_P9_42_37-00A0.dtbo uboot_overlay_addr1=/lib/firmware/PRU-GPIO-EXAMPLE-00A0.dtbo #uboot_overlay_addr2=/lib/firmware/<file2>.dtbo #uboot_overlay_addr3=/lib/firmware/<file3>.dtbo ### ###Additional custom capes #uboot_overlay_addr4=/lib/firmware/<file4>.dtbo #uboot_overlay_addr5=/lib/firmware/<file5>.dtbo #uboot_overlay_addr6=/lib/firmware/<file6>.dtbo #uboot_overlay_addr7=/lib/firmware/<file7>.dtbo ### ###Custom Cape #dtb_overlay=/lib/firmware/<file8>.dtbo ### ###Disable auto loading of virtual capes (emmc/video/wireless/adc) #disable_uboot_overlay_emmc=1 disable_uboot_overlay_video=1 disable_uboot_overlay_audio=1 disable_uboot_overlay_wireless=1 disable_uboot_overlay_adc=1 ### ###PRUSS OPTIONS ###pru_rproc (4.4.x-ti kernel) uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-4-TI-00A0.dtbo ###pru_uio (4.4.x-ti & mainline/bone kernel) #uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo ### ###Cape Universal Enable enable_uboot_cape_universal=1 ### ###Debug: disable uboot autoload of Cape #disable_uboot_overlay_addr0=1 #disable_uboot_overlay_addr1=1 #disable_uboot_overlay_addr2=1 #disable_uboot_overlay_addr3=1 ### ###U-Boot fdt tweaks... #uboot_fdt_buffer=0x60000 ###U-Boot Overlays### cmdline=coherent_pool=1M net.ifnames=0 quiet #In the event of edid real failures, uncomment this next line: #cmdline=coherent_pool=1M net.ifnames=0 quiet video=HDMI-A-1:1024x768@60e #cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

/dts-v1/;
/plugin/;

/ {
        compatible = "ti,beaglebone", "ti,beaglebone-green", "ti,beaglebone-black";
        part-number = "PRU-GPIO-EXAMPLE";       //same as filename without 00A0
        version = "00A0";                       //always seems to be 00A0
        exclusice-use = "P8.12", "pru0";

        fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        example_pins: pinmux_pru_pru_pins {
                                pinctrl-single,pins = <
                                        0x30 0x06
                                >;
                        };
                };
        };

        //Enables PRU and assigns GPIO for use in EGP mode.
        fragment@1 {
                target = <&pruss>;
                __overlay__ {
                        satus = "okay";
                        pinctrl-names = "default";
                        pinctrl-0 = <&example_pins>;
                };
        };
};


I´m using the deplay.sh file from https://github.com/ZeekHuge/BeagleScope to compile and load the firmware to the PRU. Until now everything is working and I´m able to drive some NeoPixels.
The second step was to communicate from the Host to the PRU. I followed this instructions: https://gist.github.com/alexanderhiam/2c4187c710b2c409d8dde8c4015fe007.
I also wrote a .sh file for this example to compile and load the firmware into the PRU. During running the example PRU_RPMsg_Echo_Interrupt0 everything seemed to work. I modified the example code
(see below) and included a strncmp to see if my code is working or if I only read the message that I wrote to rpmsg_pru30. Here is what i got back:


echo "test" > /dev/rpmsg_pru30
cat /dev/rpmsg_pru30
test
Done! -> GPO pin remained low

echo "test123" > /dev/rpmsg_pru30
cat /dev/rpmsg_pru30
test123
Error! -> GPO pin became high



Here my modified code:

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <pru_cfg.h>
#include <pru_intc.h>
#include <rsc_types.h>
#include <pru_rpmsg.h>
#include "resource_table_0.h"

volatile register uint32_t __R31, __R30;

#define HOST_INT                        ((uint32_t) 1 << 30)

/* 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                     16
#define FROM_ARM_HOST                   17

#define CHAN_NAME                       "rpmsg-pru"
#define CHAN_DESC                       "Channel 30"
#define CHAN_PORT                       30
#define VIRTIO_CONFIG_S_DRIVER_OK       4


//uint8_t payload[RPMSG_MESSAGE_SIZE];
char payload[RPMSG_MESSAGE_SIZE];

void main(void)
{
        struct pru_rpmsg_transport transport;
        uint16_t src, dst, len;
        volatile uint8_t *status;

        char error[] = "Error!\n";
        char msg[] = "Done!\n";
        char command[] = "test\n";


        /* 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);

        __R30 &= 0xBFFF;

        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;

//                      if(__R31 & HOST_INT){
//                              while(1){
//                                      __R30 |= 0x4000;
//                              }
//                      }

                        while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS){

                                pru_rpmsg_send(&transport, dst, src, payload, sizeof(payload));

                                if(strncmp(payload, command, len) == 0){
                                        pru_rpmsg_send(&transport, dst, src, msg, sizeof(msg));
                                        __R30 &= 0xBFFF;
                                }
                                else{
                                        pru_rpmsg_send(&transport, dst, src, error, sizeof(error));
                                        __R30 |=0x4000;
                                }
                        }
                }
        }
}




The problem I´m stuck with is, that the bit 30 of register R31 always toggles back high after I cleared the flag (CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST;). I tried to figure this out by inserting the
uncommended part. The system always got captured in this while loop. I tried several of different solutions to solve this problem but nothing worked. 
                      if(__R31 & HOST_INT){
                              while(1){
                                      __R30 |= 0x4000;
                              }
                      }
Here some things I´ve already tried:
- wait some time after the flag was cleared until I checked the bit again
- insert the clear-flag command into a while loop until the bit is cleard
- also tried this solution because it seemed to be similar but also no success: http://e2e.ti.com/support/arm/sitara_arm/f/791/p/705580/2614884

Thank you in advance!

Regards,

Nathanael