Menu Close

RISC-V PLIC软件设计(2)

1.PLIC软件设计

 

相关参考文章:

RISC-V教学教案

 

1.4. plic_driver.c

 

#include "platform.h"
#include "plic.h"
#include "plic_driver.h"
#include "encoding.h"
#include <string.h>


//把区间内的值初始化为0,volatile表示变量不需要进行优化,随时可变

void volatile_memzero(u8_t * base, unsigned int size)
{
    volatile u8_t * ptr;
    for (ptr = base; ptr < (base + size); ptr++){
        *ptr = 0;
    }
}


//初始化

void PLIC_init (
    plic_instance_t * this_plic,
    uintptr_t base_addr,
    u32_t num_sources,
    u32_t num_priorities
)
{

    //访问this_plic_struct内的变量
    this_plic->base_addr = base_addr;
    this_plic->num_sources = num_sources;
    this_plic->num_priorities = num_priorities;

    // 禁用所有中断
    unsigned long hart_id = read_csr(mhartid);         //可适用于多核系统
    volatile_memzero((u8_t*) (this_plic->base_addr +
                              PLIC_ENABLE_OFFSET +
                              (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
//地址区间单位为1byte/8 bit,+8是因为整数的除法上舍入(round up), 这里num_sources = 64
                              (num_sources + 8) / 8);      



// 将所有中断的优先级设为0
    volatile_memzero ((u8_t *)(this_plic->base_addr + PLIC_PRIORITY_OFFSET),
                              (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);

// 将优先级阈值初始化为0, volatile表示变量不需要进行优化,随时可变
    volatile plic_threshold* threshold = (plic_threshold*)
                                         (this_plic->base_addr +
                                         PLIC_THRESHOLD_OFFSET +
                                         (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));

    *threshold = 0;    //指针所指向的阈值设为0
}



//设置优先级阈值

void PLIC_set_threshold (plic_instance_t * this_plic,
plic_threshold threshold){

    unsigned long hart_id = read_csr(mhartid);               //可适用于多核系统
    //pointer value
    volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
                                              PLIC_THRESHOLD_OFFSET +
                                              (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));

    *threshold_ptr = threshold;//address
}


//设置优先级
void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){

    if (this_plic->num_priorities > 0) {
        volatile plic_priority * priority_ptr = (volatile plic_priority *)
                                                (this_plic->base_addr +
                                                PLIC_PRIORITY_OFFSET +
                                          (source << PLIC_PRIORITY_SHIFT_PER_SOURCE));      //地址区间单位为1byte
        *priority_ptr = priority;
    }
}



//读取中断声明寄存器

plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){

    unsigned long hart_id = read_csr(mhartid);                   //可适用于多核系统

    volatile plic_source * claim_addr = (volatile plic_source * )
                                        (this_plic->base_addr +
                                        PLIC_CLAIM_OFFSET +
                                       (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));

    return *claim_addr;
}

//中断完成

void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){

    unsigned long hart_id = read_csr(mhartid);                    //可适用于多核系统
    volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
                                        PLIC_CLAIM_OFFSET +
                                        (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
    *claim_addr = source;

}

 

1.5. main.c

这里只列出了主函数中和PLIC相关的函数,主函数中其他的详细部分将在PLIC有关的工程中进行介绍。

 

//PLIC使能
static void enable_plic_int(u8_t int_src)
{
    u8_t reg_off = 0;
    u8_t reg_val = 0;

    reg_off = (int_src / 32) * 4;            //根据定义
    reg_val = int_src & 0x1f;                  //只保留31位,1F(16)=31(10)

    PLIC_REG(PLIC_ENABLE_OFFSET + reg_off) |= 1 << reg_val;      //立起相应的位

    return;
}


//PLIC禁止
static void disable_plic_int(u8_t int_src)
{
    u8_t reg_off = 0;
    u8_t reg_val = 0;

    reg_off = (int_src / 32) * 4;               //根据定义
    reg_val = int_src & 0x1f;                    //只保留31位,1F(16)=31(10)

    PLIC_REG(PLIC_ENABLE_OFFSET + reg_off) &= ~(1 << reg_val);     //清除相应的位

    return;
}

 

 

Posted in RISC-V, RISC-V, RISC-V 外设, RISC-V 教案, 应用开发, 开发板, 教材与教案, 文章

发表评论

相关链接