AM2432: AM2432 - PRU GPO Toggling Issue

Part Number: AM2432
Other Parts Discussed in Thread: SYSCONFIG

Hi TI Support team,

As we required to toggle PRU Pins at the maximum toggling speed (in Mhz), i have taken the reference firmware for R5F - freertos core and PRU Core. For R5F FreeRTOS Project, i have taken reference firmware: - empty_pru_io_am243x-lp_r5fss0-0_freertos_ti-arm-clang  which configure and enable PRU cores and load it's fir

/*
 * Copyright (C) 2015 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.
 */

#include <stdint.h>
#include <pru_cfg.h>

volatile register uint32_t __R30;

/*
 * main.c
 */
int main(void)
{
	volatile uint32_t gpo;

	/* GPI Mode 0, GPO Mode 0 */
	CT_CFG.GPCFG0 = 0;

	/* Clear GPO pins */
	gpo = 0x0000;

	while (1) {
		gpo = __R30;
		gpo ^= 0xF;
		__R30 = gpo;
		__delay_cycles(100000000); // half-second delay
	}
}

mware; Similarly, for toggling PRU Pins, I have taken empty_am243x-lp_icss_g0_pru0_fw_ti-pru-cgt and written PRU Pins toggling code.

After complition of the above precedures, I built the firmware and programmed the AM243x_LP Board which result in it is not toggling the PRU Pins. 

I have gone through several documentations and followed the precedures mentioned there. However, the issue is remained same.

Can you provide me the procedures of controlling PRU Pins?

Moreover, i am going to attach my both firmware. Kindly review it or if possible then validate at your end if you have AM243x_LP Board and suggest the measures.

R5F-FreeRTOS Project: empty_pru_io_am243x-lp_r5fss0-0_freertos_ti-arm-clang.zip 

PRU Core Project: empty_am243x-lp_icss_g0_pru0_fw_ti-pru-cgt.zip 

Best regards,

Nilesh V Parmar

  • Hi,

    The thread owner is out of office till until week of Feb 17. Please ping the thread if you do not get an update during that week.

    Thank you for your patience.

    Regards,
    Harshith

  • Hi
    I see that SysConfig is missing for PRU pins. Based on PRU-ICSS instance used, please configure the pin-mux using PRU-ICSS module in SysConfig view. 

    Also, If you want to toggle pins are maximum frequency, assembly based programming would be recommended.Each PRU GPIO pin can be toggled by updating R30 register directly in 1 PRU cycle (3 ns at 333 MHz 200 MHz PRU core clock, 5 ns at 200 MHz PRU core clock and so on)

    Regards

    Dhaval

  • Hi Dhaval,

    Thanks for response.

    The problem is resolved and I'm able to toggle PRU GPIOs. So, we have achieved our first goal.

    The second goal is to make the communication channel between R5F Core and PRU Core. I believe that it can be done with PRU IPC.

    However, I could not find the examples which demonstrate the communication between PRU Core and R5F Core with IPC. 

    Can you provide the resource/examples for PRU Core and R5F Core with IPC in C language. Not in Assembly Language.

    Waiting for your response. Please response ASAP.

    Best regards,

    Nilesh

  • Nilesh

    Can you please share more details on the use-case you are trying to implement with PRU here?
    Based on that, we can provide appropriate suggestions.

    Regards

    Dhaval

  • Hi Dhruv,

    Can you please share more details on the use-case you are trying to implement with PRU here?

    Yes. Sure.

    We have data which is coming over USB in R5F core, and those data shall be transmitted to PRU Core for generating pattern on PRU Pins based on those data. Eventually, we have to drive the PRU Pins based on the data coming from R5F Core.

    To accomplish this requirement, it shall establish the connection between R5F Core and PRU Core over PRU IPC. However, the PRU Core firmware for PRU API is only available in Assembly which does not meet our requirements. Is there any resource/examples where PRU Firmware is written in C language for PRU IPC?

    Data -> Coming over USB -> R5F Core -> Write in a sharable memory -> PRU Core read data from sharable memory -> Toggle PRU Pins based on the data read from sharable memory.

    Moreover, provide your suggestions to fulfil these requirements.

  • Hello Nilesh,

    I am back from vacation. Thank you for your patience.

    Let's talk about some basic concepts.

    Training resources 

    I am the author of the brand-new AM243x PRU Academy. This is combined with the brand-new OpenPRU repo to be a complete PRU training resource for you.

    You can find the PRU Academy inside the AM243x academy here:
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AB.mSUi9ihL.a5hIt1grfw__AM24X-ACADEMY__ZPSnq-h__LATEST

    I am currently writing the next draft of the PRU Academy. If you have questions or feedback, please create a new e2e thread and it will come back to me.

    You can find the OpenPRU repo here:
    https://github.com/TexasInstruments/open-pru

    Example code

    Most of the new code that is targeted for beginning development is in the OpenPRU repo, or will be migrated to the OpenPRU repo. However, there are also example projects in other places:

    We have some very basic PRU code in the MCU+ SDK for ADC, as well as one implementation of inter-processor communication (IPC) between R5F and PRU. This IPC implementation is used in the ADC examples: 
    https://software-dl.ti.com/mcu-plus-sdk/esd/AM243X/latest/exports/docs/api_guide_am243x/PRU_IO.html 
    https://software-dl.ti.com/mcu-plus-sdk/esd/AM243X/latest/exports/docs/api_guide_am243x/EXAMPLES_PRU_IO.html 

    There is more complicated PRU firmware in the motor control SDK. I cannot remember if we include any source code in the Industrial Communication SDK at this point in time. In this stage of your software development, I do not suggest referring to that source code - it is not intended as a teaching resource.

    I will also be referring to examples in the older PRU Software Support Package (PSSP):
    https://git.ti.com/cgit/pru-software-support-package/pru-software-support-package/

    Eventually I will migrate all the examples over from PSSP to OpenPRU, but that is still a work in progress.

  • Usecase discussion: Bitbanging pins 

    The PRU cores are able to deterministically drive signals high or low on the pins (or read in pin values), with a much lower latency than any other processor core on the market, from TI or any of our competitors.

    For more information, refer to AM243x PRU Academy > Intro > What is the PRU, and what is the PRU good for? > 
    How are PRU GPIO signals different from regular GPIOs?
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AR2tkkLXaXMRE32fbWnq0w__AM24X-ACADEMY__ZPSnq-h__LATEST 

    If your waveform does not need to be perfectly precise, then writing in C code is fine. However, if you need to have exact precision over when your waveform goes high or low, then we suggest programming in assembly. You can also combine C code and assembly code into the same project. The PRU Getting Started Labs will teach you how to get started with C, assembly, or mixed C and assembly.

    Usecase discussion: IPC 

    IPC refers to ANY kind of communication between cores. The PRU IPC driver you referred to in the MCU+ SDK is one way of communicating between R5F and Linux, but it is NOT the only way.

    It sounds like your usecase would be Shared memory + notification mechanism. While I do not have a single example for you, there are multiple different examples we can pull from. Let's talk about usecase parts one at a time.

    Notification mechanism

    How will each core tell that the data is ready for consumption? By sending an interrupt? By setting the first 32 bits of the shared memory location as a software-defined "status register", and then polling the status register to see when the data is ready? etc.

    Using interrupts 

    The R5F core can use the PRUICSS APIs to receive and send interrupts to and from the PRU cores.

    For more information about how the PRU's interrupt controller (INTC) works, please refer to the PRU Academy > HW > PRU INTC
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AevsxGpIzHNOT9QB-MgrNA__AM24X-ACADEMY__ZPSnq-h__LATEST 

    You can configure the PRU's INTC either from the R5F core during PRU initialization, or from the PRU core's firmware after the PRU core has been initialized. For more information about how to use SysConfig to configure the INTC from the R5F core, refer to the PRUICSS driver documentation: https://software-dl.ti.com/mcu-plus-sdk/esd/AM243X/latest/exports/docs/api_guide_am243x/DRIVERS_PRUICSS_PAGE.html 

    Please refer to the OpenPRU training lab intc_mcu for an example of using R5F to configure PRU, and then sending and receiving interrupts between R5F and PRU core: https://github.com/TexasInstruments/open-pru/tree/main/academy/intc/intc_mcu 

    I have not had time yet to port those labs to AM243x, but all the same concepts apply to AM243x.

    But wait, the PRU firmware in that example is in assembly! What if I want to use PRU interrupts from a C program?

    Let me point you to the Linux RPMsg example for AM64x. The same concepts apply to AM243x (although obviously Linux A53 cores do not exist on AM243x):
    https://github.com/TexasInstruments/open-pru/blob/main/examples/rpmsg_echo_linux/firmware/main.c

    helper information:
    some variables set in makefile:
    https://github.com/TexasInstruments/open-pru/blob/main/examples/rpmsg_echo_linux/firmware/am64x-evm/icss_g0_pru0_fw/ti-pru-cgt/makefile
    constant table registers are defined here:
    https://github.com/TexasInstruments/open-pru/blob/main/source/include/c_code/am243x/pru_intc.h
    
    	while (1) {
    		/* Check register R31 to see if an interrupt has been received */
    		if (__R31 & HOST_INT) {
    			/* check the status of system event FROM_ARM_HOST to see if the ARM has kicked us */
    			if (CT_INTC.ENA_STATUS_REG0 & FROM_ARM_HOST_BIT) {
    				/* Clear the event status */
    				CT_INTC.STATUS_CLR_INDEX_REG_bit.STATUS_CLR_INDEX = FROM_ARM_HOST;
    				
    				/* the rest of your code goes here */
    			}
    		}
    	}

    Are there any other examples of sending and receiving interrupts with PRU C code?

    Yes.

    You can also refer to the PRU_Direct_ConnectX projects in the PSSP. I have not yet had time to port these projects to OpenPRU & port to AM243x:
    https://git.ti.com/cgit/pru-software-support-package/pru-software-support-package/tree/examples/am64x 

  • What if I want to poll a software defined status register instead? 

    Sure, you can do this. Please take another look at the PRU Getting Started Labs, where I provide an example of directly reading and writing from memory values: https://github.com/TexasInstruments/open-pru/blob/main/academy/getting_started_labs/c_code/solution/firmware/main.c 

    What about defining shared memory regions? 

    That's enough information for today. I'll let you read through everything and respond before I type out anything else.

    Regards,

    Nick

  • Please let me know that how to define share memory region and how much maximum data i can transfer in share memory in a single transactions?

  • Hello Nilesh,

    Shared memory region 

    You can define a shared memory region anywhere that both cores can access.

    So the shared memory region can be in DDR (better if this is a very large memory region), in the on-chip SRAM (if you need lower read/write latency), or even in the R5F subsystem or the PRU subsystem.

    For an example of defining a shared memory region from the R5F side in the SysConfig Memory Configurator tool, refer to page Application Development on Remote Cores > Allocate memory in the AM64x Multicore academy. Ignore the references to Linux, since AM243x does not have A53 cores:
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AXdlNVv-3hxEuToJ8O8ivg__AM64-ACADEMY__WI1KRXP__LATEST

    From the PRU side, how you access that shared memory would depend on where the memory was, how strict your timing requirements were, etc.

    I am reassigning your thread to another team member to comment on whether we have any examples for R5F reading and writing to a shared memory region.

    Regards,

    Nick

  • Please let me know that how to define share memory region and how much maximum data i can transfer in share memory in a single transactions?

    For shared memory logging, please refer KERNEL_DPL_DEBUG for details.

  • Hello Tushar,

    I have implemented the PRU IPC in my code and it's working as expected. However, we are facing some issues during the data transfer.

    We performed two cases in our application and observed that one is successfully executed and second one fails.

    CASE 0: (READ & WRITE 128BYTES (Block size: 32) - Block 0 of Buffer0

    1.  In R5F Project, configured PRU IPC as mentioned in below picture.

    2. Allocated memory region for share memory for address 0x30010000.

    3. In PRU Project, the linker script of PRU Project is updated based on the memory region allocated for shared memory in R5F Project. Below mentioned image shows that how linker is edited.

    3. For data transmission and receiving, R5F Core writes 128Bytes (32 Words) in a shared memory (Add: 0x30010000) and generate an interrupt event to PRU0 core.

    4.  PRU0 Firmware polling interrupt status register continuously and check that does interrupt occurred or not. Once the interrupt occurred then it reads data from the shared memory (Add: 0x30010000) and store in a buffer.

    5. Once the data is read, PRU0 firmware send an interrupt to R5F core for acknowledging that the data is received successfully.

    The case0 is working as expected.

    CASE 0: (READ & WRITE 256BYTES (Block size: 64) - Block 0 of Buffer0

    1. In R5F Project, configured PRU IPC as mentioned in below picture.

    2. Step 2 & 3 is same as mentioned in case0.

    3. For data transmission and receiving, R5F Core writes 256Bytes (64 Words) in a shared memory (Add: 0x30010000) and generate an interrupt event to PRU0 core.

    4.  PRU0 Firmware polling interrupt status register continuously and check that does interrupt occurred or not. Once the interrupt occurred then it reads data from the shared memory (Add: 0x30010000) and store in a buffer.

    5. Once the data is read, PRU0 firmware send an interrupt to R5F core for acknowledging that the data is received successfully.

    In result, the PRU firmware is not reading greater than 128bytes from a shared memory.

    Below is the data reading logic in PRU Firmware:

    PRU_IPC_MEM_BASE = 0x30010000

    As I observed the memory data in R5F Firmware for a shared memory, R5F Core is writing 256 bytes of data successfully. (Address: 0x30010000 to 0x30010100)

    Below images represent the data which I'm writing in a shared memory (In R5F Project).

    Below images represents the data I have read from the shared memory in PRU Firmware:

    It can be observed that the PRU Firmware is reading first 128 bytes (32 Words) correctly, but after it, it is reading the values from 0x30010000 instead of 0x30010080. 

    What could be the reason/bug behind it? Do I configure the PRU IPC correctly or not.

    Kindly review the above-mentioned images and provide the response as soon as possible.

    If you have an example which shows that how I can send more than 128bytes, then kindly share it with us.

    Best regards,

    Nilesh

  • Hello Nilesh,

    Hypothesis: maybe memcpy is not generating the correct assembly read instructions

    A single Load Byte Burst command (LBBO or LBCO) can only copy up to 124 bytes of data (refer to https://www.ti.com/lit/spruij2 ).

    If memcpy is smart enough, then I would expect it to break up the read command across multiple instructions, and update the read offset for each new instruction. But perhaps it is doing something else.

    Actions from your side

    Please share the PRU assembly code which is getting generated from your C code when you attempt to read larger amounts of data. For guidance on how to keep the generated assembly code, refer to the PRU Getting Started Labs > Lab 3: Compiling > Advanced Options > Assembler options
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AanXU02bdxmfZM6lEn3iHA__AM24X-ACADEMY__ZPSnq-h__LATEST 

    I will not have much time to map the assembly code to your C code, so please add some comments in the assembly code file showing me where the read command starts.

    You can see the association between your C code and the generated assembly code by stepping through your C code in CCS, and viewing the generated assembly code in the "Dissassembly" window. For more information, refer to PRU Getting Started Labs > Lab 5: Debug > Viewing and navigating assembly code
    https://dev.ti.com/tirex/explore/node?isTheia=false&node=A__AX1K.lD2Cl7kpC-fonM13A__AM24X-ACADEMY__ZPSnq-h__LATEST 

    Regards,

    Nick

  • Hello Nick,

    I have attached the system project which includes R5F Project and PRU Project.

    In PRU Project, we have two files, C files and assembly files.

    Interrupt handling and configurations are done in assembly files.

    Data reading from share memory is done in C file.

    7120.empty_am243x-lp_system_freertos_March19.zip

    Kindly review the PRU and R5F Firmware and provide your feedback.

    Let's us know if you need any further information.

    Best regards,

    Nilesh