Closed roman3017 closed 8 years ago
Hi :D So basicaly, there is a bug in GDB to show C variables, basicaly, the GCC compile access relative the the frame pointer, but GDB debug access relatively to the stack pointer. To workaround that issue, i have trick the GDB server to return the frame pointer value when you ask the stack pointer value XD If you want i can add a flag to disable this workaround :) ?
Thanks for the prompt reply. I do not mind the workaround as long as I understand how it works. Is there a way to get SP register value? The failure I experience is in ctors_loop at least based on registers.
This is listing with what seems as a failure:
00000148 <_start>:
148: 0ff00513 li a0,255
14c: 0405200b custom0 0,a0,0,2
150: 00001117 auipc sp,0x1
154: 86810113 addi sp,sp,-1944 # 9b8 <_stack_start>
00000158 <bss_init>:
158: 40000517 auipc a0,0x40000
15c: 6e050513 addi a0,a0,1760 # 40000838 <_copy_section>
160: 40000597 auipc a1,0x40000
164: 6e058593 addi a1,a1,1760 # 40000840 <_bss_end>
00000168 <bss_loop>:
168: 00b50863 beq a0,a1,178 <bss_done>
16c: 00052023 sw zero,0(a0)
170: 00450513 addi a0,a0,4
174: ff5ff06f j 168 <bss_loop>
00000178 <bss_done>:
178: 40000517 auipc a0,0x40000
17c: 6bc50513 addi a0,a0,1724 # 40000834 <_etext>
180: ffc10113 addi sp,sp,-4
00000184 <ctors_loop>:
184: 40000597 auipc a1,0x40000
188: 6b458593 addi a1,a1,1716 # 40000838 <_copy_section>
18c: 00b50e63 beq a0,a1,1a8 <ctors_done>
190: 00052683 lw a3,0(a0)
194: 00450513 addi a0,a0,4
198: 00a12023 sw a0,0(sp)
19c: 000680e7 jalr a3
1a0: 00012503 lw a0,0(sp)
1a4: fe1ff06f j 184 <ctors_loop>
000001a8 <ctors_done>:
1a8: 00410113 addi sp,sp,4
1ac: 40000317 auipc t1,0x40000
1b0: e84300e7 jalr t1,-380 # 40000030 <main>
000001b4 <infinitLoop>:
1b4: 0000006f j 1b4 <infinitLoop>
(gdb) load
Loading section .yolo, size 0x1b8 lma 0x0
Loading section .text, size 0x834 lma 0x40000000
Loading section .ctors, size 0x4 lma 0x40000834
Start address 0x148, load size 2544
Transfer rate: 54 KB/sec, 848 bytes/write.
(gdb) stepi
0x0000014c in _start ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x000000ff 255
a1 0x00000000 0
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x0000014c 332
(gdb) stepi
0x00000150 in _start ()
(gdb) stepi
0x00000154 in _start ()
(gdb) stepi
0x00000158 in bss_init ()
(gdb) stepi
0x0000015c in bss_init ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000158 1073742168
a1 0x00000000 0
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x0000015c 348
(gdb) stepi
0x00000160 in bss_init ()
(gdb) stepi
0x00000164 in bss_init ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000838 1073743928
a1 0x40000160 1073742176
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x00000164 356
(gdb) stepi
0x00000168 in bss_loop ()
(gdb) stepi
0x0000016c in bss_loop ()
(gdb) stepi
0x00000170 in bss_loop ()
(gdb) stepi
0x00000174 in bss_loop ()
(gdb) stepi
0x00000168 in bss_loop ()
(gdb) stepi
0x0000016c in bss_loop ()
(gdb) stepi
0x00000170 in bss_loop ()
(gdb) stepi
0x00000174 in bss_loop ()
(gdb) stepi
0x00000168 in bss_loop ()
(gdb) stepi
0x00000178 in ctors_init ()
(gdb) stepi
0x0000017c in ctors_init ()
(gdb) stepi
0x00000180 in ctors_init ()
(gdb) stepi
0x00000184 in ctors_loop ()
(gdb) stepi
0x00000188 in ctors_loop ()
(gdb) stepi
0x0000018c in ctors_loop ()
(gdb) stepi
0x00000190 in ctors_loop ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000834 1073743924
a1 0x40000838 1073743928
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x00000190 400
(gdb) stepi
0x00000194 in ctors_loop ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000834 1073743924
a1 0x40000838 1073743928
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x00000194 404
(gdb) stepi
0x00000198 in ctors_loop ()
(gdb) stepi
0x0000019c in ctors_loop ()
(gdb) info reg
ra 0x00000000 0
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000838 1073743928
a1 0x40000838 1073743928
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x0000019c 412
(gdb) stepi
0x00000000 in ?? ()
(gdb) info reg
ra 0x000001a0 416
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x40000838 1073743928
a1 0x40000838 1073743928
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x00000000 0
This time PC value is 0. I expected a3 to change at step 190.
Hoo, maybe it is an SDRAM issue (that make everything going wrong) Did you adapt timings for your FPGA kit ? At which frequency are you running your system ? What you can try is to change the linker script to put every thing on the internal ram. (you can also recompile the Pinsec with an bigger internal ram)
Also, i recently add a test that use timer to make leds blink (cDemo) and that do an uart echo (with interrupt aswell) I think it's a better starting point than the "uart test". Also it's better to have the head of the SpinalHDL repository to generate the RTL, i just patched an issue that make debuging not working when you mix breakpoint + interrupt.
Let's me know how are going things :D Ii use an DE1-SoC kit to do all my tests, as far i know every thing is working (Interrupt, debug, breakpoint, mandelbrot, bubble demo, uart, timer, sdram, onechip memory)
So, i susspect an SDRAM issue, because the first usage of it come in the ctors_loop loop :) How did you manage the external SDRAM clock phase ? On my kit it's -2.5 ns for example.
What you can do to check it (a little bit), is to use GDB to write/read value from SDRAM, and check every thing is fine. You can also check that the embedded RAM is fine,
I am trying cDemo now and it is behaving better and I can step through main() in SDRAM. I have also updated and recompiled gdb. I do not see uart print outs yet but that can be Pinsec/SDRAM issue as you have pointed out. I will try to to regenerate Pinsec and read/write SDRAM from gdb. I run at 100MHz and have not modified SDRAM timing yet. I am using Scarab's miniSpartan6+ board. Thank you very much for your help.
(gdb) step
Single stepping until exit from function _start,
which has no line number information.
0x00000158 in bss_init ()
(gdb) step
Single stepping until exit from function bss_init,
which has no line number information.
0x00000168 in bss_loop ()
(gdb) step
Single stepping until exit from function bss_loop,
which has no line number information.
0x00000178 in ctors_init ()
(gdb) step
Single stepping until exit from function ctors_init,
which has no line number information.
0x00000184 in ctors_loop ()
(gdb) step
Single stepping until exit from function ctors_loop,
which has no line number information.
0x000001a8 in ctors_done ()
(gdb) step
Single stepping until exit from function ctors_done,
which has no line number information.
main () at src/main.c:60
60 int main() {
(gdb) step
Breakpoint 1, main () at src/main.c:61
61 initUart();
(gdb) step
62 initTimer();
(gdb) step
63 initGpio();
...
Great :) So, for me that stuff also work with eclipse + zylin embedded debug plugin.
Initialize command : target remote localhost:3333 monitor reset halt load
Run command : continue
Let's me know how are going things :)
Unfortunately I have a problem to generate Pinsec after updating git repo:
$ sbt "project SpinalHDL-lib" "run-main spinal.lib.soc.pinsec.Pinsec"
[info] Loading project definition from ~/projects/SpinalHDL/project
[info] Set current project to SpinalHDL all (in build file:~/projects/SpinalHDL/)
[info] Set current project to SpinalHDL Lib (in build file:~/projects/SpinalHDL/)
[warn] Scala version was updated by one of library dependencies:
[warn] * org.scala-lang:scala-library:2.11.6 -> 2.11.7
[warn] To force scalaVersion, add the following:
[warn] ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }
[warn] Run 'evicted' to see detailed eviction warnings
[warn] Scala version was updated by one of library dependencies:
[warn] * org.scala-lang:scala-library:2.11.6 -> 2.11.7
[warn] To force scalaVersion, add the following:
[warn] ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }
[warn] Run 'evicted' to see detailed eviction warnings
[info] Compiling 16 Scala sources to ~/projects/SpinalHDL/core/target/scala-2.11/classes...
[error] missing or invalid dependency detected while loading class file 'BaseTypeFactory.class'.
[error] Could not access type BoolFactory in package spinal.core,
[error] because it (or its dependencies) are missing. Check your build definition for
[error] missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.)
[error] A full rebuild may help if 'BaseTypeFactory.class' was compiled against an incompatible version of spinal.core.
...
It look like it's an scala setup/cache problem, i just tryed your command with a clean clone of the SpinalHDL repo, and everything is going fine. Maybe you need to do a "sbt clean".
The command 'sbt clean' had some java errors but deleting folder and checking it out again has fixed the issue. Thanks.
After recompiling Pinsec, gdb is much better behaved. PC does not go off to completely strange addresses as in the beginning. I still do not have uart or blink. This can be an issue with my FPGA configuration so I will close this. Thank you very much for your help.
(gdb) monitor reset halt
JTAG tap: fpga_spinal.bridge tap/device found: 0x10001fff (mfg: 0x7ff (<invalid>), part: 0x0001, ver: 0x1)
fpga_spinal.cpu0: target state: halted
(gdb) load
Loading section .yolo, size 0x1b8 lma 0x0
Loading section .text, size 0xc4b8 lma 0x40000000
Loading section .data, size 0x8c0 lma 0x4000c4b8
Start address 0x148, load size 53040
Transfer rate: 45 KB/sec, 3536 bytes/write.
(gdb) step
Single stepping until exit from function _start,
which has no line number information.
0x00000158 in bss_init ()
(gdb) step
Single stepping until exit from function bss_init,
which has no line number information.
0x00000168 in bss_loop ()
(gdb) step
Single stepping until exit from function bss_loop,
which has no line number information.
0x00000178 in ctors_init ()
(gdb) step
Single stepping until exit from function ctors_init,
which has no line number information.
0x00000184 in ctors_loop ()
(gdb) step
Single stepping until exit from function ctors_loop,
which has no line number information.
0x000001a8 in ctors_done ()
(gdb) step
Single stepping until exit from function ctors_done,
which has no line number information.
main () at src/main.c:60
60 int main() {
(gdb) info reg
ra 0x000001b4 436
sp 0x00000000 0
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x400001ac 1073742252
t2 0x00000000 0
fp 0x00000000 0
s1 0x00000000 0
a0 0x4000c4b8 1073792184
a1 0x4000c4b8 1073792184
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000000 0
a5 0x00000000 0
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x40000130 1073742128
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x43fffff8 in ?? ()
Ok :D So basicaly, the boot assembly is loaded into the FPGA memory, but as soon it go in the main function, it load instruction from the sdram.
To simplify debugging I am not using SDRAM for now:
$ git diff
diff --git a/resources/linker.ld b/resources/linker.ld
index 9e40908..f861057 100755
--- a/resources/linker.ld
+++ b/resources/linker.ld
@@ -18,8 +18,14 @@ OUTPUT_ARCH( "riscv" )
/*----------------------------------------------------------------------*/
MEMORY {
- onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x00000000, LENGTH = 96K
+/*
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 96K
sdram (W!RX) : ORIGIN = 0x40000000, LENGTH = 64M
+*/
+
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 32K
+ sdram (W!RX) : ORIGIN = 0x00008000, LENGTH = 64K
+
}
_stack_size = 2k;
_heap_size = 8k;
But there is still something wrong with the code when I step through it. Do you use the latest toolchain? The latest one does not work for me so I use:
git clone https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
git checkout 7e48594
git submodule update --init --recursive
mkdir buildi; cd buildi
../configure --with-arch=RV32I --prefix=/opt/riscv32i
make -j$(nproc)
cd -
mkdir buildim; cd buildim
../configure --with-arch=RV32IM --prefix=/opt/riscv32im
make -j$(nproc)
So, about the RISCV toolchain, i had a lot of issues with it, I finaly find one version that work well for me XD
If you want can send you compiled tools.
Also, do you update that line in the pinsec.scala ? : ram.io.axi -> (0x00000000L, 32 kB),
and that lines ? : val ram = Axi4SharedOnChipRam( dataWidth = 32, byteCount = 32 kB, idWidth = 4 )
sorry 96 KB in place of 32 of course
Just to know, what happen if you just run the program, without breakpoint, without step by step ? Does it work ? (GPIO A should count up slowly, some uart message 115200, 1 stop bit, no parity should come aswell)
If I just run it there is no uart or blink. That is why I am stepping through it. Thanks for pointing out the memory, I thought 96k is default and now I see 4k is default. No wonder I am getting weird results. I am updating it now. Do you know what is hash of your toolchain? I am using 7e48594, which is toolchain used by picorv32.
I'm sorry, i realy don't know what was the hash used for my toolchain, i compiled it a long time ago, and the toolchain repository isn't with the right hash. But probably it's the same than the picorv32.
But maybe, with the 96k fix, everything will be fine :D Anyway tools where uploaded there (400 MB) : https://drive.google.com/open?id=0B-CqLXDTaMbKYnEwTzNFanVCNk0
Thank you very much, I am downloading your toolchain. I have some problems with routing/placing with 96k RAM since I have a small Spartan6 chip but now I know the problem and will play with it till it works. You are very helpful. Thanks again.
No problems :) If you want to fit all the binary + stack + heap in smaller onchip ram => you can comment out all printf and as mutch #include "stdxxx.h" as you can, they consume a lot of binary space.
Good luck ^^
Just a quick update in case someone tries the same; I have got LEDs working, UART is still not working. Managed to fit everything to 36k RAM, which fits to Spartan 6 LX9 FPGA:
$ git diff
diff --git a/resources/linker.ld b/resources/linker.ld
index 9e40908..e9d00f0 100755
--- a/resources/linker.ld
+++ b/resources/linker.ld
@@ -18,8 +18,14 @@ OUTPUT_ARCH( "riscv" )
/*----------------------------------------------------------------------*/
MEMORY {
- onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x00000000, LENGTH = 96K
+/*
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 36K
sdram (W!RX) : ORIGIN = 0x40000000, LENGTH = 64M
+*/
+
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 4K
+ sdram (W!RX) : ORIGIN = 0x00001000, LENGTH = 32K
+
}
_stack_size = 2k;
_heap_size = 8k;
diff --git a/tests/cDemo/src/main.c b/tests/cDemo/src/main.c
index 6d3b618..bacfeba 100755
--- a/tests/cDemo/src/main.c
+++ b/tests/cDemo/src/main.c
@@ -1,7 +1,7 @@
#include <stdio.h>
-#include <string.h>
+//#include <string.h>
#include <stdint.h>
-#include <stdlib.h>
+//#include <stdlib.h>
#define CORE_HZ 100000000
@@ -49,7 +49,7 @@ void initTimer(){
void initGpio(){
//Set leds to zero
- GPIO_A_BASE[0] = 0;
+ GPIO_A_BASE[0] = 0x81;
}
void setInterruptMask(uint32_t mask){
@@ -66,7 +66,8 @@ int main() {
printf("Hello world\n");
printf("a\n");
printf("b\n");
-
+ printf("c\n");
+#if 0
while(1){
uint64_t sum = 0;
for(uint32_t idx = 0;idx < 10000000;idx++){
@@ -74,7 +75,7 @@ int main() {
}
printf("Sum from 0 to 10000000 = %x%x ref = 2d7987f0d4c0\n",(uint32_t)(sum >> 32),(uint32_t)(sum));
}
-
+#endif
}
@@ -103,7 +104,7 @@ void irqC(uint32_t irq){
//Implement stdio functions to redirect the printf to the uart.
int close(int fd) {return 0;}
-int fstat(int fd, struct _stat *buffer) {return 0;}
+int fstat(int fd, void *buffer) {return 0;}
int isatty(int fd) {return 0;}
long lseek(int fd, long offset, int origin) {return 0;}
int read(int fd, void *buffer, unsigned int count) {return 0;}
Now it is clear that there is something wrong with my SDRAM and UART.
I have a question about UART code, since when I step into the printf code it does not step to the write method. On the other hand, when I define puts method instead, printf would step to it but it gets stuck:
+int puts(const char *buffer)
+{
+ int idx;
+ for (idx = 0; buffer[idx] != 0; idx++) {
+ while((UART_BASE[1] & 0x00FF0000) == 0);
+ UART_BASE[0] = buffer[idx];
+ }
+ return idx;
+}
+#if 0
//Implement stdio functions to redirect the printf to the uart.
int close(int fd) {return 0;}
int fstat(int fd, struct _stat *buffer) {return 0;}
int isatty(int fd) {return 0;}
long lseek(int fd, long offset, int origin) {return 0;}
int read(int fd, void *buffer, unsigned int count) {return 0;}
int write(int fd, const void *buffer, unsigned int count) {
for (int idx = 0; idx < count; idx++) {
while(((UART_BASE[1] >> 16) & 0xFF) == 0);
UART_BASE[0] = ((char*) buffer)[idx];
}
return count;
}
+#endif
Have you seen this problem before?
Hi,
So on your experiments, the execution is stuck on : while(((UART_BASE[1] >> 16) & 0xFF) == 0); ? I never had this issue. What is the value of UART_BASE[0](watch expression) ?
About printf, i had the issue that it won't transmit until a \n come, i lose some time on that XD
How fast is going your FPGA clock ? (update #define CORE_HZ 100000000)
UART_BASE[1] is 0x00100002 and it is freezing elsewhere and I have some problems to debug it. I do not step and just use continue, get frozen, press Ctr-C and get stack at random points sometimes inside irqC and cannot step or continue anymore and have to reload. When frozen it looks like this:
(gdb) disas
Dump of assembler code for function main:
0x00001134 <+0>: addi sp,sp,-16
0x00001138 <+4>: sw ra,12(sp)
0x0000113c <+8>: sw s0,8(sp)
0x00001140 <+12>: addi s0,sp,16
0x00001144 <+16>: jal 0x1000 <initUart>
0x00001148 <+20>: jal 0x10e8 <initGpio>
0x0000114c <+24>: lui a5,0x1
0x00001150 <+28>: addi a0,a5,752 # 0x12f0
0x00001154 <+32>: jal 0x1298 <puts>
=> 0x00001158 <+36>: lui a5,0x1
0x0000115c <+40>: addi a0,a5,764 # 0x12fc
0x00001160 <+44>: jal 0x1298 <puts>
0x00001164 <+48>: lui a5,0x1
0x00001168 <+52>: addi a0,a5,768 # 0x1300
0x0000116c <+56>: jal 0x1298 <puts>
0x00001170 <+60>: lui a5,0x1
0x00001174 <+64>: addi a0,a5,772 # 0x1304
0x00001178 <+68>: jal 0x1298 <puts>
0x0000117c <+72>: j 0x117c <main+72>
End of assembler dump.
(gdb) info reg
ra 0x00001158 4440
sp 0x000009a4 2468
gp 0x00000000 0
tp 0x00000000 0
t0 0x00000000 0
t1 0x00000000 0
t2 0x00000000 0
fp 0x000009a4 2468
s1 0x00000000 0
a0 0x000012f0 4848
a1 0x00001404 5124
a2 0x00000000 0
a3 0x00000000 0
a4 0x00000007 7
a5 0x00000013 19
a6 0x00000000 0
a7 0x00000000 0
s2 0x00000000 0
s3 0x00000000 0
s4 0x00000000 0
s5 0x00000000 0
s6 0x00000000 0
s7 0x00000000 0
s8 0x00000000 0
s9 0x00000000 0
s10 0x00000000 0
s11 0x00000000 0
t3 0x00000000 0
t4 0x00000000 0
t5 0x00000000 0
t6 0x00000000 0
pc 0x00001158 4440
(gdb) x/10x 0xf0010000
0xf0010000: 0x00000000 0x00100002 0x00000000 0x00000000
0xf0010010: 0x00000000 0x00100002 0x00000000 0x00000000
0xf0010020: 0x00000000 0x00100002
Oddly enough, if I comment out initTimer and setInterruptMask and slowly step through the code, UART prints out "Hello world". If I just continue, execution gets stuck and nothing prints out.
The FPGA clock I pass to Pinsec is 100MHz. Do you pass an external timer to Pinsec? I do not:
io_timerExternal_clear => '0',
io_timerExternal_tick => '0',
UART_BASE[1] = 0x00100002 is correct.
So i just tried to do breakpoints, step by step, assembly step by step from eclipse zylin CDT, and that work correctly on my kit.
I'm not an expert of debuging C application directly from GDB, could you send me all command lines that i need to use to go in the same situation than you ?
I don't use external timer. As you do it's fine. Do you checked the synthesis repport ? maybe 100 Mhz is to fast for Spartan 6 and it produce some random bugs ?
Hoo and currently, what is working if you just run the program ? only leds ?
Just to be sure, the SpinalHDL head that you use is the one dated from the Oct 13, 2016 / ec6e9bee447546f1b25b74740371acf8427d7e22 ? I fix an issue related to debug + interrupt in that commit.
The only gdb commands I use are:
monitor reset halt
load
continue
Ctrl-C //interrupt execution
step //step over C line
stepi //step over assembly line
disassemble //show disassembler
p /x *buffer //print variable in hex
x/12x 0xf0010000 //display 12 memory locations starting at 0xf0010000 in hex
info reg //show registers
I am just about to decrease the clock in FPGA to 50MHz. Currently I can see UART prints when I manually step through the code without timers/interrupts and I can see an LED pattern set in initGpio.
The latest commit to SpinalHDL in my repo is:
commit ec6e9bee447546f1b25b74740371acf8427d7e22
Author: Dolu1990 <charles.papon.90@gmail.com>
Date: Thu Oct 13 17:58:20 2016 +0200
RISCV cpu, add IRQ inhibate flag. Used by debugExtension
Ok, that was it, after changing the clock speed to 50MHz I can see changing LED pattern caused by the timer interrupts and UART is working as well. To summarize, I had the following problems:
And this issue is still there:
Thanks again for your help.
:D :D Great :D No problems ^^
I'm happy to know that somebody else in the world has this Pinsec SoC working ^^ You probably are the first one XD
Here are my changes in order to fit it to 36k RAM I have defined in Pinsec for Spartan 6 LX9 FPGA:
$ git diff
diff --git a/resources/linker.ld b/resources/linker.ld
index 9e40908..e9d00f0 100755
--- a/resources/linker.ld
+++ b/resources/linker.ld
@@ -18,8 +18,14 @@ OUTPUT_ARCH( "riscv" )
/*----------------------------------------------------------------------*/
MEMORY {
- onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x00000000, LENGTH = 96K
+/*
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 36K
sdram (W!RX) : ORIGIN = 0x40000000, LENGTH = 64M
+*/
+
+ onChipRam (W!RX) : ORIGIN = 0x00000000, LENGTH = 4K
+ sdram (W!RX) : ORIGIN = 0x00001000, LENGTH = 32K
+
}
_stack_size = 2k;
_heap_size = 8k;
diff --git a/tests/cDemo/src/main.c b/tests/cDemo/src/main.c
index 6d3b618..4d44bdf 100755
--- a/tests/cDemo/src/main.c
+++ b/tests/cDemo/src/main.c
@@ -3,7 +3,7 @@
#include <stdint.h>
#include <stdlib.h>
-#define CORE_HZ 100000000
+#define CORE_HZ 50000000
#define GPIO_A_BASE ((volatile uint32_t*)(0xF0000000))
#define GPIO_B_BASE ((volatile uint32_t*)(0xF0001000))
@@ -63,18 +63,20 @@ int main() {
initGpio();
setInterruptMask(0xFF);
- printf("Hello world\n");
- printf("a\n");
- printf("b\n");
+ printf("Hello world\r\n");
+ printf("a\r\n");
+ printf("b\r\n");
- while(1){
+ while(1);
+#if 0
+ {
uint64_t sum = 0;
for(uint32_t idx = 0;idx < 10000000;idx++){
sum += idx;
}
printf("Sum from 0 to 10000000 = %x%x ref = 2d7987f0d4c0\n",(uint32_t)(sum >> 32),(uint32_t)(sum));
}
-
+#endif
}
@@ -82,7 +84,7 @@ void irqC(uint32_t irq){
if(irq & 0x20){ //TimerABCD interrupt ?
uint32_t pendings = TIMER_INTERRUPT_BASE[0];
if(pendings & 0x1){ //TimerA ?
- printf("TimerB tick\n");
+ printf("TimerB tick\r\n");
TIMER_INTERRUPT_BASE[0] = 0x1;
}
if(pendings & 0x2){ //TimerB ?
@@ -103,7 +105,7 @@ void irqC(uint32_t irq){
//Implement stdio functions to redirect the printf to the uart.
int close(int fd) {return 0;}
-int fstat(int fd, struct _stat *buffer) {return 0;}
+int fstat(int fd, void *st) {return 0;}
int isatty(int fd) {return 0;}
long lseek(int fd, long offset, int origin) {return 0;}
int read(int fd, void *buffer, unsigned int count) {return 0;}
Thanks :)
Then if you want to have SDRAM working, tell me, i can tell you things/tips that you need.
Any tip would be great. I am working on SDRAM right now. It is Winbond 4M x 4BANKS x 16BITS SDRAM W9825G6JH-6. I have added to SdramDevices.scala:
object W9825G6JH {
def layout = SdramLayout(
bankWidth = 2,
columnWidth = 9,
rowWidth = 13,
dataWidth = 16
)
def timingGrade7 = SdramTimings(
bootRefreshCount = 8,
tPOW = 200 us,
tREF = 64 ms,
tRC = 60 ns,
tRFC = 60 ns,
tRAS = 42 ns,
tRP = 18 ns,
tRCD = 18 ns,
cMRD = 2,
tWR = 7.5 ns,
cWR = 1
)
}
I have also changed sdramCtrl in Pinsec.scala:
val sdramCtrl = Axi4SharedSdramCtrl(
axiDataWidth = 32,
axiIdWidth = 4,
layout = W9825G6JH.layout,
timing = W9825G6JH.timingGrade7,
CAS = 3
)
I use ODDR2 in FPGA to export 50MHz SDRAM clock from 50MHz clock used for Pinsec. I wish SDRAM controller in Pinsec would output SDRAM_CLK.
Hoo, yes you are right about timings changes. Also do not forget to change the frequancy setup in the scala "def main" function
About the generation of the clock that drive the SDRAM clock. It should be generated in your toplevel, it's not related the the Pinsec SDRAM controller. because it's realy target specific.
So, virtualy, the SDRAM chip should have the same clock than the FPGA, which mean, you need to use a PLL to create the FPGA axi clock and the sdram chip clock with a phase shift (-2.5 ns on Cyclone V is working, i get this number from a reference design, so if you find a Xilinx Spartan 6 reference design that use SDRAM, it's jackpot ^^)
How do you use the ODDR2 to export the 50 mhz clock ?
I generate 50MHz axi_Clk with PLL from input clock CLK_I and then export it with ODDR2 as follows:
clk_inst: clk
port map(
CLK_IN1 => CLK_I,
CLK_OUT1 => axiClk,
CLK_OUT2 => open
);
sdram_clk_export: ODDR2
port map(
Q => SDRAM_CLK, C0 => axiClk, C1 => not axiClk, CE => '1',
R => '0', S => '0', D0 => '1', D1 => '0'
);
I have borrowed this code from a working SDRAM code example. But since it does not work, I will try a phase shift. I have also tried CLK_OUT2.
I have modified Pinsec.scala as follows:
object Pinsec {
def main(args: Array[String]) {
val config = SpinalConfig().dumpWave()
config.generateVerilog(new Pinsec(50 MHz))
config.generateVhdl(new Pinsec(50 MHz))
}
Ahhhhh ok :D So, are sdram input output flops inside the FPGA io buffer ? or they are in the FPGA fabric ? you have to force them to be in the FPGA io buffers to have good timings. For example on altera, it's a "fast input register" "fast output register" "fast output enable register" configuration to give in the pin mapping file.
Hoo also, be carefull, limit the current of SDRAM pin to 4 mA to avoid burning things XD (I never had that issue, but who know ?)
They seem to be inside io buffers:
clkin1_buf : IBUFG
port map
(O => clkin1,
I => CLK_IN1);
clkout1_buf : BUFG
port map
(O => clk_out1_internal,
I => clk0);
CLK_OUT1 <= clk_out1_internal;
I will read some more about it. All timing constraints are met. Based on the timing report the minimum period is 8ns while I use 20ns. So from FPGA point of view even 125MHz should work.Thanks.
Finally I have got SDRAM working. I had a typo mistake in pin locations. These are my Pinsec.scala chages:
--- a/lib/src/main/scala/spinal/lib/soc/pinsec/Pinsec.scala
+++ b/lib/src/main/scala/spinal/lib/soc/pinsec/Pinsec.scala
@@ -139,15 +139,15 @@ class Pinsec(axiFrequency : BigDecimal) extends Component{
val ram = Axi4SharedOnChipRam(
dataWidth = 32,
- byteCount = 4 kB,
+ byteCount = 36 kB,
idWidth = 4
)
val sdramCtrl = Axi4SharedSdramCtrl(
axiDataWidth = 32,
axiIdWidth = 4,
- layout = IS42x320D.layout,
- timing = IS42x320D.timingGrade7,
+ layout = W9825G6JH6.layout,
+ timing = W9825G6JH6.timingGrade7,
CAS = 3
)
@@ -200,8 +200,8 @@ class Pinsec(axiFrequency : BigDecimal) extends Component{
val axiCrossbar = Axi4CrossbarFactory()
axiCrossbar.addSlaves(
- ram.io.axi -> (0x00000000L, 4 kB),
- sdramCtrl.io.axi -> (0x40000000L, 64 MB),
+ ram.io.axi -> (0x00000000L, 36 kB),
+ sdramCtrl.io.axi -> (0x40000000L, 32 MB),
apbBridge.io.axi -> (0xF0000000L, 1 MB)
)
@@ -268,7 +268,7 @@ class Pinsec(axiFrequency : BigDecimal) extends Component{
object Pinsec{
def main(args: Array[String]) {
val config = SpinalConfig().dumpWave()
- config.generateVerilog(new Pinsec(100 MHz))
- config.generateVhdl(new Pinsec(100 MHz))
+ config.generateVerilog(new Pinsec(50 MHz))
+ config.generateVhdl(new Pinsec(50 MHz))
}
}
Thanks again for your help. Do you want me to submit a pull request for SdramDevices.scala containing my SDRAM timings?
Since SDRAM is working now I was thinking to try VGA test but have some problems to compile it. My RAM is 36K and SDRAM 32M:
make[2]: Entering directory '~/projects/pinsecSoftware/tests/ugfx'
makefile:8: ugfx_lib/gfx.mk: No such file or directory
makefile:9: ugfx_lib/drivers/gdisp/framebuffer/driver.mk: No such file or directory
make[2]: *** No rule to make target 'ugfx_lib/drivers/gdisp/framebuffer/driver.mk'. Stop.
make[2]: Leaving directory '~/projects/pinsecSoftware/tests/ugfx'
This one has just some missing files but the following one fails to link:
make[2]: Entering directory '~/projects/pinsecSoftware/tests/vga'
mkdir -p build/src/
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -c -g -march=RV32IXcustom -O3 -m32 -static -I../../libs/test/ -I../../libs/uart/ -I../../libs/vga/ -I../../libs/ -o build/src/main.o src/main.cpp
src/main.cpp: In function 'int main()':
src/main.cpp:34:26: warning: iteration 48 invokes undefined behavior [-Waggressive-loop-optimizations]
vgaFramebuffer[0][idx] = idx;
~~~~~~~~~~~~~~~~~~~~~~~^~~~~
src/main.cpp:33:27: note: within this loop
for(uint32_t idx = 0;idx < RES_X*RES_Y;idx++){
^
mkdir -p build/src/
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -c -g -march=RV32IXcustom -O3 -m32 -static -o build/src/crt.o src/crt.S -D__ASSEMBLY__=1
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -g -march=RV32IXcustom -O3 -m32 -static -o build/vga.elf build/src/main.o build/src/crt.o -e_start -nostartfiles -T ../../resources/linker.ld -Wl,-Map,build/vga.map /opt/riscv32i/riscv32-unknown-elf/lib//libc.a /opt/riscv32i/riscv32-unknown-elf/lib//libnosys.a
build/src/crt.o: In function `trap_entry':
(.text+0x90): relocation truncated to fit: R_RISCV_JAL against symbol `irqCpp' defined in .text section in build/src/main.o
collect2: error: ld returned 1 exit status
../../resources/subproject.mk:36: recipe for target 'build/vga.elf' failed
make[2]: *** [build/vga.elf] Error 1
make[2]: Leaving directory '~/projects/pinsecSoftware/tests/vga'
Have you seen anything like this? There is another test failing to compile with a similar error:
make[2]: Entering directory '~/projects/pinsecSoftware/tests/gpio'
mkdir -p build/src/
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -c -march=RV32IXcustom -g -O0 -m32 -static -o build/src/main.o src/main.cpp
mkdir -p build/src/
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -c -march=RV32IXcustom -g -O0 -m32 -static -o build/src/crt.o src/crt.S -D__ASSEMBLY__=1
/opt/riscv32i//bin/riscv32-unknown-elf-gcc -march=RV32IXcustom -g -O0 -m32 -static -o build/gpio.elf build/src/main.o build/src/crt.o -e_start -nostartfiles -T ../../resources/linker.ld -Wl,-Map,build/gpio.map /opt/riscv32i/riscv32-unknown-elf/lib//libc.a /opt/riscv32i/riscv32-unknown-elf/lib//libnosys.a
build/src/crt.o: In function `trap_entry':
(.text+0x90): relocation truncated to fit: R_RISCV_JAL against symbol `irqCpp' defined in .text section in build/src/main.o
collect2: error: ld returned 1 exit status
../../resources/subproject.mk:36: recipe for target 'build/gpio.elf' failed
make[2]: *** [build/gpio.elf] Error 1
make[2]: Leaving directory '~/projects/pinsecSoftware/tests/gpio'
They are failing for me even when I have 96K RAM and 64M SDRAM defined in linker.ld.
Oddly enough moving .text section to RAM has fixed it. I have noticed crt.S file is bit different for test projects which are failing to link. Is it intentional?
Great !
So yes, having more sdram timing is usefull :)
About (.text+0x90): relocation truncated to fit: R_RISCV_JAL against symbol `irqCpp' defined in .text section in build/src/main.o I fixed that issues with a commit on pinsecSoftware 3 days ago. Basicaly it's because i used the JAL instruction to jump from the RAM to the SDRAM, but that jump is to big, i had to use the CALL meta-instruction. I forgot to update that for all tests, now it's ok.
About makefile:8: ugfx_lib/gfx.mk: No such file or directory It's because there is an inner repository, when you clone pinsecSoftware , you have to add --recursive argument in the git command. Also, i'm not sure about what is doing the VGA test, but the UGFX test is playing a fancy demo, and i'm sure the UGFX one work.
I will read some more about it. All timing constraints are met. Based on the timing report the minimum period is 8ns while I use 20ns. So from FPGA point of view even 125MHz should work.Thanks. So, you mean you can run your Spartan at 125 Mhz with Pinsec ?
Regards
Hooo another question, Du you use the generated Verilog or the generated VHDL ?
Unfortunately I cannot run Pinsec at that speed. It is just that the timing report is claiming that the minimum period is 8ns. So the timing will not fail even if I set the axi clock to 125MHz. But unfortunately it does not work at that speed and I have it working at 50MHz now. So far I am using VHDL but I will try Verilog next.
Ahh ok, So currently (to recapitulate) everything work at 50 Mhz with the VHDL ? My personnal setup use the Verilog ^^ (because of cocotb + Icarus Verilog)
Yes, everything (gpio, interrupts, uart, sdram) work with VHDL at 50MHz. I will try VGA and then Verilog. It seems that the VHDL TB is generated but not the Verilog one.
Ahh cool. So about TB, it's normal, only the VHDL backend generate an additional TB file. It's a feature that come from a long time ago :D
I have some problems executing your programs on FPGA (Spartan6) running Pinsec. I have compiled uart test and here is the top of the assembly file:
I have connected with openocd over JTAG:
Then I have stepped through instructions. I expect SP register to change when executing lines 150 and 154 but it is not the case:
I did try to use stepi and correctly stepped over all instructions from 148 to 158 and the result is the same. The program fails since there is no stack and there is no uart print out. Please, let me know if there is anything I am missing.