Giter Site home page Giter Site logo

cortex-m-semihosting's People

Contributors

adamgreig avatar aurabindo avatar bors[bot] avatar eldruin avatar evq avatar homunkulus avatar japaric avatar jascha-n avatar jonas-schievink avatar korken89 avatar kubo39 avatar leseulartichaut avatar m-ou-se avatar nezza avatar nickray avatar nicoretti avatar pftbest avatar schodet avatar therealprof avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cortex-m-semihosting's Issues

Why is it so slow?

I'm not expert with embedded, but why is semihosting so slow? Single characters appear on the host stdio taking some 100s of ms for each one. I know that semihosting is slow in general, but I hadn't any issue using it from Ada which uses the following implementation:

package body System.Semihosting is

   type SH_Word is new Interfaces.Unsigned_32;

   function To_SH_Word is new Ada.Unchecked_Conversion
     (Source => System.Address, Target => SH_Word);

   function Generic_SH_Call (R0, R1 : SH_Word) return SH_Word;
   --  Handles the low-level part of semihosting, setting the registers and
   --  executing a breakpoint instruction.

   subtype Syscall is SH_Word;

   SYS_WRITEC : constant Syscall := 16#03#;
   SYS_WRITE0 : constant Syscall := 16#04#;
   SYS_READC  : constant Syscall := 16#07#;

   --  Output buffer

   --  Because most of the time required for semihosting is not consumed for
   --  the data itself but rather in the handling of breakpoint and
   --  communication between the target and debugger, sending one byte costs
   --  almost as much time as sending a buffer of multiple bytes.
   --
   --  For this reason, we use an output buffer for the semihosting Put
   --  functions. The buffer is flushed when full or when a line feed or NUL
   --  character is transmitted.

   Buffer_Size : constant := 128;
   type Buffer_Range is range 1 .. Buffer_Size;
   Buffer : array (Buffer_Range) of Unsigned_8;
   Buffer_Index : Buffer_Range := Buffer_Range'First;

   procedure Flush;
   --  Send the content of the buffer with semihosting WRITE0 call

   ---------------------
   -- Generic_SH_Call --
   ---------------------

   function Generic_SH_Call (R0, R1 : SH_Word) return SH_Word is
      Ret : SH_Word;
   begin
      Asm ("mov r0, %1" & ASCII.LF & ASCII.HT &
           "mov r1, %2" & ASCII.LF & ASCII.HT &
           "bkpt #0xAB" & ASCII.LF & ASCII.HT &
           "mov %0, r0",
           Outputs  => (SH_Word'Asm_Output ("=r", Ret)),
           Inputs   => (SH_Word'Asm_Input ("r", R0),
                        SH_Word'Asm_Input ("r", R1)),
           Volatile => True,
           Clobber => ("r1, r0"));
      return Ret;
   end Generic_SH_Call;

   -----------
   -- Flush --
   -----------

   procedure Flush is
      Unref : SH_Word;
      pragma Unreferenced (Unref);
   begin
      if Buffer_Index /= Buffer'First then
         --  Set null-termination
         Buffer (Buffer_Index) := 0;

         --  Send the buffer with a semihosting call
         Unref := Generic_SH_Call (SYS_WRITE0, To_SH_Word (Buffer'Address));

         --  Reset buffer index
         Buffer_Index := Buffer'First;
      end if;
   end Flush;

   ---------
   -- Put --
   ---------

   procedure Put (Item : Character) is
      Unref : SH_Word;
      pragma Unreferenced (Unref);

      C : Character with Volatile;
      --  Use a volatile variable to avoid compiler's optimization

   begin
      if Item = ASCII.NUL then
         --  The WRITE0 semihosting call that we use to send the output buffer
         --  expects a null terminated C string. Therefore it is not possible
         --  to have an ASCII.NUL character in the middle of the buffer as this
         --  would truncate the buffer.
         --
         --  For this reason the ASCII.NUL character is sent separately with a
         --  WRITEC semihosting call.

         --  Flush the current buffer
         Flush;

         --  Send the ASCII.NUL with a WRITEC semihosting call
         C := Item;
         Unref := Generic_SH_Call (SYS_WRITEC, To_SH_Word (C'Address));

      else

         Buffer (Buffer_Index) := Character'Pos (Item);
         Buffer_Index := Buffer_Index + 1;

         --  Flush the buffer when it is full or if the character is a line
         --  feed.
         if Buffer_Index = Buffer'Last or else Item = ASCII.LF then
            Flush;
         end if;
      end if;
   end Put;

   ---------
   -- Put --
   ---------

   procedure Put (Item : String) is
   begin
      for Index in Item'Range loop
         Put (Item (Index));
      end loop;
   end Put;

   ---------
   -- Get --
   ---------

   procedure Get (Item : out Character) is
      Ret : SH_Word;
   begin
      Ret := Generic_SH_Call (SYS_READC, 0);
      Item := Character'Val (Ret);
   end Get;

end System.Semihosting;

I know that just pasting the Ada implementation may not be helpful, but unfortunately I'm myself a rookie at both languages and embedded programming (although the code is quite natural to read). I just checked this lib implementation and it already uses a buffer, so I don't what might be the issue. The asm instructions seem also to be the similar although Ada does something more with the registers, but don't trust me.

write_all crashes if syscall fails

If syscall! fails and returns -1 inside write_all, it crashes because the write_all loop still tries to calculate the new buffer offset. Maybe syscall! should return isize (or c_int?). Gdb seems to report back -1 if a hostio call fails (just like libc does on the host).

For some reason all writes to stdout fail for me (syscall returning -1), while stderr works fine. (SAM3X, black magic probe 1.6, gdb 7.10.1, rustc nightly 2017-05-01)

open() must be called for stdin/stdout/stderr; FDs may not be 0/1/2

cortex-m-semihosting never initializes stdin, stdout, and stderr with open(). As such, it never hears from gdb that the file descriptors being used for those are not the traditional 0/1/2 (in my case, gdb is giving out 1/2/3), resulting in the wrong stream being used.

This works for me:

let _stdin = unsafe{ syscall!(OPEN, ":tt".as_bytes().as_ptr(), 0, 3) };
let _stdout = unsafe{ syscall!(OPEN, ":tt".as_bytes().as_ptr(), 4, 3) };
let _stderr = unsafe{ syscall!(OPEN, ":tt".as_bytes().as_ptr(), 8, 3) };

let buffer = "Hello, world!\n";
unsafe{ syscall!(WRITE, _stdout, buffer.as_ptr(), buffer.len()) };

We need something akin to newlib's initialise_monitor_handles to actually send the OPEN syscalls and record the file descriptors in use.

nucleof334 debugging problem

i am following rust tutorial https://rust-embedded.github.io/bookshelf/book/start/hardware.html to start with embedded programming.

my hardware is NUCLEOF334R8 with STM32F334R8T6
i am running into problem with debugging against openocd when running simple "Hello world".

gdb> target remote :3333

results into this error:

cortex_m_semihosting::hio::HStderr::write_all ( self=0x80002eb, buffer=...) at /home/soni/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-semihosting-0.3.1/src/hio.rs:48 48 open(":tt\0", nr::open::W_APPEND).map(|fd| HStderr { fd }

your help would be appreciated

thanks

print macros should not return a result

The hprint{ln} macros currently all return a Result to the caller. There are two reasons for why this is not ideal:

  • It doesn't match the print{ln} macros in libstd, which return nothing (()).
  • It sets the wrong expectation that semihosting failures are reliably reported via Err. This is not the case as semihosting calls will just crash the application when no debugger is attached (it would be great to fix that regardless).

Documentation improvements

Hello,

While going trough tutorial I’ve encountered the following problems:

  • cargo generate is used, but installation step for it is missing;
  • in order to run example on nucleo-f303k8 you need to change values in memory.x to correct ones or else your debug session will always end in PanicHandler.

The second one is quite hostile for beginners.

JLink debuggers

I have run into the issue that #35 was meant to fix.

Environment:

Example: https://github.com/nickray/lpc55s6x-hal/blob/master/examples/semihosting.rs

(gdb) c
Continuing.
uuid = [panicked at '
Program received signal SIGTRAP, Trace/breakpoint trap.
0x000024ae in __bkpt ()

For now, the fix in that pull request fixed it:

(gdb) c
Continuing.
uuid = [c8ded018, 55025d23, 906643bc, 3e3c4a61]

Using openocd is not an option, as it currently has no support for the chip AFAIK.

stm32l475 semihosting doesn't work

Hi everyone,

I am following this tutotial: https://rust-embedded.github.io/book/start/hardware.html
but for stm32l475.

First of all, I changed the memory.x for stm32l475:

/* Linker script for the STM32L475VG*/
MEMORY
{
  /* NOTE 1 K = 1 KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x08000000, LENGTH = 1000K /*1MBYTE*/
  RAM : ORIGIN = 0x20000000, LENGTH = 128K /*128KBYTE*/
}

The source code of the program which I want to run on stm32 chip is:
hello.rs

use cortex_m_rt::entry;
use cortex_m_semihosting::{hprintln};


#[entry]
fn main() -> ! {
    
    hprintln!("Hello, world!").unwrap();
    loop {}
}

Then, I run these commands:
For compilation:
cargo run --example hello
For openocd:
openocd -f interface/stlink-v2-1.cfg -f target/stm32l4x.cfg

In another terminal, I run the gdb program and commands for flush etc.:

$ gdb-multiarch -q target/thumbv7em-none-eabi/debug/examples/hello
$ (gdb) target remote :3333
$ (gdb) load
$ (gdb) monitor arm semihosting enable
$ semihosting is enabled
$ (gdb) continue
Continuing.

^ the program stucks at this point.

Afterwards, I terminated the program, and Ι reopened a new gdb process.
Ι gave the same commands until the command "monitor arm semihosting enable".
At this point, I set breakpoint to the main function.

$ break main
$ jump main
Line 33 is not in `HardFault_'.  Jump anyway? (y or n) y
Continuing at 0x8000708.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 1, main () at examples/hello.rs:33
$ continue
$Continuing...

Again, the program stucks at this point.
I pressed Ctrl-C and it printed out the command that the program execution is blocked:

0x080008f0 in cortex_m_semihosting::hio::hstdout () at /home/tasosxak/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-semihosting-0.3.2/src/hio.rs:53
53	    open(":tt\0", nr::open::W_TRUNC).map(|fd| HStdout { fd })

OS : Ubuntu 18.04.1 LTS
rustc version : rustc 1.34.0-nightly (146aa60f3 2019-02-18)

cargo .config file:

[target.thumbv7em-none-eabi]
//noth
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
//noth
rustflags = ["-C", "link-arg=-Tlink.x"]
[build]
target = "thumbv7em-none-eabi"

Semihosting broken with rust-lld

After changing my project to use lld, the semi hosting calls don't go through it hangs on the __syscall(_nr, _arg) in lib.rs:150. I switched back to gcc to confirm they still work.

Flags for rust-lld

rustflags = ["-C", "link-arg=-Tlink.x"]

Flags for GCC

rustflags = [
  "-C", "link-arg=-Tlink.x",
  "-C", "linker=arm-none-eabi-ld",
  "-Z", "linker-flavor=ld",
  "-Z", "thinlto=no",
]

Edit:

I should mention I am only using panic-semihosting, I haven't tested normal semihosting yet.

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.