probe-rs / rtt-target

Target side implementation of the RTT (Real-Time Transfer) I/O protocol
MIT License
125 stars 30 forks source link

problems with multiple channels #1

Closed tpilt closed 4 years ago

tpilt commented 4 years ago

Hi,

I'm having problems with getting from channel 1,2,3 printed on the host side. Channel 0 works fine, and downlink channel 0 also works fine.

#[entry]
fn main() -> ! {
    let channels = rtt_init! {
        up: {
            0: {
                size: 1024
                name: "Trace"
            }
            1: {
                size: 1024
                name: "Shell up"
            }
        }
    };
    let mut shell_up = channels.up.1;
    let mut trace_up = channels.up.0;

    trace_up.write(b"trace_up\n"); // works fine
    shell_up.write(b"shell_up\n"); // does NOT work!

    set_print_channel(trace_up); // works fine
    rprintln!("main() says hello...");  // works fine

    loop {}
}

This does not print "shell_up" as expected. Is it a blunder on my side? :-)

mvirkkunen commented 4 years ago

What command are you using to view the output?

tpilt commented 4 years ago
###RTT Client: Connected.

SEGGER J-Link V6.70c - Real time terminal output
SEGGER J-Link ARM V10.0, SN=600001020
Process: JLinkGDBServerCLExe
trace_up
main() says hello...

Also tried the Gui version. (I'm on linux)

I tried singlestepping a bit into the write-call, and I got quite deep, I think it wrote something to some buffer... then I gave up.

How do we debug this? Should I try to NOT have the client connected. Then I can hex-dump the entire RTT memory before and after the call. (I'll need help for the hex-dumping :-) )

Or should we caputre the USB communication?

mvirkkunen commented 4 years ago

I haven't used that particular client because I don't have a J-Link and I assume it only works with those. Does it have command line options to specify which channels to use? Is it possible that by default it only looks at channel 0?

mvirkkunen commented 4 years ago

While I can't test this, these posts would suggest that the official viewer only supports channel 0 (Terminal):

https://forum.segger.com/index.php/Thread/2030-RTT-multiple-channels/

https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/multiple-channels-in-rtt

Apparently you're supposed to use "RTT Logger" instead if you want to view multiple channels.

You could also use cargo embed, which has a multi-channel viewer implemented with an RTT host library I also wrote and is known to work - although if you can spare the time, I'd be glad if you could also test with Segger's logger software just to verify.

tpilt commented 4 years ago

Thx, turns out that there is a difference between 'channels', and 'terminals', in Seggers terminology, that I was unaware of.

As written I also tried 'the GUI version', which is this: https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/ This has different tabs , I assumed them to be 'channels' , but they are 'terminals'.

Looks like they send some kind of escape sequence, to set a new 'terminal' (0xFF 0x02 for terminal 2, if I'm not mistaken) and then send the string/data on CHANNEL 0. https://github.com/contiki-os/contiki/blob/master/platform/nrf52dk/rtt/segger-rtt.c

Regarding JLinkRTTLogger, you're (also!) right:

Searching for RTT Control Block...OK. 2 up-channels found.
RTT Channel description: 
  Index: 1
  Name:  Shell up
  Size:  1024 bytes.

Output file: /home/xxx/.config/SEGGER\RTTLogger_Channel_Shell up.log

( notice the backslash in the filename ... I think this was intended to go into a subdir, and indeed it will on windows :-) )

I must choose which channel to log from, but on linux at least, I can successfully have the VSCode debugging the application, and run two JLinkRTTLogger at the same time, logging to two different files.

I think I will look into the "cargo embed" crate soon. Just for fun, I might also try to send the "\xFF\x2" sequence, and see, if the JLinkRTTViewer now pick it up as 'terminal' 2.

mvirkkunen commented 4 years ago

rtt-target also supports the escape sequences for the different virtual terminals! It also takes care of not sending it partially if the buffer is almost full.

If using rprintln! there's a special syntax for it: https://docs.rs/rtt-target/0.1.1/rtt_target/macro.rprintln.html

If not, you can create a TerminalChannel: https://docs.rs/rtt-target/0.1.1/rtt_target/struct.TerminalChannel.html

tpilt commented 4 years ago

Indeed, this makes JLinkRTTViewer write into different 'terminals':

        let ch0: [u8; 2] = [0xFF, b'0'];
        let ch1: [u8; 2] = [0xFF, b'1'];
        // toggle alive-leds
        if second_elapsed {
            if uptime & 0x01 == 0 {
                efm_per.GPIO.pa_dout.write(|w| unsafe { w.bits(0x55) });
                trace_up.write(&ch0);
                trace_up.write(b"hoping for this to arrive at terminal 0\n");
            } else {
                trace_up.write(&ch1);
                trace_up.write(b"hoping for this to arrive at terminal 1\n");
                efm_per.GPIO.pa_dout.write(|w| unsafe { w.bits(0xAA) });
            }
        }

"All Terminals" Tab:

00> hoping for this to arrive at terminal 0
01> hoping for this to arrive at terminal 1
00> hoping for this to arrive at terminal 0
01> hoping for this to arrive at terminal 1
00> hoping for this to arrive at terminal 0
01> hoping for this to arrive at terminal 1
00> hoping for this to arrive at terminal 0

"Terminal 0" Tab

hoping for this to arrive at terminal 0
hoping for this to arrive at terminal 0
hoping for this to arrive at terminal 0
...

"Terminal 1" Tab

hoping for this to arrive at terminal 1
hoping for this to arrive at terminal 1
hoping for this to arrive at terminal 1
...
tpilt commented 4 years ago

Argh, these post crossed.... I WAS looking at the ( => 2, "hello") syntax at one time. But had trouble working all this out. Thx for all help :-)

mvirkkunen commented 4 years ago

Maybe it'd be a good idea to document what channels and terminals mean in the library docs because it can be confusing if you don't already know.