I have some bare FE310-g002 from crowdsupply which I have placed on a custom PCB. Code does not seem to run from QSPI flash after hardware reset/POR. If I halt the core and resume at 0x2000000 via JTAG, the code written to QSPI flash executes as expected.
Reading out 0x00001000 via JTAG indicates that MSEL is 0x03 which causes execution to start at mask rom which jumps to OTP according to the manual. Readouts of the 0x00020000-0x00021FFF region via JTAG seem to indicate that OTP is all zeros.
it would really be nice to find where is the external hardwired control of MSEL; my best guess is in the discussion at the link above.
also, note the minor difference between -g000 and -g002:
Chapter 5 of the User Manual states the four values of MSEL[1:0] are MSEL[1:0] 0 0 trap loop 0 1 jump to QSPI (0x2000 0000) 1 0 jump to OTP (0x0002 0000) 1 1 jump to ROM (0x0001 0000) (on -G000 it’s 0x00001000, not a typo)
I just messed around with the chip a bit more and really just confirmed what the manual says. On reset, pc starts at 0x1004 in gate ROM. The gate ROM jumps to mask ROM at 0x00010000 since MSEL is 0x03. Mask ROM then jumps to OTP at 0x00020000. After the jump, 0x00000000 is fetched from OTP which triggers an illegal instruction trap. Since the POR state of mtvec is zero, pc ends up at 0x00000000 and stays there until I JTAG the core to somewhere else (or poke mtvec via JTAG)
Unless I’m missing something here (I’m new to RISC-V), seems like I either need to program a jump into the beginning of OTP or set MSEL to 0x01 if that’s possible.
I think that programming OTP is the only solution here. These MSEL lines exist inside the chip, but they do not have any connections to the outside world.
I attempted to program the OTP and I can’t seem to set any bits when following the procedure in the manual. I wrote a barebones C program to write to OTP since metal doesn’t implement an OTP control interface. I’m sort of at a loss for what to do here since the disassembly and stepping through the program seems to indicate that it’s correctly following the manual’s procedure.
I’ve included my code below. It’s called from a _start that simply initializes the stack and jumps to main. I’ve been running this code out of DTIM at 0x80000000.
I’m not sure if this warrants a documentation bug/issue. The FE310-g002 datasheet says that the beginning and end of OTP come programmed but all of OTP is zeros when read via the memory mapped region at 0x00020000 and when read using the OTP control registers.
Solved it. I checked out all of the pads on the chip and found that pin 12, OTP_AIVDD, had not made a connection to the PCB. I got some solder under that pad and everything works as expected now.
When I was poking around on my original HiFive1 several years ago I found that the OTP didn’t read correctly if the CPU clock was 256 MHz but it worked fine and I saw the documented values when I ran at 16 MHz.