Differences between post-programming and powerup state

Hey everybody,

I am working on a program, written in RV32 assembly language, for the HiFive1 to drive a strip of WS2812B leds. WS2812B relies of very tight timings (1.25 ns tolerance), and I had a fair bit of trouble getting things right. However, by enabling the PLL, setting a high multiplier, and using my oscilloscope to make sure all the timing was correct, I was able to get everything working. However, I was surprised to discover that it only works when connected to my computer machine and after it is reprogrammed via openocd. It does not work after a reset or when first powered on.
I have looked at all the documentation I could find, but I can’t figure out what might be different between when the board is powered on and post programming.

If anybody has any insight, please let me know, and thank you in advance. If I have no provided enough information or I am not making sense or being an idiot or something, please forgive me, after all, I have been drinking, as I always do while writing assembly code.

I program the board with openocd using the following commands (from my makefile). These are basically just adapted from the fe310 sdk, ./config/openocd.cfg is copied from the fe310 sdk:

upload:
    openocd -f config/openocd.cfg &
    $(HOST)-gdb $(PROGRAM) --batch -ex "set remotetimeout 240" -ex "target extended-remote localhost:3333" -ex "monitor reset halt" -ex "monitor flash protect 0 64 last off" -ex "load" -ex "monitor resume" -ex "monitor shutdown" -ex "quit"

Hi Prushik,

I don’t exactly what to tell you, but I wrote a NeoPixel demo on the HiFive1 in C that does not have the problem you describe. Just like you, I needed to configure the PLL to get the timing correct.

The code and setup are described here:

https://github.com/cbrune/hifive1-neopixel

I just used the upload method from the Freedom-E-SDK.

Perhaps you can look at my code see a difference between that and what you are doing.

Cheers,
Curt

Out of reset, the chip runs off of its DROSC (internal clock source). Many applications compiled with the SDK will first turn on the PLL and run off of that, because it’s part of the _init code. So, when you connect with the debugger to something that is already running a program, then load your code, the board probably already had the PLL configured and was running at the higher frequency. When it runs out of reset it doesn’t get the PLL configured so it runs slower.

So you probably want to ensure that your program itself configures the PLL or whichever clock source you want it to use.

See https://github.com/sifive/freedom-e-sdk/blob/master/bsp/env/freedom-e300-hifive1/init.c#L222

Thank you.

Curt, I saw your example code, and it looks great, much better than what I wrote. Once I get this work I will use your code as a reference to improve mine.

Megan, I believe I am setting up the PLL, but I must be doing something incorrectly. Later today I will post exactly what I set the cfg registers to. What really confuses me though, is that “running too slow” is not the issue. I get no output at all after a reset, not too slow, not too fast, nothing. Yet after programming it works fine. My other programs which run without setting up the PLL work fine after a reset.

My code sets the HFROSC_CFG register to 0x40000004, which should mean enable=1, div=4, trim=0.
Then I set the PLL_CFG register to 0x00010ff1, which should mean pllr=1, pllf=127, pllq=3, pllsel=1, pllrefsel=0, pllbypass=0.