iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0
tags: 鐵人賽

0. 前言

今天我們來聊聊該如何使用這些 CSR 指令呢,前些日子裡我們已經有介紹許多 CSR 了,可以先觀看 DAY2 以及 DAY3 的文章唷,介紹了許多 CSR,有些是只能讀,有些只能寫,有些可以讀以及寫,根據該 CSR 定義的不同,則有所不同,以下我們正式介紹。

1. CSR 用法

事實上 Linux kernel 有提供我們相關 Macro 可以方便我們使用

/* csr.h */
#define csr_read(reg) ({ unsigned long __tmp; \
  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
  __tmp; })

#define csr_write(reg, val) ({ \
  asm volatile ("csrw " #reg ", %0" :: "rK"(val)); })

#define csr_set(reg, bit) ({ unsigned long __tmp; \
  asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
  __tmp; })

#define csr_clear(reg, bit) ({ unsigned long __tmp; \
  asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
  __tmp; })

#define csr_swap(reg, val) ({ \
    unsigned long __v = (unsigned long)(val); \
    asm volatile ("csrrw %0, " #reg ", %1" : "=r" (__v) : "rK" (__v) : "memory"); \
    __v; })

根據 kernel 的 csr.h 文件當中一共有五個 macro 讓我們來操作這些 CSR,根據觀察這些 macro ,可以發現他們是由 assembly 的方式實作的,因此有需要時,也可以直接使用 csr* 指令的方式進行 CSR 的操作。

  • csr_read(reg)
    讀取某個 CSR 的值
  • csr_write(reg, val)
    將 val 寫入到該 CSR 當中
  • csr_set(reg, bit)
    將該 CSR 的第幾位 bit 舉起(設為1)
  • csr_clear(reg, bit)
    將該 CSR 的第幾位 bit 清空(設為0)
  • csr_swap (reg, val)
    將該 CSR 中的值寫入val,val 的值寫入 CSR

CSR 指令

接下來我們將細部說明各個 csr* 指令

  • CSRRW(Atomic Read/Write CSR):CSRRW 讀取當前 CSR 中的值,將其補零擴展到 XLEN 位,然後寫到 rd 中,再將 rs1 中的值將被寫入 CSR 中。

    • for example:
    csrrw a0, misa,zero
    

    a0rd ,zero 是rs1misa(machine ISA register)是 CSR,
    因此,讀取misa的值將其放進a0,最後將 zero 的值寫入到misa

  • CSRRS (Atomic Read and Set Bit in CSR) :CSRRS 讀取當前 CSR 中的值,寫到 rd 中,再將 rs1 的值對應第幾位 bit 為1的寫入 CSR 當中的對應 bit 將其設為1(很饒口嗎,看例子好懂)

    • for example:
    li a1,0X3
    csrrs a0, mie, a1
    

    a1 為 0x3(二進制來觀察就是 0011)
    a0rd, a1rs1mie(machine interrupt enable)是CSR,
    因此,讀取mie的值寫到a0,接著將a1當中對應 bit 為1的,寫到mie,因此mie的 bit 0 以及 bit 1 皆被設為1了,再一個例子。

    li a1, 0x5
    csrrs a0, mie, a1
    

    a1為0x5(二進制來觀察就是 0101)
    一樣讀取mie的值寫到a0,接著a1當中對應 bit 為1的寫到mie,因此mie的bit 0以及bit 2皆被設為1了

  • CSRRC(Atomic Read and Clear Bit in CSR):rs1 中對應bit為 1 的位,將導致 CSR 中對應位被清0,這跟前一個類似,應該說剛好相反吧,總之看例子較好理解

    • for example:
    li a1,0x3
    csrrc a0, mie,a1
    

    a0rd, a1rs1mie(machine interrupt enable)是CSR,因此,讀取mie的值寫到a0,接著將a1當中對應bit為1的,對應到mie並清0,因此mie的bit0以及bit1皆被設為0了

  • CSRRWI

    • for example:
    csrrwi zero,mstatus,1 
    

    只寫1到mstatus中,不讀取csr

  • CSRRSI

    • for example:
    csrrsi zero,mstatus,0x02 
    

    只設置bit 1(因為0x2二進制就是 0010)數值為1,不讀csr

後記

今日我們介紹了許多 CSR 的用法,通常直接使用 macro 會是比較平易近人的作法,但也不排除可能會需要用到 assembly 的方式,因此這邊也作一些介紹,明天來說明如何使用 sbi_ecall。


上一篇
DAY3: RISC-V: 不懂 CSR 那就放棄吧(二)
下一篇
DAY5: RISC-V sbi_ecall 流程與用法
系列文
RISC-V: 深入淺出從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言