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.

AM3359 ICE Pin Toggle - as fast as possible

Other Parts Discussed in Thread: AM3359

Hello

I want to test the GPIOs with a simple toggle pin program. It works, but I wonder why it is so "slow". Here my code for toggeling GPIO1 Pin8:

#include "soc_AM335x.h"
#include "gpio_v2.h"
#include "hw_cm_per.h"
#include "hw_types.h"

#define CONTROL_CONF_UART_CTSN(n)   (0x968 + ((n) * 0x10))

void main(void) {

    HWREG(SOC_CONTROL_REGS + CONTROL_CONF_UART_CTSN(0)) = 0x00000007u;    //pinmux mode7
    
    HWREG(SOC_CM_PER_REGS + CM_PER_GPIO1_CLKCTRL) = 0x02;

    /* Enabling the GPIO module. */
    GPIOModuleEnable(SOC_GPIO_1_REGS);
    /* Setting the GPIO pin as an output pin. */
    GPIODirModeSet(SOC_GPIO_1_REGS, 8, GPIO_DIR_OUTPUT);
    while(1)
    {
        HWREG(SOC_GPIO_1_REGS + GPIO_SETDATAOUT) = 256;       //set GPIO 1.8
        HWREG(SOC_GPIO_1_REGS + GPIO_CLEARDATAOUT) = 256;      //clear GPIO 1.8
    }
}

On my oscilloscope I measure an on-time of 200ns and an off-time of 270ns, making a period of 470ns. That runs with full optimization on L3 OCMC SRAM and Turbo Config (720MHz) set via GEL file.  When I put on the debugger and look the disassembly I see the following reasonable short code for the while loop:

21                                     HWREG(SOC_GPIO_1_REGS + GPIO_SETDATAOUT) = 256;       //set GPIO 1.8
                               $C$L1:
402f10d0: $C$L1+0                E59F0020 LDR             R0, $C$CON4
402f10d4:                        E3A0CC01 MOV             R12, #256
402f10d8:                        E580C000 STR             R12, [R0]
22                                     HWREG(SOC_GPIO_1_REGS + GPIO_CLEARDATAOUT) = 256;      //clear GPIO 1.8
402f10dc:                        E59F0018 LDR             R0, $C$CON5
402f10e0:                        E3A0CC01 MOV             R12, #256
402f10e4:                        E580C000 STR             R12, [R0]
19                                 while(1)
402f10e8:                        EAFFFFF8 B               $C$L1

Is this the fastest possible configuration for the GPIO ? Seems too slow to me. Is there a datasheet for (pin) timings for am3359?

Greetings, Björn

  • Bjoern,

    I haven't tried that but you need to keep in mind that access to GPIO module is via the L4 cross bar. So your code will have wait states I think.

    You might want to check CPU cycles using CCS. This assumes you have MMU and cache enabled of course.

    Regards.

  • Bjoern,

    As Frank said, these accesses to GPIO go over the L4 interconnect which is for least demanding of the peripherals. So, it is unlikely to be the CPU operating frequency that is causing the delay. At 200MHz L3 speed, 470ns is 94 cycles for two - set and clear - operations.

    If you are interested in toggling pins at very fast pace, you can consider developing code for the PRU subsystem where you can toggle a pin (not GPIO, but PRU pins) at every cycle, that is, every 5 ns.

    Thanks,

    Maneesh

  • Hi Maneesh,

    Thanks for the hint!

    I checked the beagleboard-am335x_pru_package from github and followed the documentation and was able to assemble and execute some basic PIN toggle code for the PRU on the ICE board.  But it does not work as I expected.

    What I did:

    I located a free PIN, that is A14 = PR1_PRU0_PRU_R30_7=mcasp0_ahclkr from ICE schematic. In Code Composer Studio I executed a pinmux code in the A8 core:

    #define mcasp0_ahclkr 0x99C;  //register offset

    void main(void) {

         HWREG(SOC_CONTROL_REGS + mcasp0_ahclkr) = 0x0005;    //mode5

         while(1);
    }

    Then executet PRU_ICSS_INIT from the GEL file.

    With the Memory Browser I loaded the bin file to be executed in PRU0 to address 0x00000000:

            .origin 0    
    loop_label:
            MOV r30, 0xffffffff
            MOV r30, 0x00000000    
            qbne     loop_label, r0, 0
            ret
           

    I can see Core Register R30 of PRU0 change its value, when I step in disassembly.         -But I see no output signal on my scope on that pin-

    What am I doing wrong ? Is anything missing in the initialization ?

    Well, I see in the ethercat example for the ICE that it uses the PRU instructions in a C array, which can be assembled with pasm.exe as well. I would like to use this way. My problem is the initialization part, pin muxing, code loading and starting of the PRUSS for a simple PIN Toggle program.

    Does anyone have a basic example to do this (without sys/bios if possible), please ?

    Thanks again, Björn

  • Bjoern,

    I think you got the wrong pin. A14 is mcasp0_ahclkx...

    But you configured B12 which is actually in use by something else.

    Regards.

  • Hi,

    i having problem in detect fast toggling input (around 4Mhz), i discover that my GPIO need around 1us to detect a level high input signal, that mean i will miss detect the 4Mhz input signal.

    How to increase my GPIO input detection speed?

    i write my code in kernel space, as following:

    static unsigned char *mmio;

    volatile unsigned int *gpio_dir, *gpio_out, *gpio_in;

    int core_init(void)

    {

          mmio = ioremap(GPIO1_BASE, GPIO_SIZE);  //GPIO1 mapping

          gpio_dir = (unsigned int *)(mmio + GPIO_DIR); //GPIO1 direction register mapping

          gpio_out = (unsigned int *)(mmio + GPIO_OUT); //GPIO1 output register mapping

          gpio_in = (unsigned int *)(mmio + GPIO_IN); //GPIO1 input register mapping

          *gpio_dir |= (1 << 0); //set gpio1 pin 0 to input

          while(1)

           {

                       if(*gpio1_in & (1 << 0)) //if gpio1 pin 0 equal to logic 1

                       {

                                  printk("signal detected!");

                                  break;

                       }

           }

            return 0;

    }

    Thanks & Regards

    Keldy

  • Hello Frank,

    You are right, it was the wrong pin, but the signal output still does not work. I use this code to set the MCASP0_AHCLKX pin to PRU0 R30[7]:

    #include "soc_AM335x.h"
    #include "hw_types.h"
    #include "hw_control_AM335x.h"

    void main(void) {
        HWREG(SOC_CONTROL_REGS + CONTROL_CONF_MCASP0_AHCLKX) = 0x0005;    //mode5
         while(1);
    }

    In CCS5 debugger I do:

    -connect to A8 core

    -load and execute TMDXICE3359.gel "AM3359_ICE_Initialization" script

    -load and execute AM335x_PRU_ICSS.gel "PRU_ICSS_Init" script.

    -connect to PRU_0 core

    -in the Memory Browser I load "toggle.bin" to Start Address 0x0 of PRU_0 program memory

    toggle.bin has the following (assembled via pasm.exe -b toggle.asm) content:

    .origin 0           
    loop_label:
            MOV r30, 0xffffffff
            MOV r30, 0x00000000            
            qbne     loop_label, r0, 0

    -start A8 and PRU_0 core
          

    Still no signal coming out at pin GPIO3[21], even if I step in the PRU_0 disassembly. If I toggle the same pin via code run in A8 core, I see the signal coming out.

    Any ideas what is missing here ?

    Is there some basic code to do the whole init, load, run sequence from the A8 code ?

    I found some linux code for the beagle board, but not for the ICE board. It should be possible to generate toggle_bin.h file that contains something like const unsigned int PRUcode[] = {....}.

    Btw: Does TI offer some educational training around the AM335x Industrial Communication Engine ?

    Greetings, Björn