Following the last posting, I'll continue to talk about Interrupt controler register.
typedef union DistributorCtrl_t
{
uint32_t all;
struct {
uint32_t Enable:1; // 0
uint32_t reserved:31;
} bits;
} DistributorCtrl_t;
Now I will examine the code.
#include "stdint.h"
#include "memio.h"
#include "Interrupt.h"
#include "HalInterrupt.h"
#include "armcpu.h"
extern volatile GicCput_t* GicCpu;
extern volatile GicDist_t* GicDist;
static InterHdlr_fptr sHandlers[INTERRUPT_HANDLER_NUM];
void Hal_interrupt_init(void){
GicCpu->cpucontrol.bits.Enable =1;
GicDist->distributorctrl.bits.Enable = 1;
GicCpu->prioritymask.bits.Prioritymask = GIC_PRIORITY_MASK_NONE;
for(uint32_t i = 0; i< INTERRUPT_HANDLER_NUM; i++){
sHandlers[i] = NULL;
}
enable_irq();
}
void Hal_interrupt_enable(uint32_t interrupt_num){
if((interrupt_num < GIC_IRQ_START) ||(interrupt_num > GIC_IRQ_END ) )
return;
uint32_t bit_num = interrupt_num - GIC_IRQ_START;
if(bit_num < GIC_IRQ_START){
SET_BIT(GicDist->setenable1, bit_num);
}
else{
bit_num = bit_num - GIC_IRQ_START;
SET_BIT(GicDist->setenable2, bit_num);
}
}
void Hal_interrupt_disable(uint32_t interrupt_num){
if((interrupt_num < GIC_IRQ_START) ||(interrupt_num > GIC_IRQ_END ) )
return;
uint32_t bit_num = interrupt_num - GIC_IRQ_START;
if(bit_num < GIC_IRQ_START){
CLR_BIT(GicDist->setenable1, bit_num);
}
else{
bit_num = bit_num - GIC_IRQ_START;
CLR_BIT(GicDist->setenable2, bit_num);
}
}
void Hal_interrupt_register_handler(InterHdlr_fptr handler, uint32_t interrupt_num){
sHandlers[interrupt_num] = handler;
}
void Hal_interrupt_run_handler(){
uint32_t interrupt_num = GicCpu->interruptack.bits.InterruptID;
if(sHandlers[interrupt_num] != NULL){
sHandlers[interrupt_num]();
}
GicCpu->endofinterrupt.bits.InterruptID = interrupt_num;
}
It mainly sets registers previously described in this and last posting.
'sHandler [ Interrupt_num ]' is a containor of interrupt handlers.
'SET_BIT' and 'CLR_BIT' are macro defined in 'memio.h'
#define SET_BIT(p,n) ((p) |= ( 1 << (n)))
#define CLR_BIT(p,n) ((p) &= ~( 1 << (n)))
Therefore, "SET_BIT(GicDist->setenable1, n)" set n th bit 1. And "CLR_BIT" oppositely works.
void enable_irq(void){
__asm__ ("PUSH {r0, r1}");
__asm__ ("MRS r0, cpsr");
__asm__ ("BIC r1, r0, #0x80");
__asm__ ("MSR cpsr, r1");
__asm__ ("POP {r0, r1}");
}