我的工程是从vlfft_evmc6678l衍生出来的一个工程,程序架构我参考了mcsdk下面的image_processing_evmc6678l ipc模式的架构设计,该工程也实现了多核计算FFT的功能,core0是主核,其余core是从核,核间通过ipc ,MessageQ实现通信。多核加载方式为EMIF NOR FLASH 模式,core0 通过自己写的bootload.asm实现自启,core0启动之后,由core0将flash中其他core的程序代码拷贝到各自的L2中,发送IPC中断实现自启。
但是现在遇到以下的问题。
整体上有两个工程,一个主核的master工程,一个从核的slave工程。在使用JTAG仿真调试的时候,除了在load程序的之前,需要进行一下System Reset,否则会出错,程序没有任何问题,运行也很稳定。
现在我把工程烧写在Nor Flash,想要上电自启,但是不能成功。
我尝试了以下几种情况,确定了问题是跟Ipc_start有关系。
先做一个说明:
主核和从核程序代码的主函数在后面附有。#if0…#end 之间代码是Ipc_start 和 MessageQ建立的一些代码。从现象来看问题就和这段代码有关。
尝试一:屏蔽主核和从核程序中#if0…#end之间的代码,只让core0通过bootload实现自启,没有core0加载其他core1-7的过程。观察core0 的0x860000地址的值是否正确,结果为可以成功加载。
尝试二:屏蔽主核和从核程序中#if0…#end之间的代码,core0通过bootload实现自启,添加core0加载其他core1-7的过程。观察每个core的0x860000地址的值是否正确,结果为可以成功加载。 此时,我查看了core0的 IER 的值为0x4783,中断 IE14(未知),IE7-10(网络中断),NMI 处于激活状态。Core1-7的 IER为0x3。
尝试三:屏蔽主核程序中#if0…#end之间的代码,打开从核程序中#if0…#end之间的代码,core0通过bootload实现自启,添加core0加载其他core1-7的过程。观察每个core的0x860000地址的值是否正确,结果为可以成功加载,但是core1-7 的pc指针会停在各自的Ipc_start函数中,这与预想结果一致。
尝试四:打开主核和从核程序中#if0…#end之间的代码,即将主核和从核代码中的#if0改成#if1,core0通过bootload实现自启,添加core0加载其他core1-7的过程。观察每个core的0x860000地址的值是否正确,结果为加载失败。我连接JTAG,查看所有core的pc指针,发现所有core都处于复位状态,如下图所示。此时,我查看了core0的 IER 的值为0x1,Core1-7的 IER为0x13。但是在这种情况下,用JTAG仿真调试一点问题都没有,跑的也很稳定。怎么解释?
我想问以下几个问题:
- load程序之前需要进行一下System Reset,即使是重新上电也需要System Reset,否则会出错,是怎么原因导致的。它会不会影响自启,我bootmode配置的是EMIF NOR FLASH。
- IE14是ROM bootloader中激活的ipc中断,还是IE04是,对Ipc_start()有没有影响?我尝试在main函数开头设置IER = 0;好像不起作用,还会把网络中断也给disable。目前我将IER = 0放在Reset模块的 system_reset的函数中,但是没有什么作用。
- 很明显,现象跟Ipc_start()的执行有关,我想请问Ipc_start()对自启到底有什么影响?为什么会将系统复位了? 还是在未进main函数之前系统就已经复位了,再也没有进入到main函数之中来。
- 在config文件中,Ipc.procSync is set to Ipc.ProcSync_ALL, 和 core0 启动其它core1-7的ipc中断有没有冲突?有冲突怎么解决?
- 你们有没有做过带有IPC MessageQ实现核间通信的工程可以进行flash自启的例子,可否提供一个?image_processing_evmc6678l ipc模式的工程好像与此类似,不知你们是否试过这个可否实现多核加载。
以下是主核core0函数的代码,
/*
* ======== main ========
* Synchronizes all processors (in Ipc_start) and calls BIOS_start
*/
Int main(Int argc, Char* argv[])
{
Int status;
HeapBufMP_Handle heapHandle;
HeapBufMP_Params heapBufParams;
Task_Params params;
System_printf("enter main()\n");
Board_init();//系统时钟,DDR3,EMIF,以太网初始化,
*(int*) 0x860000 = 0xaa55aa55; //自启测试地址
#if 0
/*
* Ipc_start() calls Ipc_attach() to synchronize all remote processors
* because 'Ipc.procSync' is set to 'Ipc.ProcSync_ALL' in *.cfg
*/
status = Ipc_start();
if (status < 0) {
System_abort("Ipc_start failed\n");
}
/*
* Create the heap that will be used to allocate messages.
*/
HeapBufMP_Params_init(&heapBufParams);
heapBufParams.regionId = 0;
heapBufParams.name = HEAP_NAME;
heapBufParams.numBlocks = 24;
heapBufParams.align = 128;
heapBufParams.blockSize = sizeof(process_message_t);
heapHandle = HeapBufMP_create(&heapBufParams);
if (heapHandle == NULL) {
System_abort("HeapBufMP_create failed\n" );
}
/* Register this heap with MessageQ */
MessageQ_registerHeap((IHeap_Handle)heapHandle, HEAPID);
/* Generate queue names based on own proc ID and total number of procs */
System_sprintf(localQueueName, "CORE%d", MultiProc_self());
System_sprintf(core0QueueName, "CORE%d", 0 );
System_sprintf(core1QueueName, "CORE%d", 1 );
System_sprintf(core2QueueName, "CORE%d", 2 );
System_sprintf(core3QueueName, "CORE%d", 3 );
System_sprintf(core4QueueName, "CORE%d", 4 );
System_sprintf(core5QueueName, "CORE%d", 5 );
System_sprintf(core6QueueName, "CORE%d", 6 );
System_sprintf(core7QueueName, "CORE%d", 7 );
/* Create a unique 'master' Task if on proc 0 */
Task_Params_init(¶ms);
params.stackSize = 0x2000;
params.priority = 7;
Task_create(tsk_master_func, ¶ms, NULL);
#endif
BIOS_start();
return (0);
}
从核(core1-core7)代码:
/*
* ======== main ========
* Synchronizes all processors (in Ipc_start) and calls BIOS_start
*/
Int main(Int argc, Char* argv[])
{
Int status;
Task_Params params;
System_printf("enter main()\n");
IER = 0x3;
*(int*)0x860000 = 0xAA55AA55;
#if 0
/*
* Ipc_start() calls Ipc_attach() to synchronize all remote processors
* because 'Ipc.procSync' is set to 'Ipc.ProcSync_ALL' in *.cfg
*/
status = Ipc_start();
if (status < 0) {
System_abort("Ipc_start failed\n");
}
/* Generate queue names based on own proc ID and total number of procs */
System_sprintf(localQueueName, "CORE%d", MultiProc_self());
System_sprintf(core0QueueName, "CORE%d", 0 );
System_sprintf(core1QueueName, "CORE%d", 1 );
System_sprintf(core2QueueName, "CORE%d", 2 );
System_sprintf(core3QueueName, "CORE%d", 3 );
System_sprintf(core4QueueName, "CORE%d", 4 );
System_sprintf(core5QueueName, "CORE%d", 5 );
System_sprintf(core6QueueName, "CORE%d", 6 );
System_sprintf(core7QueueName, "CORE%d", 7 );
/* Create a unique Task */
Task_Params_init(¶ms);
params.stackSize = 0x2000;
Task_create(tsk_slave_func, ¶ms, NULL);
#endif
BIOS_start();
return (0);
}