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

43 views
Skip to first unread message

Clark Sann

unread,
Jun 13, 2017, 7:50:33 PM6/13/17
to BeagleBoard
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

Charles Steinkuehler

unread,
Jun 13, 2017, 8:16:40 PM6/13/17
to beagl...@googlegroups.com
On 6/13/2017 6:50 PM, Clark Sann wrote:
>
> 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;
>
> 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?

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

--
Charles Steinkuehler
cha...@steinkuehler.net

Clark Sann

unread,
Jun 13, 2017, 8:29:50 PM6/13/17
to beagl...@googlegroups.com
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?
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/B5xIRj4FrrE/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to beagleboard...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/e601ff9c-da92-2cb6-5158-e5b7ac23a42d%40steinkuehler.net.
> For more options, visit https://groups.google.com/d/optout.

Charles Steinkuehler

unread,
Jun 13, 2017, 8:54:42 PM6/13/17
to beagl...@googlegroups.com
On 6/13/2017 7:29 PM, Clark Sann wrote:
> 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 *)

--
Charles Steinkuehler
cha...@steinkuehler.net

Greg

unread,
Jun 13, 2017, 10:33:36 PM6/13/17
to BeagleBoard
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 

Clark Sann

unread,
Jun 14, 2017, 11:25:43 AM6/14/17
to BeagleBoard
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.


Reply all
Reply to author
Forward
0 new messages