Comments (18)
mcmodel=medium support landed in nightly! rust-lang/rust#62281
from riscv-rt.
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.
Probably you could link it with riscv64-unknown-elf-ld
see my cargo config: https://github.com/Dantistnfs/riscv_k210
from riscv-rt.
@Dantistnfs it may work for you because you don't use riscv-rt
and any static constants like strings and arrays.
from riscv-rt.
@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.
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.
I figured out that on K210 it's possible to run code from address
0x40000000
instead of0x80000000
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.
@medusacle Is this behavior reproducible in plain C and official SDK?
from riscv-rt.
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.
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.
Updated relevant crates to reflect these changes.
from riscv-rt.
@medusacle Thanks again! This hack with 0xffffffff80000000
address is really great!
from riscv-rt.
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.
@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.
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.
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.
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, sopc
is 39 bits wide
from riscv-rt.
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)
- Doesn't compile with the latest nightly toolchain. HOT 4
- Using this as a library? HOT 4
- Linker relocation issue (QEMU / OpenSBI) HOT 1
- Can you have two versions of riscv-rt in the build tree at the same time? HOT 1
- Implement multi-core support
- Implement FPU initialization HOT 10
- Bizarre warning behavior around #[entry] macro and `&mut FnMut`
- LiteX/VexRiscv support HOT 4
- Execution start address varies. HOT 3
- Update r0 to 1.0 HOT 1
- Relocation R_RISCV_ALIGN linker error
- ELF output contains lots of zero data: linker script issue? HOT 4
- RAM init code violates pointer provenance and aliasing rules HOT 1
- Migration to GitHub Actions HOT 1
- sp may not be aligned to 16 bytes
- Lots of rust-lld errors HOT 3
- Pre initialization trap handling HOT 2
- Prune unused symbols
- New crates.io release HOT 4
- Accessing parameters passed in register by the previous boot stage HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from riscv-rt.