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.
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