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

📄 atl_mix.c

📁 基于ARM的读U盘
💻 C
📖 第 1 页 / 共 3 页
字号:
	unsigned short	i;

	transfer_instance *tr_instance_ptr;
	
	atl_stat	= atl_buffer_state( ATL_STATUS__DONE | ATL_STATUS__FULL );	// 读ATL缓冲区状态
	atl_full	= atl_stat & ATL_STATUS__FULL;							// 获取ATL缓冲区是否为懑状态
	atl_done	= atl_stat & ATL_STATUS__DONE;							// 获取ATL缓冲区是否完成状态

	if ( atl_full && !atl_done )									//	If the ATL buffer waiting for transfer...
		return;												//		exit from this function

	if ( atl_done && g_atl_access_length )						//	If ATL has been finished and data are waiting for read out
	{
		atl_read_buffer( g_atl_buffer, g_atl_access_length );	//		read buffer
		atl_buffer_parse( g_atl_buffer );//		parsing buffer.
	}

	g_atl_access_length		= 0;	

	// 插入新的传输描述符
	if(g_is_add)
		for( i=0; i< NUMBER_OF_TRANSFER_TYPES;i++)
		{	
			g_is_add = 0;
			if(g_insert_tr_list_ptr[i] == NULL)
				continue;

			if(g_tr_list_ptr[i]==NULL)// 如果传输列表为空,则直接将插入列表传结列表
			{	
				g_tr_list_ptr[i] =  g_insert_tr_list_ptr[i];
				g_insert_tr_list_ptr[i]=NULL;
				continue;
			}
			else
			{
				tr_instance_ptr = g_tr_list_ptr[i]->tr_list_for_tr.Flink;	// 传输描述链表的最后一项

				g_tr_list_ptr[i]->tr_list_for_tr.Flink = g_insert_tr_list_ptr[i]->tr_list_for_tr.Flink;
				tr_instance_ptr->tr_list_for_tr.Blink = g_insert_tr_list_ptr[i];
				g_insert_tr_list_ptr[i]->tr_list_for_tr.Flink = tr_instance_ptr;	
				g_insert_tr_list_ptr[i] = NULL;
			}
		}
	
	atl_schedule( g_atl_buffer, InitVal_HcATLBufferLength, &g_atl_access_length);	// 传输调度

	if ( g_atl_access_length )
		atl_write_buffer( g_atl_buffer, g_atl_access_length );		// 写PTD影像到ATL BUFFER
}


//***********************************************************************
//函数名称:atl_read_buffer
//输入参数: bp,
//			      length,
//输出参数:无
//功能描述:读ATL缓冲区
//***********************************************************************
void atl_read_buffer( unsigned char *bp, unsigned short length )
{
	write_register16( Com16_HcTransferCounter, length );
	read_register_burst_char( Com16_HcATLBufferPort, bp, length );
}

//*******************************************************************************************
// 函数名称:atl_write_buffer
// 输入参数:bp,写入ATL缓冲区的数据指针
//		 length,写
// 输出参数:无
// 功能描述:写ATL缓冲区
//******************************************************************************************
void atl_write_buffer( unsigned char *bp, unsigned short length )
{
	write_register16( Com16_HcTransferCounter, length );
	write_register_burst_char( Com16_HcATLBufferPort, bp, length );
}


#ifdef	TRANSFER_STATUS_MONITOR
#include	<conio.h>
#endif

//*******************************************************************************************
//函数名称:atl_buffer_parse
//输入参数:ptd_start,ATL缓冲区指针
//输出参数:无
//功能描述:ATL缓冲区PTD数据解析
//*******************************************************************************************
void atl_buffer_parse( unsigned char *ptd_start )
{
	transfer_instance	*tr_inst_ptr;
	PTD_header_param	ph;
	int					i;

	for(i=0;i<NUMBER_OF_TRANSFER_TYPES;i++)// 传输类型:中断/控制/批量
	{
		for( tr_inst_ptr = g_tr_list_ptr[i]; 
			 tr_inst_ptr!=NULL; 
			 tr_inst_ptr =tr_inst_ptr->tr_list_for_tr.Blink)	// 指向下一个传输描述符列表
		{
	   		if ( tr_inst_ptr->data_ptr_start == NULL )
				continue;												//	No transfer instance exist in this slot
	   		if ( tr_inst_ptr->readout_position == NULL )
				continue;												//	This slot has not been scheduled
			ptd_start	= tr_inst_ptr->readout_position;
			
			get_PTD_header( &ph, ptd_start );	//获取PTD头,将压缩的PTD转换为PTD数据结构

			   if ( i == BULK_TRANSFER)
					tr_inst_ptr->readout_position	= NULL;// test test										
	// ***********************************************************
			if ( ph.ActualBytes )		//	Data transfer happaned!
			{				
			   if ( i == BULK_TRANSFER)
					tr_inst_ptr->readout_position	= NULL;// test test
				if ( tr_inst_ptr->direction == IN )
					memcpy( tr_inst_ptr->data_ptr_start, ptd_start + PTD_HEADER_LENGTH, ph.ActualBytes );

				tr_inst_ptr->data_ptr_start	+= ph.ActualBytes;	// 更新传输后的缓冲区指针
				tr_inst_ptr->transferred_size	+= ph.ActualBytes;	// 更新已完成传输字节数
			}

			tr_inst_ptr->readout_position	= NULL;
	// ******************************************************
			// 传输出错计数,当连续出错超过三次,即中止该传输实例
			tr_inst_ptr->fatal_error		 = (tr_inst_ptr->fatal_error << 1) | (( (!ph.CompletionCode) || (ph.CompletionCode & 0x8) ) ? 0 : 1);
			tr_inst_ptr->completion_code	 = ph.CompletionCode;



			if ( !((!ph.CompletionCode) || (ph.CompletionCode & 0x8)) )  /* 2005-2-24 updata */
			{
				(tr_inst_ptr->epi_ptr)->toggle = !ph.Toggle;
			}
			else
			{	

				if ( (i == INTERRUPT_TRANSFER) && (ph.DirectionPID == IN) && !ph.Active && !ph.ActualBytes )
					ph.Toggle	= !ph.Toggle;
				else
					(tr_inst_ptr->epi_ptr)->toggle = ph.Toggle;
			}
	// ********************************************************
			if ( ((!ph.Active)&&(!(tr_inst_ptr->data_ptr_start < tr_inst_ptr->data_ptr_end))) 	//	Data filled
					/*2005-2-3 UPDATA 处理空包传输	*/ 
				|| (tr_inst_ptr->fatal_error		== 0x7) 				//	Consequtive fatal errors 3 times.
				|| (tr_inst_ptr->completion_code == CompletionCode_DataUnderrun)				//	Short packet
				//|| (tr_inst_ptr->completion_code == CompletionCode_DeviceNotResponding)	// 2005-2-23UP 设备没回应
				|| (tr_inst_ptr->completion_code == CompletionCode_Stall))					// 2005-2-23UP 收到停止包
			{
				tr_inst_ptr->data_ptr_start = NULL;						//	Clear the transfer清除传输(传输结束)
				(*(tr_inst_ptr->callback))( tr_inst_ptr );				//	Call the callback function
			}
		}
	}
}


//******************************************************************************************
//函数名称:atl_schedule
//输入参数:bp,ATL影像缓冲区指针
//				  length,ATL缓冲区的长度
//				  atl_buffer_access_length,
//输出参数:无
//功能描述:ATL传输调度处理.
//******************************************************************************************
void atl_schedule( unsigned char *bp, unsigned short length, unsigned short *atl_buffer_access_length )
{
	transfer_instance_ptr	tr_inst_ptr;
	PTD_header_param		ph;
	unsigned char			*ptd_start;
	unsigned char			*ptd_end;
	unsigned char			*last_ptd_start;
	unsigned short			required_transfer_size;
	unsigned short			transfer_size;
	unsigned short			transfer_size_limit;
	unsigned short			size_may_be_written;
	unsigned short			packet_size;

	int						i;
							
	ptd_start						= bp;			// 设置PTD影像缓冲区指针
	ptd_end						= bp + length;		// 本次调度结束指针
	last_ptd_start				  	= ptd_start;		// 上一个PTD数据结构结整指针

for(i=0;i<NUMBER_OF_TRANSFER_TYPES;i++)// 传输类型:中断/控制/批量
	for(tr_inst_ptr = g_tr_list_ptr[i]; 
		tr_inst_ptr!=NULL; 
		tr_inst_ptr = tr_inst_ptr->tr_list_for_tr.Blink)// 指向下一个传输描述符列表
	{
			if(tr_inst_ptr->lock == DELETE)		// 删除列表
			{
				tr_inst_ptr->lock = UNLOCK;
				remove_tr_list(&g_tr_list_ptr[i],tr_inst_ptr);	// 
				remove_tr_from_ep(tr_inst_ptr);
				continue;	
			}
			/********************************************************/
			/*	Is this transfer waiting scheduling?				*/
			/********************************************************/
			// data_ptr_start指针为空,即该描述数据结构没有需传输
     	   		if ( tr_inst_ptr->data_ptr_start == NULL )					//	No transfer to schedule.
				continue;

	   		if ( tr_inst_ptr->readout_position != NULL )		//	Read-out has not been done.
				continue;
	                                                                                                                                                                                                                                                                                                                                                                                                                        			
	   		if ( tr_inst_ptr->direction == HOLD )						//	Client needs the transfer hold and callback again
				continue;
			// 该实例为中断传输
			if ( i == INTERRUPT_TRANSFER )							//	Interrupt transfer needs to transfer this instance?
			{
				if ( g_sof_counter < (tr_inst_ptr->poll_timing_timer) )		// 中断传输周期未到暂不处理
					continue;
				else
					tr_inst_ptr->poll_timing_timer = g_sof_counter + tr_inst_ptr->schedule_rate;// 设置下次中断传输处理时间
			}
 

			/********************************************************/
			/*	Calculate available time slot for buffer writing	*/
			/*     为写缓冲区计算可用的时间空位*/
			/********************************************************/
			
			size_may_be_written	= ptd_end - ptd_start;						// ATL当前可写的缓冲区长度
			packet_size			= (tr_inst_ptr->epi_ptr)->max_packet_size;		// 该端点最大封包
			// 
			transfer_size_limit		= (size_may_be_written < MAX_DATA_SIZE_IN_A_FRAME) ? 	((size_may_be_written / packet_size) * packet_size) : MAX_DATA_SIZE_IN_A_FRAME;// 可用于该传输描述符传输的最大长度
			// 该传输实例中,需传输的数据传长度
			required_transfer_size	= (unsigned short)((unsigned long)(tr_inst_ptr->data_ptr_end) - (unsigned long)(tr_inst_ptr->data_ptr_start));					// 传输描述符需要传输的数据长度
			transfer_size			= (required_transfer_size < transfer_size_limit) ? required_transfer_size : transfer_size_limit;									// 实际将要传输的字节数
			// 该次调度不足完成本次调度
			if ( required_transfer_size && !transfer_size )				//	如果一个包的数据都不能传输,即暂缓该传输描述符调度
				continue;


			/********************************************************/
			/*	Calculate size/position of this PTD image		 	*/
			/********************************************************/
			if ( !((ptd_start + PTD_HEADER_LENGTH +  transfer_size) < ptd_end) )	// 记算ATL映象缓冲区剩除长度是否满足传输	when the data size is bigger than expected
				continue;

			tr_inst_ptr->readout_position	= ptd_start;	// ATL传输完成后,需读出数据存存的指针,如为NULL就不处理
			last_ptd_start	 				= ptd_start;	// 记录最后一个PTD的起始地址

			/********************************************************/
			/*	write a PTD in ATL image buffer						*/
			/********************************************************/

			ph.ActualBytes		= 0;
			ph.CompletionCode	= 0;
			ph.Active			= 1;
			ph.Toggle			= (tr_inst_ptr->epi_ptr)->toggle;
			ph.MaxPacketSize	= packet_size;
			ph.EndpointNumber	= (tr_inst_ptr->epi_ptr)->ep_num;
			ph.Last			= 0;
			ph.Speed			= (tr_inst_ptr->epi_ptr)->speed;
			ph.TotalBytes		= transfer_size;
			ph.DirectionPID	= tr_inst_ptr->direction;
			ph.Format		= 0x03&(tr_inst_ptr->epi_ptr)->tr_type;
			ph.FunctionAddress	= (tr_inst_ptr->epi_ptr)->dev_addr;
		  if ( i == BULK_TRANSFER)
					ph.FunctionAddress	= (tr_inst_ptr->epi_ptr)->dev_addr;// test test

			#define	A_BIT_FOR_INTERRUPT_TR	0x2
			// 如果是中断传输,即在一帧内最多只产生一次NAK
			ph.test	= (i == INTERRUPT_TRANSFER) ? A_BIT_FOR_INTERRUPT_TR : 0x0;// 如为中断传输设置为A_BIT_FOR_INTERRUPT_TR
			// 将ph数据结构压缩为8字节的PTD数据结构,并写到缓冲区
			set_PTD_header( ptd_start, &ph );			//	write PTD header
			
			if ( tr_inst_ptr->direction != IN )				//	write PTD payload
				memcpy( ptd_start + PTD_HEADER_LENGTH, tr_inst_ptr->data_ptr_start, transfer_size );


			/********************************************************/
			/*	update memory position in ATL image buffer			*/
			/********************************************************/
			// 更新下一个PTD开始缓冲区指针,
			ptd_start	= ptd_start + PTD_HEADER_LENGTH + transfer_size;
			ptd_start	= mem_align( ptd_start );	// 
			

⌨️ 快捷键说明

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