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.

am335x pru gpioToggle example

I am new to the PRUSS. And I am trying to make baby steps into getting where i want to be.

My first goal is to physically measure GPIO's (as outputs) , driven by the PRU. Meaning I am creating a gpioToggle example which is missing for am335x.

I have done many experiments on the code to try and get the GPIO's working, but remain unsuccessful.

I have the am335x specsheet. the PRUv1 examples and the PRUv2 examples.

I am able to compile/load/run PRU binaries from the PRUv2 examples

https://github.com/beagleboard/am335x_pru_package/

There are many magic numbers in the old gpioToggle example without an explanation or how they can be found/calculated. (some I can understand, and most I don't)

E.g.

Some super basic stuff like:

Where can i find the logic of using the internal muxer to couple a GPIOx_x to R30?

 //PRU1_R30[15]
    M_MOV32   R0, SYS_BASE
    LBBO    R1, R0, PINMUX12, 4
    AND R1.b0,R1.b0,#0xF0
    OR R1.b0,R1.b0,#0x04
    SBBO    R1, R0, PINMUX12, 4

this actually means:

-load (sys_base + pinmux12 offset)

- do & 0xF0

- do | 0x04

-store.

I do not understand the values chosen, nor can I map them to the AM335x CPU/PRU: sys_base, pinmux, 0xF0, 0x04.

(I already found that STANDBY_INIT should be set to 0)

Perhaps instead of me trying to convert these files:

Is it possible for you to port the gpioToggle example from the old PRU to the new PRUv2 for AM335x?

If you could add enough comments (for all the magic numbers) so that I can understand the origin/calculation, then perhaps I could be able to continue on my own.

My second goal is to generate interrupts PRU2ARM by GPIO's (as inputs), but that is a separate topic if needed :-)

Thanks in advance.

  • solved.

    the migration guide (02-AM18x_PRUSS_to_AM335x_PRU-ICSS_Software_Migration_Guide.pdf) shows how to set STANDBY_INIT to 0 from ARM/C code parts

    the pinmux for that specific pin had to be set (output + mode6), pinmux control is on 0x44e10000 +834 for that specific pin for the am335x.

  • Hi Ron,

    I'm trying to do the same thing that you're doing but I'm a bit behind in where you are.  I'm currently trying to get the examples that are supposed to work already to work.

    I'm stuck trying to get a kernel image that works with the PRUSS driver.

    I've built a kernel and installed it but after doing so it doesn't seem to work--it no longer allows me to log in either via USB or ethernet on my beaglebone.

    Can you detail what steps you took to get the kernel installed?  Are you using Angstrom or something else?

    thanks,

    Fritz

  • I have a self built kernel from the git://github.com/beagleboard/kernel.git repo. (for beaglebone)

    and a self built crosscompiler created from crossdev (gentoo)

    you can use the "make CROSS_COMPILE=armv7a-your-custom-toolchain-  ARCH=arm am335x-evm-defconfig"

    to get your default kernel and afterwards optimize it (it should run out of the box)

    in the kernel options there is   "device drivers"  --> "userspace i/o drivers" ---> "texas instruments PRUSS driver"   make sure it is enabled (either as module or in the kernel)

  • Thanks for the reply Ron.  I finally got past my problem.  The main problems I was having were not knowing what to expect with the new kernel install.  The original kernel that I had (Angstrom linux for beaglebone from a non-ti source) would blink some LEDs so you'd know it was doing something.  The TI kernel didn't.

    I also didn't know that you could see boot output by connecting the beaglebone to your PC (in my case a mac) via USB and going through the steps to connect it to a terminal window.

    I also didn't know that under the rootfs there's a /boot subdirectory which I thought was used to load the kernel image.  It is not.  It is loaded from the FAT partition (which TI labels as "boot").  The kernel is called uImage, in my case at least.  I ended up copying the kernel to my SD card by pulling the card out of the beaglebone and inserting it into a card reader, and plugging that into the mac.  There's a script in the SDK which allows you to create a new SD card image.  I had to modify that a bit to get it to work, but ended up with something that worked.

    In my opinion, TI should get rid of all the instructions which talk about the START_HERE script.  For those of us who didn't get an SD card from TI or who accidentally had a problem and blew it away and had to reformat it, we don't have access to the START_HERE script.  And it was a big time waster for me to try to figure out what it was supposed to be doing.  Just tell people they don't need it and how to do it with the newest SDK, please.

  • Ron,

    If you've already ported (or partially ported) the gpio example, and you don't mind sharing, can you post what you did?  I'm trying to get this working today.

        thanks,

        Fritz

  • it is actually very basic.

    ...

    GPIOTOGGLE:
       SET      R30.t15 // set GPIO1_13 high
       CLR      R30.t15 // set GPIO1_13 low

    ...

    be sure that you have an oscilloscope on GPIO1_13 (somewhere on P8 or P9 connectors of beaglebone: i am sure you can find where)

    you will find a 200mhz signal

    And be sure that the pinmux is set correctly for that pin (/sys/kernel/debug/omap_mux/) like below:

    /sys/kernel/debug/omap_mux # cat gpmc_ad13
    name: gpmc_ad13.gpio1_13 (0x44e10834/0x834 = 0x0027), b NA, t NA
    mode: OMAP_PIN_INPUT_PULLDOWN | OMAP_MUX_MODE7
    signals: gpmc_ad13 | lcd_data18 | mmc1_dat5 | mmc2_dat1 | eqep2B_in | pr1_mii0_txd | pr1_pru0_pru_r30_15 | gpio1_13

    /sys/kernel/debug/omap_mux # echo "17" > gpmc_ad13

    /sys/kernel/debug/omap_mux # cat gpmc_ad13
    name: gpmc_ad13.gpio1_13 (0x44e10834/0x834 = 0x0017), b NA, t NA
    mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
    signals: gpmc_ad13 | lcd_data18 | mmc1_dat5 | mmc2_dat1 | eqep2B_in | pr1_mii0_txd | pr1_pru0_pru_r30_15 | gpio1_13
    /sys/kernel/debug/omap_mux #




  • Many thanks for your reply Ron!

      Fritz

  • Hi again, Ron.  I still have more reading to do, but I tried to just get this working by modifying one of the newer examples and just changing the .p file as follows:

    // *****************************************************************************/
    // file: PRU_gpioTest.p
    //
    // brief: test of gpio. began with an example from Melissa Watkins of TI
    //
    //
    // (C) Copyright 2012, Texas Instruments, Inc
    //
    // author M. Watkins
    // Fritz Renema
    // Dell Services Federal Government
    // NASA Ames research center
    // July 12, 2012
    //
    // version 0.1 Created
    // *****************************************************************************/

    .origin 0
    .entrypoint GPIOTOGGLE

    #include "PRU_gpioTest.hp"


    GPIOTOGGLE:


    #ifdef AM33XX

    // Configure the block index register for PRU0 by setting c24_blk_index[7:0] and
    // c25_blk_index[7:0] field to 0x00 and 0x00, respectively. This will make C24 point
    // to 0x00000000 (PRU0 DRAM) and C25 point to 0x00002000 (PRU1 DRAM).
    MOV r0, 0x00000000
    MOV r1, CTBIR_0
    ST32 r0, r1

    #endif

    GPIOTOGGLE_LOOP:
    MOV r30, 0xffffffff
    MOV r30, 0x00000000
    // SET R30.t15 //set GPIO1_13 high
    // CLR R30.t15 //set GPIO1_13 low
    JMP GPIOTOGGLE_LOOP

    #ifdef AM33XX

    // Send notification to Host for program completion
    MOV R31.b0, PRU0_ARM_INTERRUPT+16

    #else

    MOV R31.b0, PRU0_ARM_INTERRUPT

    #endif

    The only thing that worked was that the user-space side did not return, as expected, due to the infinite loop.  I've been banging my head against the wall since early this morning trying to get this to work.  Here a log of some of my problems and solutions for others who may run into the same thing:

    =================

    So while printing the very large AM335x PRU-ICSS Reference guide, I started coding something up by copying one of the

    examples for the new AM335x PRU and modifying it.  So I changed the .p file to just loop on the GPIOTOGGLE: code that

    Ron gave me, above.  Now I needed to figure out this /sys/kernel/debug/omap_mux thing because it did not exist for me.

    After a while, I found an example (http://www.nunoalves.com/open_source/?p=108) that someone posted that used a 

    shell script to turn some gpio pins on and off from

    user space.  I thought I'd try that.  Had some trouble though.  Problems were that, again, /sys/kernel/debug/omap_mux

    is not present on my system.  Also, the script relies on bash, which wasn't on my system.   Trying opkg install bash failed.

    I got around the problem of not having the omap_mux directory by going to /sys/kernel/debug and doing the following:

    root@am335x-evm:/home/fritz# mount -t debugfs none ./debug

    That worked.

    I got around the problem of not being able to get bash by going to the angstrom package browser, downloading the bash package

    for the correct processor to my mac, scp'ing it to the beagelbone, and installing it via opkg install <bash…>.ipk

    After that the script seems to have worked.  I don't know because now I have to research where the pins are located so I can

    hook up an oscilloscope and watch them.

    for angstrom package browser, which I found via this link:

    http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/

    go here:

    http://www.angstrom-distribution.org/repo/

    ok, that worked.  I looked at P8_3, which is GPIO1_6, and I found that (in BONE_SRM.pdf--the beaglebone system reference

    manual) to be on expansion Header P8 pin 3.  P8 is the expansion header on the right side of the ethernet connector, if you have the

    ethernet connector pointed up to the sky.

    Now I want to get Ron's example working on the PRU.

    He used GPIO1_13, which is pin 11 on P8.  First I'll try it with the shell script…  worked, so I got the correct pin.

    next, I need to manually look at that omap_mux the way Ron recommended…

    ok, it didn't work. 

    I noticed that doing what Ron said to do to set this up, setting the omap_mux to 17, caused the output to go high.  I also

    noticed that it was originally low and was 07, so I deduced that the tens field corresponds to the level to set it to and the ones

    field must have to do with the mode (7 must mean make it an output and use mode 7, which must mean keep it as an output

    connected to GPIO1_13).  That seems to be the case.  I found by doing this:

    root@am335x-evm:/home/fritz# echo "17" >/sys/kernel/debug/omap_mux/gpmc_ad13; echo "07" >/sys/kernel/debug/omap_mux/gpmc_ad13

    that the pulse width was 184.5us.  I tried this several times and it was fairly consistently between 155.5us and 184.5us.

    now, why isn't my program working?  It's partially working, because it does not return now.  

    Next I'm going to make it so it just sets it high….

    well, it returns now like it should (b/c I got rid of the infinite loop), but it does not set the output high.  I guess I have to

    look at the example from TI for the older version and read enough to figure out what the problem is.

    ======================

    Any ideas, Ron?  :)  I'm close, but stuck, at the moment.

       regards,

       Fritz

  • Hi Fritz,

    You are indeed close to the solution: you should change the GPIO1_13 function to correspond to the PRU1_R30_15 function or PRU0_R30_15 function (depending on which PRU you decide to use)

    I believe it is mode 6 on that pin (haven't checked, but most PRU pin functions are on mode 6), if you put it on mode 7 it will remain in GPIO1_13 mode, inaccessible by PRU. So in essence: don't think of it as a GPIO function, think of it as an output of the PRU :-) and reconfigure the pinmux through the debug fs from the kernel (the content of each file should hint sufficiently to get it done correctly)

    echo 07 => output mode 7

    echo 17 => output mode 7

    echo 27 => input pulldown mode 7

    echo 37 => input pullup mode 7

    echo 47 => output pullup mode 7 (anytning 4-9 = output (the code default))

    echo 16 => output mode 6

    (this is all out of my head, didn't look it up, but should be a close match)

  • Hi Ron,

    thanks again.  I'm not following this very well because I haven't read enough yet, but it sounds like the problem I'm having is due to the pinmuxing.  So thanks for the further hints!  Back to reading and trying to figure this out for me.  :)

      Fritz

  • Still not getting it after a lot of reading.  Finally installed windows xp virtual machine on my mac so I could run the TI pin mux utility to hopefully shed some light on the subject.

    I'm not sure I'm right but it seems from glimpsing through readme files that I need to rebuild a u-boot image with the correct settings generated by the pinmux tool to enable PR1_PR0_PRU_R30[15], which corresponds with GPMC_AD13.  Does that sound right?

    I did try setting to mode 6 (which I think is correct if I read the pin mux utility screen display correctly), and it didn't seem to make any difference.  Still no output via the PRU.  :(

  • ok, woo hoo!! got it working.  the problem was that in taking the beagleboard home I disconnected the

    oscilloscope and was looking at the wrong pin (this was complicated by a computer crash which made me

    lose some changes to the shell script I was using to test that I was on the correct pin before trying things from the PRU

    side).  duh.  So mode 6 made it work.

    Incidentally, for others trying to do the same thing, the way to figure out the modes is to run the TI pinmux

    utility.  I also used information here to help me understand things (thanks, Nathan!): http://www.nathandumont.com/node/250

    The pinmux utility is windows only so I ended up installing windows XP under vmware fusion on my mac just

    for that utility.  After learning that mode 6 was necessary, I set it to mode six by doing this on the beaglebone's

    linux side (as root): echo "06" >gpmc_ad13.

    My assembly code that I ended up running was this:

    GPIOTOGGLE:

    #ifdef AM33XX

        // Configure the block index register for PRU0 by setting c24_blk_index[7:0] and

        // c25_blk_index[7:0] field to 0x00 and 0x00, respectively.  This will make C24 point

        // to 0x00000000 (PRU0 DRAM) and C25 point to 0x00002000 (PRU1 DRAM).

        MOV       r0, 0x00000000

        MOV       r1, CTBIR_0

        ST32      r0, r1

    #endif

        MOV      r3, 0x0000ffff

    GPIOTOGGLE_LOOP:

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

        OR       r30, r30, r3

        MOV      r30, 0x00000000

    //    MOV       PRU0_r30, 0x00000000

    //    SET       R30.t15 //set GPIO1_13 high

    //    CLR       R30.t15 //set GPIO1_13 low

        JMP       GPIOTOGGLE_LOOP

    I ended up using a bunch of copies of the set and clear as you see so that I could see 5ns wide pulses on the oscilloscope.  The jump instruction adds a delay.  I'm seeing pulses that are not very squared off, and I'm thinking I need to do more reading on the mode to set a pull-up or pulldown or something.  But in general it looks like it's working!  yeay!!!

  • good to hear the progress.

    Good luck reaching your end-goal :-)

  • Thanks again Ron--you too!  :)

  • Hi Fritz,

    Where can I find this  PRU_gpioTest example ?

    Thanks,

    Reuben

  • Hi Reuben,

    I posted the code in this thread.  It's just something I threw together by changing an existing example.  If you read what I wrote, you should be able to do the same thing pretty easily, hopefully.

      cheers,

      Fritz

  • Hi Fritz,

    I've managed to toggle an output pin on the P8/P9 headers using the PRU GPOs and measured it with an oscilloscope.

    Now I'm trying to do test the PRU GPIs. I hooked up a function generator to one of the header pins and I'm trying to read in the values using the PRU. To do this, I've set up the multiplexing of the appropriate pin (to mode 6) and read values from the appropriate bit from R31. But, I'm always reading 0's even when I send a high input through the header pin.

    Could you please point out if I'm missing anything ? Is there any other step which I need to do other than these ? 

    Thanks