Introduction
In the last article, we used sbi_hart_suspend
and sbi_set_timer
to implement sleep
functions. But the method is unusual, and we can implement the sleep function in a more common way. In this article, we will implement sleep
by comparing the current cycles of timebase frequency with the cycles when the function is called in loops instead of suspending the hart.
Analysis
In RISC-V, Control and status register (CSR) is a register that stores various information in CPU. The mtime
CSR stores the cycles based on the timebase frequency since the CPU started, and we can calculate the uptime of the CPU by dividing the value of the mtime
CSR by the timebase frequency of the CPU.
uptime = mtime / timebase_frequency
So we can implement the sleep function by comparing the current time with the time when the function is called in loops. When the current time is greater than the time when the function is called plus the sleep time, the loop will exit.
However, It’s not efficient to compare the current time with the time when the function is called in loops. CPU will keep running in the loop, which will consume a lot of power. So we can use the wfi
instruction to suspend the CPU until the interrupt occurs. wfi
is short for “wait for interrupt”, when the CPU executes this instruction, wfi
puts the CPU core on which it is executing into a low power state until an interrupt is received.
In the last article, we have learned how to use sbi_set_timer
to set the timer interrupt. We can use the same method to implement the sleep function.
Solution
Prepare
In the last article, we have learned how to get the timebase frequency of the CPU and how to add riscv
crate to dependencies. We can use the same method to prepare the environment.
Implementation
|
|
In this implementation, we use the riscv::register::time::read()
function to get mtime
. Then we calculate stime
by adding the number of cycles of a certain time to the value of the mtime
CSR. After that, we set the timer interrupt to this value by calling sbi_set_timer
. Finally, we use wfi
to put CPU core to low power state until the interrupt occurs. The condition of loop is needed to avoid sleep
function returning before the time is up caused by other interrupts.
Use and Test
|
|
After adding the sleep function, we can use it in the rust_main
function to test it.
Summary
In this article, we implemented the sleep function by comparing the current time with the time when the function is called in loops. We used the wfi
instruction to reduce power consumption, and we used the sbi_set_timer
function to set the timer interrupt to wake up the CPU. It’s a more common way to implement the sleep function.