raven FW with data and interrupt transfer (based on bldc project)
This commit is contained in:
		
							
								
								
									
										163
									
								
								raven/bsp/drivers/clic/clic_driver.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								raven/bsp/drivers/clic/clic_driver.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
// See LICENSE for license details.
 | 
			
		||||
 | 
			
		||||
#include "sifive/devices/clic.h"
 | 
			
		||||
#include "clic/clic_driver.h"
 | 
			
		||||
#include "platform.h"
 | 
			
		||||
#include "encoding.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void volatile_memzero(uint8_t * base, unsigned int size) {
 | 
			
		||||
  volatile uint8_t * ptr;
 | 
			
		||||
  for (ptr = base; ptr < (base + size); ptr++){
 | 
			
		||||
    *ptr = 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Note that there are no assertions or bounds checking on these
 | 
			
		||||
// parameter values.
 | 
			
		||||
void clic_init (
 | 
			
		||||
                clic_instance_t * this_clic,
 | 
			
		||||
                uintptr_t hart_addr,
 | 
			
		||||
                interrupt_function_ptr_t* vect_table,
 | 
			
		||||
                interrupt_function_ptr_t default_handler,
 | 
			
		||||
                uint32_t num_irq,
 | 
			
		||||
                uint32_t num_config_bits
 | 
			
		||||
                )
 | 
			
		||||
{
 | 
			
		||||
  this_clic->hart_addr=  hart_addr;
 | 
			
		||||
  this_clic->vect_table= vect_table;
 | 
			
		||||
  this_clic->num_config_bits= num_config_bits;
 | 
			
		||||
 | 
			
		||||
  //initialize vector table
 | 
			
		||||
  for(int i=0;i++;i<num_irq)  {
 | 
			
		||||
    this_clic->vect_table[i] = default_handler;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //set base vectors
 | 
			
		||||
  write_csr(mtvt, vect_table);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //clear all interrupt enables and pending
 | 
			
		||||
  volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIE), num_irq);
 | 
			
		||||
  volatile_memzero((uint8_t*)(this_clic->hart_addr+CLIC_INTIP), num_irq);
 | 
			
		||||
 | 
			
		||||
  //clear nlbits and nvbits; all interrupts trap to level 15
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG)=0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler) {
 | 
			
		||||
    this_clic->vect_table[source] = handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source) {
 | 
			
		||||
    *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source){
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIE+source) = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_set_pending(clic_instance_t * this_clic, uint32_t source){
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source){
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTIP+source) = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg){
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source) = intcfg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t clic_get_intcfg  (clic_instance_t * this_clic, uint32_t source){
 | 
			
		||||
  return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_INTCFG+source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg){
 | 
			
		||||
  *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG) = cfg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t clic_get_cliccfg  (clic_instance_t * this_clic){
 | 
			
		||||
  return *(volatile uint8_t*)(this_clic->hart_addr+CLIC_CFG);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//sets an interrupt level based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level) {
 | 
			
		||||
  //extract nlbits
 | 
			
		||||
  uint8_t nlbits = clic_get_cliccfg(this_clic);
 | 
			
		||||
  nlbits = (nlbits >>1) & 0x7;
 | 
			
		||||
 | 
			
		||||
  //shift level right to mask off unused bits
 | 
			
		||||
  level = level>>((this_clic->num_config_bits)-nlbits); //plus this_clic->nmbits which is always 0 for now.
 | 
			
		||||
  //shift level into correct bit position
 | 
			
		||||
  level = level << (8-this_clic->num_config_bits) + (this_clic->num_config_bits - nlbits);
 | 
			
		||||
 
 | 
			
		||||
  //write to clicintcfg
 | 
			
		||||
  uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
 | 
			
		||||
  clic_set_intcfg(this_clic, source, (current_intcfg | level));
 | 
			
		||||
 | 
			
		||||
  return level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//gets an interrupt level based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source) {
 | 
			
		||||
  uint8_t level;
 | 
			
		||||
  level = clic_get_intcfg(this_clic, source);
 | 
			
		||||
 | 
			
		||||
  //extract nlbits
 | 
			
		||||
  uint8_t nlbits = clic_get_cliccfg(this_clic);
 | 
			
		||||
  nlbits = (nlbits >>1) & 0x7;
 | 
			
		||||
 | 
			
		||||
  //shift level
 | 
			
		||||
  level = level >> (8-(this_clic->num_config_bits));
 | 
			
		||||
 | 
			
		||||
  //shift level right to mask off priority bits
 | 
			
		||||
  level = level>>(this_clic->num_config_bits-nlbits); //this_clic->nmbits which is always 0 for now.
 | 
			
		||||
 | 
			
		||||
  return level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//sets an interrupt priority based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority) {
 | 
			
		||||
  //priority bits = num_config_bits - nlbits
 | 
			
		||||
  //extract nlbits
 | 
			
		||||
  uint8_t nlbits = clic_get_cliccfg(this_clic);
 | 
			
		||||
  nlbits = (nlbits >>1) & 0x7;
 | 
			
		||||
 | 
			
		||||
  uint8_t priority_bits = this_clic->num_config_bits-nlbits;
 | 
			
		||||
  if(priority_bits = 0) {
 | 
			
		||||
    //no bits to set
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  //mask off unused bits
 | 
			
		||||
  priority = priority >> (8-priority_bits);
 | 
			
		||||
  //shift into the correct bit position
 | 
			
		||||
  priority = priority << (8-(this_clic->num_config_bits));
 | 
			
		||||
 | 
			
		||||
  //write to clicintcfg
 | 
			
		||||
  uint8_t current_intcfg = clic_get_intcfg(this_clic, source);
 | 
			
		||||
  clic_set_intcfg(this_clic, source, (current_intcfg | priority));
 | 
			
		||||
  return current_intcfg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//gets an interrupt priority based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source) {
 | 
			
		||||
  uint8_t priority;
 | 
			
		||||
  priority = clic_get_intcfg(this_clic, source);
 | 
			
		||||
 | 
			
		||||
  //extract nlbits
 | 
			
		||||
  uint8_t nlbits = clic_get_cliccfg(this_clic);
 | 
			
		||||
  nlbits = (nlbits >>1) & 0x7;
 | 
			
		||||
 | 
			
		||||
  //shift left to mask off level bits
 | 
			
		||||
  priority = priority << nlbits;
 | 
			
		||||
 | 
			
		||||
  //shift priority
 | 
			
		||||
  priority = priority >> (8-((this_clic->num_config_bits)+nlbits));
 | 
			
		||||
 | 
			
		||||
 return priority;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										44
									
								
								raven/bsp/drivers/clic/clic_driver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								raven/bsp/drivers/clic/clic_driver.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
// See LICENSE file for licence details
 | 
			
		||||
 | 
			
		||||
#ifndef PLIC_DRIVER_H
 | 
			
		||||
#define PLIC_DRIVER_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#include "platform.h"
 | 
			
		||||
 | 
			
		||||
typedef void (*interrupt_function_ptr_t) (void);
 | 
			
		||||
 | 
			
		||||
typedef struct __clic_instance_t
 | 
			
		||||
{
 | 
			
		||||
  uintptr_t hart_addr;
 | 
			
		||||
  interrupt_function_ptr_t* vect_table;
 | 
			
		||||
  uint32_t num_config_bits;
 | 
			
		||||
  uint32_t num_sources;  
 | 
			
		||||
} clic_instance_t;
 | 
			
		||||
 | 
			
		||||
// Note that there are no assertions or bounds checking on these
 | 
			
		||||
// parameter values.
 | 
			
		||||
void clic_init (clic_instance_t * this_clic, uintptr_t hart_addr, interrupt_function_ptr_t* vect_table, interrupt_function_ptr_t default_handler, uint32_t num_irq,uint32_t num_config_bits);
 | 
			
		||||
void clic_install_handler (clic_instance_t * this_clic, uint32_t source, interrupt_function_ptr_t handler);
 | 
			
		||||
void clic_enable_interrupt (clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
void clic_disable_interrupt (clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
void clic_set_pending(clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
void clic_clear_pending(clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
void clic_set_intcfg (clic_instance_t * this_clic, uint32_t source, uint32_t intcfg);
 | 
			
		||||
uint8_t clic_get_intcfg (clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
void clic_set_cliccfg (clic_instance_t * this_clic, uint32_t cfg);
 | 
			
		||||
uint8_t clic_get_cliccfg  (clic_instance_t * this_clic);
 | 
			
		||||
//sets an interrupt level based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_set_int_level( clic_instance_t * this_clic, uint32_t source, uint8_t level);
 | 
			
		||||
//get an interrupt level based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_get_int_level( clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
//sets an interrupt priority based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_set_int_priority( clic_instance_t * this_clic, uint32_t source, uint8_t priority);
 | 
			
		||||
//sets an interrupt priority based encoding of nmbits, nlbits
 | 
			
		||||
uint8_t clic_get_int_priority( clic_instance_t * this_clic, uint32_t source);
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include "platform.h"
 | 
			
		||||
 | 
			
		||||
#ifdef PRCI_BASE_ADDR
 | 
			
		||||
#ifdef PRCI_CTRL_ADDR
 | 
			
		||||
#include "fe300prci/fe300prci_driver.h"
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,19 +22,20 @@ void PLIC_init (
 | 
			
		||||
                plic_instance_t * this_plic,
 | 
			
		||||
                uintptr_t         base_addr,
 | 
			
		||||
                uint32_t num_sources,
 | 
			
		||||
                uint32_t num_priorities
 | 
			
		||||
                uint32_t num_priorities,
 | 
			
		||||
				uint32_t target_hartid
 | 
			
		||||
                )
 | 
			
		||||
{
 | 
			
		||||
  
 | 
			
		||||
  this_plic->base_addr = base_addr;
 | 
			
		||||
  this_plic->num_sources = num_sources;
 | 
			
		||||
  this_plic->num_priorities = num_priorities;
 | 
			
		||||
  this_plic->target_hartid = target_hartid;
 | 
			
		||||
  
 | 
			
		||||
  // Disable all interrupts (don't assume that these registers are reset).
 | 
			
		||||
  unsigned long hart_id = read_csr(mhartid);
 | 
			
		||||
  volatile_memzero((uint8_t*) (this_plic->base_addr +
 | 
			
		||||
                               PLIC_ENABLE_OFFSET +
 | 
			
		||||
                               (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
 | 
			
		||||
                               (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET)),
 | 
			
		||||
                   (num_sources + 8) / 8);
 | 
			
		||||
  
 | 
			
		||||
  // Set all priorities to 0 (equal priority -- don't assume that these are reset).
 | 
			
		||||
@@ -46,7 +47,7 @@ void PLIC_init (
 | 
			
		||||
  volatile plic_threshold* threshold = (plic_threshold*)
 | 
			
		||||
    (this_plic->base_addr +
 | 
			
		||||
     PLIC_THRESHOLD_OFFSET +
 | 
			
		||||
     (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
 | 
			
		||||
     (this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET));
 | 
			
		||||
 | 
			
		||||
  *threshold = 0;
 | 
			
		||||
  
 | 
			
		||||
@@ -55,10 +56,9 @@ void PLIC_init (
 | 
			
		||||
void PLIC_set_threshold (plic_instance_t * this_plic,
 | 
			
		||||
			 plic_threshold threshold){
 | 
			
		||||
 | 
			
		||||
  unsigned long hart_id = read_csr(mhartid);  
 | 
			
		||||
  volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
 | 
			
		||||
                                                              PLIC_THRESHOLD_OFFSET +
 | 
			
		||||
                                                              (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
 | 
			
		||||
                                                              (this_plic->target_hartid << PLIC_THRESHOLD_SHIFT_PER_TARGET));
 | 
			
		||||
 | 
			
		||||
  *threshold_ptr = threshold;
 | 
			
		||||
 | 
			
		||||
@@ -67,10 +67,9 @@ void PLIC_set_threshold (plic_instance_t * this_plic,
 | 
			
		||||
 | 
			
		||||
void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
 | 
			
		||||
 | 
			
		||||
  unsigned long hart_id = read_csr(mhartid);
 | 
			
		||||
  volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
 | 
			
		||||
                                                        PLIC_ENABLE_OFFSET +
 | 
			
		||||
                                                        (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
 | 
			
		||||
                                                        (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) +
 | 
			
		||||
                                                        (source >> 3));
 | 
			
		||||
  uint8_t current = *current_ptr;
 | 
			
		||||
  current = current | ( 1 << (source & 0x7));
 | 
			
		||||
@@ -80,10 +79,9 @@ void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
 | 
			
		||||
 | 
			
		||||
void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){
 | 
			
		||||
  
 | 
			
		||||
  unsigned long hart_id = read_csr(mhartid);
 | 
			
		||||
  volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
 | 
			
		||||
                                                         PLIC_ENABLE_OFFSET +
 | 
			
		||||
                                                         (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
 | 
			
		||||
                                                         (this_plic->target_hartid << PLIC_ENABLE_SHIFT_PER_TARGET) +
 | 
			
		||||
                                                         (source >> 3));
 | 
			
		||||
  uint8_t current = *current_ptr;
 | 
			
		||||
  current = current & ~(( 1 << (source & 0x7)));
 | 
			
		||||
@@ -104,12 +102,10 @@ void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_pr
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
     (this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET));
 | 
			
		||||
 | 
			
		||||
  return  *claim_addr;
 | 
			
		||||
  
 | 
			
		||||
@@ -117,10 +113,9 @@ plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
                                                                (this_plic->target_hartid << PLIC_CLAIM_SHIFT_PER_TARGET));
 | 
			
		||||
  *claim_addr = source;
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ typedef struct __plic_instance_t
 | 
			
		||||
 | 
			
		||||
  uint32_t num_sources;
 | 
			
		||||
  uint32_t num_priorities;
 | 
			
		||||
  
 | 
			
		||||
  uint32_t target_hartid;
 | 
			
		||||
} plic_instance_t;
 | 
			
		||||
 | 
			
		||||
typedef uint32_t plic_source;
 | 
			
		||||
@@ -25,7 +25,8 @@ void PLIC_init (
 | 
			
		||||
                plic_instance_t * this_plic,
 | 
			
		||||
                uintptr_t         base_addr,
 | 
			
		||||
                uint32_t num_sources,
 | 
			
		||||
                uint32_t num_priorities
 | 
			
		||||
                uint32_t num_priorities,
 | 
			
		||||
				uint32_t target_hartid
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
void PLIC_set_threshold (plic_instance_t * this_plic,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user