[WIP] Bare-metal register browsing

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

[WIP] Bare-metal register browsing

Vladimir Prus-3

The attached patches implement accessing peripheral registers on bare-metal targets. Typically,
these registers are memory-mapped, so one can poke at them using memory operations, but it's
far from convenient. Also, on some targets the registers might require a custom way of access,
which makes things even less convenient.

This patch allows target XML to describe 'spaces' - contains of registers, which can be further grouped.
Given that descrpiption, GDB allows one to do something like:

        (gdb) print $io.GPIO_PORTF.GPIO_PORTFDIR
        $7 = -1

to access registers. One can also do

        (gdb) ptype $io

to see top-level register groups in space 'io', and so find the desired register.

Internally, new qXfer object, called 'spaces' is used to implement this functionality.
Remote target is in position to use any mechanism it sees fit to access the registers.
However, there's also a shortcut that allow the target xml to specify that space is
memory-mapped, and GDB will use ordinary memory operations. One can therefore write
target xml that will enable register browsing with unmodified remote side - in fact
I've used pristine OpenOCD to test this patch.

This was written back in 2006 by Jim Blandy, Daniel Jacobowitz and myself, and was used in
a product for that time, so somewhat time-tested. What I post is functional, but it does
not yet add MI integration and in particular support for read-sensitive registers - those
where reading has side effects, for which frontend should take special care. These bits
are somewhat tricky, so before posting a complete patch I'd appreciate feedback on the
current state. Any big design objections, or any other guidance?

Thanks,

--
Vladimir Prus
CodeSourcery / Mentor Embedded
http://www.mentor.com/embedded-software/

0001-set_internalvar_lazy.patch (2K) Download Attachment
0002-Initial-register-browsing-patches.patch (25K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Yao Qi
Vladimir Prus <[hidden email]> writes:

Hi Vladimir,

> The attached patches implement accessing peripheral registers on
> bare-metal targets. Typically,
> these registers are memory-mapped, so one can poke at them using
> memory operations, but it's
> far from convenient. Also, on some targets the registers might require
> a custom way of access,
> which makes things even less convenient.
>
> This patch allows target XML to describe 'spaces' - contains of
> registers, which can be further grouped.
> Given that descrpiption, GDB allows one to do something like:
>
> (gdb) print $io.GPIO_PORTF.GPIO_PORTFDIR
> $7 = -1
>
> to access registers. One can also do
>
> (gdb) ptype $io
>
> to see top-level register groups in space 'io', and so find the
> desired register.

What does the xml using 'spaces' look like?  A small example would be
useful.  Target description "reg" has already had a component "type",
can't we extend "type" for memory-mapped registers?  I am trying to
understand how useful it is to add 'spaces' here.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Vladimir Prus-2

On 04/24/2015 12:47 PM, Yao Qi wrote:>

Vladimir Prus <[hidden email]> writes:
 >
 > Hi Vladimir,
 >
 >> The attached patches implement accessing peripheral registers on
 >> bare-metal targets. Typically,
 >> these registers are memory-mapped, so one can poke at them using
 >> memory operations, but it's
 >> far from convenient. Also, on some targets the registers might require
 >> a custom way of access,
 >> which makes things even less convenient.
 >>
 >> This patch allows target XML to describe 'spaces' - contains of
 >> registers, which can be further grouped.
 >> Given that descrpiption, GDB allows one to do something like:
 >>
 >> (gdb) print $io.GPIO_PORTF.GPIO_PORTFDIR
 >> $7 = -1
 >>
 >> to access registers. One can also do
 >>
 >> (gdb) ptype $io
 >>
 >> to see top-level register groups in space 'io', and so find the
 >> desired register.
 >
 > What does the xml using 'spaces' look like?  A small example would be
 > useful.  Target description "reg" has already had a component "type",
 > can't we extend "type" for memory-mapped registers?  I am trying to
 > understand how useful it is to add 'spaces' here.

Hi Yao,

Here's extract from an actual file

        <space annex="memory" name="io">
        <group name="UART2">
        <reg bitsize="32" name="UART2CTL" offset="0x4000e030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
        <reg bitsize="32" name="UART2LTIM" offset="0x4000e098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
        </group>
        <group name="UART3">
        size="32" name="UART3CTL" offset="0x4000f030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
        <reg bitsize="32" name="UART3LTIM" offset="0x4000f098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
        </group>

The full file can be found at https://drive.google.com/open?id=0BzXbGnw_jIF6cThVZHU2T3l0SXM&authuser=0


The space and group elements are not 100% required - it might be possible to instead have something like:

        <struct id="UART2">
                <field offset="0x4000e030" bitsize="32" type="int" name="UAR2CTL"/>
        </struct>
        <struct id="UART3">
                <field offset="0x4000f030" bitsize="32" type="int" name="UART3CTL"/>
        </struct>
        <struct id="io">
                <field name="UART2" type="UART2"/>
                <field name="UART3" type="UART3"/>
        </struct>
        <reg name="io" type="io"/>

But it seems to me that this overloading of existing concepts might not be perfect:

- Normally, top level 'reg' element are accessed using ordinary packets, so we'd need to special case 'reg' above
- Using 'reg' element to refer to large number of registers, and using 'field' to refer to registers can be
   confusing.
- GDB type system does not support 'offset' field for physical address, and unlike space, there is no easy
   place to add this information.

So it seems to me that the original syntax is more straight-forward representation of hardware.

Thanks,
Volodya

--
Vladimir Prus
CodeSourcery / Mentor Embedded
http://vladimirprus.com


--
Vladimir Prus
CodeSourcery / Mentor Embedded
http://vladimirprus.com
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Vladimir Prus-2

Yao,

did you have any further comments?

Thanks,

On 4/27/2015 9:25 PM, Vladimir Prus wrote:

>
> On 04/24/2015 12:47 PM, Yao Qi wrote:>
>
> Vladimir Prus <[hidden email]> writes:
>  >
>  > Hi Vladimir,
>  >
>  >> The attached patches implement accessing peripheral registers on
>  >> bare-metal targets. Typically,
>  >> these registers are memory-mapped, so one can poke at them using
>  >> memory operations, but it's
>  >> far from convenient. Also, on some targets the registers might require
>  >> a custom way of access,
>  >> which makes things even less convenient.
>  >>
>  >> This patch allows target XML to describe 'spaces' - contains of
>  >> registers, which can be further grouped.
>  >> Given that descrpiption, GDB allows one to do something like:
>  >>
>  >>     (gdb) print $io.GPIO_PORTF.GPIO_PORTFDIR
>  >>     $7 = -1
>  >>
>  >> to access registers. One can also do
>  >>
>  >>     (gdb) ptype $io
>  >>
>  >> to see top-level register groups in space 'io', and so find the
>  >> desired register.
>  >
>  > What does the xml using 'spaces' look like?  A small example would be
>  > useful.  Target description "reg" has already had a component "type",
>  > can't we extend "type" for memory-mapped registers?  I am trying to
>  > understand how useful it is to add 'spaces' here.
>
> Hi Yao,
>
> Here's extract from an actual file
>
>      <space annex="memory" name="io">
>      <group name="UART2">
>      <reg bitsize="32" name="UART2CTL" offset="0x4000e030"
> read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
>      <reg bitsize="32" name="UART2LTIM" offset="0x4000e098"
> read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
>      </group>
>      <group name="UART3">
>      size="32" name="UART3CTL" offset="0x4000f030" read-sensitive="no"
> save-restore="yes" type="UART0_UART0CTL"/>
>      <reg bitsize="32" name="UART3LTIM" offset="0x4000f098"
> read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
>      </group>
>
> The full file can be found at
> https://drive.google.com/open?id=0BzXbGnw_jIF6cThVZHU2T3l0SXM&authuser=0
>
>
> The space and group elements are not 100% required - it might be
> possible to instead have something like:
>
>      <struct id="UART2">
>          <field offset="0x4000e030" bitsize="32" type="int"
> name="UAR2CTL"/>
>      </struct>
>      <struct id="UART3">
>          <field offset="0x4000f030" bitsize="32" type="int"
> name="UART3CTL"/>
>      </struct>
>      <struct id="io">
>          <field name="UART2" type="UART2"/>
>          <field name="UART3" type="UART3"/>
>      </struct>
>      <reg name="io" type="io"/>
>
> But it seems to me that this overloading of existing concepts might not
> be perfect:
>
> - Normally, top level 'reg' element are accessed using ordinary packets,
> so we'd need to special case 'reg' above
> - Using 'reg' element to refer to large number of registers, and using
> 'field' to refer to registers can be
>    confusing.
> - GDB type system does not support 'offset' field for physical address,
> and unlike space, there is no easy
>    place to add this information.
>
> So it seems to me that the original syntax is more straight-forward
> representation of hardware.
>
> Thanks,
> Volodya
>


Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Yao Qi
In reply to this post by Vladimir Prus-2
Vladimir Prus <[hidden email]> writes:

> <space annex="memory" name="io">
> <group name="UART2">
> <reg bitsize="32" name="UART2CTL" offset="0x4000e030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
> <reg bitsize="32" name="UART2LTIM" offset="0x4000e098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
> </group>
> <group name="UART3">
> size="32" name="UART3CTL" offset="0x4000f030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
> <reg bitsize="32" name="UART3LTIM" offset="0x4000f098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
> </group>

It is good to have a "group" element, so that we can easily define a
group of registers.  However, what is the usefulness of element "space"?
to define a group of "group" elements?

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Vladimir Prus-2
On 6/2/2015 4:00 PM, Yao Qi wrote:

> Vladimir Prus <[hidden email]> writes:
>
>> <space annex="memory" name="io">
>> <group name="UART2">
>> <reg bitsize="32" name="UART2CTL" offset="0x4000e030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
>> <reg bitsize="32" name="UART2LTIM" offset="0x4000e098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
>> </group>
>> <group name="UART3">
>> size="32" name="UART3CTL" offset="0x4000f030" read-sensitive="no" save-restore="yes" type="UART0_UART0CTL"/>
>> <reg bitsize="32" name="UART3LTIM" offset="0x4000f098" read-sensitive="no" save-restore="yes" type="UART0_UART0LTIM"/>
>> </group>
>
> It is good to have a "group" element, so that we can easily define a
> group of registers.  However, what is the usefulness of element "space"?
> to define a group of "group" elements?

The original motivation was to indicate that particular set of registers are not usual registers, and must
be accessed in a different way. It's not strictly necessary, we can rewrite the above as:

    <group name="io" target-object="spaces" annex="memory">
        <group name="UART2">
                <reg offset="0x4000e030" .../>
         </group>
    </group>

Maybe my patch can be modified to not introduce a new target object, after all. We can use:

    <group name="io" target-object="memory">
        <group name="UART2">
                <reg offset="0x4000e030" .../>
         </group>
    </group>

to describe memory-mapped io registers.

It sounds like this should be possible to implement. What do you think?

Two questions:

- Is 'group' ok, or 'register-group' would be more clear? We found that the size of these XML
files can be sometimes a problem

- I'd propose that 'target-object' and 'annex' attribute are only allowed for top-level 'group' element,
   and not for top-level 'reg' or nested 'group' element, to make implementation simpler. Is that fine?

Thanks,
Volodya


Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Yao Qi
Vladimir Prus <[hidden email]> writes:

> Maybe my patch can be modified to not introduce a new target object, after all. We can use:
>
>    <group name="io" target-object="memory">
> <group name="UART2">
> <reg offset="0x4000e030" .../>
>         </group>
>    </group>
>
> to describe memory-mapped io registers.
>
> It sounds like this should be possible to implement. What do you
> think?

That is fine to me, but I am not sure the meaning of
target-object="memory" here?  Does this mean this group of registers are
mapped to memory?  Does "offset=0x4000e030" mean this register is mapped
at address 0x4000e030?  If the answers of both questions are yes, is
target-object="memory" still necessary?  Without it, we can still define
a group of memory-mapped registers like:

 <group name="io">
     <reg offset="0x4000e030" name="UART1_1">
     <reg offset="0x4000e034" name="UART1_2">
     <reg offset="0x4000e038" name="UART1_3">
 </group>

and we may even can define a group of normal registers and memory-mapped
registers, (even it is not likely in practise)

 <group name="io">
     <reg offset="0x4000e030" name="UART1_1">
     <reg offset="0x4000e034" name="UART1_2">
     <reg name="UART1_3">
 </group>

In this case, UART1_1 and UART1_2 are memory-mapped, while UART1_3 is
not.  IMO, memory-map-ness is an attribute of each register instead of a
group, so better to define such attribute on each register level.

>
> Two questions:
>
> - Is 'group' ok, or 'register-group' would be more clear? We found that the size of these XML
> files can be sometimes a problem

I don't have preference here.

>
> - I'd propose that 'target-object' and 'annex' attribute are only allowed for top-level 'group' element,
>   and not for top-level 'reg' or nested 'group' element, to make implementation simpler. Is that fine?

You have to explain the meaning of target-object and annex first and
what are the possible values of them.

My last concern is about the testing of these new things in target
description.  We need some test cases that people can run in their own
dev env, without involving setting up OpenOCD/JTAG probe/embedded boards.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Vladimir Prus-2

Yao,

On 6/4/2015 5:38 PM, Yao Qi wrote:

> Vladimir Prus <[hidden email]> writes:
>
>> Maybe my patch can be modified to not introduce a new target object, after all. We can use:
>>
>>     <group name="io" target-object="memory">
>> <group name="UART2">
>> <reg offset="0x4000e030" .../>
>>          </group>
>>     </group>
>>
>> to describe memory-mapped io registers.
>>
>> It sounds like this should be possible to implement. What do you
>> think?
>
> That is fine to me, but I am not sure the meaning of
> target-object="memory" here?  Does this mean this group of registers are
> mapped to memory?

It's a bit more generic - it means that to obtain values of any register
in this group, GDB should perform qXfer of the specified target object
and annex, using register's offset. Memory is the most typical target object,
but in our case, we had other sorts of registers, so I'd prefer the design to
not lock us into memory-mapped registers.

> Does "offset=0x4000e030" mean this register is mapped
> at address 0x4000e030?  If the answers of both questions are yes, is
> target-object="memory" still necessary?  Without it, we can still define
> a group of memory-mapped registers like:
>
>   <group name="io">
>       <reg offset="0x4000e030" name="UART1_1">
>       <reg offset="0x4000e034" name="UART1_2">
>       <reg offset="0x4000e038" name="UART1_3">
>   </group>
>
> and we may even can define a group of normal registers and memory-mapped
> registers, (even it is not likely in practise)
>
>   <group name="io">
>       <reg offset="0x4000e030" name="UART1_1">
>       <reg offset="0x4000e034" name="UART1_2">
>       <reg name="UART1_3">
>   </group>
>
> In this case, UART1_1 and UART1_2 are memory-mapped, while UART1_3 is
> not.  IMO, memory-map-ness is an attribute of each register instead of a
> group, so better to define such attribute on each register level.

It is possible in theory, but I think it has two drawbacks.

First, I think specifying target object is more explicit (and therefore better
than implicit, especially for machine-oriented format) and more generic, as it allows
us to use other target objects.

Second, implementing such mixed registers group is extra complexity, and we did
not find any need for that in practice.

May I suggest we start from a simple use case, where an alternative access mechanism
can only be specified for a top-level group, and it's explicitly specified by
target-object attribute? Should the need arise for mixing differently-accessed
registers inside one group, that can be implemented later with extra code.

>> Two questions:
>>
>> - Is 'group' ok, or 'register-group' would be more clear? We found that the size of these XML
>> files can be sometimes a problem
>
> I don't have preference here.
>
>>
>> - I'd propose that 'target-object' and 'annex' attribute are only allowed for top-level 'group' element,
>>    and not for top-level 'reg' or nested 'group' element, to make implementation simpler. Is that fine?
>
> You have to explain the meaning of target-object and annex first and
> what are the possible values of them.
>
> My last concern is about the testing of these new things in target
> description.  We need some test cases that people can run in their own
> dev env, without involving setting up OpenOCD/JTAG probe/embedded boards.

That's a valid concern. I was using a particular board with USB interface, so did not need a probe,
but even that is not trivial to setup or automate.

If we were to test on a regular computer, I suppose the only way is to have some variables in a C program,
determine their addresses after debug session start, and generate target XML dynamically from that?

- Volodya


Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Yao Qi
On 09/06/15 21:49, Vladimir Prus wrote:
> It's a bit more generic - it means that to obtain values of any register
> in this group, GDB should perform qXfer of the specified target object
> and annex, using register's offset. Memory is the most typical target
> object,
> but in our case, we had other sorts of registers, so I'd prefer the
> design to
> not lock us into memory-mapped registers.
>

I don't object to it.

>> Does "offset=0x4000e030" mean this register is mapped
>> at address 0x4000e030?  If the answers of both questions are yes, is
>> target-object="memory" still necessary?  Without it, we can still define
>> a group of memory-mapped registers like:
>>
>>   <group name="io">
>>       <reg offset="0x4000e030" name="UART1_1">
>>       <reg offset="0x4000e034" name="UART1_2">
>>       <reg offset="0x4000e038" name="UART1_3">
>>   </group>
>>
>> and we may even can define a group of normal registers and memory-mapped
>> registers, (even it is not likely in practise)
>>
>>   <group name="io">
>>       <reg offset="0x4000e030" name="UART1_1">
>>       <reg offset="0x4000e034" name="UART1_2">
>>       <reg name="UART1_3">
>>   </group>
>>
>> In this case, UART1_1 and UART1_2 are memory-mapped, while UART1_3 is
>> not.  IMO, memory-map-ness is an attribute of each register instead of a
>> group, so better to define such attribute on each register level.
>
> It is possible in theory, but I think it has two drawbacks.
>
> First, I think specifying target object is more explicit (and therefore
> better
> than implicit, especially for machine-oriented format) and more generic,
> as it allows
> us to use other target objects.
>
> Second, implementing such mixed registers group is extra complexity, and
> we did
> not find any need for that in practice.

If such mixed registers group brings extra complexity in the
implementation, then I am inclined to start from a simple one.

>
> May I suggest we start from a simple use case, where an alternative
> access mechanism
> can only be specified for a top-level group, and it's explicitly
> specified by
> target-object attribute? Should the need arise for mixing
> differently-accessed
> registers inside one group, that can be implemented later with extra code.
>
>>> Two questions:
>>>
>>> - Is 'group' ok, or 'register-group' would be more clear? We found
>>> that the size of these XML
>>> files can be sometimes a problem
>>
>> I don't have preference here.
>>
>>>
>>> - I'd propose that 'target-object' and 'annex' attribute are only
>>> allowed for top-level 'group' element,
>>>    and not for top-level 'reg' or nested 'group' element, to make
>>> implementation simpler. Is that fine?
>>
>> You have to explain the meaning of target-object and annex first and
>> what are the possible values of them.
>>
>> My last concern is about the testing of these new things in target
>> description.  We need some test cases that people can run in their own
>> dev env, without involving setting up OpenOCD/JTAG probe/embedded boards.
>
> That's a valid concern. I was using a particular board with USB
> interface, so did not need a probe,
> but even that is not trivial to setup or automate.
>
> If we were to test on a regular computer, I suppose the only way is to
> have some variables in a C program,
> determine their addresses after debug session start, and generate target
> XML dynamically from that?

Yes, that is what I want to suggest too.

--
Yao (齐尧)
Reply | Threaded
Open this post in threaded view
|

Re: [WIP] Bare-metal register browsing

Vladimir Prus-2
On 6/11/2015 11:56 AM, Yao Qi wrote:

> On 09/06/15 21:49, Vladimir Prus wrote:
>> It's a bit more generic - it means that to obtain values of any register
>> in this group, GDB should perform qXfer of the specified target object
>> and annex, using register's offset. Memory is the most typical target
>> object,
>> but in our case, we had other sorts of registers, so I'd prefer the
>> design to
>> not lock us into memory-mapped registers.
>>
>
> I don't object to it.
>
>>> Does "offset=0x4000e030" mean this register is mapped
>>> at address 0x4000e030?  If the answers of both questions are yes, is
>>> target-object="memory" still necessary?  Without it, we can still define
>>> a group of memory-mapped registers like:
>>>
>>>   <group name="io">
>>>       <reg offset="0x4000e030" name="UART1_1">
>>>       <reg offset="0x4000e034" name="UART1_2">
>>>       <reg offset="0x4000e038" name="UART1_3">
>>>   </group>
>>>
>>> and we may even can define a group of normal registers and memory-mapped
>>> registers, (even it is not likely in practise)
>>>
>>>   <group name="io">
>>>       <reg offset="0x4000e030" name="UART1_1">
>>>       <reg offset="0x4000e034" name="UART1_2">
>>>       <reg name="UART1_3">
>>>   </group>
>>>
>>> In this case, UART1_1 and UART1_2 are memory-mapped, while UART1_3 is
>>> not.  IMO, memory-map-ness is an attribute of each register instead of a
>>> group, so better to define such attribute on each register level.
>>
>> It is possible in theory, but I think it has two drawbacks.
>>
>> First, I think specifying target object is more explicit (and therefore
>> better
>> than implicit, especially for machine-oriented format) and more generic,
>> as it allows
>> us to use other target objects.
>>
>> Second, implementing such mixed registers group is extra complexity, and
>> we did
>> not find any need for that in practice.
>
> If such mixed registers group brings extra complexity in the
> implementation, then I am inclined to start from a simple one.

Yes, I think it brings extra complexity.

Thanks for your comments; I plan to update the patch to:

- Use top-level group for register browsing, as opposed to <space> element
- Do some form of testing that does not require hardware.

Thanks,
Volodya