static void ksz8851snl_update()

in device_firmware/libraries/freertos_plus/standard/freertos_plus_tcp/source/portable/NetworkInterface/ksz8851snl/NetworkInterface.c [658:994]


static void ksz8851snl_update()
{
	uint16_t txmir = 0;

/* Check for free PDC. */
	switch( xMicrelDevice.ul_spi_pdc_status )
	{
	case SPI_PDC_TX_ERROR:
		{
		uint32_t ulValue;
	//		/* TX step11: end TX transfer. */
			gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );

			vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
			vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
			vTaskDelay( 1 );

			/* Disable asynchronous transfer mode. */
			xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;

			/* TX step12: disable TXQ write access. */
			ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );

			ulValue = ksz8851snl_reset_tx();

			xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;

			FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );
		}
		break;

	case SPI_PDC_RX_ERROR:
		{
		uint32_t ulValue;
			/* TX step11: end TX transfer. */
			gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );

			vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
			vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
			vTaskDelay( 1 );

			/* Disable asynchronous transfer mode. */
			xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;

			/* TX step12: disable TXQ write access. */
			ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );

			//ulValue = ksz8851snl_reset_rx();
			ulValue = ksz8851snl_reinit();

			xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );

			FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );
		}
		break;
	}
	switch( xMicrelDevice.ul_spi_pdc_status )
	{
		case SPI_PDC_IDLE:
		{
		int txTail = xMicrelDevice.us_tx_tail;

			/*
			 * ========================== Handle RX ==========================
			 */
			if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )
			{
			int rxHead = xMicrelDevice.us_rx_head;
			NetworkBufferDescriptor_t *pxNetworkBuffer;
#warning try
				xMicrelDevice.ul_had_intn_interrupt = 0;

				if( xMicrelDevice.us_pending_frame == 0 )
				{
				uint16_t int_status;
					/* RX step1: read interrupt status for INT_RX flag. */
					int_status = ksz8851_reg_read( REG_INT_STATUS );


					/* RX step2: disable all interrupts. */
					ksz8851_reg_write( REG_INT_MASK, 0 );

					/* RX step3: clear INT_RX flag. */
					ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );

					/* RX step4-5: check for received frames. */
					xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
					if( xMicrelDevice.us_pending_frame == 0 )
					{
						/* RX step24: enable INT_RX flag. */
						ksz8851_reg_write(REG_INT_MASK, INT_RX);
						return;
					}
				}
#warning try
				xMicrelDevice.ul_had_intn_interrupt = 0;

				/* Now xMicrelDevice.us_pending_frame != 0 */

				/* Don't break Micrel state machine, wait for a free descriptor first! */
				if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )
				{
					FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",
							xMicrelDevice.us_rx_tail, rxHead ) );
					return;
				}
				pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];

				if( pxNetworkBuffer == NULL )
				{
					ksz8851snl_rx_populate_queue();
					FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );
					return;
				}

				/* RX step6: get RX packet status. */
				fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
				if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )
				{
					ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);
					FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );

					/* RX step4-5: check for received frames. */
					xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;
					if( xMicrelDevice.us_pending_frame == 0 )
					{
						/* RX step24: enable INT_RX flag. */
						ksz8851_reg_write(REG_INT_MASK, INT_RX);
					}
					ulISREvents |= EMAC_IF_ERR_EVENT;
				}
				else
				{
				size_t xLength;
					/* RX step7: read frame length. */
					xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;

					/* RX step8: Drop packet if len is invalid or no descriptor available. */
					if( xLength == 0 )
					{
						ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );
						FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );
						ulISREvents |= EMAC_IF_ERR_EVENT;
					}
					else
					{
					size_t xReadLength = xLength;

						xMicrelDevice.ul_total_rx++;
						/* RX step9: reset RX frame pointer. */
						ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);

						/* RX step10: start RXQ read access. */
						ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);
						/* RX step11-17: start asynchronous FIFO read operation. */
						xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;
						gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
						if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )
						{
							xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;
						}

						/* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */
						ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );
						/* Remove CRC and update buffer length. */
						xLength -= 4;
						pxNetworkBuffer->xDataLength = xLength;
						/* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */
					}
				}
				break;
			} /* ul_had_intn_interrupt || us_pending_frame */
			/*
			 * ========================== Handle TX ==========================
			 */

			/* Fetch next packet to be sent. */
			if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&
				( xMicrelDevice.us_pending_frame == 0 ) &&
				( xMicrelDevice.ul_had_intn_interrupt == 0 ) )
			{
			NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];
			size_t xLength = pxNetworkBuffer->xDataLength;
			int iIndex = xLength;

				xLength = 4 * ( ( xLength + 3 ) / 4 );
				while( iIndex < ( int ) xLength )
				{
					pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';
					iIndex++;
				}
				pxNetworkBuffer->xDataLength = xLength;

				/* TX step1: check if TXQ memory size is available for transmit. */
				txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
				txmir = txmir & TX_MEM_AVAILABLE_MASK;

				if( txmir < ( xLength + 8 ) )
				{
					if( wait_tx_space == pdFALSE )
					{
						tx_status = ksz8851_reg_read( REG_TX_STATUS );
						fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );
						wait_tx_space = pdTRUE;
					}
					//return;
					rx_debug = 1;
					tx_space = txmir;
				}
				else
				{
					tx_space = txmir;

					/* TX step2: disable all interrupts. */
					ksz8851_reg_write( REG_INT_MASK, 0 );

					xMicrelDevice.tx_space -= xLength;

					/* TX step3: enable TXQ write access. */
					ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );
					/* TX step4-8: perform FIFO write operation. */
					xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;
					xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;
					/* Bring SPI SS low. */
					gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );
					xMicrelDevice.ul_total_tx++;

					ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );
				}
			}
		}
		break;	/* SPI_PDC_IDLE */

	case SPI_PDC_RX_COMPLETE:
		{
		int rxHead = xMicrelDevice.us_rx_head;
			/* RX step18-19: pad with dummy data to keep dword alignment. */
			/* Packet lengths will be rounded up to a multiple of "sizeof size_t". */
//			xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;
//			if( xLength != 0 )
//			{
//				ksz8851_fifo_dummy( 4 - xLength );
//			}

			/* RX step20: end RX transfer. */
			gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );

			/* Disable asynchronous transfer mode. */
			xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;

			/* RX step21: end RXQ read access. */
			ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);

			/* RX step22-23: update frame count to be read. */
			xMicrelDevice.us_pending_frame -= 1;

			/* RX step24: enable INT_RX flag if transfer complete. */
			if( xMicrelDevice.us_pending_frame == 0 )
			{
				ksz8851_reg_write(REG_INT_MASK, INT_RX);
			}

			/* Mark descriptor ready to be read. */
			xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;
			if( ++rxHead == MICREL_RX_BUFFERS )
			{
				rxHead = 0;
			}
			xMicrelDevice.us_rx_head = rxHead;
			if( rx_debug != 0 )
			{
			uint32_t txmir;
				rx_debug = 0;
				txmir = ksz8851_reg_read( REG_TX_MEM_INFO );
				txmir = txmir & TX_MEM_AVAILABLE_MASK;
			}
			/* Tell prvEMACHandlerTask that RX packets are available. */
			ulISREvents |= EMAC_IF_RX_EVENT;
		}	/* case SPI_PDC_RX_COMPLETE */
		break;

	case SPI_PDC_TX_COMPLETE:
		{
		int txTail = xMicrelDevice.us_tx_tail;
		NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];

		size_t xLength;
			/* TX step9-10: pad with dummy data to keep dword alignment. */
			/* Not necessary: length is already a multiple of 4. */
			xLength = pxNetworkBuffer->xDataLength & 3;
			if( xLength != 0 )
			{
//				ksz8851_fifo_dummy( 4 - xLength );
			}

//			/* TX step11: end TX transfer. */
			gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );

			/* Disable asynchronous transfer mode. */
			xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;

			/* TX step12: disable TXQ write access. */
			ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );

			xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;

			/* TX step12.1: enqueue frame in TXQ. */
			ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );

			/* RX step13: enable INT_RX flag. */
//			ksz8851_reg_write( REG_INT_MASK, INT_RX );
			/* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */
			vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );

			xMicrelDevice.tx_buffers[ txTail ] = NULL;
			xMicrelDevice.tx_busy[ txTail ] = pdFALSE;
			if( ++txTail == MICREL_TX_BUFFERS )
			{
				txTail = 0;
			}

			xMicrelDevice.us_tx_tail = txTail;
			/* Experiment. */
			//xMicrelDevice.ul_had_intn_interrupt = 1;
			if( xTransmitHandle != NULL )
			{
				xTaskNotifyGive( xTransmitHandle );
			}
#warning moved downward
			/* RX step13: enable INT_RX flag. */
			ksz8851_reg_write( REG_INT_MASK, INT_RX );
			/* Prevent the EMAC task from sleeping a single time. */
			ulISREvents |= EMAC_IF_TX_EVENT;
		}	/* case SPI_PDC_TX_COMPLETE */
		break;
	}	/* switch( xMicrelDevice.ul_spi_pdc_status ) */
}