PRU help needed....I don't understand pointers well enough to understand them.

I am obsessed with the BB and the PRU. I think I need treatment!

With that out of the way, after slaving over my computer for the last several days, I have succeeded in writing a C program for the PRU which controls standard GPIO outputs using the Sitara memory map, getting it built using clpru, and then deployed to the PRU using Remoteproc. Then I was able to debug it so I finally got it to execute. I also have figured out how to start the PRU automatically at reboot. Whew. Now I need to learn how to pass data in and out of the PRU using RPMsg. And I am clueless how to remotely debug code (either PRU or userspace code) running on the BB.

But what I really need to know is how do I interpret this statement:

#define GPIO0_SETDATAOUT (*(volatile uint32_t *)(GPIO0_BASE + 0x190))

One way I use it is as follows:

GPIO0_SETDATAOUT = 1u << PWM2A_OFFSET;

I think I understand the second statement, it first shifts a 1 to the left until the 1 is in the proper bit position for the desired GPIO. Then it writes into the proper memory location for the GPIOs SetDataOut register. This causes a certain GPIO output to be turned on. I also understand how the memory address for the GPIO0 SetDataOut register is computed based on the values from the TRM.

What I don’t understand is how I intrepret the first statement, especially the bolded part. I understand the meaning of #define and I understand the simple GPIO0BASE + 0x190 offset math. What I don’t understand is the bolded part. It looks like it is a pointer to a pointer to a uint32_t, but that doesn’t make sense to me. I don’t see the need for double indirection. And I’m not too clear on the difference between a uint32 and a uint32_t.

Can someone give me a plain english translation for the #define statement?

Clark

The #define results in a simple text replacement prior to the C
compiler actually running. The actual code that would be compiled is
something like:

  *(volatile uint32_t *)*(GPIO0_BASE + 0x190)) = 1u << PWM2A_OFFSET;

Basically this takes the value of GPIO0_BASE + 0x190 (the address of
the SETDATAOUT register), casts it to a volatile uint32_t pointer, and
stores the result of the right-hand side of the equals to the address
being pointed to.

This is all very basic C code...just read up on some tutorials
regarding the C pre-processor (the #dfine), pointer handling (the *'s)
and the volatile keyword.

Breaking the first bit down to hopefully help you out a bit:

  uint32_t : a 32-bit unsigned value

  uint32_t * : a pointer to a 32-bit unsigned value

  volatile uint32_t * : a pointer to a 32-bit unsigned value that
    may change in ways the compiler doesn't expect (ie: don't optimize
    away all the reads/writes to this value)

  *(volatile uint32_t *) : The actual 32-bit unsigned data value at
    the address contained in the following expression

Thanks Charles.

I understand everything except for your last statement.

I don’t understand the difference between
*(volatile uint32_t *)
and (volatile uint32_t *).

Why is the leading * needed? That is why I thought it meant a pointer to a pointer, which didn’t seem to make sense in this context.

And I just noticed there is even a third pointer symbol * after the first closing paren. What is that thing doing there?

Thanks Charles.

I understand everything except for your last statement.

I don’t understand the difference between
*(volatile uint32_t *)
and (volatile uint32_t *).

Like I said, read up on some basic C tutorials, they'll explain it
much better than I can.

Why is the leading * needed? That is why I thought it meant a pointer to a pointer, which didn’t seem to make sense in this context.

No.

(uint32_t *) is a pointer (address) to a uint32_t

*(uint32_t *) is the value (data) pointed to by (uint32_t *)

http://icube-icps.unistra.fr/index.php/File:ModernC.pdf#file

Try the above 308 page PDF file for starters. Click on the bird.

Regards,
Greg

Thank you both for your help. The pdf that Greg referenced is very good. I’ve looked at it and other web resources. I now understand that the * is a dereference operator as well as part of a type definition.