⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 最新的FreeRTOS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static void prvReadRegister( unsigned portCHAR *pucDestination, unsigned portSHORT usAddress, unsigned portLONG ulLength )
{
unsigned portCHAR ucRxBuffer[ tcpMAX_REGISTER_LEN ];

	/* Read a register value from the WIZnet device. */

	/* First write out the address of the register we want to read. */
	i2cMessage( ucRxBuffer, i2cNO_DATA_REQUIRED, tcpDEVICE_ADDRESS, usAddress, i2cWRITE, NULL, portMAX_DELAY );
	
	/* Then read back from that address. */
	i2cMessage( ( unsigned portCHAR * ) pucDestination, ulLength, tcpDEVICE_ADDRESS, i2cNO_ADDR_REQUIRED, i2cREAD, xMessageComplete, portMAX_DELAY );

	/* I2C messages are queued so use the semaphore to wait for the read to 
	complete - otherwise we will leave this function before the I2C 
	transactions have completed. */
	xSemaphoreTake( xMessageComplete, tcpLONG_DELAY );
}
/*-----------------------------------------------------------*/

void vTCPHardReset( void )
{
	/* Physical reset of the WIZnet device by using the GPIO lines to hold the 
	WIZnet reset lines active for a few milliseconds. */

	/* Make sure the interrupt from the WIZnet is disabled. */
	VICIntEnClear |= tcpEINT0_VIC_CHANNEL_BIT;

	/* If xMessageComplete is NULL then this is the first time that this 
	function has been called and the queue and semaphore used in this file
	have not yet been created. */
	if( xMessageComplete == NULL )
	{
		/* Create and obtain the semaphore used when we want to wait for an i2c
		message to be completed. */
		vSemaphoreCreateBinary( xMessageComplete );
		xSemaphoreTake( xMessageComplete, tcpNO_DELAY );

		/* Create the queue used to communicate between the WIZnet and TCP tasks. */
		xTCPISRQueue = xQueueCreate( tcpISR_QUEUE_LENGTH, tcpISR_QUEUE_ITEM_SIZE );
	}

	/* Use the GPIO to reset the network hardware. */
	GPIO_IOCLR = tcpRESET_ACTIVE_LOW;
	GPIO_IOSET = tcpRESET_ACTIVE_HIGH;

	/* Delay with the network hardware in reset for a short while. */
	vTaskDelay( tcpRESET_DELAY );

	GPIO_IOCLR = tcpRESET_ACTIVE_HIGH;
	GPIO_IOSET = tcpRESET_ACTIVE_LOW;

	vTaskDelay( tcpINIT_DELAY );

	/* Setup the EINT0 to interrupt on required events from the WIZnet device.
	First enable the EINT0 function of the pin. */
	PCB_PINSEL1 |= tcpENABLE_EINT0_FUNCTION;
	
	/* We want the TCP comms to wake us from power save. */
	SCB_EXTWAKE = tcpWAKE_ON_EINT0;

	/* Install the ISR into the VIC - but don't enable it yet! */
	portENTER_CRITICAL();
	{
		extern void ( vEINT0_ISR_Wrapper )( void );

		VICIntSelect &= ~( tcpEINT0_VIC_CHANNEL_BIT );
		VICVectAddr3 = ( portLONG ) vEINT0_ISR_Wrapper;

		VICVectCntl3 = tcpEINT0_VIC_CHANNEL | tcpEINT0_VIC_ENABLE;
	}
	portEXIT_CRITICAL();

	/* Enable interrupts in the WIZnet itself. */
	i2cMessage( ucDataEnableISR, sizeof( ucDataEnableISR ), tcpDEVICE_ADDRESS, tcpISR_MASK_REG, i2cWRITE, NULL, portMAX_DELAY );

	vTaskDelay( tcpLONG_DELAY );
}
/*-----------------------------------------------------------*/

portLONG lTCPSoftReset( void )
{
unsigned portCHAR ucStatus;
extern volatile portLONG lTransactionCompleted;

	/* Send a message to the WIZnet device to tell it set all it's registers
	back to their default states.  Then setup the WIZnet device as required. */

	/* Reset the internal WIZnet registers. */
	i2cMessage( ucDataReset,	sizeof( ucDataReset ),	tcpDEVICE_ADDRESS, tcpCOMMAND_REG, i2cWRITE, NULL, portMAX_DELAY );

	/* Now we can configure the protocol.   Here the MAC address, gateway 
	address, subnet mask and IP address are configured. */
	i2cMessage( ucDataSHAR,		sizeof( ucDataSHAR ),	tcpDEVICE_ADDRESS, tcpSOURCE_HA_REG, i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataGAR,		sizeof( ucDataGAR ),	tcpDEVICE_ADDRESS, tcpGATEWAY_ADDR_REG, i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataMSR,		sizeof( ucDataMSR ),	tcpDEVICE_ADDRESS, tcpSUBNET_MASK_REG,	i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataSIPR,		sizeof( ucDataSIPR ),	tcpDEVICE_ADDRESS, tpcSOURCE_IP_REG,	i2cWRITE, NULL, portMAX_DELAY );
	
	/* Next the memory buffers are configured to give all the WIZnet internal
	memory over to a single socket.  This gives the socket the maximum internal
	Tx and Rx buffer space. */
	i2cMessage( ucDataSetTxBufSize, sizeof( ucDataSetTxBufSize ), tcpDEVICE_ADDRESS, tcpTX_MEM_SIZE_REG, i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataSetRxBufSize, sizeof( ucDataSetRxBufSize ), tcpDEVICE_ADDRESS, tcpRX_MEM_SIZE_REG, i2cWRITE, NULL, portMAX_DELAY );

	/* Send the sys init command so the above parameters take effect. */
	i2cMessage( ucDataInit,		sizeof( ucDataInit ),	tcpDEVICE_ADDRESS, tcpCOMMAND_REG, i2cWRITE, NULL, portMAX_DELAY );

	/* Seems to like a little wait here. */
	vTaskDelay( tcpINIT_DELAY );

	/* Read back the status to ensure the system initialised ok. */
	prvReadRegister( &ucStatus, tcpINTERRUPT_STATUS_REG, tcpSTATUS_READ_LEN );

	/* We should find that the sys init was successful. */
	if( ucStatus != tcpISR_SYS_INIT )
	{
		return ( portLONG ) pdFAIL;
	}

	/* No i2c errors yet. */
	portENTER_CRITICAL();
		lTransactionCompleted = pdTRUE;
	portEXIT_CRITICAL();

	return ( portLONG ) pdPASS;
}
/*-----------------------------------------------------------*/

portLONG lTCPCreateSocket( void )
{
unsigned portCHAR ucStatus;

	/* Create and configure a socket. */

	/* Setup and init the socket.  Here the port number is set and the socket
	is initialised. */
	i2cMessage( ucDataProtocol, sizeof( ucDataProtocol),tcpDEVICE_ADDRESS, tpcSOCKET_OPT_REG, i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataPort,		sizeof( ucDataPort),	tcpDEVICE_ADDRESS, tcpSOURCE_PORT_REG, i2cWRITE, NULL, portMAX_DELAY );
	i2cMessage( ucDataSockInit, sizeof( ucDataSockInit),tcpDEVICE_ADDRESS, tcpCOMMAND_REG, i2cWRITE, xMessageComplete, portMAX_DELAY );

	/* Wait for the Init command to be sent. */
	if( !xSemaphoreTake( xMessageComplete, tcpLONG_DELAY ) )
	{
		/* For some reason the message was not transmitted within our block
		period. */
		return ( portLONG ) pdFAIL;
	}

	/* Allow the socket to initialise. */
	vTaskDelay( tcpINIT_DELAY );

	/* Read back the status to ensure the socket initialised ok. */
	prvReadRegister( &ucStatus, tcpINTERRUPT_STATUS_REG, tcpSTATUS_READ_LEN );
	
	/* We should find that the socket init was successful. */
	if( ucStatus != tcpISR_SOCKET_INIT )
	{
		return ( portLONG ) pdFAIL;
	}


	/* Setup the Tx pointer registers to indicate that the Tx buffer is empty. */
	i2cMessage( ucDataTxReadPointer, sizeof( ucDataTxReadPointer ), tcpDEVICE_ADDRESS, tcpTX_READ_POINTER_REG, i2cWRITE, NULL, portMAX_DELAY );
	vTaskDelay( tcpSHORT_DELAY );
	i2cMessage( ucDataTxWritePointer, sizeof( ucDataTxWritePointer ), tcpDEVICE_ADDRESS, tcpTX_WRITE_POINTER_REG, i2cWRITE, NULL, portMAX_DELAY );
	vTaskDelay( tcpSHORT_DELAY );
	i2cMessage( ucDataTxAckPointer,	  sizeof( ucDataTxAckPointer ),	  tcpDEVICE_ADDRESS, tcpTX_ACK_POINTER_REG, i2cWRITE, NULL, portMAX_DELAY );
	vTaskDelay( tcpSHORT_DELAY );

	return ( portLONG ) pdPASS;
}
/*-----------------------------------------------------------*/

void vTCPListen( void )
{
unsigned portCHAR ucISR;

	/* Start a passive listen on the socket. */

	/* Enable interrupts in the WizNet device after ensuring none are 
	currently pending. */
	while( SCB_EXTINT & tcpCLEAR_EINT0 )
	{
		/* The WIZnet device is still asserting and interrupt so tell it to 
		clear. */
		i2cMessage( ucDataClearInterrupt, sizeof( ucDataClearInterrupt ), tcpDEVICE_ADDRESS, tcpINTERRUPT_REG, i2cWRITE, xMessageComplete, portMAX_DELAY );
		xSemaphoreTake( xMessageComplete, tcpLONG_DELAY );

		vTaskDelay( 1 );
		SCB_EXTINT = tcpCLEAR_EINT0;
	}

	while( xQueueReceive( xTCPISRQueue, &ucISR, tcpNO_DELAY ) )
	{
		/* Just clearing the queue used by the ISR routine to tell this task
		that the WIZnet device needs attention. */
	}

	/* Now all the pending interrupts have been cleared we can enable the 
	processor interrupts. */
	VICIntEnable |= tcpEINT0_VIC_CHANNEL_BIT;

	/* Then start listening for incoming connections. */
	i2cMessage( ucDataListen, sizeof( ucDataListen ), tcpDEVICE_ADDRESS, tcpCOMMAND_REG, i2cWRITE, NULL, portMAX_DELAY );
}
/*-----------------------------------------------------------*/

portLONG lProcessConnection( void )
{
unsigned portCHAR ucISR, ucState, ucLastState = 2, ucShadow;
extern volatile portLONG lTransactionCompleted;
portLONG lSameStateCount = 0, lDataSent = pdFALSE;
unsigned portLONG ulWritePointer, ulAckPointer;

	/* No I2C errors can yet have occurred. */
	portENTER_CRITICAL();
		lTransactionCompleted = pdTRUE;
	portEXIT_CRITICAL();

	/* Keep looping - processing interrupts, until we have completed a 
	transaction.   This uses the WIZnet in it's simplest form.  The socket
	accepts a connection - we process the connection - then close the socket.
	We then go back to reinitialise everything and start again. */
	while( lTransactionCompleted == pdTRUE )
	{
		/* Wait for a message on the queue from the WIZnet ISR.  When the 
		WIZnet device asserts an interrupt the ISR simply posts a message
		onto this queue to wake this task. */
		if( xQueueReceive( xTCPISRQueue, &ucISR, tcpCONNECTION_WAIT_DELAY ) )
		{
			/* The ISR posted a message on this queue to tell us that the
			WIZnet device asserted an interrupt.  The ISR cannot process
			an I2C message so cannot tell us what caused the interrupt so
			we have to query the device here.  This task is the highest
			priority in the system so will run immediately following the ISR. */
			prvReadRegister( &ucISR, tcpINTERRUPT_STATUS_REG, tcpSTATUS_READ_LEN );

			/* Once we have read what caused the ISR we can clear the interrupt
			in the WIZnet. */
			i2cMessage( ucDataClearInterrupt, sizeof( ucDataClearInterrupt ), tcpDEVICE_ADDRESS, tcpINTERRUPT_REG, i2cWRITE, NULL, portMAX_DELAY );

			/* Now we can clear the processor interrupt and re-enable ready for
			the next. */
			SCB_EXTINT = tcpCLEAR_EINT0;
			VICIntEnable |= tcpEINT0_VIC_CHANNEL_BIT;
	
			/* Process the interrupt ... */

			if( ucISR & tcpISR_ESTABLISHED )
			{
				/* A connection has been established - respond by sending
				a receive command. */
				i2cMessage( ucDataReceiveCmd, sizeof( ucDataReceiveCmd ), tcpDEVICE_ADDRESS, tcpCOMMAND_REG, i2cWRITE, NULL, portMAX_DELAY );
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -