Lots of Questions... (RISCY BUSINESS Day 21)


(岩倉 澪) #1

Hi all, today’s episode of my show left me with a lot of unanswered questions:

  • Why does trying to upload to my hifive1 often fail requiring a reset or even killing openocd? I am worried that this could brick the hifive1 (?)
  • Is the configuration string on the hifive1 properly padded with 0x00/0xff and null-terminated? We are having trouble properly searching to it and printing it.
  • What is the story on the privileged arch 1.9.1 manual and the 1.9 draft chapter 8? The draft has information on syntax but is missing the part about searching which is in the 1.9.1 manual.
  • Is printf just an empty shim? It doesn’t print anything when tried in our demo_gpio and uploading the hello demo also failed to print anything…
  • What is /include/, is the value a memory offset to more configuration information? We failed to find any helpful information about this in the manuals

Relevant episode:


(Drew) #2

Why does trying to upload to my hifive1 often fail requiring a reset or even killing openocd? I am worried that this could brick the hifive1 (?)

The current OpenOCD code has some problems where it doesn’t always clean up after itself, and doesn’t handle all the cases when the previous OpenOCD session didn’t clean up after itself. If you can provide a specific set of actions that doesn’t work for you, we can try to reproduce it and make a patch to OpenOCD.

This should not permanently harm your HiFive1 board. If you get into trouble, you can always double tap the reset button to get into safe boot mode as describe in the HiFive1 Boot Sequence in the getting started guide.

Is the configuration string on the hifive1 properly padded with 0x00/0xff and null-terminated? We are having trouble properly searching to it and printing it.

The Configuration String can be printed with the following code:

unsigned char * ConfigString = (unsigned char*)*(volatile uint32_t *) 0x0000100C;
write (STDOUT_FILENO, ConfigString, strlen(ConfigString));

The string is also documented in the SiFive-E310-G000 manual here. Hopefully they match :wink:

What is the story on the privileged arch 1.9.1 manual and the 1.9 draft chapter 8? The draft has information on syntax but is missing the part about searching which is in the 1.9.1 manual.

I’m not sure I understand the question?

Is printf just an empty shim? It doesn’t print anything when tried in our demo_gpio and uploading the hello demo also failed to print anything…

Be sure to put the \n in your printf or to call fflush after. For example the following should work:
printf(“this is a test”);
fflush(stdout);

What is /include/, is the value a memory offset to more configuration information? We failed to find any helpful information about this in the manuals

Yes you are correct. This include statement points to another location in memory where we have the option of placing more configuration information in the HiFive1 OTP memory. In the HiFive1 getting started manual you will see address documented in the OTP Contents section at offset 0x0004. At the moment, nothing is programmed here. I believe there will be more information on this in version 1.10 of the RISC-V Privileged spec.


(岩倉 澪) #3

The current OpenOCD code has some problems where it doesn’t always clean up after itself, and doesn’t handle all the cases when the previous OpenOCD session didn’t clean up after itself. If you can provide a specific set of actions that doesn’t work for you, we can try to reproduce it and make a patch to OpenOCD.

Steps to reproduce:

  1. make software PROGRAM="$program" BOARD=freedom-e300-hifive1
  • make upload PROGRAM="$program" BOARD=freedom-e300-hifive1
  • screen /dev/ttyUSB1 115200
  • reset hifive1 to check output of program
  • C-a \ to terminate screen
  • modify the source code of the program being tested
  • repeat

This is the development cycle I was following on episode 21, it does not fail 100% of the time, but it is pretty frequent/easy to reproduce.

This should not permanently harm your HiFive1 board. If you get into trouble, you can always double tap the reset button to get into safe boot mode as describe in the HiFive1 Boot Sequence in the getting started guide.

Awesome, that is great to know :slight_smile:

The Configuration String can be printed with the following code:

unsigned char * ConfigString = (unsigned char*)*(volatile uint32_t *) 0x0000100C;
write (STDOUT_FILENO, ConfigString, strlen(ConfigString));

The string is also documented in the SiFive-E310-G000 manual here. Hopefully they match

I’ll try that code on today’s episode, thanks! I was trying to do it like this:

char *config_string = 0x0000100C;
while (*config_string == 0x00 || *config_string == 0xff)
    ++config_string;
write(STDOUT_FILENO, config_string, strlen(config_string));

I’m not an expert when it comes to C, does it store the constant 0x0000100C in the read only data section and set the value of config_string to the address of that literal instead of assigning the value 0x0000100C to the pointer? Based on your code I take it that casting is my problem? Although it looks like you are de-referencing the pointer after the cast to volatile uint32_t and then casting that to a pointer… So wait, rather than the string living at or after 0x0000100C, 0x0000100C holds an address to the actual location of the string? I’m sure I’ll figure these questions out once I poke around with your code example today :slight_smile:

I’m not sure I understand the question?

I’m learning about the config string from the following document: https://riscv.org/wp-content/plugins/pdf-viewer/stable/web/viewer.html?file=https://content.riscv.org/wp-content/uploads/2016/11/riscv-privileged-v1.9.1.pdf

…but Hossein linked me this document: https://people.eecs.berkeley.edu/~krste/papers/riscv-privileged-v1.9.pdf

If you look at the document I was referencing, chapter 8 talks about a search procedure, whereas the document Hossein linked does not talk about a search procedure, but instead talks about syntax. I’m wondering what the deal is with the discrepancy between the documents? If the 1.9 draft is more recent than the standard one, does that mean searching for the string was scrapped? Or is 1.9.1 more up-to-date than that draft? (in which case, why doesn’t it detail the syntax of the string?)

Be sure to put the \n in your printf or to call fflush after. For example the following should work:
printf(“this is a test”);
fflush(stdout);

Thanks for the tip!

Yes you are correct. This include statement points to another location in memory where we have the option of placing more configuration information in the HiFive1 OTP memory. In the HiFive1 getting started manual you will see address documented in the OTP Contents section at offset 0x0004. At the moment, nothing is programmed here. I believe there will be more information on this in version 1.10 of the RISC-V Privileged spec.

Sweet, thanks for the info :slight_smile:


(Drew) #4

Thanks will see if we can get a reproducible use case.

I’m not an expert when it comes to C, does it store the constant 0x0000100C in the read only data section and set the value of config_string to the address of that literal instead of assigning the value 0x0000100C to the pointer? Based on your code I take it that casting is my problem? Although it looks like you are de-referencing the pointer after the cast to volatile uint32_t and then casting that to a pointer… So wait, rather than the string living at or after 0x0000100C, 0x0000100C holds an address to the actual location of the string? I’m sure I’ll figure these questions out once I poke around with your code example today

Sure, happy to help where i can :slight_smile: The string is a constant held in Read Only memory at the address 0x0000_100C. There are 2 parts to the assignment - (volatile uint32_t) declares and then de-references a pointer at the desired address.From here we are able to assign a pointer of any type we like to point to that address, unsigned char* in this case. When all is said and done the variable, ConfigString in my case, lives in the data scratchpad but points to the config string address.

If you look at the document I was referencing, chapter 8 talks about a search procedure, whereas the document Hossein linked does not talk about a search procedure, but instead talks about syntax. I’m wondering what the deal is with the discrepancy between the documents? If the 1.9 draft is more recent than the standard one, does that mean searching for the string was scrapped? Or is 1.9.1 more up-to-date than that draft? (in which case, why doesn’t it detail the syntax of the string?)

1.9.1 is the newer document (dated November 2016). I believe this section will receive some attention in the next revision of the spec.


(岩倉 澪) #5

A few notes:

I realized today I still had my jumper set to 5V (moved it there when I first got my hifive1 because I thought that might be the problem, turned out the problem I was having then was faulty usb ports on the front of my computer’s case). I moved it back to 3.3V today thinking that it might have been causing my problems, didn’t seem to make a difference though.

Spent all of episode 22 playing around with pointers & printing stuff based on your example and I now fully understand how that is working :slight_smile:

Lastly, I noticed in the hifive1 getting started guide that in the OTP there is an address for “board identifier.” I tried printing that as if it were a string but got garbage, tried it as an int and it was a really big number, treating that value as a pointer like with the config string caused it to trap when de-referenced. Do you have any insights regarding the board id?


(Megan A. Wachs) #6

It’s actually just a hex number representing a timestamp of when the OTP was burned. Try entering it into something like this:

https://www.epochconverter.com/hex


(岩倉 澪) #7

Both Hossein and I get the value of 0xED93DB27 for memory address 0x1FE4
Also searched for reasonable values from 0x1004 to 0x2000 and didn’t find any, the closest hit was 0x1634: 5714AE28

But hossein had the same value and that is April of 2016, little bit early…


(Megan A. Wachs) #8

The addresses at 0x1000 reside in Mask ROM, not OTP, so you’re reading some code that is in the Mask ROM (some test and library functions).

The addresses for the OTP contents given in Table 7.2 of the HiFive1 Getting Started Guide are offsets within the OTP, not the absolute addresses. The OTP region starts at 0x20000. So, you should look at 0x21FE4 to find your “Chip ID”.


(岩倉 澪) #9

The value I have at that address is 5041988E which would be Sat, 01 Sep 2012 05:09:34 GMT
That seems suspiciously early to me!


(Megan A. Wachs) #10

Strange!

Can you print out the rest of the OTP contents to see if they match what you expect from the HiFive1 Getting Started Guide? Perhaps we’re still off in the location we’re looking.

Megan


(Megan A. Wachs) #11

Also, make sure your clock isn’t running too fast when you’re trying to read the OTP contents. You’ll need to set the OTP divider properly if your clock is running at the 256MHz level.


(岩倉 澪) #12
core freq at 267203379 Hz
0x20000: 6550006D        
0x21fe4: 5041988E
0x21fe8: 0       
0x21fec: 9
0x21ff0: 1
0x21ff4: 7
0x21ff8: 200002B5
0x21ffc: 28061   

It looks like we are looking in the right place, but the values are off. I haven’t messed with the clock frequency of my board at all, but perhaps it is running faster than expected? I will look into setting the OTP divider today


(Megan A. Wachs) #13

You can also try using the led_fade demo as your starting point, as it uses the -DNO_INIT flag but still sets up clock source to be 16MHz and configures the UART appropriately within the code.

By default (without NO_INIT define), the freedom-e-sdk initialization code will switch you over to the PLL, and 267MHz is way too fast to read the OTP without setting the OTP clock divider.


(岩倉 澪) #14

Awesome, that works! My board id is Tue, 20 Dec 2016 20:54:39 GMT! :smiley:


(岩倉 澪) #15

So the values I got from the OTP were

0x20000: 7F50106F
0x21fe4: 58599A8F
0x21fe8: 0       
0x21fec: 9
0x21ff0: 1
0x21ff4: F
0x21ff8: 200002B7
0x21ffc: 28067   

All the values look correct, except for that last one, shouldn’t it be 28057? Wondering if the read wasn’t perfect…


(MohammadHossein AskariHemmat) #16

@miotatsu @mwachs5 Seems mio got his chip fabricated earlier than me!
I got Thu, 22 Dec 2016 01:52:44 GMT

Here are the values I am getting in OTP:

0x21fe4: 585b31ec 
0x21fe8: 0 
0x21fec: 9 
0x21ff0: 1 
0x21ff4: f 
0x21ff8: 200002b7 
0x21ffc: 28067

#17

The value for address 0x00021ffc seems to be a documentation error.
0x00028067 is the encoding of jalr x0, x5, 0 which is the equivalent of the documented pseudo instruction jr t0.
As far as I can tell an instruction for the opcode 0x57 is not assigned.


(Megan A. Wachs) #18

Yes you’re all correct. Someone pointed this out to us already and we have apparently yet to update the documentation.


(Bruce Hoult) #19

Yes, I reported this on Feb 13.


(Megan A. Wachs) #20

Thanks all for finding the typo in the Getting Started Guide. We’ve posted an updated version with the corrected OTP contents.