【TMS320C6678】IPC中断响应2次原因

IPC

IPC(Inter-Processor Communication)是C6678中用于核间交互的一种方式。

每个核可以通过IPC中断来和其他核进行交互,以达到核间同步的目的,也可以用作一个核给另外一个核的定向通知。

Each of the cores can communicate with one another through inter-processor interrupts for core synchronization, allowing for direct notification from one core to another.

IPC寄存器

在C6678(Keystone I)架构中,有IPCGRx和IPCARx两类寄存器,其中x表示为核心号core_num。

IPCGRx

IPCGRx(IPC Generation Register)用于产生一个IPC中断。其寄存器结构如下图所示:
IPCGR
在IPCGRx中,IPCGRx[0](IPCG)为IPC中断使能位,当该位置1,将会给核心core_num = x产生一个IPC中断;IPCGR[31:4](SRCS)是可以用来区分IPC中断的源ID,用户可以自由的将这几位配置成不同含义,用于不同消息类型的IPC通知。

IPCARx

IPCARx(IPC Acknowledgement Register)是用来相应IPC中断的寄存器。其寄存器结构如下图所示:
IPCAR
在IPCAR[31:4](SRCC)中写入1,可清除IPCGR中对应的SRCS位。

IPC中断程序

IPC中断配置

IPC中断作为一个Primary Events,跟其他Primary Events的配置方式也相同。
两个核心都需要使能全局中断和IPC中断。

使能全局中断
CSL_IntcContext context;
CSL_IntcEventHandlerRecord recordTable[CSL_INTC_EVENTID_CNT];

int interrupt_init(void)
{
    // the interrupt handler function table
    context.eventhandlerRecord = recordTable;
    // the num of interrupt, equal the num of the function table
    context.numEvtEntries = CSL_INTC_EVENTID_CNT;        // 不懂什么意思
    // must be called once before using the CSL INTC APIs.
    if (CSL_intcInit(&context) != CSL_SOK){
        printf("Error: GEM-INTC initialization failed\n");
        return -1;
    }

    // enable the global interrupt and NMI
    // must be enabled if want to use INT4-15
    if (CSL_intcGlobalEnable(NULL) != CSL_SOK){
        printf("Error: GEM-INTC global NMI enable failed\n");
        return -1;
    }

    if (CSL_intcGlobalNmiEnable() != CSL_SOK)
    {
        printf("Error: GEM-INTC global NMI enable failed\n");
        return -1;
    }

    return 0;
}
使能IPC中断
static ipc_interruptCfg ipc_intInfo[8] = 
{
    {0,     91,     CSL_INTC_VECTID_6,  NULL},
    {1,     91,     CSL_INTC_VECTID_6,  &IPC_ISR_core1},
    {2,     91,     CSL_INTC_VECTID_6,  NULL},
    {3,     91,     CSL_INTC_VECTID_6,  NULL},
    {4,     91,     CSL_INTC_VECTID_6,  NULL},
    {5,     91,     CSL_INTC_VECTID_6,  NULL},
    {6,     91,     CSL_INTC_VECTID_6,  NULL},
    {7,     91,     CSL_INTC_VECTID_6,  NULL},
};

static volatile unsigned int IPCGRx_addr[8] =
{
    0x02620240,               //IPCGR0
    0x02620244,               //IPCGR1
    0x02620248,               //IPCGR2
    0x0262024c,               //IPCGR3
    0x02620250,               //IPCGR4
    0x02620254,               //IPCGR5
    0x02620258,               //IPCGR6
    0x0262025c,               //IPCGR7
};

static volatile unsigned int IPCGAx_addr[8] =
{
    0x02620280,               //IPCAR0
    0x02620284,               //IPCAR1
    0x02620288,               //IPCAR2
    0x0262028c,               //IPCAR3
    0x02620290,               //IPCAR4
    0x02620294,               //IPCAR5
    0x02620298,               //IPCAR6
    0x0262029c,               //IPCAR7
};

void ipc_interrupt_init(void)
{
    Uint32 core_id;
    CSL_IntcObj ipc_intc_obj;
    CSL_IntcHandle  ipc_intc_hnd;
    CSL_IntcEventHandlerRecord EventRecord;
    CSL_IntcEventId event_ID;
    CSL_IntcParam   vectID;
    
    core_id = CSL_chipReadReg(CSL_CHIP_DNUM);
    if( ipc_intInfo[core_id].core == core_id )
    {
        event_ID = ipc_intInfo[core_id].event_ID;
        vectID = ipc_intInfo[core_id].vect;

        ipc_intc_hnd = CSL_intcOpen(&ipc_intc_obj, event_ID, &vectID, NULL);
        if(ipc_intc_hnd == NULL)
        {
            printf("Error: GEM-INTC Open failed\n");
            return;
        }

        if (ipc_intInfo[core_id].isr != NULL)
        {
            EventRecord.handler = ipc_intInfo[core_id].isr;
        }
        else
        {
            printf("Please add a ISR function!\n");
            return;
        }
        EventRecord.arg = (void *)event_ID;
        if (CSL_intcPlugEventHandler(ipc_intc_hnd, &EventRecord) != CSL_SOK)
        {
            printf("Error: GEM-INTC Plug event handler failed\n");
            return;
        }

        /* Enabling the events. */
        if (CSL_intcHwControl(ipc_intc_hnd, CSL_INTC_CMD_EVTENABLE, NULL) != CSL_SOK)
        {
            printf("Error: GEM-INTC CSL_INTC_CMD_EVTENABLE command failed\n");
            return;
        }
    }
    else
    {
        printf("IPC: ipc_intInfo.core is in wrong order, ipc init failed !!!\n");
    }
}
触发IPC中断
#include <ti/csl/csl_bootcfgAux.h>
void ipc_interrupt_trig(int core_id, Uint32 src)
{
    CSL_BootCfgUnlockKicker();
    *(volatile unsigned int *)(IPCGRx_addr[core_id]) = src & 0xFFFFFFF8;   // send a inter-core interrupt to core[dnum]
    *(volatile unsigned int *)(IPCGRx_addr[core_id]) |= 1;
    CSL_BootCfgLockKicker();
}
IPC中断服务函数
void IPC_ISR_core1(void *arg)
{
    volatile unsigned int read_ipcgr;
    Uint32 core_id;
    core_id = CSL_chipReadReg(CSL_CHIP_DNUM);

    //当前核接收到的信息
    read_ipcgr = *(volatile unsigned int *)(IPCGRx_addr[core_id]);
    
    CSL_BootCfgUnlockKicker();
    //清除SRCS位
    *(volatile unsigned int *) IPCGAx_addr[core_id] = read_ipcgr; //clear the related source info
    CSL_BootCfgLockKicker();

    //根据read_ipcgr中的源ID添加相应的中断处理
}

IPC中断使能一次,但是IPC_ISR响应两次

在Keystone I关于IPC的手册(2.4节)中说明,

Any master that has access to BOOTCFG space can write to these registers.

向IPCGRx和IPCARx寄存器中写入数据都需要访问BOOTCFG的权限,因此在IPC中断触发和清楚IPC中断标志位的过程中写入寄存器IPCGRx和IPCARx都需要进行KICK0和KICK1的解锁操作,即CSL_BootCfgUnlockKicker();这样才能正确清除IPC中断标志位,否则将触发两次IPC中断,执行两次IPC中断服务函数。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值