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

📄 atl_mix.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	tip->time_of_service		= 0xFFFFFFFF;
	
	free_transfer_block( tip );

	enable_INT();	//	##	version1.2c
}


transfer_instance *atlmix_set_transfer( unsigned char transfer_type, unsigned char polling_rate, unsigned char index, unsigned char *buffer_ptr, unsigned short length, unsigned char direction, endpoint_info_ptr epi_ptr, void (*callback)( endpoint_info_ptr epi_ptr ) )
{
	transfer_instance_ptr	tip;
	unsigned short			intr_en;

	disable_INT();

	switch ( transfer_type )
	{
		case CONTROL_TRANSFER :
		case BULK_TRANSFER :
		
			if ( !(index < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks) )
				return ( NULL );
				
			tip		= &(g_atl_transfer_slot[ index ]);
			
			{
				if ( index == g_pp_block0 )
				{
					tip->paired		= True;
					tip->ping_pong	= 0;
				}
				else if ( index == g_pp_block1 )
				{
					tip->paired		= True;
					tip->ping_pong	= 1;
				}
				else
				{
					tip->paired		= False;
					tip->ping_pong	= 0;
				}
			}
			
			break;
			
		case INTERRUPT_TRANSFER :
		
			if ( !(index < g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks) )
				return ( NULL );
				
			tip		= &(g_intl_transfer_slot[ index ]);
			break;
			
		default :
			mprintf( LIGHTRED, ABORT, "atlmix_set_transfer : Unsupported transfer type   transfer_type = %d   \r\n", transfer_type );
			break;
	}

	epi_ptr->transfer_instance		= tip;

	tip->data_ptr_base				= buffer_ptr;
	tip->data_ptr_start				= buffer_ptr;
	tip->data_ptr_end				= buffer_ptr + length;
	tip->epi_ptr					= epi_ptr;
	tip->callback					= callback;
	tip->transferred_size			= 0;
	tip->direction					= direction;
	tip->completion_code			= 0;
	tip->fatal_error				= 0;
	tip->transfer_type				= transfer_type;
	tip->retry_count				= 0;
	tip->timeout					= TEST_VALUE;
	
	switch ( transfer_type )
	{
		case CONTROL_TRANSFER :
		case BULK_TRANSFER :

			atl_scheduler( index );
			break;
			
		case INTERRUPT_TRANSFER :

			intl_scheduler( index, polling_rate );
			break;
			
		default :
			mprintf( LIGHTRED, ABORT, "atlmix_set_transfer : Unsupported transfer type   transfer_type = %d   \r\n", transfer_type );
			break;
	}

	enable_INT();

	return ( tip );
}


void re_enable_atl_transfer( transfer_instance_ptr tip )
{
	unsigned short			intr_en;

	disable_INT();

	atl_scheduler( tip->index );

	enable_INT();
}


void atlmix_re_enable_interrupt_transfer( transfer_instance_ptr tip )
{
	unsigned short	v;

	tip->data_ptr_start		= tip->data_ptr_base;
	
	read_direct_access( tip->target_address, (unsigned char *)(&v), 2 );

	v	&= 0x0400;		//	Do not clear "Toggle" information
	v	|= 0x0800;		//	Set "Active" bit to activate this PTD

	write_direct_access( tip->target_address, (unsigned char *)(&v), 2 );		//	Needs to re-write these 2 bytes

	write_register32( Com32_HcINTLPTDSkipMap, read_register32( Com32_HcINTLPTDSkipMap ) & ~(0x00000001L << (tip->index)) );
}



/***************************************
 ***************************************
 **
 **		Schedulers
 **
 ***************************************
 ***************************************/


void atl_scheduler( unsigned char i )
{
	transfer_instance_ptr	tip;

#ifdef USE_SKIPMAP
	unsigned long			skip_map;
#endif

	tip		= &(g_atl_transfer_slot[ i ]);


#if 0
	if ( tip->target_block_index != 0xFF )
		mprintf( YELLOW, ABORT, "atl_scheduler error (%u) : ( tip->target_block_index != 0xFF )\r\n", i );
	
	if ( tip->data_ptr_start == NULL )
		mprintf( YELLOW, ABORT, "atl_scheduler error (%u|%p) : ( tip->data_ptr_start == NULL )\r\n", i, tip );
#endif


#ifdef USE_SKIPMAP
	skip_map	= read_register32( Com32_HcATLPTDSkipMap );

	if ( ~skip_map & (0x1 << i) )
		mprintf( YELLOW, ABORT, "atl_scheduler error (%u) : ( skip_map & (0x1 << i) )\r\n", i );
#endif

	tip->target_block_index					= i;
	g_atl_slot_number_by_block[ i ]			= i;
	
	tip->target_address						= g_buffer_parameter[ CTRL_BULK_TRANSFER ].base_address + ((g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size + PTD_HEADER_SIZE) * i);

	write_a_PTD_into_1362( tip );
}


void intl_scheduler( unsigned char index, unsigned char polling_rate )
{
	transfer_instance_ptr	tip;
	unsigned short			tartget_address_1362_buffer;
	unsigned char			i;

	tip		= &(g_intl_transfer_slot[ index ]);


	tip->target_block_index			= index;

	tartget_address_1362_buffer		= g_buffer_parameter[ INTERRUPT_TRANSFER ].base_address + ((g_buffer_parameter[ INTERRUPT_TRANSFER ].payload_size + PTD_HEADER_SIZE) * index);
	
	tip->target_address				= tartget_address_1362_buffer;
	tip->polling_rate				= (128 < polling_rate) ? 128 : polling_rate;

	write_a_PTD_into_1362( tip );
}


void write_a_PTD_into_1362( transfer_instance_ptr tip )
{
	unsigned short		transfer_size;
	unsigned short		payload_size;
	unsigned char		ptd_header_buffer_ptr[ PTD_HEADER_SIZE ];
	PTD_header_param	ph;
	unsigned short		skipmap_register;
	unsigned short		buffer_enable_mask;
	unsigned char		i;

	payload_size		= g_buffer_parameter[ CTRL_BULK_TRANSFER ].payload_size;
	
	transfer_size		= tip->data_ptr_end - tip->data_ptr_start;		//	remaining data size
	transfer_size		= (payload_size < transfer_size) ? payload_size : transfer_size;

	ph.ActualBytes		= 0;


	ph.CompletionCode	= 0xE;

	ph.CompletionCode	= 0;

	ph.Active			= 1;
	ph.Toggle			= (tip->epi_ptr)->toggle;
	ph.MaxPacketSize	= (tip->epi_ptr)->max_packet_size;
	ph.EndpointNumber	= (tip->epi_ptr)->ep_num;
	ph.Last				= 0;
	ph.Speed			= (tip->epi_ptr)->speed;
	ph.TotalBytes		= transfer_size;
	ph.DirectionPID		= tip->direction;
	ph.Format			= (tip->epi_ptr)->tr_type;
	ph.FunctionAddress	= (tip->epi_ptr)->dev_addr;

	if ( tip->transfer_type == INTERRUPT_TRANSFER )
	{
		for ( i = 7; i > 0; i-- )
			if ( (tip->polling_rate) & (0x01 << i) )
				break;
				
		ph.PollingRate		= i;
		ph.StartingFrame	= tip->index;
		ph.Paired			= False;
		ph.PingPong			= 0;
	
		skipmap_register	= Com32_HcINTLPTDSkipMap;
		buffer_enable_mask	= 0x4;
	}
	else
	{
		ph.PollingRate		= 0;
		ph.StartingFrame	= 0;
		ph.Paired			= tip->paired;
		ph.PingPong			= tip->ping_pong;
		
		skipmap_register	= Com32_HcATLPTDSkipMap;
		buffer_enable_mask	= g_pp_pause ? 0x0 : 0x8;
	}
	

	set_PTD_header( ptd_header_buffer_ptr, &ph );			//	write PTD header
	
	if ( read_register16( Com16_HcATLPTDDoneThresholdTimeOut ) )
		tip->timeout			= gp_sof_counter + read_register16( Com16_HcATLPTDDoneThresholdTimeOut );
	else
		tip->timeout			= 0xFFFFFFFF;

	write_direct_access( tip->target_address, ptd_header_buffer_ptr, PTD_HEADER_SIZE );
	
	if ( tip->direction != IN )
		write_direct_access( tip->target_address + PTD_HEADER_SIZE, tip->data_ptr_start, transfer_size );

	write_register32( skipmap_register, read_register32( skipmap_register ) & ~(0x00000001L << tip->target_block_index) );

	write_register16( Com16_HcBufferStatus,  read_register16( Com16_HcBufferStatus  ) |  buffer_enable_mask );
}


/***************************************
 ***************************************
 **
 **		IRQs
 **
 ***************************************
 ***************************************/


void ATL_IRQ_service( unsigned char dummy_for_func_compatibility )
{
	unsigned long	done_map;
	unsigned long	enable_map;
	unsigned long	check_timeout_map;
	unsigned long	timeout_map				= 0L;
	unsigned char	i;

	dummy_for_func_compatibility	= dummy_for_func_compatibility;	//	This line for erase warning

	done_map			=  read_register32( Com32_HcATLPTDDoneMap );	
	enable_map			= ~read_register32( Com32_HcATLPTDSkipMap );
	check_timeout_map	= ~done_map & enable_map;

	if ( check_timeout_map && !g_pp_active )
	{
		for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
			if ( check_timeout_map & (0x1 << i) )
				if ( g_atl_transfer_slot[ g_atl_slot_number_by_block[ i ] ].timeout < gp_sof_counter )
					timeout_map		|= (0x1L << i);

		done_map	|= timeout_map;
	}

	if ( done_map )
	{
		write_register32( Com32_HcATLPTDSkipMap, ~enable_map | done_map );

		if ( 0x00000000 == (enable_map & ~done_map) )
		{
			write_register16( Com16_HcBufferStatus,  read_register16( Com16_HcBufferStatus  ) & ~0x8 );
			
			if ( !g_atl_flag_mask )
				g_atl_disabled_time		= gp_sof_counter;
		}
			
		for ( i = 0; i < g_buffer_parameter[ CTRL_BULK_TRANSFER ].number_of_blocks; i++ )
		{
			if ( done_map & (0x1 << i) )
			{
				if ( (timeout_map & (0x1 << i)) && (read_register16( Com16_HcBufferStatus  ) & 0x8) )
				{
					//	Wait the HC leave from ABORTED ptd-block.
					//	
					//	If it is not aborted ptd-block, software does not need to 
					//	check this. Because HC will not touch this ptd-block 
					//	with no-active flag in pth-header.
					
					//	Version 1.2b : 
					//    When the "HcBufferStatus.ATL_Active (bit position 0x8)" is cleared, 
					//    the HC stops scnanning. In this case, no need to wait the scan goes 
					//    to other slot.
					//    If following loop enabled with ATL_Active==0, the program ca not exit. 
				
					while ( read_register32( Com16_HcATLCurrentActiePTD ) == i )
						;
				}

	//			handle_transfer_done( &(g_atl_transfer_slot[ g_atl_slot_number_by_block[ i ] ]) );
				handle_transfer_done( &(g_atl_transfer_slot[ i ]) );
			}
		}
	}
}


void INTL_IRQ_service( unsigned char dummy_for_func_compatibility )
{
	unsigned long	done_map;
	unsigned char	i;

	dummy_for_func_compatibility	= dummy_for_func_compatibility;	//	This line for erase warning
	
	done_map		= read_register32( Com32_HcINTLPTDDoneMap );
	
	write_register32( Com32_HcINTLPTDSkipMap, read_register32( Com32_HcINTLPTDSkipMap ) | done_map );

	for ( i = 0; i < g_buffer_parameter[ INTERRUPT_TRANSFER ].number_of_blocks; i++ )
		if ( done_map& (0x1 << i) )
			handle_transfer_done( &(g_intl_transfer_slot[ i ]) );
}


/***************************************

⌨️ 快捷键说明

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