Esempio n. 1
0
/**************************************************************************************************
 * @fn          npi_poll_entry
 *
 * @brief       Poll Thread entry function
 *
 * input parameters
 *
 * @param      ptr
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
static void *npi_poll_entry(void *ptr)
{
	int ret = NPI_LNX_SUCCESS;
	uint8 readbuf[128];
	char tmpStr[1024];
#ifndef SRDY_INTERRUPT
	uint8 pollStatus = FALSE;
#endif //SRDY_INTERRUPT

	((void)ptr);
	snprintf(tmpStr, sizeof(tmpStr), "[%s] Locking Mutex for Poll Thread \n", __FUNCTION__);
	time_printf(tmpStr);

	/* lock mutex in order not to lose signal */
	pthread_mutex_lock(&npi_poll_mutex);

	snprintf(tmpStr, sizeof(tmpStr), "[%s] Poll Thread Started\n", __FUNCTION__);
	time_printf(tmpStr);

	//This lock wait for Initialization to finish (reset)
	pthread_mutex_lock(&npiPollLock);

	snprintf(tmpStr, sizeof(tmpStr), "[%s] Poll Thread Continues After Synchronization\n", __FUNCTION__);
	time_printf(tmpStr);

#ifdef SRDY_INTERRUPT
	if ( __BIG_DEBUG_ACTIVE == TRUE )
	{
		snprintf(tmpStr, sizeof(tmpStr), "[%s] Lock Poll mutex (SRDY=%d) \n", __FUNCTION__, global_srdy);
		time_printf(tmpStr);
	}
	pthread_cond_wait(&npi_srdy_H2L_poll, &npiPollLock);
	if ( __BIG_DEBUG_ACTIVE == TRUE )
	{
		snprintf(tmpStr, sizeof(tmpStr), "[%s] Locked Poll mutex (SRDY=%d) \n",	__FUNCTION__, global_srdy);
		time_printf(tmpStr);
	}
#else
	pthread_mutex_unlock(&npiPollLock);
#endif

	/* thread loop */
	while(!npi_poll_terminate)
	{

#ifndef SRDY_INTERRUPT
		pthread_mutex_lock(&npiPollLock);
#endif
		if (PollLockVar)
		{
			ret = PollLockVarError(__LINE__, PollLockVar);
		}
		else
		{
			PollLockVar = 1;
			if ( __BIG_DEBUG_ACTIVE == TRUE )
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] PollLockVar set to %d\n",
						__FUNCTION__, PollLockVar);
				time_printf(tmpStr);
			}
		}

		//Ready SRDY Status
		// This Test check if RNP has asserted SRDY line because it has some Data pending.
		// If SRDY is not Used, then this line need to be commented, and the Poll command need
		// to be sent regularly to check if any data is pending. this is done every 10ms (see below npi_poll_cond)
#ifndef SRDY_INTERRUPT
		ret =  HAL_RNP_SRDY_CLR();
		if(TRUE == ret)
#else
		//Interruption case, In case of a SREQ, SRDY will go low a end generate an event.
		// the npiPollLock will prevent us to arrive to this test,
		// BUT an AREQ can immediately follow  a SREQ: SRDY will stay low for the whole process
		// In this case, we need to check that the SRDY line is still LOW or is HIGH.
		if (HalGpioSrdyCheck(0) == TRUE)
#endif
		{
			if ( __BIG_DEBUG_ACTIVE == TRUE )
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] Polling received... \n", __FUNCTION__);
				time_printf(tmpStr);
			}

			//RNP is polling, retrieve the data
			*readbuf = 0; //Poll Command has zero data bytes.
			*(readbuf+1) = RPC_CMD_POLL;
			*(readbuf+2) = 0;
			ret = npi_i2c_pollData((npiMsgData_t *)readbuf);
			if (ret == NPI_LNX_SUCCESS)
			{
				//Check if polling was successful
				if ((readbuf[RPC_POS_CMD0] & RPC_CMD_TYPE_MASK) == RPC_CMD_AREQ)
				{
//					((uint8 *)readbuf)[RPC_POS_CMD0] =  RPC_SUBSYSTEM_MASK;
					ret = NPI_AsynchMsgCback((npiMsgData_t *)(readbuf));
					if (ret != NPI_LNX_SUCCESS)
					{
						// Exit thread to invoke report to main thread
						npi_poll_terminate = 1;
						error_printf("%s:%d: ERROR! Terminating poll because RPC_CMD_AREQ.\n", __FUNCTION__, __LINE__);
					}
				}
			}
			else
			{
				// An error has occurred
				// Check what error it is, some errors are expected
				char *errorMsg;
				switch (npi_ipc_errno)
				{
				case NPI_LNX_ERROR_HAL_GPIO_WAIT_SRDY_CLEAR_POLL_TIMEDOUT:
					errorMsg = "npi_i2c_pollData timed out waiting for SRDY. Could be SBL which only responds to SREQ. Please check global error message\n";
					NPI_LNX_IPC_NotifyError(NPI_LNX_ERROR_MODULE_MASK(NPI_LNX_ERROR_HAL_GPIO_WAIT_SRDY_CLEAR_POLL_TIMEDOUT), errorMsg);
					// The RNP may be in SBL or may only respond to SREQ. We should not exit POLL thread.
					ret = NPI_LNX_SUCCESS;
				break;
					case  NPI_LNX_ERROR_HAL_I2C_READ_TIMEDOUT:
					// The RNP may have reset unexpectedly, keep going
					ret = NPI_LNX_SUCCESS;
					break;
				case  NPI_LNX_ERROR_HAL_I2C_WRITE_TIMEDOUT:
					// The RNP may have reset unexpectedly, keep going
						ret = NPI_LNX_SUCCESS;
					break;
				default:
					// Exit clean so main knows...
					npi_poll_terminate = 1;
					error_printf("%s:%d: ERROR! Terminating poll because error return (ret=%d, npi_ipc_errno=%d).\n", __FUNCTION__, __LINE__, ret, npi_ipc_errno);
					break;
				}
			}

			if (!PollLockVar)
			{
				ret = PollLockVarError(__LINE__, !PollLockVar);
			}
			else
			{
				PollLockVar = 0;
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] PollLockVar set to %d\n", __FUNCTION__, PollLockVar);
					time_printf(tmpStr);
				}
			}

#ifndef SRDY_INTERRUPT
			if ( 0 == pthread_mutex_unlock(&npiPollLock))
			{
				pollStatus = TRUE;
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] Unlock SRDY mutex \n", __FUNCTION__);
					time_printf(tmpStr);
				}
			}
			else
			{
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] Failed to unlock SRDY mutex \n", __FUNCTION__);
					time_printf(tmpStr);
				}
			    npi_ipc_errno = NPI_LNX_ERROR_I2C_POLL_THREAD_POLL_UNLOCK;
			    ret = NPI_LNX_FAILURE;
				npi_poll_terminate = 1;
				error_printf("%s:%d: ERROR! Terminating poll because POLL mutex unlock failed.\n", __FUNCTION__, __LINE__);
			}
#endif //SRDY_INTERRUPT
		}
		else
		{
			if (!PollLockVar)
			{
				ret = PollLockVarError(__LINE__, !PollLockVar);
			}
			else
			{
				PollLockVar = 0;
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] PollLockVar set to %d\n", __FUNCTION__, PollLockVar);
					time_printf(tmpStr);
				}
			}

#ifdef SRDY_INTERRUPT
			if ( __BIG_DEBUG_ACTIVE == TRUE )
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] SRDY was not 0 when we expected!\n", __FUNCTION__);
				time_printf(tmpStr);
			}
#else
			if ( 0 == pthread_mutex_unlock(&npiPollLock))
			{
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] Unlock SRDY mutex \n", __FUNCTION__);
					time_printf(tmpStr);
				}
			}
			else
			{
				if ( __BIG_DEBUG_ACTIVE == TRUE )
				{
					snprintf(tmpStr, sizeof(tmpStr), "[%s] Failed to unlock SRDY mutex \n", __FUNCTION__);
					time_printf(tmpStr);
				}
			    npi_ipc_errno = NPI_LNX_ERROR_I2C_POLL_THREAD_POLL_UNLOCK;
			    ret = NPI_LNX_FAILURE;
				npi_poll_terminate = 1;
				error_printf("%s:%d: ERROR! Terminating poll because POLL mutex unlock failed.\n", __FUNCTION__, __LINE__);
			}
			pollStatus = FALSE;
#endif //SRDY_INTERRUPT
		}

#ifdef SRDY_INTERRUPT
		if ( __BIG_DEBUG_ACTIVE == TRUE )
		{
			snprintf(tmpStr, sizeof(tmpStr), "[%s] Unlock POLL mutex by conditional wait (SRDY=%d) \n", __FUNCTION__, global_srdy);
			time_printf(tmpStr);
		}
		if (TRUE == HAL_RNP_SRDY_SET())
		{
			if ( __BIG_DEBUG_ACTIVE == TRUE )
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] Waiting for SRDY to go low\n", __FUNCTION__);
				time_printf(tmpStr);
			}
			int condWaitRetVal = pthread_cond_wait(&npi_srdy_H2L_poll, &npiPollLock);
			if (condWaitRetVal)
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] pthread_cond_wait returned with %d (%s, %s)\n", __FUNCTION__,
						condWaitRetVal, strerror(condWaitRetVal), strerror(errno));
				time_printf(tmpStr);
				if (condWaitRetVal == 1) exit(-1);
			}
		}
		else if (npi_poll_terminate)
		{
			// Just unlock mutex, while loop will exit next
			pthread_mutex_unlock(&npiPollLock);
		}
		else
		{
			if (PollLockVar)
			{
				ret = PollLockVarError(__LINE__, PollLockVar);
			}
			if ( __BIG_DEBUG_ACTIVE == TRUE )
			{
				snprintf(tmpStr, sizeof(tmpStr), "[%s] SRDY found high after poll, poll again\n", __FUNCTION__);
				time_printf(tmpStr);
			}
			// After a synchronous request we need to poll RNP again. The RNP will only release SRDY after
			// replying with 0x00 0x00 0x00 to a poll request.
		}
		if ( __BIG_DEBUG_ACTIVE == TRUE )
		{
			snprintf(tmpStr, sizeof(tmpStr), "[%s] Locked POLL mutex because condition was met (SRDY=%d) \n", __FUNCTION__, global_srdy);
			time_printf(tmpStr);
		}
#else
		if (!pollStatus) //If previous poll failed, wait 10ms to do another one, else do it right away to empty the RNP queue.
		{
			struct timespec expirytime;

			clock_gettime(CLOCK_REALTIME, &expiryTime);

			expirytime.tv_nsec += 10000000; // 10ms
			if (expirytime.tv_nsec >= 1000000000) {
				expirytime.tv_nsec -= 1000000000;
				expirytime.tv_sec++;
			}
			pthread_cond_timedwait(&npi_poll_cond, &npi_poll_mutex, &expirytime);
		}
#endif
	}
	error_printf("[POLL] WARNING. Thread exiting with ret=%d, npi_ipc_errno0x%x...\n", ret, npi_ipc_errno);
	pthread_mutex_unlock(&npi_poll_mutex);

	char const *errorMsg;
	if (ret == NPI_LNX_FAILURE)
	{
		errorMsg = "[POLL] Thread exited with error. Please check global error message\n";
	}
	else
	{
		errorMsg = "[POLL] Thread exited without error\n";
	}

	NPI_LNX_IPC_NotifyError(NPI_LNX_ERROR_MODULE_MASK(NPI_LNX_ERROR_I2C_POLL_THREAD_FAILED_LOCK), errorMsg);

	return ptr;
}
Esempio n. 2
0
/**************************************************************************************************
 *
 * @fn          npi_ipc_handleThreadFunc
 *
 * @brief       This function initializes RTI Surrogate
 *
 * input parameters
 *
 * @param       ipAddress - path to the NPI Server Socket
 *
 * output parameters
 *
 * None.
 *
 * @return      TRUE if the surrogate module started off successfully.
 *              FALSE, otherwise.
 *
 **************************************************************************************************/
static void *npi_ipc_handleThreadFunc (void *ptr)
{
	int done = 0, tryLockFirstTimeOnly = 0;

	// Handle message from socket
	do {

		if (tryLockFirstTimeOnly == 0)
		{
			// Lock mutex
			debug_verbose_printf("[CLIENT HANDLE][MUTEX] Lock AREQ Mutex (Handle)\n");
			int mutexRet = 0, writeOnce = 0;
			while ( (mutexRet = pthread_mutex_trylock(&npiLnxClientAREQmutex)) == EBUSY)
			{
				if (writeOnce == 0)
				{
					debug_verbose_printf("[CLIENT HANDLE][MUTEX] AREQ Mutex (Handle) busy");
					fflush(stdout);
					writeOnce++;
				}
				else
				{
					writeOnce++;
					if ( (writeOnce % 1000) == 0)
					{
						debug_verbose_printf(".");
					}
					if (writeOnce > 0xEFFFFFF0)
						writeOnce = 1;
					fflush(stdout);
				}
			}
			debug_verbose_printf("\n[CLIENT HANDLE][MUTEX] AREQ Lock (Handle) status: %d\n", mutexRet);
			tryLockFirstTimeOnly = 1;
		}

		// Conditional wait for the response handled in the AREQ handling thread,
		debug_verbose_printf("[CLIENT HANDLE][MUTEX] Wait for AREQ Cond (Handle) signal... (areqMsgProcessStatus = %d), effectively releasing lock\n", areqMsgProcessStatus);
		pthread_cond_wait(&npiLnxClientAREQcond, &npiLnxClientAREQmutex);
		debug_verbose_printf("[CLIENT HANDLE][MUTEX] AREQ (Handle) has lock\n");

		// Walk through all received AREQ messages before releasing MUTEX
		areqMsg *searchList = npi_ipc_areq_proc_buf, *clearList;
		while (searchList != NULL)
		{
			debug_verbose_printf("\n\n[CLIENT HANDLE][DBG] Processing \t@ %p next \t@ %p\n",
					(void *)searchList,
					(void *)(searchList->nextMessage));

			// Must remove command type before calling NPI_AsynchMsgCback
			searchList->message.subSys &= ~(RPC_CMD_TYPE_MASK);

			debug_verbose_printf("[CLIENT HANDLE][MUTEX] AREQ Calling NPI_AsynchMsgCback (Handle)...\n");

			NPI_AsynchMsgCback((npiMsgData_t *)&(searchList->message));

			debug_verbose_printf("[CLIENT HANDLE][MUTEX] AREQ (Handle) (message @ %p)...\n", (void *)searchList);

			clearList = searchList;
			// Set search list to next message
			searchList = searchList->nextMessage;
			// Free processed buffer
			if (clearList == NULL)
			{
				// Impossible error, must abort
				done = 1;
				printf("[CLIENT HANDLE][ERR] clearList buffer was already free\n");
				break;
			}
			else
			{
				messageCount--;
				debug_verbose_printf("[CLIENT HANDLE][DBG] Clearing \t\t@ %p (processed %d messages)...\n",
						(void *)clearList,
						messageCount);
				memset(clearList, 0, sizeof(areqMsg));
				free(clearList);
			}
		}
		debug_verbose_printf("[CLIENT HANDLE][MUTEX] AREQ Signal message(s) handled (Handle) (processed %d messages)...\n", messageCount);
		// Signal to the read thread that we're ready for more
		//			pthread_cond_signal(&npiLnxClientAREQcond);
		areqMsgProcessStatus = NPI_MSG_AREQ_READY;

		debug_printf("[CLIENT HANDLE][DBG] Finished processing (processed %d messages)...\n",
				messageCount);

	} while (!done);

	return ptr;
}