Hi all, I recently put together FreeRTOS and freedom-e-sdk to run on a HiFive1 board, but it was running slower than it should. I realised later that FreeRTOS was working correctly, but that the calculated ticks were too long. For example: the demo used pdMSTOTICKS( 1000 ) to delay a task for 1 second. However that would take minutes of real time. In the end I had to use these values to get close to the real time delays: define configCPUCLOCKHZ ( 17500 ) define configTICKRATEHZ ( ( TickType_t ) 100 ) Please, have anyone tried FreeRTOS on a HiFive1 and got different results? And do you think it is a problem to “lie” to FreeRTOS about the clock, in order to get timers close to real time values? Thanks! More details: – Regarding freedom-e-sdk, I’m using this commit as the base: https://github.com/sifive/freedom-e-sdk/tree/dca1dfaf1cfb80ec30a7a16b899efa1040e3451d It is much simpler compared to current implementation using metal library. – I also tried running FreeRTOS on an Arty A7-100T FPGA and got the exact same results. – freedom-e-sdk tries to measure the CPU frequency by checking the CSR mtime: https://github.com/sifive/freedom-e-sdk/blob/dca1dfaf1cfb80ec30a7a16b899efa1040e3451d/bsp/env/freedom-e300-hifive1/init.c#L141 And the values the boards printed was: arty: 64959283Hz hifive: 264971878Hz
You shouldn’t need to ‘lie’ to FreeRTOS. The likely problem is that the port layer has a bug for that system and isn’t setting up the tick timer right. The define configCPUCLOCKHZ should only be used by the port layer to setup the timer, which should also be using the configTICKRATEHZ define. If the ticks aren’t occuring at the right rate, that setup function is wrong. I don’t know those particular systems/projects, but I do know how FreeRTOS works, and getting wrong period tick interurpts it the responsibility/fault of the port layer in port.c in a function called an named to set up the system timer (I don’t have the code in front of me to get the exact name, but it should be obvious looking throgh port.c). Values being that far off sounds like something may be wanting values scaled differently than being provided.
What is generating the clock input to the MCU? Does the part have a CLINT (I think it does)? If so, does it have a machine clock (mclock – I think it does)? If so, how do you know how fast the machine clock is running? Maybe the clock needs initialising to do something like enable the PLL to make it go quickly.
Thanks for you prompt response. And thanks to your answers I (almost) found the issue! There are two cycle counters on RISC-V, as described on the The RISC-V Instruction Set Manual Volume II: Privileged Architecture (https://content.riscv.org/wp-content/uploads/2017/05/riscv-privileged-v1.10.pdf): – “The mcycle CSR holds a countof the number of cycles the hart has executed since some arbitrary time in the past.” (section 3.1.16) – “Platforms provide a real-time counter, exposed as a memory-mapped machine-mode register, mtime. mtime must run at constant frequency, and the platform must provide a mechanism for determining the time base of mtime.” (section 3.1.15) I found considerable evidence that mtime frequency is 32768 Hz, or 32KHz: – The SiFive E31 Core Complex Manual v2p0 (https://sifive.cdn.prismic.io/sifive%2Fb06a2d11-19ea-44ec-bf53-3e4c497c7997sifive-e31-manual-v2p0.pdf) on section 6.3 says: “mtime is a 64-bit read-write register that contains the number of cycles counted from the rtctoggle signal described in the E31 Core Complex User Guide.” – And in turn the E31 Core Complex User Guide says on section 8.2.1: “Generally, rtc_toggle is connected to either a Real Time Clock (e.g. 32.768 kHz) or to the base clock input frequency of the platform.” The code that tries to measure the clock takes the mcycle/mtime difference into account: https://github.com/sifive/freedom-e-sdk/blob/dca1dfaf1cfb80ec30a7a16b899efa1040e3451d/bsp/env/freedom-e300-hifive1/init.c#L42 It looks to correctly measure how many “mcycle cycles” happened between each “mtime cycle”, and then uses the 32KHz to calculate the mcycle frequency. But the code on FreeRTOS/Source/portable/GCC/RISCV/port.c, more specifically, the function vPortSetupTimerInterrupt, wasn’t considering it. I “fixed” it dividing the clock by 32KHz, which is the frequency of the mtime cycles: const uint32t ulTimerIncrementsForOneTick = ( uint32t ) ( ( configCPUCLOCKHZ / 32768) / configTICKRATEHZ ); Now it calculates the next tick using “mtime cycles”, which happen at a frequency of 32KHz. By the end the timers are no longer wrong by a factor of 8000. However, they are still wrong by a factor of 4. (32/8=4) So I’ll continue looking into what is wrong. I’ll probably explore this sentence: “Generally, rtc_toggle is connected to either a Real Time Clock (e.g. 32.768 kHz) or to the base clock input frequency of the platform.” Please, if you have anything to say, or know who could I talk to about fixing the file above, leave a response.
Thanks for reporting back. Grateful if you can post any updates to the port code you made too.
Since my last post I was able to run the “test suite” found on FreeRTOS/Demo/RISC-V-Qemu-sifivee-FreedomStudio/fulldemo/mainfull.c with mixed results. When running them all (dynamic tasks, block timer, etc) they mostly failed. When running them individually they all pass. I think it might be related to timing, and I’m having better results by, for example, tweaking configTICKRATEHZ from 1000 to 10. Some tests use small delays that when converted using the macro pdMSTO_TICKS would result in a 0 ticks delay. Anyway, the whole thing still feels unstable. Side note: I’ve also run out of memory and I had to re-program Arty’s SRAM from 16KB to 64KB.
I have not tried running on the Arty – what is the clock frequency it is using? You are right in that the tests are self monitoring and check their own timing. Depending on how many you are running, if the hardware is slow, physics might get in the way of them all passing at once. I have an Arty and can give this a go myself (although not sure when I will get the chance) so please let me know as much about your hardware configuration as possible.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.