Skip to content

Add GCC example for rpmsg echo#113

Open
dinuxbg wants to merge 4 commits intoTexasInstruments:mainfrom
dinuxbg:gcc-for-rpmsg-example
Open

Add GCC example for rpmsg echo#113
dinuxbg wants to merge 4 commits intoTexasInstruments:mainfrom
dinuxbg:gcc-for-rpmsg-example

Conversation

@dinuxbg
Copy link

@dinuxbg dinuxbg commented Feb 19, 2026

User description

I figured it would be nice to have one example with GCC.

The GCC support is relatively non-intrusive. A few places in shared code required #ifdef statements due to different syntax in GCC and CGT.

I tested the firmware on BeaglePlay with kernel 6.12.43-ti-arm64-r54.


PR Type

Enhancement, Bug fix


Description

  • Add GCC compiler support for rpmsg echo example

    • New Makefile and INTC map header for gnu-pru-gcc toolchain
    • Conditional compilation directives for GCC-specific syntax
  • Fix compiler warnings and compatibility issues

    • Fix signedness comparison warning in pru_virtqueue.c
    • Fix pointer-to-integer cast warning using uintptr_t consistently
    • Add missing string.h header for memcpy usage
  • Update resource table initialization for GCC compatibility

    • Restructure initialization with proper nested braces
    • Add GCC section attribute support

Diagram Walkthrough

flowchart LR
  A["GCC Toolchain Support"] --> B["New Build System"]
  A --> C["Code Compatibility"]
  B --> D["Makefile for gnu-pru-gcc"]
  B --> E["INTC Map Header"]
  C --> F["Conditional Compilation"]
  C --> G["Compiler Warnings Fixed"]
  F --> H["Register Access via pru/io.h"]
  F --> I["Section Attributes"]
  G --> J["Signedness Cast Fix"]
  G --> K["Pointer Cast Fix"]
  G --> L["Missing Header Added"]
Loading

File Walkthrough

Relevant files
Configuration changes
Makefile
GCC build system for PRU rpmsg echo                                           

examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/gnu-pru-gcc/Makefile

  • New build system for GCC-based PRU compilation
  • Configures compiler flags, header directories, and source files
  • Defines RPMsg and INTC configuration macros
  • Provides targets for ELF, assembly, and binary image generation
+116/-0 
Enhancement
intc_map.h
INTC mapping header for GCC toolchain                                       

examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/gnu-pru-gcc/intc_map.h

  • New header file defining PRU INTC mapping for rpmsg
  • Configures system event 17 mapping to host interrupt
  • Uses conditional compilation for GCC vs CGT syntax
  • Includes documentation on INTC configuration and device tree usage
+53/-0   
main.c
GCC-compatible register access in main                                     

examples/rpmsg_echo_linux/firmware/main.c

  • Add conditional compilation for __R31 register access
  • GCC uses pru/io.h header instead of direct register declaration
  • Maintains compatibility with CGT compiler
+5/-1     
pru_intc.h
GCC-compatible INTC register declaration                                 

source/include/c_code/am62x/pru_intc.h

  • Add conditional compilation for CT_INTC declaration
  • GCC uses macro-based pointer cast instead of cregister attribute
  • Maintains CGT compatibility with pragma directives
+4/-0     
resource_table.h
GCC-compatible resource table definition                                 

source/include/c_code/linux/resource_table.h

  • Add conditional compilation for resource table section placement
  • GCC uses __attribute__((section())) instead of pragmas
  • Restructure initialization with proper nested braces for GCC
  • Maintains compatibility with CGT compiler
+14/-6   
Bug fix
pru_virtio_ring.h
Fix pointer cast warning in vring init                                     

source/include/c_code/linux/pru_virtio_ring.h

  • Fix pointer-to-integer cast warning in vring_init function
  • Change intermediate cast from uint64_t to uintptr_t
  • Ensures consistent pointer size handling across architectures
+1/-1     
pru_rpmsg.c
Add missing string.h header                                                           

source/rpmsg/pru_rpmsg.c

  • Add missing #include <string.h> header
  • Required for memcpy function usage
+1/-0     
pru_virtqueue.c
GCC compatibility and signedness warning fix                         

source/rpmsg/pru_virtqueue.c

  • Add conditional compilation for __R31 register access
  • GCC uses pru/io.h header instead of direct register declaration
  • Fix signedness comparison warning by casting head to uint32_t
  • Ensures negative values are properly handled as invalid heads
+5/-1     

Dimitar Dimitrov added 4 commits February 19, 2026 19:54
Validated on BeaglePlay with kernel 6.12.43-ti-arm64-r54.

Signed-off-by: Dimitar Dimitrov <[email protected]>
Using memcpy requires string.h header, so include it.

Signed-off-by: Dimitar Dimitrov <[email protected]>
GCC issues the following warning:

  ../../../../../../source/rpmsg/pru_virtqueue.c:116:18: warning: comparison of integer expressions of different signedness: ‘int16_t’ {aka ‘short int’} and ‘uint32_t’ {aka ‘long unsigned int’} [-Wsign-compare]
    116 |         if (head > num)

Fix by explicitly using unsigned integers for the comparison.

Negative value should never be passed to pru_virtqueue_add_used_buf
because it is an invalid head. If it is passed, though, making it
unsigned would make it too large, and trigger the early exit with an
error.

Signed-off-by: Dimitar Dimitrov <[email protected]>
GCC issues this warning:

  ../../../../../../source/include/c_code/linux/pru_virtio_ring.h:138:41: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    138 |         vr->used = (void *)(uintptr_t)(((uint64_t)&vr->avail->ring[num]

Fix by using uintptr_t consistently. On the 32-bit PRU the
upper bits of the intermediate result would be discarded anyway by the
second cast to uintptr_t, anyway.

Signed-off-by: Dimitar Dimitrov <[email protected]>
@qodo-code-review
Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Build Break

The GCC path uses an __attribute__ with unavailable(...), which is not a standard GCC attribute (commonly Clang-specific). This may break builds on gnu-pru-gcc; consider replacing with a GCC-supported attribute (or omitting it) while still ensuring the symbol is retained/placed in the expected section.

#if !defined(__GNUC__)
  #pragma DATA_SECTION(my_irq_rsc, ".pru_irq_map")
  #pragma RETAIN(my_irq_rsc)
  #define __pru_irq_map		/* */
#else
  #define __pru_irq_map __attribute__((section(".pru_irq_map"),unavailable("pru_irq_map is for usage by the host only")))
#endif

struct pru_irq_rsc my_irq_rsc __pru_irq_map = {
	0,			/* type = 0 */
	1,			/* number of system events being mapped */
	{
		{17, 0, 0},	/* {sysevt, channel, host interrupt} */
	},
};
Boundary Check

The head index validation was changed to cast head to uint32_t before comparison. Verify the intended bounds: typically valid heads are in the range [0, num-1], so the check may need to be >= num (and/or an explicit head < 0 check) to avoid accepting head == num if that is invalid for the ring implementation.

int16_t pru_virtqueue_add_used_buf(
    struct pru_virtqueue	*vq,
    int16_t			head,
    uint32_t			len
)
{
	struct vring_used_elem	*used_elem;
	uint32_t		num;
	struct vring_used	*used;

	num = vq->vring.num;
	used = vq->vring.used;

	if ((uint32_t)head > num)
		return PRU_VIRTQUEUE_INVALID_HEAD;
Build Robustness

The build uses mkdir $(OUT) without -p, which can fail when the directory already exists or in parallel builds. Consider using mkdir -p $(OUT) and (optionally) using order-only prerequisites consistently if parallelism is expected.

$(OUT):
	mkdir $(OUT)

$(ELF): $(SRC) $(HEADERS) | $(OUT)
	$(CROSS_COMPILE)gcc $(CFLAGS) $(SRC) -o $@

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Consider a more scalable build structure

Instead of adding a toolchain-specific directory like gnu-pru-gcc for build
files, centralize the build logic. A configurable, higher-level system that
selects the toolchain via parameters would improve maintainability.

Examples:

examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/gnu-pru-gcc/Makefile [1-116]
# Copyright (c) 2026, Dimitar Dimitrov
#   All rights reserved.
#
#   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

 ... (clipped 106 lines)
examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/gnu-pru-gcc/intc_map.h [1-53]
#ifndef _INTC_MAP_H_
#define _INTC_MAP_H_

/*
 * ======== PRU INTC Map ========
 *
 * Define the INTC mapping for interrupts going to the ICSS / ICSSG:
 * 	ICSS Host interrupts 0, 1
 * 	ICSSG Host interrupts 0, 1, 10-19
 *

 ... (clipped 43 lines)

Solution Walkthrough:

Before:

/examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/
  |- cgt-pru/      # Existing toolchain-specific directory
  |   |- Makefile
  |   |- ...
  |- gnu-pru-gcc/  # New toolchain-specific directory
  |   |- Makefile
  |   |- intc_map.h
  |- main.c

After:

/build/
  |- common.mk # Centralized build logic

/examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/
  |- Makefile      # Generic makefile, includes common.mk
  |- main.c
  |- intc_map.h    # Uses ifdefs for toolchain differences
  |- ...

# Build command
# make TOOLCHAIN=gnu-pru-gcc
# make TOOLCHAIN=cgt-pru
Suggestion importance[1-10]: 8

__

Why: This is a strong architectural suggestion that addresses a significant maintainability and scalability issue with the proposed build system structure, which would become problematic as the project grows.

Medium
Possible issue
Fix incorrect signed-to-unsigned comparison

Fix the validation of the head parameter in pru_virtqueue_add_used_buf. Add a
check for head < 0 before the unsigned comparison to correctly handle negative
values, which would otherwise be misinterpreted as large positive indices.

source/rpmsg/pru_virtqueue.c [103-117]

 int16_t pru_virtqueue_add_used_buf(
     struct pru_virtqueue	*vq,
     int16_t			head,
     uint32_t			len
 )
 {
 	struct vring_used_elem	*used_elem;
 	uint32_t		num;
 	struct vring_used	*used;
 
 	num = vq->vring.num;
 	used = vq->vring.used;
 
-	if ((uint32_t)head > num)
+	if (head < 0 || (uint32_t)head >= num)
 		return PRU_VIRTQUEUE_INVALID_HEAD;
 
 	/*
 ...

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a latent bug in the validation logic for the head parameter. The PR's change from head > num to (uint32_t)head > num silences a compiler warning but introduces incorrect behavior for negative head values, which this suggestion fixes.

Medium
Preserve resource table in binary

Add the used attribute to the __resource_table macro. This prevents the compiler
from optimizing away the resourceTable variable, ensuring it is included in the
final binary.

source/include/c_code/linux/resource_table.h [42]

-#define __resource_table __attribute__((section(".resource_table")))
+#define __resource_table __attribute__((section(".resource_table"), used))
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that without the used attribute, the resourceTable might be optimized away by the compiler as an unused variable. Adding __attribute__((used)) ensures this critical table is retained in the final binary.

Medium
Fix incorrect handling of .bss section

In the Makefile, modify the dmem.bin rule to stop including the .bss section in
the output binary. This will reduce the binary size and correctly handle
uninitialized data.

examples/rpmsg_echo_linux/firmware/am62x-sk/pruss0_pru0_fw/gnu-pru-gcc/Makefile [97-102]

 %.dmem.bin : %.elf
 	$(CROSS_COMPILE)objcopy -O binary              \
 	  --only-section=.data*                        \
-	  --only-section=.bss*                         \
-	  --set-section-flags .bss=alloc,load,contents \
 	  $< $@
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that including the .bss section with the contents flag in the binary image is incorrect and inefficient, leading to a larger file size. The proposed change aligns with standard practices for handling .bss sections.

Low
  • More

@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@nsaulnier-ti
Copy link
Collaborator

Hey @dinuxbg, thank you for submitting a pull request! I have not spent any time yet playing with a GCC version of the PRU compiler at this point in time, so please forgive me if my questions are a bit "beginner level".

  1. At this point in time, your GCC additions are ignored by my PRU-CGT makefiles - so we don't have any build automation in place to make sure that the GCC build does not break in the future. Is that the vision, or were you eventually hoping to add GCC support to the automated build tests?

  2. Can you help me think through the usecases for when someone would want to use the GCC compiler instead of the PRU-CGT compiler?

  3. I have been focused on the TI-supported stuff so far: no programming in the older PASM, only using the TI compiler, etc. So perspectives like yours are useful to expose my blind spots. Are there other PRU compiler options people are using other than PRU-CGT and your gnupru project? I am not clear if GCC pages like this refer specifically to your repository, or if there are multiple versions of the GCC PRU compiler out there that people are using.

  4. This repo is big, and it's going to get much bigger. I want to make it as easy as possible for customers to find the specific information they are looking for. I am concerned that your GCC code is so well hidden that customers might not be able to find it. My initial thought was that it might be better to have a separate GCC project, like this: examples/gcc_project_name, and then include a short description of the GCC project in examples/readme.md. That would also give you a space to provide more information for customers in examples/gcc_project_name/readme.md, link to other trainings, etc. Thoughts?

@dinuxbg
Copy link
Author

dinuxbg commented Feb 20, 2026

Hey @dinuxbg, thank you for submitting a pull request! I have not spent any time yet playing with a GCC version of the PRU compiler at this point in time, so please forgive me if my questions are a bit "beginner level".

  1. At this point in time, your GCC additions are ignored by my PRU-CGT makefiles - so we don't have any build automation in place to make sure that the GCC build does not break in the future. Is that the vision, or were you eventually hoping to add GCC support to the automated build tests?

I can add a CI pipeline to verify that the GCC example builds. Looking at this CI pipeline from a GCC user, it should be easy.

  1. Can you help me think through the usecases for when someone would want to use the GCC compiler instead of the PRU-CGT compiler?

I admit that commercial users would probably pick the toolchain provided and supported by the SoC vendor (i.e. PRU-CGT). So if that it is the target for open-pru, I would totally understand if you reject this pull request, in order to avoid confusion that TI supports PRU GCC.

As author and maintainer of the PRU port for GCC, I'm biased. Anyway, here are my reasons for using it:

  • GCC is free software, which seems to be appealing to fellow hobbyists.
  • GCC supports the latest language standards (e.g. C23 and C2Y), and numerous extensions.
  • GCC has a really nice static analyzer.
  • GCC has powerful extension for writing snippets of inline assembly inside C functions.
  1. I have been focused on the TI-supported stuff so far: no programming in the older PASM, only using the TI compiler, etc. So perspectives like yours are useful to expose my blind spots. Are there other PRU compiler options people are using other than PRU-CGT and your gnupru project? I am not clear if GCC pages like this refer specifically to your repository, or if there are multiple versions of the GCC PRU compiler out there that people are using.

I know someone tried to port LLVM, but I think it never got finished or mainlined.

Since the PRU port of GCC is in mainline, there is only one PRU GCC source code, and it is in the main GCC GIT repository. I provide prebuilt toolchains as a convenience in my gnupru Github page. I'm not aware of anyone else providing prebuilt toolchains, but I've shared my build scripts so anyone is free to do so.

  1. This repo is big, and it's going to get much bigger. I want to make it as easy as possible for customers to find the specific information they are looking for. I am concerned that your GCC code is so well hidden that customers might not be able to find it. My initial thought was that it might be better to have a separate GCC project, like this: examples/gcc_project_name, and then include a short description of the GCC project in examples/readme.md. That would also give you a space to provide more information for customers in examples/gcc_project_name/readme.md, link to other trainings, etc. Thoughts?

This sounds reasonable.

Regards,
Dimitar

@nsaulnier-ti
Copy link
Collaborator

Hello @dinuxbg ,

Ok. Let's keep this PR for updates to the RPMsg libraries, but drop the GCC updates to the rpmsg_echo example.

Our team has not done a great job of pointing customers to all the great work you and others are doing in the broader community. I can't promise that we will turn a full 180 degrees (e.g., I joined the beagleboard discord last year, but never have time to read it unless someone points me to a specific post), but I DO want to be more intentional about helping customers to find useful resources, regardless of whether those resources come from TI or from the community.

In this PR or a separate PR, it would be great if I could get you to create a separate example, just for showing off GCC.

  • Make it look however you want
  • Similar to your current implementation, it is probably cleaner if the example is not included in the top-level makefile build infrastructure
  • Add the project to the examples folder readme
  • Use the project readme as your billboard to point customers to useful resources and pitch people on GCC. For example, I liked a lot of the links you listed above. As long as you state up top that PRU GCC and the GCC example is not supported by TI, anything goes

@nsaulnier-ti
Copy link
Collaborator

Additional notes:

  • The ASM functionality for GCC is a fun alternative to our implementation. With the PRU-CGT, the cleanest way I've found to pass data between C and assembly is to use a function call to force variables into known registers, demonstrated in the PRU Getting Started Labs. Not sure if GCC allows more flexibility in returning more than one updated value back to the C code?
  • I am curious if PRU GCC includes support for additional PRU assembly instructions added in silicon v4. It's fairly minor if I understand correctly, related to enabling Task Manager on PRU_ICSSG subsystems

@dinuxbg
Copy link
Author

dinuxbg commented Feb 20, 2026

Additional notes:

  • The ASM functionality for GCC is a fun alternative to our implementation. With the PRU-CGT, the cleanest way I've found to pass data between C and assembly is to use a function call to force variables into known registers, demonstrated in the PRU Getting Started Labs. Not sure if GCC allows more flexibility in returning more than one updated value back to the C code?

Yes, GCC supports arbitrary number of inputs, outputs and clobbers for inline assembly.

  • I am curious if PRU GCC includes support for additional PRU assembly instructions added in silicon v4. It's fairly minor if I understand correctly, related to enabling Task Manager on PRU_ICSSG subsystems

The v4 instructions are not yet supported. I plan to add them.

@nsaulnier-ti
Copy link
Collaborator

nsaulnier-ti commented Feb 24, 2026

Yes, GCC supports arbitrary number of inputs, outputs and clobbers for inline assembly.

Good to know, I'll make a mental note about this if any customers ask

The v4 instructions are not yet supported. I plan to add them.

I have not yet added the v4 instructions to https://www.ti.com/lit/spruij2. We'll see if I get around to updating that doc in 1H2026, if you need guidance on the v4 instructions in the future feel free to create an e2e thread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants