📄 atl_mix.c
字号:
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 + -