mcapi communication between arm core and sharc core2 on sc589

Hello,

I have been trying to get some basic mcapi comms working between the arm core and sharc core1 and also the arm core and sharc core2. Arm -> Sharc Core1 worked very easily but for some reason that I can't figure out yet I can't get the arm -> Sharc Core2 to work. As in the arm application hangs when it tries to get the remote endpoint from sharc core2.

I am compiling the sharc application as loader file (ldr) and then I'm successfully loading it using the loadSharc_SC589 loader on the board. The applications run successfully on both cores (and the project settings in cces are set appropriately for each core). They are literally just the code the the loader needs (copied from Audio_passthrough_I2S_Core1 ->recv_arg.c file) and then just some basic mcapi code to initialize mcapi, create a local endpoint and get the remote endpoint (that is running on the arm core). It looks like this:

   

#include <sys/platform.h>
#include <sys/adi_core.h>

#include <stdio.h>
#include <stdlib.h>
#include <defSC589.h>
#include <mcapi.h>
#include <string.h>
#include "adi_initialize.h"
#include "recv_arg.h"

#define BUF_SIZE		64
#define DOMAIN			0
#define NODE_0			0

/*
 * mcapiErrorCheck()
 *
 * This function checks the status code, and if it is not MCAPI_SUCCESS then
 * an error message is output and the program exits. This should typically
 * be called after every MCAPI call which returns a status, during development
 * and debugging at least.
 */
static void mcapiErrorCheck(mcapi_status_t mcapi_status, const char *psContext, int result)
{
	char errorStringBuff[BUF_SIZE];

	if ((MCAPI_SUCCESS != mcapi_status) && (MCAPI_PENDING != mcapi_status))
	{
		mcapi_display_status(mcapi_status, errorStringBuff, sizeof(errorStringBuff));
		printf("MCAPI Error %s, status = %d [%s]\n",
				psContext,
				mcapi_status,
				errorStringBuff);
		exit(result);
	}
}

int main(int argc, char *argv[])
{
	/* Receive arguments from the RSL */
	recv_arg(&argc, &argv);

	int recv_num = 0;
	size_t msg_size = 0;
	char msg[BUF_SIZE];
	mcapi_status_t mcapi_status;
	mcapi_endpoint_t local_ep;
	mcapi_endpoint_t remote_ep;

	/* Initialize managed drivers and/or services */
	if ( 0 != adi_initComponents() )
	{
		printf("[CORE2]: Error initializing components\n");
	}

	local_ep = mcapi_endpoint_create(101, &mcapi_status);
	mcapiErrorCheck(mcapi_status, "create endpoint", 2);
	remote_ep = mcapi_endpoint_get(DOMAIN, NODE_0, 5, MCAPI_TIMEOUT_INFINITE, &mcapi_status);
	mcapiErrorCheck(mcapi_status, "get endpoint", 2);

	while (1)
    {
		// reset string before reading new value
		memset(msg, 0, BUF_SIZE);
		mcapi_msg_recv(local_ep, msg, sizeof(msg)-1, &msg_size, &mcapi_status);
		mcapiErrorCheck(mcapi_status, "msg_recv", 2);
		if (MCAPI_SUCCESS == mcapi_status)
		{
		    mcapi_msg_send(local_ep, remote_ep, msg, strlen(msg), 0, &mcapi_status);
		    mcapiErrorCheck(mcapi_status, "msg_send", 2);
		}
	}

	mcapi_endpoint_delete(local_ep, &mcapi_status);
	mcapiErrorCheck(mcapi_status, "del_endpoint", 2);
	mcapi_finalize(&mcapi_status);
	mcapiErrorCheck(mcapi_status, "finalize", 2);
	return 0;
}


where adi_initComponents() looks like this:

int32_t adi_initComponents(void)
{
	int32_t result = 0;

	result = adi_sec_Init();


	if (result == 0) {
		result = adi_mcapi_Init(); /* auto-generated code (order:6) */
	}

	return result;
}

and adi_mcapi_Init() looks like this:

int32_t adi_mcapi_Init(void)
{
	mcapi_status_t mcapi_status;
	int32_t result = 0;

	/* Initialize MCAPI */

	mcapi_initialize(
		0u,                         /* the domain is always 0 */
		2u,                         /* Node ID */
		NULL,                       /* MCAPI node attributes */
		&adi_mcapi_init_parameters, /* MCAPI init parameters */
		&adi_mcapi_info,
		&mcapi_status );

	/* MCAPI status codes begin with 1 for MCAPI_SUCCESS, so it can't be 
	 * returned as a zero == success.
	 */
	if (MCAPI_SUCCESS != mcapi_status)
	{
		 result = mcapi_status; 
	} 

	return (result);
}

Also for reference the code that the loader uses (i.e. the code in recv_arg.c) is this:

/*
 * recv_arg.c
 */
#include <stdint.h>
#include <stdlib.h>
#include <sys/platform.h>

// For SC589
#define L2_START 0x20080000
// For SC573
//#define L2_START 0x20000000
#define L2_MCAPI_SH1_OFFSET (12*1024)
#define L2_MCAPI_SH2_OFFSET (8*1024)
#define L2_MCAPI_SH1_START (L2_START + L2_MCAPI_SH1_OFFSET)
#define L2_MCAPI_SH2_START (L2_START + L2_MCAPI_SH2_OFFSET)

#ifdef CORE1
#define L2_MCAPI_START L2_MCAPI_SH1_START
#elif (defined CORE2)
#define L2_MCAPI_START L2_MCAPI_SH2_START
#endif

void recv_arg(int *argc, char **argv[]) {
	// The mailbox is located in the L2 memory
	// Though it will not be used afterwards, the user still should be cautious
	// not to use this area for static non-zero variable storage. It is safe
	// to use as zero initialized variable storage , heap or stack storage.
	volatile uint32_t *ptrMboxSh2Arm_l2 = (uint32_t *)L2_MCAPI_START;
	volatile uint32_t *ptrMboxArm2Sh_l2 = ptrMboxSh2Arm_l2 + 1;
	volatile uint32_t *ptrDataSh2Arm_l2 = ptrMboxSh2Arm_l2 + 2;
	volatile uint32_t *ptrDataArm2Sh_l2 = ptrMboxSh2Arm_l2 + 3;

	uint32_t cmdline_length;
	volatile char *cmdline;
	volatile char *p;
	int arg_count;
	char * *arg_value;

	// Tell the ARM that the SHARC is running
	*ptrMboxSh2Arm_l2 = 0x5555;
	// Waiting ack and fetch length from ARM
	while (*ptrMboxArm2Sh_l2 != 0x5555);
	cmdline_length = *ptrDataArm2Sh_l2;

	// Try to allocate the memory and send back the address
	cmdline = malloc(cmdline_length);
	if (cmdline == NULL) {
		*ptrMboxSh2Arm_l2 = 0xdead;
		// We still need to wait the ARM to confirm the error
		// So we do not clean the mailbox value too early
		while (*ptrMboxArm2Sh_l2 != 0xbeef);
		goto _clean;
	}
	*ptrDataSh2Arm_l2 = (uint32_t)cmdline;
	*ptrMboxSh2Arm_l2 = 0xbbbb;

	// Wait till ARM has finished the transmission
	while(*ptrMboxArm2Sh_l2 != 0x6666);

	// Parse the string
	// First step is determine the count of arguments
	// So the memory for argv (pointer array) can be allocated
	p = cmdline;
	if (*p) {
		arg_count = 1; // non empty, at least one
		while (*p) {
			if (*p++ ==' ') arg_count ++;
		}
	}
	else {
		arg_count = 0;
	}

	if (arg_count != 0) {
		p = cmdline;
		arg_value = malloc(arg_count * sizeof(char *));
		arg_count = 0;
		arg_value[arg_count ++] = (char *)p;
		while (*p) {
			if (*p==' ') {
				arg_value[arg_count ++] = (char *)p + 1;
				*p = '\0';
			}
			p++;
		}
		*argc = arg_count;
		*argv = arg_value;
	}
	else {
		// No arguments, return 0.
		*argc = 0;
		*argv = NULL;
	}

_clean:
	// Intentionally not freeing the cmdline
	// So the user can use the arguments in the application
	*ptrMboxSh2Arm_l2 = 0x0000;
	*ptrMboxArm2Sh_l2 = 0x0000;
	*ptrDataSh2Arm_l2 = 0x0000;
	*ptrDataArm2Sh_l2 = 0x0000;
	return;
}

As mentioned the loader code seems to be working fine and the application starts successfully on sharc core2 using command: loadSharc_SC589 -i theApplication.ldr -s 2 -d 3 -a "some unused args". But for some reason the arm side cannot reach the sharc core2 endpoint.

I thought it could be because of some limitation to the number of nodes on the mcapi implementation on the arm side and searched through the headers and found that in mca.h the MCA_MAX_NODES is defined as 2. I changed that to 3 rebuilt everything in buildroot but still it didn't work. I have seen that there is an example that does what I want to do called "Three Core example" and I've literally checked my code against it line by line and its exactly the same. The only difference is that I'm loading the sharc applications from linux using the loader and that I'm running the arm application again from inside linux whereas that example uses bare metal toolchain and requires ice1000. I don't want to go down that path though as I need to get this working from inside linux.

Any help would be much appreciated.