Discussion:
cortex-m xml register descriptions for m-system
Christopher Friedt
2015-12-14 17:04:57 UTC
Permalink
Hi list,

I've been using GDB and OpenOCD to debug ARM Cortex-M devices for
quite a while. One thing that I always noticed when using OpenOCD is
that the m-system registers are listed, which is *incredibly* useful
for writing code on just about any Cortex-M microcontroller.

Somewhat recently, Qemu has also begun to support Cortex-M based
virtual devices, and it seems to be fairly usable.

The down side, is that they do not expose the m-system registers,
simply because binutils-gdb does not (at this time) have an XML file
for them.

Just to catch anyone up to speed who might be reading this, the
m-system registers are

MSP (main stack pointer)
PSP (process stack pointer)
PRIMASK (1-bit register that says if interrupts are enabled)
BASEPRI (8-bit register that sets the NVIC base priority)
FAULTMASK (1-bit register that says if fault interrupts are enabled)
CONTROL (3-bit register that indicates presence of FP, whether PSP is
selected, and whether running in unprivileged mode)

Now, these are "system" registers, and on a full blown microprocessor,
it might be unusual to expose them, but on a microcontroller, it's
quite important. The other debuggers that I have seen (IAR,
specifically) also list the m-system registers along with the general
purpose ones for Cortex-M.

The following XML is sufficient to describe the m-system registers so
that they appear to the GDB client.

<feature name="org.gnu.gdb.arm.m-system">
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>

The first question I would ask for clarification from the binutils-gdb
developers, is, which regnum is appropriate to assign to each of those
m-system registers? Should these registers enumerate starting with 26
(resuming from the xpsr)?

Just for comparison, the current binutils-gdb arm-m-profile.xml is
here (https://goo.gl/hpTye8), and the openocd variant is here
(http://goo.gl/FFn56X).

The second question I would like to ask is, what is the best way to
add this XML? Should it

1) Should it be inserted directly into arm-m-profile.xml?
2) Should it be included from arm-m-profile.xml as arm-m-system.xml?

IMHO, the 1st or 2nd option would make sense, as all Cortex-M's
contain these registers.

I'm asking because I have a patch ready to submit for this on a whim's
notice, but would just like to get some buy-in ahead of time.


C
Pedro Alves
2015-12-14 18:55:09 UTC
Permalink
Post by Christopher Friedt
Hi list,
I've been using GDB and OpenOCD to debug ARM Cortex-M devices for
quite a while. One thing that I always noticed when using OpenOCD is
that the m-system registers are listed, which is *incredibly* useful
for writing code on just about any Cortex-M microcontroller.
Somewhat recently, Qemu has also begun to support Cortex-M based
virtual devices, and it seems to be fairly usable.
The down side, is that they do not expose the m-system registers,
simply because binutils-gdb does not (at this time) have an XML file
for them.
Just to catch anyone up to speed who might be reading this, the
m-system registers are
MSP (main stack pointer)
PSP (process stack pointer)
PRIMASK (1-bit register that says if interrupts are enabled)
BASEPRI (8-bit register that sets the NVIC base priority)
FAULTMASK (1-bit register that says if fault interrupts are enabled)
CONTROL (3-bit register that indicates presence of FP, whether PSP is
selected, and whether running in unprivileged mode)
Now, these are "system" registers, and on a full blown microprocessor,
it might be unusual to expose them, but on a microcontroller, it's
quite important. The other debuggers that I have seen (IAR,
specifically) also list the m-system registers along with the general
purpose ones for Cortex-M.
The following XML is sufficient to describe the m-system registers so
that they appear to the GDB client.
<feature name="org.gnu.gdb.arm.m-system">
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>
Does GDB need to be aware of these registers at all? That is, does gdb
need to be aware of org.gnu.gdb.arm.m-system? Usually GDB needs to
be aware of specific registers if for instance Dwarf can refer to them.
Otherwise, the design of xml descriptions is such that you're free
to send any additional registers you want without a specific feature.
GDB will show them.
Post by Christopher Friedt
The first question I would ask for clarification from the binutils-gdb
developers, is, which regnum is appropriate to assign to each of those
m-system registers? Should these registers enumerate starting with 26
(resuming from the xpsr)?
I don't think the regnums matter. GDB should be adjusting itself
dynamically.

The regnums only matter for backward compatibility with stubs that
don't report XML descriptions. In that case, GDB will fallback to
internal XML descriptions guessed from e.g., the binary loaded, and
in that case the expected offsets in the g/G packets must match what
the stub actually sends.
Post by Christopher Friedt
Just for comparison, the current binutils-gdb arm-m-profile.xml is
here (https://goo.gl/hpTye8), and the openocd variant is here
(http://goo.gl/FFn56X).
The second question I would like to ask is, what is the best way to
add this XML? Should it
1) Should it be inserted directly into arm-m-profile.xml?
2) Should it be included from arm-m-profile.xml as arm-m-system.xml?
IMHO, the 1st or 2nd option would make sense, as all Cortex-M's
contain these registers.
Even though all Cortex-M CPUs have these registers, userspace
debuggers/servers can't access them, right?
Post by Christopher Friedt
I'm asking because I have a patch ready to submit for this on a whim's
notice, but would just like to get some buy-in ahead of time.
C
Thanks,
Pedro Alves
Christopher Friedt
2015-12-14 23:11:24 UTC
Permalink
Post by Pedro Alves
Post by Christopher Friedt
Hi list,
I've been using GDB and OpenOCD to debug ARM Cortex-M devices for
quite a while. One thing that I always noticed when using OpenOCD is
that the m-system registers are listed, which is *incredibly* useful
for writing code on just about any Cortex-M microcontroller.
Somewhat recently, Qemu has also begun to support Cortex-M based
virtual devices, and it seems to be fairly usable.
The down side, is that they do not expose the m-system registers,
simply because binutils-gdb does not (at this time) have an XML file
for them.
Just to catch anyone up to speed who might be reading this, the
m-system registers are
MSP (main stack pointer)
PSP (process stack pointer)
PRIMASK (1-bit register that says if interrupts are enabled)
BASEPRI (8-bit register that sets the NVIC base priority)
FAULTMASK (1-bit register that says if fault interrupts are enabled)
CONTROL (3-bit register that indicates presence of FP, whether PSP is
selected, and whether running in unprivileged mode)
Now, these are "system" registers, and on a full blown microprocessor,
it might be unusual to expose them, but on a microcontroller, it's
quite important. The other debuggers that I have seen (IAR,
specifically) also list the m-system registers along with the general
purpose ones for Cortex-M.
The following XML is sufficient to describe the m-system registers so
that they appear to the GDB client.
<feature name="org.gnu.gdb.arm.m-system">
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>
Does GDB need to be aware of these registers at all? That is, does gdb
need to be aware of org.gnu.gdb.arm.m-system? Usually GDB needs to
be aware of specific registers if for instance Dwarf can refer to them.
Otherwise, the design of xml descriptions is such that you're free
to send any additional registers you want without a specific feature.
GDB will show them.
Hmm... It's hard for me to say. The MSP and PSP are banked stack
pointers, control instructs the core which stack pointer to use, and
they are also tightly coupled to exception entry, so I would lean
towards yes?
Post by Pedro Alves
Post by Christopher Friedt
The first question I would ask for clarification from the binutils-gdb
developers, is, which regnum is appropriate to assign to each of those
m-system registers? Should these registers enumerate starting with 26
(resuming from the xpsr)?
I don't think the regnums matter. GDB should be adjusting itself
dynamically.
The regnums only matter for backward compatibility with stubs that
don't report XML descriptions. In that case, GDB will fallback to
internal XML descriptions guessed from e.g., the binary loaded, and
in that case the expected offsets in the g/G packets must match what
the stub actually sends.
Exactly, I just want to ensure that the numbering *is* backward
compatible with stubs that don't support XML descriptions. I believe
anything beyond 26 should be fine, as it does not interfere with core
registers, the PSR, or FPA registers. Is that a correct assumption?
Post by Pedro Alves
Even though all Cortex-M CPUs have these registers, userspace
debuggers/servers can't access them, right?
With the chips I have worked with, I definitely could access (i.e.
write to) the msp, psp, primask, faultmask, basepri, and control
registers, via OpenOCD. I think the only non-addressible register that
can't be written is the xpsr, iirc (which is not part of m-system).
Pedro Alves
2015-12-15 00:13:14 UTC
Permalink
Post by Christopher Friedt
Post by Pedro Alves
Does GDB need to be aware of these registers at all? That is, does gdb
need to be aware of org.gnu.gdb.arm.m-system? Usually GDB needs to
be aware of specific registers if for instance Dwarf can refer to them.
Otherwise, the design of xml descriptions is such that you're free
to send any additional registers you want without a specific feature.
GDB will show them.
Hmm... It's hard for me to say. The MSP and PSP are banked stack
pointers, control instructs the core which stack pointer to use, and
they are also tightly coupled to exception entry, so I would lean
towards yes?
If you can think of some gdb feature that would need hard coding
the awareness of the existence of these registers, then that's an
indication you'd want to create a new standard target feature to wrap
the registers, so gdb could check whether the feature is present
on the target gdb just connected to. Then gdb's ARM backend code (gdb/arm-tdep.c)
would check whether the feature is listed as present in the target description
the stub sent, and if it is present, validate that the corresponding
set of register registers is included in the reported description,
like is done already for other standard features:

https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html

TBC, the stub is free to send other unknown registers in the target
description. That is, if you adjust your stub to send a description
like this:

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32"/>

<!-- System registers below. Note these are not
_required_ by org.gnu.gdb.arm.m-profile. -->
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>

It'll work just as well. GDB will display the registers just fine.

IOW, if you're not sure, it probably means no, you don't need the
new feature.

(BTW, features put under the "org.gnu.gdb" namespace must all
be documented in the gdb's manual.)

That said, if multiple projects want it, I guess it wouldn't hurt to
put an official xml file in the gdb tree, just so everyone has a
canonical place to copy the file from.
Post by Christopher Friedt
Post by Pedro Alves
Post by Christopher Friedt
The first question I would ask for clarification from the binutils-gdb
developers, is, which regnum is appropriate to assign to each of those
m-system registers? Should these registers enumerate starting with 26
(resuming from the xpsr)?
I don't think the regnums matter. GDB should be adjusting itself
dynamically.
The regnums only matter for backward compatibility with stubs that
don't report XML descriptions. In that case, GDB will fallback to
internal XML descriptions guessed from e.g., the binary loaded, and
in that case the expected offsets in the g/G packets must match what
the stub actually sends.
Exactly, I just want to ensure that the numbering *is* backward
compatible with stubs that don't support XML descriptions.
Can you clarify? What stubs would those be? Since GDB has no built-in
knowledge of these registers, when debugging against stubs that don't
sent a target description, there's no way they would ever be presented.
Post by Christopher Friedt
I believe
anything beyond 26 should be fine, as it does not interfere with core
registers, the PSR, or FPA registers. Is that a correct assumption?
Post by Pedro Alves
Even though all Cortex-M CPUs have these registers, userspace
debuggers/servers can't access them, right?
With the chips I have worked with, I definitely could access (i.e.
write to) the msp, psp, primask, faultmask, basepri, and control
registers, via OpenOCD. I think the only non-addressible register that
can't be written is the xpsr, iirc (which is not part of m-system).
I meant things like Linux/ptrace, where a non-privileged
userspace debugger normally can't access system/privileged registers.
Even though m-profile targets the microcontroller space, there's a
Linux port that runs on it, for example.
Post by Christopher Friedt
1) Should it be inserted directly into arm-m-profile.xml?
2) Should it be included from arm-m-profile.xml as arm-m-system.xml?
If you asking about gdb's copy of the files, the answer is neither.
Leave those alone for stubs that don't have access to the system
registers.

We'd instead need a new file arm-m-system.xml that lists the system
registers and then a new arm-with-m-system.xml wrapper file that is like
arm-with-m.xml but also xi:includes arm-m-system.xml. Something like:

$ diff -up arm-with-m.xml arm-with-m-system.xml
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
<architecture>arm</architecture>
<xi:include href="arm-m-profile.xml"/>
+ <xi:include href="arm-m-system.xml"/>
</target>

Then stubs pick either arm-with-m-system.xml or arm-with-m.xml
depending on access to the system registers.

Thanks,
Pedro Alves
Christopher Friedt
2015-12-15 15:35:17 UTC
Permalink
Just so we can have consensus, please indicate what you think is the
best solution - Pedro, Yao, & Tristan.

Based on Tristan's feedback as well, it confirms that these registers
are necessary for DWARF handling.
Post by Pedro Alves
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32"/>
<!-- System registers below. Note these are not
_required_ by org.gnu.gdb.arm.m-profile. -->
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>
I do like Pedro's suggestion. The above XML could be called arm-7m-profile.xml .

Based on Yao's feedback and the ARMv6M A.R.M., I would also suggest
something like the following for arm-6m-profile.xml.

Please note, I suggest using adding regnum="25" for the xpsr in both cases.

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32" regnum="25"/>

<!-- System registers below. Note these are not
_required_ by org.gnu.gdb.arm.m-profile. -->
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>

<!-- Slack for unused basepri and faultmask registers.
See arm-fpa.xml. -->
<reg name="" bitsize="8" type="int8" regnum="16"/>
<reg name="" bitsize="8" type="int8" regnum="16"/>

<reg name="control" bitsize="3" type="int8"/>
</feature>

It borrows from arm-with-m-fpa-layout.xml in that it specifies some
nameless registers (which I assume are ignored by gdb - Pedro, can you
confirm?). The benefit is that the regnum fields of the 6m and 7m
profiles would align easily, simplifying stub implementation. It's a
bit messy though.

Let's call the above 'option A'.

Let's call the alternative below 'option B'.

Common / base case for all ARM Cortex-M devices
arm-m-profile.xml

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32" regnum="25"/>

<!-- System registers below. Note these are not
_required_ by org.gnu.gdb.arm.m-profile. -->
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>

Additional registers for ARMv7M

arm-7m-profile.xml

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32" regnum="25"/>

<!-- System registers below. Note these are not
_required_ by org.gnu.gdb.arm.m-profile. -->
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
</feature>

If we can improve 'option B' via <xi:include> and reuse
arm-m-profile.xml, please let me know.

Thanks,

C
Tristan Gingold
2015-12-16 13:51:07 UTC
Permalink
Post by Christopher Friedt
Just so we can have consensus, please indicate what you think is the
best solution - Pedro, Yao, & Tristan.
Based on Tristan's feedback as well, it confirms that these registers
are necessary for DWARF handling.
Not sure about that. To my understanding, DWARF doesn’t need to refer
to psp or msp.

Tristan.
Christopher Friedt
2015-12-16 17:12:59 UTC
Permalink
Post by Tristan Gingold
Post by Christopher Friedt
Just so we can have consensus, please indicate what you think is the
best solution - Pedro, Yao, & Tristan.
Based on Tristan's feedback as well, it confirms that these registers
are necessary for DWARF handling.
Not sure about that. To my understanding, DWARF doesn’t need to refer
to psp or msp.
Wait... just yesterday you wrote:

"I do think so too.

I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp."

Maybe I'm confused. I presumed DWARF was involved in unwinding to some
extent, but if its purely just used for debugging, it might not
require PSP / MSP at all.

In any case PSP / MSP are most definitely used in unwinding.
Tristan Gingold
2015-12-17 08:31:56 UTC
Permalink
Post by Christopher Friedt
Post by Tristan Gingold
Post by Christopher Friedt
Just so we can have consensus, please indicate what you think is the
best solution - Pedro, Yao, & Tristan.
Based on Tristan's feedback as well, it confirms that these registers
are necessary for DWARF handling.
Not sure about that. To my understanding, DWARF doesn’t need to refer
to psp or msp.
"I do think so too.
I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp."
Maybe I'm confused. I presumed DWARF was involved in unwinding to some
extent, but if its purely just used for debugging, it might not
require PSP / MSP at all.
No, for unwinding through HW exceptions, dwarf is not used and couldn’t
be use: there is no code at the return addresses.

PSP is required because that can be previous stack before the exception.
Post by Christopher Friedt
In any case PSP / MSP are most definitely used in unwinding.
I think that only PSP and SP are required (of course SP could be MSP).

Tristan.
Christopher Friedt
2018-08-14 18:14:40 UTC
Permalink
I might be going for the Guiness record of the longest delay in a thread!

Kind of funny, but I was using gdb / QEMU again, and found that I was
missing some critical registers again.

In any case, let's continue the conversation.
Post by Tristan Gingold
I think that only PSP and SP are required (of course SP could be MSP).
I think I agree that only the psp and sp are required (not the msp).

That would mean the following should be added for armv7-m:

psp, primask, basepri, faultmask, control

and the following would need to be added for armv6-m:

psp, faultmask, control

However, we also have the armv8-m and the following would need to be added
for armv8-m:

psp, msplim, psplim, primask, basepri, basepri_max, faultmask, control,
msp_ns, psp_ns, msplim_ns, psplim_ns, primask_ns, basepri_ns, faultmask_ns,
control_ns, sp_ns.

Does all of that make sense? I think I could probably throw together a
patch and just put it on the list, if that's ok.
Tristan Gingold
2015-12-15 11:44:20 UTC
Permalink
Post by Christopher Friedt
Post by Pedro Alves
Post by Christopher Friedt
Hi list,
I've been using GDB and OpenOCD to debug ARM Cortex-M devices for
quite a while. One thing that I always noticed when using OpenOCD is
that the m-system registers are listed, which is *incredibly* useful
for writing code on just about any Cortex-M microcontroller.
Somewhat recently, Qemu has also begun to support Cortex-M based
virtual devices, and it seems to be fairly usable.
The down side, is that they do not expose the m-system registers,
simply because binutils-gdb does not (at this time) have an XML file
for them.
Just to catch anyone up to speed who might be reading this, the
m-system registers are
MSP (main stack pointer)
PSP (process stack pointer)
PRIMASK (1-bit register that says if interrupts are enabled)
BASEPRI (8-bit register that sets the NVIC base priority)
FAULTMASK (1-bit register that says if fault interrupts are enabled)
CONTROL (3-bit register that indicates presence of FP, whether PSP is
selected, and whether running in unprivileged mode)
Now, these are "system" registers, and on a full blown microprocessor,
it might be unusual to expose them, but on a microcontroller, it's
quite important. The other debuggers that I have seen (IAR,
specifically) also list the m-system registers along with the general
purpose ones for Cortex-M.
The following XML is sufficient to describe the m-system registers so
that they appear to the GDB client.
<feature name="org.gnu.gdb.arm.m-system">
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>
Does GDB need to be aware of these registers at all? That is, does gdb
need to be aware of org.gnu.gdb.arm.m-system? Usually GDB needs to
be aware of specific registers if for instance Dwarf can refer to them.
Otherwise, the design of xml descriptions is such that you're free
to send any additional registers you want without a specific feature.
GDB will show them.
Hmm... It's hard for me to say. The MSP and PSP are banked stack
pointers, control instructs the core which stack pointer to use, and
they are also tightly coupled to exception entry, so I would lean
towards yes?
I do think so too.

I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp.

I plan to submit it early January.

Tristan.
Pedro Alves
2015-12-15 11:59:49 UTC
Permalink
Post by Tristan Gingold
Post by Christopher Friedt
Hmm... It's hard for me to say. The MSP and PSP are banked stack
pointers, control instructs the core which stack pointer to use, and
they are also tightly coupled to exception entry, so I would lean
towards yes?
I do think so too.
I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp.
Alright, that's indeed a very good reason.

Thanks,
Pedro Alves
Pedro Alves
2015-12-15 12:11:02 UTC
Permalink
Post by Tristan Gingold
Post by Christopher Friedt
Post by Pedro Alves
Post by Christopher Friedt
Hi list,
I've been using GDB and OpenOCD to debug ARM Cortex-M devices for
quite a while. One thing that I always noticed when using OpenOCD is
that the m-system registers are listed, which is *incredibly* useful
for writing code on just about any Cortex-M microcontroller.
Somewhat recently, Qemu has also begun to support Cortex-M based
virtual devices, and it seems to be fairly usable.
The down side, is that they do not expose the m-system registers,
simply because binutils-gdb does not (at this time) have an XML file
for them.
Just to catch anyone up to speed who might be reading this, the
m-system registers are
MSP (main stack pointer)
PSP (process stack pointer)
PRIMASK (1-bit register that says if interrupts are enabled)
BASEPRI (8-bit register that sets the NVIC base priority)
FAULTMASK (1-bit register that says if fault interrupts are enabled)
CONTROL (3-bit register that indicates presence of FP, whether PSP is
selected, and whether running in unprivileged mode)
Now, these are "system" registers, and on a full blown microprocessor,
it might be unusual to expose them, but on a microcontroller, it's
quite important. The other debuggers that I have seen (IAR,
specifically) also list the m-system registers along with the general
purpose ones for Cortex-M.
The following XML is sufficient to describe the m-system registers so
that they appear to the GDB client.
<feature name="org.gnu.gdb.arm.m-system">
<reg name="msp" bitsize="32" type="data_ptr"/>
<reg name="psp" bitsize="32" type="data_ptr"/>
<reg name="primask" bitsize="1" type="int8"/>
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
<reg name="control" bitsize="3" type="int8"/>
</feature>
Does GDB need to be aware of these registers at all? That is, does gdb
need to be aware of org.gnu.gdb.arm.m-system? Usually GDB needs to
be aware of specific registers if for instance Dwarf can refer to them.
Otherwise, the design of xml descriptions is such that you're free
to send any additional registers you want without a specific feature.
GDB will show them.
Hmm... It's hard for me to say. The MSP and PSP are banked stack
pointers, control instructs the core which stack pointer to use, and
they are also tightly coupled to exception entry, so I would lean
towards yes?
I do think so too.
I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp.
I plan to submit it early January.
Tristan.
Thanks,
Pedro Alves
Pedro Alves
2015-12-15 12:13:10 UTC
Permalink
Pressed send too early...
Post by Tristan Gingold
I do think so too.
I have just written a patch so that gdb unwinds correctly on cortex-m
exceptions, and this of course requires that gdb knows about at least
psp.
I plan to submit it early January.
I meant to say a bell just rang... This was attempted before,
though never finished:

https://sourceware.org/ml/gdb-patches/2014-09/msg00649.html

Thanks,
Pedro Alves
Yao Qi
2015-12-15 08:55:23 UTC
Permalink
Post by Christopher Friedt
The first question I would ask for clarification from the binutils-gdb
developers, is, which regnum is appropriate to assign to each of those
m-system registers? Should these registers enumerate starting with 26
(resuming from the xpsr)?
Just for comparison, the current binutils-gdb arm-m-profile.xml is
here (https://goo.gl/hpTye8), and the openocd variant is here
(http://goo.gl/FFn56X).
The number doesn't matter, but the name does. In the target
descriptions from openocd, the register is named as "xPSR" in
standard feature org.gnu.gdb.arm.m-profile.

{ ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },

however, in gdb/arm-tdep.c, gdb expects "xpsr"

if (is_m)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "xpsr");
else
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "cpsr");

so I suspect that GDB won't accept the org.gnu.gdb.arm.m-profile feature
from openocd.
--
Yao (齐尧)
Pedro Alves
2015-12-15 10:25:52 UTC
Permalink
Post by Yao Qi
The number doesn't matter, but the name does. In the target
descriptions from openocd, the register is named as "xPSR" in
standard feature org.gnu.gdb.arm.m-profile.
{ ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
however, in gdb/arm-tdep.c, gdb expects "xpsr"
if (is_m)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "xpsr");
else
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "cpsr");
so I suspect that GDB won't accept the org.gnu.gdb.arm.m-profile feature
from openocd.
No, that's fine actually -- tdesc_numbered_register uses strcasecmp.

From https://sourceware.org/gdb/onlinedocs/gdb/Target-Description-Format.html:

"The names of registers are not case sensitive for the purpose of
recognizing standard features, but gdb will only display registers
using the capitalization used in the description. "

Thanks,
Pedro Alves
Pedro Alves
2015-12-15 10:32:33 UTC
Permalink
Post by Pedro Alves
No, that's fine actually -- tdesc_numbered_register uses strcasecmp.
"The names of registers are not case sensitive for the purpose of
recognizing standard features, but gdb will only display registers
using the capitalization used in the description. "
Sorry, wrong URL. It's here:

https://sourceware.org/gdb/onlinedocs/gdb/Standard-Target-Features.html

Thanks,
Pedro Alves
Yao Qi
2015-12-16 09:49:14 UTC
Permalink
Post by Pedro Alves
"The names of registers are not case sensitive for the purpose of
recognizing standard features, but gdb will only display registers
using the capitalization used in the description. "
OK, so the openocd is correct then. Thanks for pointing it out.
--
Yao (齐尧)
Yao Qi
2015-12-15 09:13:18 UTC
Permalink
Post by Christopher Friedt
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
These two don't exist in armv6-m profile.
--
Yao (齐尧)
Christopher Friedt
2015-12-15 12:19:46 UTC
Permalink
Post by Yao Qi
Post by Christopher Friedt
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
These two don't exist in armv6-m profile.
Just read that as well from the ARMv6M A.R.M.

Rather than use a separate XML file for v6m, that excludes basepri and
faultmask, do you think it's rational to simply RAZ / IW?
Christopher Friedt
2015-12-15 15:09:20 UTC
Permalink
On Tue, Dec 15, 2015 at 7:19 AM, Christopher Friedt
Post by Christopher Friedt
Post by Yao Qi
Post by Christopher Friedt
<reg name="basepri" bitsize="8" type="int8"/>
<reg name="faultmask" bitsize="1" type="int8"/>
These two don't exist in armv6-m profile.
Just read that as well from the ARMv6M A.R.M.
Rather than use a separate XML file for v6m, that excludes basepri and
faultmask, do you think it's rational to simply RAZ / IW?
Should be easy enough to create an arm-6m-profile.xml and an
arm-7m-profile.xml, in any case.
Loading...