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

📄 atl_mix.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 3 页
字号:
 ***************************************
 **
 **		Buffer maintenance for transfer done and timeout
 **
 ***************************************
 ***************************************/

void handle_transfer_done( transfer_instance_ptr tip )
{
	unsigned char		ptd_header_buffer_ptr[ PTD_HEADER_SIZE ];
	PTD_header_param	ph;
	unsigned short		transferred_bytes;

	if ( tip->data_ptr_start == NULL )
		return;

	g_processing_block	= tip;
	
	read_direct_access( tip->target_address, ptd_header_buffer_ptr, PTD_HEADER_SIZE );

	get_PTD_header( &ph, ptd_header_buffer_ptr );

	tip->fatal_error		<<= 1;

	(tip->epi_ptr)->toggle	 = ph.Toggle;

	transferred_bytes		 = ph.ActualBytes;

	if ( tip->direction == IN )
		read_direct_access( tip->target_address + PTD_HEADER_SIZE, tip->data_ptr_start, transferred_bytes );

	tip->data_ptr_start		+= transferred_bytes;
	tip->transferred_size	+= transferred_bytes;
	tip->completion_code	 = ph.CompletionCode;
	tip->retry_count		 = 0;

	gp_cc_logger[ ph.CompletionCode ]++;

	switch ( ph.CompletionCode )
	{
		case 0x0 :		//	No error
			break;
			
		case 0x4 :		//	Stall					- Fatal error
		case 0x9 :		//	DataUnderrun			- Non-fatal error
			break;
			
		case 0x3 :		//	DataToggleMismatch		- Fatal error
		
#ifdef AUTO_TRANSFER_RETRY_ENABLE

			{
				if ( tip->transfer_type == INTERRUPT_TRANSFER )
					atlmix_re_enable_interrupt_transfer( tip );
				else
					re_enable_atl_transfer( tip );
				
				return;
			}
			
#else
			break;
#endif

		case 0x5 :		//	DeviceNotResponding		- Fatal error
		case 0x6 :		//	PIDCheckFailure			- Fatal error
		
			tip->fatal_error	|= 0x1;


#ifdef AUTO_TRANSFER_RETRY_ENABLE


			if ( (tip->fatal_error) != 0x7 )
			{
				if ( tip->transfer_type == INTERRUPT_TRANSFER )
					atlmix_re_enable_interrupt_transfer( tip );
				else
					re_enable_atl_transfer( tip );
				
				return;
			}
#else
			break;
#endif


		case 0x1 :		//	CRC						- Fatal error
		case 0x2 :		//	BitStuffing				- Fatal error
		case 0x7 :		//	UnexpectedPID			- Fatal error
		case 0x8 :		//	DataOverrun				- Non-fatal error
		case 0xC :		//	BufferOverrun			- Non-fatal error
		case 0xD :		//	BufferUnderrun			- Non-fatal error
			break;
			
		default :		//	Other errors
			//	un-documented error, never be happened.

			break;
			
	}


	free_transfer_block( tip );
	tip->data_ptr_start		= NULL;

//	if ( tip->epi_ptr != NULL )

	(*(tip->callback))( tip->epi_ptr );
}


/***************************************
 ***************************************
 **
 **		Utility routines
 **
 ***************************************
 ***************************************/

static void set_PTD_header( unsigned char *ph, PTD_header_param *php )
{
	*(ph + 0)	= php->ActualBytes & 0x0FF;
	
	*(ph + 1)	=     (php->CompletionCode    << 4)
					| (php->Active            << 3) 		
					| (php->Toggle            << 2) 
					| (php->ActualBytes       >> 8);
	
//	(*(ph + 1))	= (*(ph + 1)) | (0xE << 4);
	
	*(ph + 2)	= php->MaxPacketSize & 0xFF;
	
	*(ph + 3)	= 	  (php->EndpointNumber    << 4)
					| (0                      << 3) 		
					| (php->Speed             << 2) 
					| (php->MaxPacketSize     >> 8);
					
	*(ph + 4)	= php->TotalBytes & 0xFF;

//	*(ph + 5)	= 	  (php->DirectionPID      << 2)
//					| (php->TotalBytes        >> 8);
	
	*(ph + 5)	= 	  (php->Paired            << 7)
					| (php->PingPong          << 6)
					| (php->DirectionPID      << 2)
					| (php->TotalBytes        >> 8);
	
	*(ph + 6)	= 	  (php->Format            << 7)
					| (php->FunctionAddress & 0x7F);
	
	*(ph + 7)   =     (php->PollingRate       << 5)
					| (php->StartingFrame & 0x1F);
}


static void get_PTD_header( PTD_header_param *php, unsigned char *ph )
{
	php->ActualBytes		=  *(ph + 0) | ((*(ph + 1) & 0x3) << 8);
	php->CompletionCode		=  *(ph + 1) >> 4;
	php->Active				= (*(ph + 1) >> 3) & 0x01;
	php->Toggle				= (*(ph + 1) >> 2) & 0x01;
	php->MaxPacketSize		=  *(ph + 2) | ((*(ph + 3) & 0x3) << 8);
	php->EndpointNumber		=  *(ph + 3) >> 4;
	php->Last				= (*(ph + 3) >> 3) & 0x01;
	php->Speed				= (*(ph + 3) >> 2) & 0x01;
	php->TotalBytes			=  *(ph + 4) | ((*(ph + 5) & 0x3) << 8);
	php->DirectionPID		= (*(ph + 5) >> 2) & 0x03;
	php->Format				=  *(ph + 6) >> 7;
	php->FunctionAddress	=  *(ph + 6) & 0x7F;
}


unsigned char atlmix_is_fatal_error( transfer_instance *tr_inst_ptr )
{
	unsigned char	completion_code;

	completion_code		= tr_inst_ptr->completion_code;

	return ( (completion_code & 0x8) ? 0 : completion_code );
}

#define DEBUG_CODE
#ifdef DEBUG_CODE
#if 0

void atlmix_show_ptd_header( unsigned char transfer_type, unsigned char index )
{
	unsigned short	p[4];
	unsigned short	target_address;
	
	target_address	= g_buffer_parameter[ transfer_type ].base_address + (g_buffer_parameter[ transfer_type ].payload_size + PTD_HEADER_SIZE) * index;
	
	read_direct_access( target_address, (unsigned char *)p, 8 );
	mprintf( WHITE, CONTINUE, "%d-%d : PTD-h 0x %04X %04X %04X %04X \r\n", transfer_type, index, *(p + 0), *(p + 1), *(p + 2), *(p + 3) );	
}

#else

void atlmix_show_ptd_header( unsigned char transfer_type, unsigned char index )
{
	unsigned short	p[6];
	unsigned short	target_address;
	
	target_address	= g_buffer_parameter[ transfer_type ].base_address + (g_buffer_parameter[ transfer_type ].payload_size + PTD_HEADER_SIZE) * index;
	
	read_direct_access( target_address, (unsigned char *)p, 12 );
	mprintf( WHITE, CONTINUE, "%d-%d : PTD-h 0x %04X %04X %04X %04X %04X %04X \r\n", transfer_type, index, *(p + 0), *(p + 1), *(p + 2), *(p + 3), *(p + 4), *(p + 5) );	
}

#endif


void atlmix_view_PTD( unsigned char index )
{
	atlmix_show_ptd_header( CTRL_BULK_TRANSFER, index );
}


void atlmix_display_open_slot( void )
{
	unsigned char	i;
	
	for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
		mprintf( YELLOW, CONTINUE, "%c", (g_atl_transfer_slot[ i ].lock == LOCK) ? 'L' : 'O' );

	mprintf( YELLOW, CONTINUE, "\r\n" );
}

#endif	//	DEBUG_CODE








void atlmix_buffer_parameter_initialize( buffer_info *bip )
{
	unsigned char	i;
	unsigned short	next_base_address;
	
	
	//	ISTL parameters
	
	next_base_address	= 0;
	
	g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].base_address			= 0x0000;
	g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size	= ((bip->isochr).single_buffer_size) << 1;
	g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].payload_size			= 0;
	g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].number_of_blocks		= 0;

	next_base_address	+= g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size;	
	

	//	INTL parameters
	
	g_buffer_parameter[ INTERRUPT_TRANSFER   ].base_address			= next_base_address;
	g_buffer_parameter[ INTERRUPT_TRANSFER   ].total_buffer_size	= (PTD_HEADER_SIZE + (bip->interr).payload_size) * (bip->interr).n_of_blocks;
	g_buffer_parameter[ INTERRUPT_TRANSFER   ].payload_size			= (bip->interr).payload_size;
	g_buffer_parameter[ INTERRUPT_TRANSFER   ].number_of_blocks		= (bip->interr).n_of_blocks;

	next_base_address	+= g_buffer_parameter[ INTERRUPT_TRANSFER ].total_buffer_size;


	//	ATL parameters

#ifdef USE_PAIRED_PTD
	
	{
		unsigned char	c	= 0;
		
		for ( i = 0; i < 10; i++ )
			c	+= (((bip->aperio).payload_size >> i) & 0x1) ? 1 : 0;
		
		if (c != 1)
			mprintf( LIGHTRED, CONTINUE, "\r\n*** WARNING! ***\r\nFor the paired-PTD, the ATL payload size is needed to be \"(2^N) && (>=128)\".\r\n\r\n" );	
	}
	
#else

#endif

	g_buffer_parameter[ CTRL_BULK_TRANSFER   ].base_address			= next_base_address;
	g_buffer_parameter[ CTRL_BULK_TRANSFER   ].total_buffer_size	= 4096 - next_base_address;
	g_buffer_parameter[ CTRL_BULK_TRANSFER   ].payload_size			= (bip->aperio).payload_size;
	g_buffer_parameter[ CTRL_BULK_TRANSFER   ].number_of_blocks		= (4096 - next_base_address) / (PTD_HEADER_SIZE + (bip->aperio).payload_size);


	//	First block is reserved for ControlTransfer in this program

	g_buffer_parameter[ CONTROL_TRANSFER     ].base_address			= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].base_address;
	g_buffer_parameter[ CONTROL_TRANSFER     ].total_buffer_size	= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].payload_size + PTD_HEADER_SIZE;
	g_buffer_parameter[ CONTROL_TRANSFER     ].payload_size			= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].payload_size;
	g_buffer_parameter[ CONTROL_TRANSFER     ].number_of_blocks		= 1;

	g_buffer_parameter[ BULK_TRANSFER        ].base_address			= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].base_address + g_buffer_parameter[ CONTROL_TRANSFER     ].payload_size + PTD_HEADER_SIZE;
	g_buffer_parameter[ BULK_TRANSFER        ].total_buffer_size	= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].total_buffer_size - g_buffer_parameter[ CONTROL_TRANSFER     ].total_buffer_size;
	g_buffer_parameter[ BULK_TRANSFER        ].payload_size			= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].payload_size;
	g_buffer_parameter[ BULK_TRANSFER        ].number_of_blocks		= g_buffer_parameter[ CTRL_BULK_TRANSFER   ].number_of_blocks - 1;

	//	Buffer general
	write_register16( Com16_HcBufferStatus,                 0                                                                      );
	
	//	Buffer sizes
	write_register16( Com16_HcATLBufferSize,                g_buffer_parameter[ CTRL_BULK_TRANSFER   ].total_buffer_size             );
	write_register16( Com16_HcINTLBufferSize,               g_buffer_parameter[ INTERRUPT_TRANSFER   ].total_buffer_size             );
	write_register16( Com16_HcISTLBufferSize,              (g_buffer_parameter[ ISOCHRONOUS_TRANSFER ].total_buffer_size) >> 1       );	//	Set size of single buffer

	//	ISTL settings
	write_register16( Com16_HcISTLToggleRate,               0                                                                      );

	//	INTL settings
	write_register16( Com16_HcINTLBlkSize,					g_buffer_parameter[ INTERRUPT_TRANSFER   ].payload_size                  );
	write_register32( Com32_HcINTLPTDSkipMap,				0xFFFFFFFF                                                             );
	write_register32( Com32_HcINTLLastPTD,					0x1 << (g_buffer_parameter[ INTERRUPT_TRANSFER   ].number_of_blocks - 1) );
	
	//	ATL settings
	write_register16( Com16_HcATLBlkSize,					g_buffer_parameter[ CTRL_BULK_TRANSFER   ].payload_size                  );
	write_register32( Com32_HcATLPTDSkipMap,				0xFFFFFFFF                                                             );
	write_register32( Com32_HcATLLastPTD,					0x1 << (g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks - 1)   );
	write_register16( Com16_HcATLPTDDoneThresholdCount,     InitVal_HcATLPTDDoneThresholdCount                                     );
	write_register16( Com16_HcATLPTDDoneThresholdTimeOut,	InitVal_HcATLPTDDoneThresholdTimeOut                                   );

	if ( NULL == (g_atl_transfer_slot		= (transfer_instance *)malloc( sizeof( transfer_instance ) * g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks )) )
		mprintf( LIGHTRED, ABORT, "failed to make transfer instances for ATL slots for %u blocks", g_buffer_parameter[ BULK_TRANSFER ].number_of_blocks);

	if ( NULL == (g_intl_transfer_slot	= (transfer_instance *)malloc( sizeof( transfer_instance ) * g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks )) )
		mprintf( LIGHTRED, ABORT, "failed to make transfer instances for INTL slots for %u blocks", g_buffer_parameter[ BULK_TRANSFER ].number_of_blocks);

	for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
	{
		atlmix_free_transfer_index( CTRL_BULK_TRANSFER, i );
		g_atl_transfer_slot[ i ].index			= i;
		g_atl_transfer_slot[ i ].transfer_type	= CTRL_BULK_TRANSFER;
	}
	
	for ( i = 0; i < g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks; i++ )
	{
		atlmix_free_transfer_index( INTERRUPT_TRANSFER, i );
		g_intl_transfer_slot[ i ].index			= i;
		g_intl_transfer_slot[ i ].transfer_type	= INTERRUPT_TRANSFER;
	}
	
	for ( i = 0; i < 32; i++ )
		g_atl_slot_number_by_block[ i ]	= 0xFF;
	
}












⌨️ 快捷键说明

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