Intro
- The CSRs that are available are implementation dependent
- CSRs are generally accessed via special instructions into a 4096 entry register space, but may be memory mapped (e.g. mtime).
- CSRs have a defined priviledge level at which they can be accessed.
- CSRs may be unique per hart, or share a common value for all harts.
Example Code
The quick reference on this blog is generated from a YAML description (csr.yaml). Using that with a web template engine script (generators/yaml_jinja.py) and a template (templates/riscv-csr.h) code can be easily generated.
The C is code is include/riscv-csr.h, and there is an example examples/test_csr.c.
Accessing CSRs
The instructions to modifiy CSRs are listed here Some examples are shown below.
- Read a CSR. For example read the vendor ID mvendorid.
- Write a CSR. For example set the machine mode interrupt vector base address mtvec.
- Set a bit or bits via a register value. The zero register is used to discard the previous value. For example enable an interrupt via mie.
- Atomically read and set a bit or bits via a register value. For example enable an interrupt via mie and save the previous enabled interrupts.
- Set a bit or bits via a immediate mask. The mask can be a constant. For example MASK=0x8 will set (mstatus.mie ) to enable machine interrupts..
- Clear a bit or bits via a immediate mask to mstatus. The mask can be a constant. For example MASK=0x8 will clear (mstatus.mie ) to disable machine interrupts..