-
Notifications
You must be signed in to change notification settings - Fork 168
Safe API to enable the ITM #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hm, ITM is incredibly powerful and the code above is a rather specific configuration. Maybe we should talk to ITM experts like @mubes to get an opinion about a useful API. BTW: Check out his blog about some of his incredible ITM work: http://shadetail.com/blog/ . It would be outstanding to have good ITM support in Rust. |
Hi guys, the magic of gitter informed me about this conversation. Bearing in mind that I have very little context here my first reaction is to ask why you want to switch ITM stimulus ports on and off from program code? The normal use case is to spit everything out over the various ports in your code and then use the debugger to switch them on and off as needed....after all, you don't really need them if there's no debugger (actually, there's no intrinsic need for a debugger since ITM output comes via different routes, but it's certainly the normal use case). If you look at orbuculum you will find gdb macros that do the needed on/off switching..the idea is that you can decide what debug output you actually want at any point in the debug cycle. I remember reading somewhere that Arm claim that the low overhead means you can leave the calls in production code with the ITM switched off....I'm not sure I agree with that, but you can see the intent. (Not sure gitter will be bright enough to keep me informed of follow ups, so if I don't respond can you poke me please Daniel?). Dave |
We have to start somewhere though. Having to use unsafe code to get logging, the most basic ITM feature, working is kind of ... sad. We could design the API so that adding more functionality, like tracing interrupt entry/exit times, can be added later in a backwards compatible fashion. Though I don't mind making a new minor release if it's to add more ITM functionality.
Because ITM can work without a debugger and it's a nice and fast way to log data. I have used it to wirelessly (2 Mbps UART to Bluetooth adapter) log sensor data and program state from a mobile robot -- I certainly don't want to attach a debugger, or a USB cable, to a moving robot just to enable logging. |
Hey! I use the cortex-m crate, and the iprint! macro, so maybe it blocks in By the way, |
I too would love to use ITM for logging (without debugger attached) instead of using an USART. What needs to happen to move this issue forward? If need be behind some "unproven" feature. One question: What happens to such code if read out protection level 2 is activated (on ST chips)? It would be good if doing so would not cause the application to hard fault if there is embedded ITM logging code. |
I think this should be given some priority soon. |
I'm not sure this is possible - I've been poking about and it seems that you need DEBUGEN in DHCSR to be set for any DBGMCU registers to work but DEBUGEN cannot be set by the core. Here's a quick test that indicates you can't write DBGMCU:
With the debugger attached the led lights, without, it doesn't. Section 10.2.1 of the Cortex-M3 technical reference manual (page 211 in the latest version) states:
The solution offered by the stm32 forum says you need to check this flag (although that may not even work on M0 - see the note in the code) before attempting to use ITM. |
There is no point in sending stuff out of the ITM if there's nothing
connected to hear it :-)
There is a valid argument that a debugger isn't _strictly_ needed for that
purpose (after all, SWO is independent of debug) but it's the logic behind
how things work in the arm world....basically, check if the debug is
switched on before sending anything out of it.
Dave
…On Thu, 30 Jan 2020, 18:10 cs2dsb, ***@***.***> wrote:
I'm not sure this is possible - I've been poking about and it seems that
you need DEBUGEN in DHCSR to be set for any DBGMCU registers to work but
DEBUGEN cannot be set by the core. Here's a quick test that indicates you
can't write DBGMCU:
let x = 0x00000027;
while core::ptr::read_volatile(0xE0042004 as *mut u32) != x {
core::ptr::write_volatile(0xE0042004 as *mut u32, x);
}
usr_led.on();
With the debugger attached the led lights, without, it doesn't.
Section 10.2.1 of the Cortex-M3 technical reference manual (page 211 in
the latest version) states:
C_DEBUGEN - Enables debug. This can only be written by AHB-AP and not by
the core. It
is ignored when written by the core, which cannot set or clear it.
The solution offered by the stm32 forum
<https://community.st.com/s/question/0D50X00009XkaEn/itmsendchar-blocks-when-no-debugger-attached>
says you need to check this flag (although that may not even work on M0 -
see the note in the code
<https://github.com/rust-embedded/cortex-m/blob/22d47dd75e9fb5004e0192666123d28f0a418310/src/peripheral/dcb.rs#L45>)
before attempting to use ITM.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#82?email_source=notifications&email_token=ABJTBD56DTV2AJE5HLEBTODRAMJZJA5CNFSM4ESE5KHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKL664Q#issuecomment-580382578>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJTBD7DNUNBLOLX5YT3M6DRAMJZJANCNFSM4ESE5KHA>
.
|
@mubes In my case, I have my UART dongle connected to SWO and GND and a separate header for programming so I was listening for ITM packets but if I reset the device without OpenOCD connected it wouldn't work. It would be nice to get a crate that is able to detect if ITM is configured and available and sets up the log crates logger instance to either something that sends logs over ITM or a stubbed out nop logger. I've implemented a logger for ITM here which works fine IF ITM is enabled. The checks I added to detect if the stim port was enabled turned out to not be sufficient to detect if is_fifo_ready will block or not. Based off the note in the code it might be non trivial to support this across multiple device families. Do you know of a reliable method to detect if the fifo will block that works across all the cortex_m range (since DHCSR.DEBUGEN is impl specific)? The same detection method could be used in this crate in ITM::enable and have it return an error if ITM can't be properly enabled. |
You can use DEMCA and the TRCENA bit to see if the ITM is being listened
to. That is a 'standard' register;
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/CEGHJDCF.html
...and also;
http://shadetail.com/blog/swo-starting-the-steroids/
It is essential you know that something is listening to you because the
flow control mechanism will effectively lock you up unless you put
timeout mechanisms in there.
Regards
DAVE
…On 30/01/2020 20:28, cs2dsb wrote:
@mubes <https://github.com/mubes> In my case, I have my UART dongle
connected to SWO and GND and a separate header for programming so I
was listening for ITM packets but if I reset the device without
OpenOCD connected it wouldn't work.
It would be nice to get a crate that is able to detect if ITM is
configured and available and sets up the log crates logger instance to
either something that sends logs over ITM or a stubbed out nop logger.
I've implemented a logger for ITM here
<https://github.com/cs2dsb/itm_logger.rs/blob/master/src/logger.rs>
which works fine IF ITM is enabled. The checks I added to detect if
the stim port was enabled turned out to not be sufficient to detect if
is_fifo_ready will block or not. Based off the note in the code
<https://github.com/rust-embedded/cortex-m/blob/22d47dd75e9fb5004e0192666123d28f0a418310/src/peripheral/dcb.rs#L45>
it might be non trivial to support this across multiple device families.
Do you know of a reliable method to detect if the fifo will block that
works across all the cortex_m range (since DHCSR.DEBUGEN is impl
specific)? The same detection method could be used in this crate in
ITM::enable and have it return an error if ITM can't be properly enabled.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#82?email_source=notifications&email_token=ABJTBDZ62DCXN7TJAN3WUUDRAM2AJA5CNFSM4ESE5KHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKMOJKQ#issuecomment-580445354>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJTBD4CKAC3MAA73ULTP43RAM2AJANCNFSM4ESE5KHA>.
|
A fly in the ointment is if you are using DWT for delays which a bunch of the hal implementations do f1/i2c for example the TRCENA bit has to be set for DWT to run. So if you've got code enabling TRCENA for DWT and enabling ITM (this issue), the three checks listed in swo-starting-the-steroids still doesn't tell you if ITM is ready because all of those bits are settable by the core. I think there needs to be an additional check on some register that the core can't update for you to be sure something is listening. Regarding your last point about having to check for something listening, is this true for all variants of tracing? I've got mine configured for SWO and the micro keeps running fine if I unplug the STLINK and/or the UART. Plugging the UART back in without the STLINK logging over SWO starts working again. |
This raises a number of issues;
1) the interlock, which is effectively a software flow control mechanism,
only tells you that the hardware has picked up your message and transmitted
it....it can't say anything about if something at the other end got it
(there's no ack mechanism on this, Swo is unidirectional). The interlock is
only there to ensure that software channel messages are spat out at an
appropriate rate. Thus, other messages such as PC sampling etc don't have
that mechanism...nothing cares if there's anything at the other end or not
- there's no flow control on hardware messages. It's the old tree falling
in the forest and noone there to hear it thing.
2) I confess to having not looked at the code you linked (I'm working from
my phone over the weekend) but if these HALs are using CYCCNT for delays
that makes me very uncomfortable. Firstly, it means the debug circuits are
always on, which is a power drain. It means we're generslly in busy loops,
which isn't nice, and it also means that when the clock speed of the CPU
changes (e.g. for power saving) the indexing factor will be wrong, or
you've got implementation details of the clock spread across your hal. I
may have misinterpreted what's been done here so I'll try to look at it
later and follow up.
Regards
Dave
…On Fri, 31 Jan 2020, 12:03 cs2dsb, ***@***.***> wrote:
A fly in the ointment is if you are using DWT for delays which a bunch of
the hal implementations do f1/i2c for example
<https://github.com/stm32-rs/stm32f1xx-hal/blob/master/src/i2c.rs> the
TRCENA bit has to be set for DWT to run.
So if you've got code enabling TRCENA for DWT and enabling ITM (this
issue), the three checks listed in swo-starting-the-steroids
<http://shadetail.com/blog/swo-starting-the-steroids/> still doesn't tell
you if ITM is ready because all of those bits are settable by the core.
I think there needs to be an additional check on some register that the
core can't update for you to be sure something is listening.
Regarding your last point about having to check for something listening,
is this true for all variants of tracing? I've got mine configured for SWO
and the micro keeps running fine if I unplug the STLINK and/or the UART.
Plugging the UART back in without the STLINK logging over SWO starts
working again.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#82?email_source=notifications&email_token=ABJTBD2OE2DVOT6RZ7ZDGTLRAQHPRA5CNFSM4ESE5KHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKOOEYQ#issuecomment-580706914>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJTBD5G4G2FWQJUL2TK6LLRAQHPRANCNFSM4ESE5KHA>
.
|
I just finished a two day investigation: why can't I use the ITM debugging. |
The In your case did you confirm that removing |
Well, I have double checked what has happened, but the final conclusion is missing: now everything works. However during the investigation the problem appeared many times: |
Even if turning the ITM on with code is not very sensible, I think it'd be good to have an API for this. With it you should be able to set the SWO speed and the used encoding. |
90: turn macros into attributes r=adamgreig a=japaric This is a PoC implementation of RFC #82. Assuming that we are OK with this implementation we should add some compile fail tests (e.g. using a function with the wrong signature as the entry point) before landing this. Look at the diff of the examples to get an overview of the changes. cc @rust-embedded/cortex-m Co-authored-by: Jorge Aparicio <[email protected]>
The ITM can easily be enabled using OpenOCD but that requires having a debugger connected to the MCU. ITM can be used for logging or as a communication channel in a production application; in that case the MCU must take care of initializing the ITM. Right now enabling the ITM requires unsafe code; this is what it looks like:
We should have a safe API to enable the ITM. The API could be an
ITM::enable(&mut self, prescaler: u32)
method to globally enable the ITM and anITM::{enable,disable}_port(&mut self, i: u8)
to enable / disable an individual port.The text was updated successfully, but these errors were encountered: