blob: e193dba64e5e0d4e56392e5903c3116d079de63d [file] [log] [blame]
// See LICENSE for license details.
#include <stdio.h>
#include "common.h"
#include "riscv_encoding.h"
#include "interrupt_control.h"
#include "register.h"
#include "FreeRTOS.h"
void pic_set_threshold(uint32_t threshold)
{
volatile uint32_t* threshold_ptr = (uint32_t*) (PIC_CTRL_ADDR +
PIC_THRESHOLD_OFFSET);
*threshold_ptr = threshold;
}
void pic_enable_interrupt(uint32_t source)
{
volatile uint32_t * current_ptr = (volatile uint32_t *)(PIC_CTRL_ADDR +
PIC_ENABLE_OFFSET +
((source >> 3) & (~0x3))//Source number divide 32 and then multip 4 (bytes)
);
uint32_t current = *current_ptr;
current = current | ( 1 << (source & 0x1f));// Only check the least 5 bits
*current_ptr = current;
}
void pic_disable_interrupt (uint32_t source){
volatile uint32_t * current_ptr = (volatile uint32_t *) (PIC_CTRL_ADDR +
PIC_ENABLE_OFFSET +
((source >> 3) & (~0x3))//Source number divide 32 and then multip 4 (bytes)
);
uint32_t current = *current_ptr;
current = current & ~(( 1 << (source & 0x1f)));// Only check the least 5 bits
*current_ptr = current;
}
void pic_set_priority (uint32_t source, uint32_t priority){
if (PIC_NUM_PRIORITIES > 0) {
volatile uint32_t * priority_ptr = (volatile uint32_t *)
(PIC_CTRL_ADDR +
PIC_PRIORITY_OFFSET +
(source << PIC_PRIORITY_SHIFT_PER_SOURCE));// Each priority reg occupy a word, so multiple 2
*priority_ptr = priority;
}
}
uint32_t pic_claim_interrupt(void){
volatile uint32_t * claim_addr = (volatile uint32_t * )
(PIC_CTRL_ADDR +
PIC_CLAIM_OFFSET
);
return *claim_addr;
}
uint32_t pic_check_eip(void){
volatile uint32_t * eip_addr = (volatile uint32_t * )
(PIC_CTRL_ADDR +
PIC_EIP_OFFSET
);
return *eip_addr;
}
void pic_complete_interrupt(uint32_t source){
volatile uint32_t * claim_addr = (volatile uint32_t *) (PIC_CTRL_ADDR +
PIC_CLAIM_OFFSET
);
*claim_addr = source;
}
void DefaultInterruptHandler(void)
{
}
int RegisterIrq(uint32_t int_num, uint32_t int_priority, function_ptr_t handler) {
pic_interrupt_handlers[int_num] = handler;
pic_set_priority(int_num, int_priority);
// pic_enable_interrupt (int_num);
return 0;
}
int UnRegisterIrq(uint32_t int_num)
{
pic_interrupt_handlers[int_num] = DefaultInterruptHandler;
pic_set_priority(int_num, 0);
return 0;
}
int EnableIrq(uint32_t ulIrq)
{
UBaseType_t uxSavedInterruptStatus;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
pic_enable_interrupt(ulIrq);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
return 0;
}
int DisableIrq(uint32_t ulIrq)
{
UBaseType_t uxSavedInterruptStatus;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
pic_disable_interrupt(ulIrq);
portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
return 0;
}
int SetIrqPriority(uint32_t ulIrq, uint32_t ulPri)
{
pic_set_priority(ulIrq, ulPri);
return 0;
}
static unsigned int irq_setting[IRQ_EN_REG_NUM];
/*N205 does not support clear pending irq.*
*Need use work around to clear pending: *
*1. disable irq (MIE) *
*2. store and disable current enable irq *
*3. enable target irq *
*4. claim and complete target irq *
*5. disable target irq *
*6. restore current irq enable setting *
*7. enable irq (MIE)
*/
int ClearPendingIrq(uint32_t ulIrq)
{
unsigned int i;
volatile uint32_t * current_ptr;
unsigned long irq_status;
irq_status = interrupt_status_get();
if (irq_status)
interrupt_disable();
for (i = 0; i < IRQ_EN_REG_NUM; i++)
{
current_ptr =
(volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET + i*4);
irq_setting[i] =
REG32(current_ptr);
REG32(current_ptr) = 0;
}
pic_enable_interrupt(ulIrq);
i = pic_claim_interrupt();
if (i)
pic_complete_interrupt(i);
pic_disable_interrupt(ulIrq);
for (i = 0; i < IRQ_EN_REG_NUM; i++)
{
current_ptr =
(volatile uint32_t *)(PIC_CTRL_ADDR + PIC_ENABLE_OFFSET + i*4);
REG32(current_ptr) = irq_setting[i];
}
if (irq_status)
interrupt_enable();
return 0;
}