Code Monkey home page Code Monkey logo

Comments (13)

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024 1

Got answer, let's close now.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024 1

One other caveat I will mention is that if your program does direct stdout to GDB via MRI's semi-hosting support, the program will hang the first time it tries to write something to stdout if GDB isn't attached since it will wait for the ack back from GDB. There are hacks that you can do for a particular platform port to work around this a bit. Let me know if you want to do know more. I can point you to some hacks that I have done in the past.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024

When using the semi host support, if you write to file handle number 1 then you are writing to stdout. Writes to file handle number 2 will go to stderr and reads from file number 0 come from stdin. Nothing needs to be done on the GDB side.

In the case of newlib, it already does this for us. When you call functions like printf(), several calls later down in the call stack you will see a call to the _write() sys call for file handle number 1. In the project I am currently working on, _write() is implemented like this: https://github.com/adamgreen/rugrover/blob/master/mriblue_boot/shared/newlib_retarget.c#L139 which ends up calling mriNewlib_SemihostWrite() that is nothing but a bkpt MRI_NEWLIB_SEMIHOST_WRITE instruction that will cause a transfer into MRI to satisfy the write request via GDB's file API. The file number of 1 will be passed to GDB and it does the right thing by sending the data to stdout.

Does that help?

from mri.

adamgreen avatar adamgreen commented on September 28, 2024

When you call printf() in NuttX, where does it send the output? You want to do whatever you need to do in NuttX to get it to use the ARM semihost layer for this output as well.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024

I should note that it is something you probably want to be able to turn on and off though as semihost redirection of stdout will be a lot slower than just dumping it out a serial port or other channel.

from mri.

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024

When using the semi host support, if you write to file handle number 1 then you are writing to stdout. Writes to file handle number 2 will go to stderr and reads from file number 0 come from stdin. Nothing needs to be done on the GDB side.

In the case of newlib, it already does this for us. When you call functions like printf(), several calls later down in the call stack you will see a call to the _write() sys call for file handle number 1. In the project I am currently working on, _write() is implemented like this: https://github.com/adamgreen/rugrover/blob/master/mriblue_boot/shared/newlib_retarget.c#L139 which ends up calling mriNewlib_SemihostWrite() that is nothing but a bkpt MRI_NEWLIB_SEMIHOST_WRITE instruction that will cause a transfer into MRI to satisfy the write request via GDB's file API. The file number of 1 will be passed to GDB and it does the right thing by sending the data to stdout.

Does that help?

Yes, very useful. I have three more questions:

  1. Where will gdb output for stdout(1)/stderr(2)
  2. Where will gdb get input for stdin(0)
  3. If the user doesn't input anything, does the semihost read block until user input something or return with 0 length directly

When you call printf() in NuttX, where does it send the output? You want to do whatever you need to do in NuttX to get it to use the ARM semihost layer for this output as well.

Yes, it's very easy to wrapper a special console/syslog driver on top of semihost layer. We will do that after the above questions get confirm.

I should note that it is something you probably want to be able to turn on and off though as semihost redirection of stdout will be a lot slower than just dumping it out a serial port or other channel.

It's reasonable since the trap and RSP add more overhead, but the benefit is that we can use the same physical UART port to do the debug and shell at the same time.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024
  1. Where will gdb output for stdout(1)/stderr(2)
  2. Where will gdb get input for stdin(0)
  3. If the user doesn't input anything, does the semihost read block until user input something or return with 0 length directly
  1. It goes to the GDB console. If you are running GDB from the command line, then it goes to the same console where you type in GDB commands and the results come back to you. If you are running in an IDE then I am not sure. Usually there is a GDB console window in the IDE where you can type commands manually to GDB even from the IDE. It should definitely show up there and maybe the IDE can intercept it and redirect it somewhere else if the GDB MI interface flags it as debuggee output...I don't know for sure. I rarely use IDEs.
  2. Same as the answer to 1.
  3. Yes, it is blocking and as far as I can tell there is no non-blocking solution for determining if the user has typed something in GDB while the debuggee is running. What I have done in some of my programs in the past is to have my embedded program not normally read from stdin. However I have a global variable named something like g_debug that I can set to 1 from within the debugger and then the main program loop checks this global and when not 0 it runs code which outputs a debug menu to stdout and then waits for input from stdin.

Here is some example output from a recent run of my robot which dumps to stdout the number of PID updates that have occurred every 10 seconds so that I can make sure that my PID loop is running at the expected frequency. You can see where I have typed commands and CTRL+C into the same GDB console that my program also dumps this stdout to:

GNU gdb (GNU Arm Embedded Toolchain 9-2020-q4-major) 8.3.1.20191211-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-apple-darwin10 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from _build/RugRover.out...
Remote debugging using :3333
0x0003c4bc in Reset_Handler ()
(gdb) c
Continuing.
1000
995
1000
1000
1000
1000
^C
Program received signal SIGINT, Interrupt.
0x00009f80 in ?? ()
(gdb) q

from mri.

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024

Thanks for the detailed explanation. The blocking reading behavior isn't very good, we can't build a shell which could interactive through gdb console natively.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024

Agreed. The only input you can type into GDB which will result in something being sent to MRI asynchronously is a CTRL+C which results in a halt :(

I have used that before to pop up a non-interactive shell. I detect that CTRL+C and the continue have been sent which means that I should pop up my debug menu as soon as I can because the user has connected to me with GDB. I just use the hooks set by mriSetDebuggerHooks() to notice that MRI has been entered/left and use that to know when I should activate the blocking debug menu.

from mri.

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024

We will try to support shell with MRI on NuttX, let's see how we can improve the input experience and report back to you.

from mri.

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024

Sure, could you point me to the related code? We can try how to integrate that piece of code to NuttX.

from mri.

adamgreen avatar adamgreen commented on September 28, 2024

An overview of a hack that I did recently and others in the past have been similar:

That particular mriblue_boot implementation puts the outbound packets in a queue and at some point it will fill up and then the code will block. There are hacks I could do in that particular implementation to work around that but I don't have a need for that at this stage in my robot project since I always have GDB attached and I want to lose as little printf() text as possible.

from mri.

xiaoxiang781216 avatar xiaoxiang781216 commented on September 28, 2024

An overview of a hack that I did recently and others in the past have been similar:

I think this is a general enhancement and should be part of the mainline.

It is right there in the packet (but hexadized so that it now takes 2 characters per byte).

Yes, 'O' need convert the binary to hex which lose the performance. But, "Fwrite" packet is more slower than 'O':

  1. Need three trip("Fwrite"->"m"->"Frr,ee,cc")
  2. "m" also need convert the binary to hex

from mri.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.