Giter VIP home page Giter VIP logo

Comments (18)

Disasm avatar Disasm commented on July 24, 2024 6

mcmodel=medium support landed in nightly! rust-lang/rust#62281

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

Unfortunately, addresses >=0x80000000 are not supported at the moment. Some details here: rust-embedded/wg#218 (comment)
I saw some patches in LLVM upstream, but haven't tested them yet.

Nice to see someone putting effort in Kendryte! At the moment I'm working on similar task: support for HiFive Unleashed board, which is also RV64GC.

from riscv-rt.

Dantistnfs avatar Dantistnfs commented on July 24, 2024

Probably you could link it with riscv64-unknown-elf-ld
see my cargo config: https://github.com/Dantistnfs/riscv_k210

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

@Dantistnfs it may work for you because you don't use riscv-rt and any static constants like strings and arrays.

from riscv-rt.

Dantistnfs avatar Dantistnfs commented on July 24, 2024

@Disasm
I think that's better than nothing, at least you can do small experiments, before patches arrive
And yes, when I tried to use arrays/strings I got "Relocation truncated to fit: R_RISCV_HI20"

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

I figured out that on K210 it's possible to run code from address 0x40000000 instead of 0x80000000. In the future, RAM-only linking will be possible with region aliases.

I've started working on k210-pac. At the moment, the only peripherals supported are GPIOHS and UARTHS, as they are pretty the same as in HiFive1. I'm planning to recover peripheral information from the SDK source code. If someone wants to help me - PRs welcome :)

from riscv-rt.

vmedea avatar vmedea commented on July 24, 2024

I figured out that on K210 it's possible to run code from address 0x40000000 instead of 0x80000000

we found out that flw and fld from the 0x4xxxxxxxx range always return 0 ! this sabotages pretty much all floating point computation—surprisingly though, it looks like 0x80000000 is aliased at 0xffffffff80000000 so this memory.x works:

MEMORY
{
    SRAM : ORIGIN = 0xffffffff80000000, LENGTH = 6M
    AI_SRAM : ORIGIN = 0xffffffff80600000, LENGTH = 2M
    SRAM_NOCACHE : ORIGIN = 0x40000000, LENGTH = 6M
    AI_SRAM_NOCACHE : ORIGIN = 0x40600000, LENGTH = 2M
}

REGION_ALIAS("REGION_TEXT", SRAM);
REGION_ALIAS("REGION_RODATA", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

@medusacle Is this behavior reproducible in plain C and official SDK?

from riscv-rt.

vmedea avatar vmedea commented on July 24, 2024

yes, it seems so, the following main.c, compiled in the SDK context:

#include <stdio.h>
#include "sysctl.h"
#include "uarths.h"
#include "sleep.h"

static float fp_const_a = 1.2345f;

int main(void)
{
    if (current_coreid() == 0)
    {
        uarths_init();
        usleep(100000);
        float *ptr_a = &fp_const_a;
        printf("%f at %p\r\n", *ptr_a, ptr_a);
        float *alt_a = (float*)(((uintptr_t)&fp_const_a) - 0x40000000);
        printf("%f at %p\r\n", *alt_a, alt_a);
    }
    while (1)
        asm volatile ("wfi");
    return 0;
}

(loading the resulting binary at 0x40000000 to skip the cache and assure it's not simply a cache coherency issue)
prints:

1.234500 at 0x8000e628
0.000000 at 0x4000e628

(for doubles I was not able to reproduce it here because the SDK is compiled with -march=rv64imafc so they go through the soft path, which like integers and character constants works fine)

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

Thanks for investigating the issue! It's a serious argument against using 0x40000000 base address. If 0xffffffff80000000 base works fine, let's use it as a workaround.

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

Updated relevant crates to reflect these changes.

from riscv-rt.

Disasm avatar Disasm commented on July 24, 2024

@medusacle Thanks again! This hack with 0xffffffff80000000 address is really great!

from riscv-rt.

WRansohoff avatar WRansohoff commented on July 24, 2024

Using 0xffffffff80000000 for the RAM addresses also seems to work for me, but I think it might cause some issues debugging with GDB and OpenOCD. When the program is actually executed in GDB, the leading ffffffff address bytes are often fully or partially dropped, which prevents GDB from finding the debugging symbols.

For example:

$ riscv64-unknown-elf-nm target/riscv64gc-unknown-none-elf/debug/test | grep main
ffffffff800000f8 T main

Loading the program onto the chip with kflash works fine, but when I open and step through it in GDB, the program usually hits main at either 0x000000ff800000f8 or 0x00000000800000f8. It looks like the program is running and stepping correctly; if I put an infinite loop{}; statement at the beginning of main, the program goes on to stop at ...800000fa. But GDB cannot associate the memory addresses with main because they do not match the records in the ELF file.

Anyone else run into that sort of issue?

from riscv-rt.

vmedea avatar vmedea commented on July 24, 2024

@medusacle Thanks again! This hack with 0xffffffff80000000 address is really great!

happy to hear that !

Using 0xffffffff80000000 for the RAM addresses also seems to work for me, but I think it might cause some issues debugging with GDB and OpenOCD

that's interesting
I cannot check now, but are you sure your code is really executing from 0xffffffff80000000 and not 0x80000000? you wouldn't notice this at all when not using a debugger
it doesn't look like it; the ROM will invoke the code at 0x80000000 and the whole path to main() uses relative addresses

ffffffff80000000 <_start>:
...
ffffffff8000004c:       0060006f                j       ffffffff80000052 <_start_rust>

ffffffff80000052 <_start_rust>:
ffffffff80000052:       1141                    addi    sp,sp,-16
ffffffff80000054:       e406                    sd      ra,8(sp)
ffffffff80000056:       00005097                auipc   ra,0x5
...
ffffffff800000a4:       00001097                auipc   ra,0x1
ffffffff800000a8:       700080e7                jalr    1792(ra) # ffffffff800017a4 <main>

a small change to the startup code could make sure it jumps to the high address…

another less likely cause could be if the upper 32 bits of the pc are hardwired to 0 on the chip so it tells your debugger it's always executing at the low address

from riscv-rt.

WRansohoff avatar WRansohoff commented on July 24, 2024

Yeah, it does seem like the code is probably running at the 'real' addresses from 0x80000000 on. It would probably be possible to patch the ELF file to remove the 0xFFFFFFFF from the start of each address, but I don't know how to do that properly.

Anyways, it might not be worth digging into too much, because the toolchain should eventually obviate this workaround: rust-lang/rust#59802

from riscv-rt.

vmedea avatar vmedea commented on July 24, 2024

that way around might work as well, got as far as:

riscv64-unknown-elf-objcopy --change-section-address=*-0xffffffff00000000

which moves the ELF sections but doesn't move the DWARF data, which seems to have internal pointers, so isn't useful in your case

from riscv-rt.

vmedea avatar vmedea commented on July 24, 2024

another less likely cause could be if the upper 32 bits of the pc are hardwired to 0 on the chip so it tells your debugger it's always executing at the low address

i checked and this definitely isn't the case,

#![feature(asm)]
#![no_std]
#![no_main]

use core::panic::PanicInfo;
use k210_hal::pac;
use k210_hal::prelude::*;
use k210_hal::stdout::Stdout;
use riscv_rt::entry;

#[panic_handler]
fn panic(info: &PanicInfo) -> ! { loop {} }

extern "C" fn get_pc() -> usize {
    let c: usize;
    unsafe { asm!("auipc $0,0" : "=r"(c) ::: "volatile"); }
    c
}

#[entry]
fn main() -> ! {
    let p = pac::Peripherals::take().unwrap();
    let clocks = k210_hal::clock::Clocks::new();
    let serial = p.UARTHS.constrain(115_200.bps(), &clocks);
    let (mut tx, _) = serial.split();
    let mut stdout = Stdout(&mut tx);
    unsafe {
        writeln!(stdout, "initial pc is 0x{:016x}", get_pc()).unwrap();
        let mut addr = get_pc as usize;
        writeln!(stdout, "function addr is 0x{:016x}", addr).unwrap();
        loop {
            let func: extern "C" fn() -> usize = core::mem::transmute(addr as *const ());
            let pc = func();
            writeln!(stdout, "call 0x{:016x} → pc 0x{:016x}", addr, pc).unwrap();
            addr = addr.wrapping_add(1<<32);
        }
    }
}

gives:

[click for raw output]
initial pc is 0x00000000800003e2
function addr is 0xffffffff8000034c

call 0xffffffff8000034c → pc 0xffffffff8000034c
call 0x000000008000034c → pc 0x000000008000034c
call 0x000000018000034c → pc 0x000000018000034c
call 0x000000028000034c → pc 0x000000028000034c
…
call 0x0000003d8000034c → pc 0x0000003d8000034c
call 0x0000003e8000034c → pc 0x0000003e8000034c
call 0x0000003f8000034c → pc 0x0000003f8000034c
call 0x000000408000034c → pc 0xffffffc08000034c
call 0x000000418000034c → pc 0xffffffc18000034c
call 0x000000428000034c → pc 0xffffffc28000034c
…
call 0x0000007d8000034c → pc 0xfffffffd8000034c
call 0x0000007e8000034c → pc 0xfffffffe8000034c
call 0x0000007f8000034c → pc 0xffffffff8000034c
call 0x000000808000034c → pc 0x000000008000034c
…
  • initially, the code runs at the low address 0x000000008xxxxxxx
  • after jumping to a high address, pc returns the high address (so doing this once before your code runs will likely solve the debugger issue)
  • it looks like bit 38 (0x0000004000000000) is sign-extended, after that it wraps around, so pc is 39 bits wide

from riscv-rt.

WRansohoff avatar WRansohoff commented on July 24, 2024

Interesting, thanks for the information and taking the time to investigate. That's a neat objcopy trick.

I tried building your example and I see the same thing; it runs from 0x000000008xxxxxxx up to 0x0000003f8xxxxxxx, then from 0xffffffc08xxxxxxx through 0xffffffff8xxxxxxx.

I still haven't gotten GDB to recognize the symbols, but I think there's enough information here to figure it out. Thanks for the example and explanations.

from riscv-rt.

Related Issues (20)

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.