problem with IPC on 4357

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

problem with IPC on 4357

712 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by maszup on Fri Apr 19 02:04:52 MST 2013

Hello

I'm trying to run a simple IPC communication between M4 and M0.
I have LPC4357 Embedded Artists EVB running 
<a title="http://www.embeddedartists.com/products/kits/lpc4357_kit.php" href="http://www.embeddedartists.com/products/kits/lpc4357_kit.php">http://www.embeddedartists.com/products/kits/lpc4357_kit.php</a>
under LPCxpresso (v5.1.2.2065 - recently downloaded).

I have found example of IPC dual core using queues for LPC4357 cpu (without RTOS):
<a title="http://www.lpcware.com/content/nxpfile/an11177-inter-processor-communication-lpc43xx " href="http://www.lpcware.com/content/nxpfile/an11177-inter-processor-communication-lpc43xx%20">http://www.lpcware.com/content/nxpfile/an11177-inter-processor-communication-lpc43xx</a> 
directly here:


<a title="http://sw.lpcware.com/?p=lpc43xx.git;a=tree;f=Examples/DUALCORE/Queue_Demo;h=397e0b718c31c4629070190..." href="http://sw.lpcware.com/?p=lpc43xx.git;a=tree;f=Examples/DUALCORE/Queue_Demo;h=397e0b718c31c4629070190...">http://sw.lpcware.com/?p=lpc43xx.git;a=tree;f=Examples/DUALCORE/Queue_Demo;h=397e0b718c31c4629070190...</a>


where in API file (IPC_queue.c) i changed only the interrupt functions to  

/* interrupt function for the Slave queue */
void M0_M4CORE_IRQHandler(void) {
LPC_CREG-&gt;M4TXEVENT = 0x0;
cmdPending = PENDING;
}

/* interrupt function setting the flags for the application */
/* interrupt to master from slave */
void M0CORE_IRQHandler() {
LPC_CREG-&gt;M0TXEVENT = 0x0;
msgPending = PENDING;
}



So...

I have put the code of M0 into its default flash address 0x1b000000. then I'm debugging M4 in following order:

1. M4 boots and runs SystemInit();

2. M4 goes directly to function cM4restart();

3. There M4 halts slave, configure IPC queue, set M0 shadow register and starts up M0 (I do not load M0's image since it is already loaded into flash)

4. M4 waits for 1st msg from M0 - it gets it

5. M4 checks the 1st msg - status is SUCCESS - everything seems to be fine

6. M4 tries to return from function cM4restart() - it hangs! debugger goes to some unkown address of M0's flash memory 0x1b000338

I have also debugged that M4 enters the M0CORE_IRQHandler() so it gets the interrupt from M0.


I already switched off everything in my code leaving only IPC. Previously I had used UART for debugging, systick in M4 for measuring time in M4, Timer0 in M0 for measuring time in M0. But then i had hard faults in M4. so i left only IPC and tried to debug.

I presume that something is going wrong with interrupts but I'm not sure.

I don't know if below addresses are OK:

/* these addresses specify where the IPC queues shall be located */
#define MASTER_CMD_BLOCK_START 0x20008000
#define SLAVE_MSG_BLOCK_START 0x2000A000

and that the interrupts of IPC have priority = 0.



[B]I have attached exported project from LPCxpresso.[/B]


Below is my cM4restart() function:

void cM4restart(void) {
Status status = ERROR;

IPC_haltSlave();
//lpc_printf("%010d Core M0 stopped\r\n",rtcGetTime_ms());

// setup the queue system
IPC_masterInitQueue(&amp;_hostCmdBufferData[0], MASTER_CMDBUF_SIZE, &amp;_hostMsgBufferData[0], SLAVE_MSGBUF_SIZE);
//lpc_printf("%010d Core M4 IPC initialized\r\n", rtcGetTime_ms());

// Set M0's vector table to point to start of M0 image
LPC_CREG-&gt;M0APPMEMMAP = 0x1B000000;//(unsigned int)&amp;CM0image_start;
//lpc_printf("%010d Core M0 shadow register 0x%X\r\n", rtcGetTime_ms(), LPC_CREG-&gt;M0APPMEMMAP);

IPC_startSlave();
//lpc_printf("%010d Core M0 started\r\n",rtcGetTime_ms());

// wait for the M0 to signal being ready via a message to the command queue
while(!IPC_msgPending())
__WFI();
//lpc_printf("%010d Core M0 IPC ready\r\n", rtcGetTime_ms(),qstatus);

qstatus = IPC_masterPopMsg(&amp;msgBack);
if(qstatus == QVALID) {

msgType = IPC_getMsgType((msgToken*)&amp;msgBack);
if(msgType == MSG_SRV) {
serviceMessage = (srvMsg*) &amp;msgBack;
taskId = serviceMessage-&gt;msgClass.parsedMsg.servicingAnswer.id;
statusInfo = serviceMessage-&gt;msgClass.parsedMsg.servicingAnswer.ss;

if(taskId == CORE_TASK_INIT &amp;&amp; statusInfo) {
//lpc_printf("%010d Core M0 initialized\r\n", rtcGetTime_ms());
status = SUCCESS;
} else {
//err
}
} else {
//err
}
} else {
//err
}

} //here the function does not return - program goes to undefined address


Thank you for any kind of help

Original Attachment has been moved to: sources-M4.zip

Original Attachment has been moved to: sources-M0_1.zip

Labels (1)
0 Kudos
1 Reply

524 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by maszup on Fri Apr 26 00:02:05 MST 2013

the problem i had was solved by doing followning actions:

1) in lpcexpresso M0/M4 projects configure MCU settings to use different RAM memory regions. proviously M0/M4 were using the same ram and i got hard faults. that allowed me to run M0 from M4

2) change the way of debugging - by using debugger in lpcxpresso i thought i was running the code on M0 but in fact i did it on M4. in order to do it properly configure your Launch configuration for M0 so that it not Load the image to target "Load image" = FALSE @ Launch Configuration-&gt;Debugger-&gt;Script Values. Then i load both codes on M0/M4 with flasher and while running the code jump into M0 code with debugger - in this way M4 always runs M0 at startup

3) configure timer in M4 and just enable/disable its interrupt in M0. I was not able to configure timer at the M0 (rit or timer0). I don't know why yet but probably i forgot about something.

4) IPC example on queues did not work. it stopped after the second message recieved from M0. so i decided to simplify that and used IPC interrupts only and made my own communication structure which i located in shared memory space:

CORE_DATA* const coreMasterData = (CORE_DATA*) MASTER_BLOCK_START;
CORE_DATA* const coreSlaveData = (CORE_DATA*) SLAVE_BLOCK_START;

typedef struct {
Bool busy;
uint32_t cmd;
uint32_t param;
}CORE_DATA;

void slaveInterruptCallback(void) {

command = coreMasterData-&gt;cmd;
parameter = coreMasterData-&gt;param;

switch(command) {

case ...

break;
case ...

break;
default:
break;
}

coreSlaveData-&gt;cmd = command;
coreSlaveData-&gt;param = parameter;

IPC_resetIntFlag();
IPC_sendInterrupt(); //send reply immediately

return;
}

Status cM4send(uint32_t cmd, uint32_t param) {

if(coreMasterData-&gt;busy) {
return ERROR;
}
coreMasterData-&gt;param = param;
coreMasterData-&gt;cmd = cmd;
coreMasterData-&gt;busy = TRUE;

IPC_sendInterrupt();

//set some custom timer to wait max time for reply from M0

return SUCCESS;
}

i don't know the reson why the eample on queues did not work longterm, probably i did something wrong but for first setup this simple data handling is enough for me.

that should be all. mostly the strange things i got was due to the common ram between cores.

I hope that helps to somone in solving dual core startup problems

0 Kudos