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.

AM6411: Implement proprietary 32bit parallel bus with PRU

Part Number: AM6411

We need to interface a chip with a proprietary 32 bit parallel interface. It works a lot like an SPI with 32 data lines. 100MHz clock frequence would be great but 50MHz is good enough/acceptable. We are considering AM6411 for this purpose.

However, I noticed in datasheet each PRU unit has only 20 output pins. Can I gang pru0 and pru1 together to implement a 32bit data bus? We only need output mode. Hopefully there is a hardware-based mechanism to reduce the synchronization overhead. If several clocks are required to sync two PRU units, I am worried that the actual data clock would drop too low.

Any confirmation and data rate estimation would be appreciated.

  • Hello Ma Tianfu

    Thank you for the query.

    Let me check internally.

    If there is a diagram explaining the planned implementation, that would help me to check internally.

    Regards,

    Sreenivasa

  • Hi

    PRU GPIOs can be toggled using registers in one instruction. On AM64x, PRUs can run at 200/250/300/333 MHz frequency. 

    Exact frequency you can achieve would depend on number of instructions needed to implement the required interface. Let's say data is fixed, you can hard-code the data as you do not need to load it from a different memory and number of instructions needed would be less. If data is not fixed, then it needs to be loaded from data memory or shared memory or through IPC scratchpad from other cores (1x PRU-ICSSG has 2 slices, each slice has 3x cores - PRU. RTU, TXPRU). 

    Following is a possible implementation:

    PRU firmware running @333 MHz (4 clks = 83.33 interface clock with 50/50 duty cycle) or @300 MHz (3 clocks = 100 MHz interface clock with odd duty cycle )


    - Synchronize 2 PRUs using IEP timer based  SYNC event. IEP is a timer within PRU-ICSS IP, which can create events based on required compare value. This event can be configured to be routed to PRU R31 bit30/31 using the PRU-ICSS interrupt controller (INTC) module. This bit in R31 can be used to synchronize multiple PRU cores. Each PRU core can pend on this bit.
    - Play back data and clk from pre-loaded pattern
    ldi r30, data1_clk_high
    nop
    ldi r30, data1_clk_low
    nop
    ldi r30m data2_clk_high
    ....
    data can be static part of firmware or loaded from RTU core over IPC_SP (32 bytes in single cycle replacing a NOP instruction).

    - 32 bit data bus is split between 2 PRUs into 2x 16 bit data lines. One PRU serves low word and other PRU serves high word. As PRU execution is always single cycle (when not using load/store like LBCO/SBCO, or WBS like instructions), the data high word and data low word come out at exactly (< 1ns skew) the same time.

    Regards

    Dhaval

  • Thank you for your reply. We do not have a clear plan on implementation detail yet. We just think the pru, the iconic feature of sitara series, would be better suited for this job, since it can toggle GPO pin very fast. And my question is straightforward. For AM64x/AM24x, each PRU unit has only 20 GPO pin and we need to transfer 32bit data. The limitation is clear. If we can use two PRU units to work synchronously, one unit could put 16bit data on bus and the other put remaining 16bit data, then we have a 32bit parallel bus.

    I have read some articles on PRU programming. It seems there's no mechanism provided to synchronize two pru units clock by clock. There is a small block of IPC RAM which could be used for synchronization (in terms of multitasking). But I don't know how to use it to make two unit write GPO simultaneously. Another possibility is to use a timer as the event trigger. When data to be send is ready in RAM, both PRU units begin to poll the event status, once the timer fired (or a similar event happens, such as a GPI pin toggled), two PRU units start to write GPO pin simultaneously. But we have no idea how 'simultaneous' the signals could be. One or two clocks of delay should be acceptable.

    Anyway we have ordered EVM board and will give it a try. Learning by doing is always a good philosophy in the embedded world.

  • Thank you for your advice. Sound promsing. We will give it a try asap.

  • Hello Ma Tianfu,

      I have implemented and tested the scheme to sync PRU0 and PRU1 using task manager. PRU0_GP0 and PRU1_GPO0 come out in sync with skew < 1ns.

    Here the source file in PRU assembler project. I am using compiler defines PRU0 and PRU1 to build out file for both PRUs.

    ; Copyright (C) 2018 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.
    ;
    ;     file:   main.asm
    ;
    ;     brief:  PRU sync using task manager. Single source filed using PRU0 and PRU1 defines
    ;             Used IEP0 CMP0 hit to trigger task manager at PRU0 and PRU1.
    ;             Toggles PRUn_GPO0 which are BP.11 and BP.33 pins.
    ;
    ;
    ;    Version        Description                                Author
    ;     0.1         Created                                      Thomas Leyrer
    
    ;************************************* includes *************************************
     ; .if $defined(PRU0)
    
    
        .include "include/PRU/icss_core_clock_macros.inc"
        .include "include/peripherals/icss_iep_regs.inc"
    
    ;CCS/makefile specific settings
        .retain     ; Required for building .out with assembly file
        .retainrefs ; Required for building .out with assembly file
    
        .global     main
        .sect    ".text"
    
    
    ;********
    ;* MAIN *
    ;********
    
    main:
    
       tsen 0
       .if(PRU0)
    ;*********************************** clock_config ************************************
    
    ; call macro to set ICSS_G0 core clock
        m_set_icssg_0_core_clock_333MHz
    
    
    ;************************************* padconfig *************************************
    ; unlock PADMMR config register
    ; partition 0
        ldi32    r2, 0x000f1008  ; LOCK0 KICK0 register
        ldi32    r3, 0x000f100c  ; LOCK0 KICK1 register
        ldi32    r4, 0x68EF3490  ; Kick 0
        ldi32    r5, 0xD172BC5A  ; kick 1
    
        sbbo     &r4, r2, 0, 4
        sbbo     &r5, r3, 0, 4
    
    ; partition 1
        ldi32    r2, 0x000f5008  ; LOCK1 KICK0 register
        ldi32    r3, 0x000f500c  ; LOCK1 KICK1 register
    
        sbbo     &r4, r2, 0, 4
        sbbo     &r5, r3, 0, 4
    
    ; pin-mux configuration - PRG0_PRU0_GPO0 - output BP.33
        ldi32    r2, 0x000F4160
        ldi32    r3, 0x00010000
        sbbo     &r3,r2, 0, 4
    
    ; pin-mux configuration - PRG0_PRU1_GPO0 - output BP.11
        ldi32    r2, 0x000F41B0
        ldi32    r3, 0x00010000
        sbbo     &r3,r2, 0, 4
    
        .endif
    
    
    ;**************************** task_manager_config **********************************
    
    ; configure task manager TS1_0 for xfr2vbus_rd0
        .if(PRU0)
        ldi32   r2, 0x0002a000  ; TM base PRU0 , ICSS_G0
        .elseif(PRU1)
        ldi32   r2, 0x0002a200  ; TM base PRU1 , ICSS_G0
        .endif
    
        ldi     r3, 0x0006      ; general purpose mode = 2 , TS1_S0 = iep_cmp0 hit (bit 2)
        sbbo    &r3, r2,0, 2
    ; set task address
    ; TS1_0
        ldi     r3.w0, $CODE(tm_iep0)
        sbbo    &r3.w0,r2,0x08, 2
    
    ; set TS1 trigger to iep0_cmp0_hit = 16
        ldi     r3.b0, 16
        sbbo    &r3,r2, 0x38, 1
    
        .if(PRU0)
    ;******************************** iep config **********************************
    ; reset iep0 timer
        ldi     r2.b0, 0x2
        sbco    &r2.b0, c26, ICSS_IEP_GLOBAL_CFG_REG, 1
    
        ldi32   r2, 0 ;0xffffffff
        sbco    &r2, c26, ICSS_IEP_COUNT_REG, 4
        sbco    &r2, c26, ICSS_IEP_COUNT_REG + 4, 4
    
    ; set CMP0 period - 2.0 us update iep counter by 1 means each count is 4 ns
        ldi32   r2, 0x1f4
        sbco    &r2, c26, ICSS_IEP_CMP0_REG, 4
    
    ; set CMP0 wrap around mode + CMP0
        ldi32   r2, 0x00000003      ; cmp0 en + wrap around
        sbco    &r2, c26, ICSS_IEP_CMP_CFG_REG, 4
    
    ;set auto clear cmp events with cmp0 wrap around
        ldi32   r2, 0x00026040     ; ICSSGx_SA_MX_REG
        ldi     r3.b0, 1
        sbbo    &r3, r2, 2 , 1
    
    ; enable iep0 timer
        ldi     r2.b0, 0x111
        sbco    &r2.b0, c26, ICSS_IEP_GLOBAL_CFG_REG, 2
    
    ;******************************** main ***************************************
        .endif
         tsen 1
    
    idle_loop:
        qba     idle_loop
    
    ;**************************** task_set_GPO0 **********************************
    tm_iep0:
        set     r30, r30, 0
        loop    wait, 256
        nop
    wait:
        clr     r30, r30, 0
    ; exit task after two instructions/cycles
        xin     252, &R0.b3,1
        nop
        nop
    
    ; ********************** end of task *******************************
    
    
    

    Let me if you have any questions.

    BR,

      Thomas