/*! * \brief This function initializes the Multi Core Communication subsystem for a given node. * * This function should only be called once per node (once in MQX, once per process in Linux). * * \param[in] node Node number that will be used in endpoints created by this process. * * \return MCC_SUCCESS * \return MCC_ERR_SEMAPHORE (semaphore handling error) * \return MCC_ERR_INT (interrupt registration error) * * \see mcc_destroy * \see MCC_BOOKEEPING_STRUCT */ int mcc_initialize(MCC_NODE node) { int i,j = 0; int return_value = MCC_SUCCESS; MCC_SIGNAL tmp_signals_received = {(MCC_SIGNAL_TYPE)0, (MCC_CORE)0, (MCC_NODE)0, (MCC_PORT)0}; #if (MCC_OS_USED == MCC_MQX) for(i=0; i<MCC_MQX_LWEVENT_COMPONENTS_COUNT; i++) { _lwevent_create(&lwevent_buffer_queued[i],0); } _lwevent_create(&lwevent_buffer_freed,0); #endif /* Initialize synchronization module */ return_value = mcc_init_semaphore(MCC_SHMEM_SEMAPHORE_NUMBER); if(return_value != MCC_SUCCESS) return return_value; /* Register CPU-to-CPU interrupt for inter-core signaling */ //mcc_register_cpu_to_cpu_isr(MCC_CORE0_CPU_TO_CPU_VECTOR); return_value = mcc_register_cpu_to_cpu_isr(); if(return_value != MCC_SUCCESS) return return_value; /* Initialize the bookeeping structure */ bookeeping_data = (MCC_BOOKEEPING_STRUCT *)MCC_BASE_ADDRESS; MCC_DCACHE_INVALIDATE_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT)); if(strcmp(bookeeping_data->init_string, init_string) != 0) { /* Zero it all - no guarantee Linux or uboot didnt touch it before it was reserved */ _mem_zero((void*) bookeeping_data, (_mem_size) sizeof(struct mcc_bookeeping_struct)); /* Set init_string in case it has not been set yet by another core */ mcc_memcpy((void*)init_string, bookeeping_data->init_string, (unsigned int)sizeof(bookeeping_data->init_string)); /* Set version_string */ mcc_memcpy((void*)version_string, bookeeping_data->version_string, (unsigned int)sizeof(bookeeping_data->version_string)); /* Initialize the free list */ bookeeping_data->free_list.head = &bookeeping_data->r_buffers[0]; bookeeping_data->free_list.tail = &bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1]; /* Initialize receive buffers */ for(i=0; i<MCC_ATTR_NUM_RECEIVE_BUFFERS-1; i++) { bookeeping_data->r_buffers[i].next = &bookeeping_data->r_buffers[i+1]; } bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1].next = null; /* Initialize signal queues */ for(i=0; i<MCC_NUM_CORES; i++) { for(j=0; j<MCC_MAX_OUTSTANDING_SIGNALS; j++) { bookeeping_data->signals_received[i][j] = tmp_signals_received; } bookeeping_data->signal_queue_head[i] = 0; bookeeping_data->signal_queue_tail[i] = 0; } /* Mark all endpoint ports as free */ for(i=0; i<MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) { bookeeping_data->endpoint_table[i].endpoint.port = MCC_RESERVED_PORT_NUMBER; } } MCC_DCACHE_FLUSH_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT)); return return_value; }
/*! * \brief This function initializes the Multi Core Communication subsystem for a given node. * * This function should only be called once per node (once in MQX, once per a process in Linux). * It tries to initialize the bookkeeping structure when the init_string member of this structure * is not equal to MCC_INIT_STRING, i.e. when no other core had performed the initialization yet. * Note, that this way of bookkeeping data re-initialization protection is not powerful enough and * the user application should not rely on this method. Instead, the application should be designed * to unambiguously assign the core that will perform the MCC initialization. * Clear the shared memory before the first core is attempting to initialize the MCC * (in some cases MCC_INIT_STRING remains in the shared memory after the application reset and could * cause that the bookkeeping data structure is not initialized correctly). * * \param[in] node Node number that will be used in endpoints created by this process. * * \return MCC_SUCCESS * \return MCC_ERR_SEMAPHORE (semaphore handling error) * \return MCC_ERR_INT (interrupt registration error) * \return MCC_ERR_VERSION (incorrect MCC version used - compatibility issue) * \return MCC_ERR_OSSYNC (OS synchronization module(s) initialization failed) * * \see mcc_destroy * \see MCC_BOOKEEPING_STRUCT */ int mcc_initialize(MCC_NODE node) { int i,j = 0; int return_value = MCC_SUCCESS; MCC_SIGNAL tmp_signals_received = {(MCC_SIGNAL_TYPE)0, {(MCC_CORE)0, (MCC_NODE)0, (MCC_PORT)0}}; /* Initialize synchronization module for shared data protection */ return_value = mcc_init_semaphore(MCC_SHMEM_SEMAPHORE_NUMBER); if(return_value != MCC_SUCCESS) return return_value; /* Initialize all necessary OS synchronization module(s) (for unblocking tasks waiting for new received data and for unblocking tasks waiting for a free buffer) */ return_value = mcc_init_os_sync(); if(return_value != MCC_SUCCESS) return return_value; /* Register CPU-to-CPU interrupt for inter-core signaling */ //mcc_register_cpu_to_cpu_isr(MCC_CORE0_CPU_TO_CPU_VECTOR); return_value = mcc_register_cpu_to_cpu_isr(); if(return_value != MCC_SUCCESS) return return_value; /* Initialize the bookeeping structure */ bookeeping_data = (MCC_BOOKEEPING_STRUCT *)mcc_get_bookeeping_data(); MCC_DCACHE_INVALIDATE_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT)); if(strcmp(bookeeping_data->init_string, init_string) != 0) { /* MCC not initialized yet, do it now */ /* Zero it all - no guarantee Linux or uboot didnt touch it before it was reserved */ memset((void*) bookeeping_data, 0, sizeof(struct mcc_bookeeping_struct)); /* Set init_string in case it has not been set yet by another core */ mcc_memcpy((void*)init_string, bookeeping_data->init_string, (unsigned int)sizeof(bookeeping_data->init_string)); /* Set version_string */ mcc_memcpy((void*)version_string, bookeeping_data->version_string, (unsigned int)sizeof(bookeeping_data->version_string)); /* Initialize the free list */ bookeeping_data->free_list.head = (MCC_RECEIVE_BUFFER*)MCC_MEM_VIRT_TO_PHYS(&bookeeping_data->r_buffers[0]); bookeeping_data->free_list.tail = (MCC_RECEIVE_BUFFER*)MCC_MEM_VIRT_TO_PHYS(&bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1]); /* Initialize receive buffers */ for(i=0; i<MCC_ATTR_NUM_RECEIVE_BUFFERS-1; i++) { bookeeping_data->r_buffers[i].next = (MCC_RECEIVE_BUFFER*)MCC_MEM_VIRT_TO_PHYS(&bookeeping_data->r_buffers[i+1]); } bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1].next = null; /* Initialize signal queues */ for(i=0; i<MCC_NUM_CORES; i++) { for(j=0; j<MCC_MAX_OUTSTANDING_SIGNALS; j++) { bookeeping_data->signals_received[i][j] = tmp_signals_received; } bookeeping_data->signal_queue_head[i] = 0; bookeeping_data->signal_queue_tail[i] = 0; } /* Mark all endpoint ports as free */ for(i=0; i<MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) { bookeeping_data->endpoint_table[i].endpoint.port = MCC_RESERVED_PORT_NUMBER; } } else { /* MCC already initialized - check the major number of the version string to ensure compatibility */ if(strncmp(bookeeping_data->version_string, version_string, 4) != 0) { return_value = MCC_ERR_VERSION; } } MCC_DCACHE_FLUSH_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT)); return return_value; }