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

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

IPCARx

IPCARx(IPC Acknowledgement Register)是用来相应IPC中断的寄存器。其寄存器结构如下图所示: 在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

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中断服务函数。

Copyright © 2088 世界杯欧洲预选赛_南非世界杯主题曲舞蹈 - lyzkxt.com All Rights Reserved.
友情链接