📄 atl_mix.c
字号:
/****************************************************************************/
/* includes */
/****************************************************************************/
#include "HostStack.h"
#ifndef MAX_TRANSFER_LIST
#define MAX_TRANSFER_LIST 60 // 设置传输描述符个数,最小值为1
#endif
/****************************************************************************/
/* constants */
/****************************************************************************/
#define PTD_HEADER_LENGTH 8
#define NUMBER_OF_TRANSFER_TYPES 3 // 3 = control + interr + bulk (ATL传输类型)
#define ATL_STATUS__FULL 0x04
#define ATL_STATUS__DONE 0x20
#define mem_align( x ) ((unsigned char *)((((unsigned long)(x)) + 3) & ~0x3))
/****************************************************************************/
/* global vars */
/****************************************************************************/
unsigned short g_atl_access_length = 0;// 访问ATL缓冲区长度
transfer_instance g_transfer_list[ MAX_TRANSFER_LIST ]; // 传输描述符
unsigned char g_static_atl_buffer[ InitVal_HcATLBufferLength + 3 ]; // 加3为了确保字对齐
unsigned char *g_atl_buffer; // ATL RAM缓冲区指针
transfer_instance *g_tr_list_ptr[3] = {NULL,NULL,NULL} ; // 中断/控制/批量,调度传输描述符链表头指针
transfer_instance *g_insert_tr_list_ptr[3] = {NULL,NULL,NULL} ; // 中断/控制/批量,插入传输描述符链表头指针
/****************************************************************************/
/* function prototypes */
/****************************************************************************/
unsigned char atl_buffer_state( unsigned short pattern );
void atl_read_buffer( unsigned char *bp, unsigned short length );
void atl_write_buffer( unsigned char *bp, unsigned short length );
void atl_buffer_parse( unsigned char *bp );
void atl_schedule( unsigned char *g_atl_buffer, unsigned short length, unsigned short *ap );
void PTD_image_create( PTD_header_param *php, unsigned char *data, unsigned char *atl_buffer );
void set_PTD_header( unsigned char *ph, PTD_header_param *php );
void set_LAST_PTD_flag( unsigned char *p );
void get_PTD_header( PTD_header_param *php, unsigned char *ph );
void remove_tr_list(transfer_instance **from_this_list, transfer_instance *list );
void insert_tr_to_ep_list(transfer_instance **to_this_list, transfer_instance *list );
void remove_tr_from_ep(transfer_instance *list);
/****************************************************************************/
/* function definitions */
/****************************************************************************/
//******************************************************************************************
//函数名称:atl_initialize
//输入参数:无
//输出参数:无
//功能描述:ATL传输列表初始化。
//******************************************************************************************
void atl_initialize( void )
{
int i;
for(i=0; i < MAX_TRANSFER_LIST ; i++)
{
(g_transfer_list[i]).lock = UNLOCK; // 初始化传输描述列表信息
(g_transfer_list[ i ]).readout_position = NULL;
(g_transfer_list[ i ]).data_ptr_start = NULL;
}
g_tr_list_ptr[0] = NULL ;
g_tr_list_ptr[1] = NULL ;
g_tr_list_ptr[2] = NULL ;
g_insert_tr_list_ptr[0] = NULL ;
g_insert_tr_list_ptr[1] = NULL ;
g_insert_tr_list_ptr[2] = NULL ;
g_atl_buffer = mem_align( g_static_atl_buffer ); // 获取缓冲区指针,并以双字对齐
install_ATLInt_service_routine( 0, atl_ATL_transfer_mixer ); // 安装ATL传输函数
install_SOF_service_routine( 1, atl_ATL_transfer_mixer ); // 安装ITL(同步)传输函数
}
unsigned char g_is_add = 0;
//****************************************************************************************
// 函数名称:insert_transfer_descriptor
// 输入参数:tr_instance_ptr,将插入的
// transfer_type,传输类型,代号与端点类型一至
// 输出参数:无
// 功能描述:插入一个传输描述符到插入链表。
//****************************************************************************************
void insert_transfer_descriptor(transfer_instance *tr_instance_ptr ,
unsigned char transfer_type)
{
transfer_instance **tr_instance_type_ptr;
disable();
g_is_add =0;
switch(transfer_type & 0x03)
{
case 3:
tr_instance_type_ptr = &g_insert_tr_list_ptr[INTERRUPT_TRANSFER];
break;
case 0:
tr_instance_type_ptr = &g_insert_tr_list_ptr[CONTROL_TRANSFER];
break;
case 2:
tr_instance_type_ptr = &g_insert_tr_list_ptr[BULK_TRANSFER];
break;
}
tr_instance_ptr->tr_list_for_tr.Flink = NULL;
tr_instance_ptr->tr_list_for_tr.Blink = NULL;
if ( *tr_instance_type_ptr == NULL) // 插入列表为空
{
*tr_instance_type_ptr = tr_instance_ptr;
(*tr_instance_type_ptr)->tr_list_for_tr.Flink = tr_instance_ptr;
(*tr_instance_type_ptr)->tr_list_for_tr.Blink = NULL;
}
else
{
(*tr_instance_type_ptr)->tr_list_for_tr.Flink->tr_list_for_tr.Blink = tr_instance_ptr;// 在插入的传输描述列表未插入一个新的传输描述符
tr_instance_ptr->tr_list_for_tr.Flink = (*tr_instance_type_ptr)->tr_list_for_tr.Flink; // 将该描述符的
tr_instance_ptr->tr_list_for_tr.Blink = NULL; // 插入描术符的下一个描述符为空
(*tr_instance_type_ptr)->tr_list_for_tr.Flink = tr_instance_ptr; // 更新插入例表指向列表的最后一个传输描述符
}
g_is_add = 1;
enable();
}
//******************************************************************************************
//函数名称:atl_get_open_index
//输入参数:epi_ptr,端点描述数据结构
//输出参数:正常返回:transfer_instance指针
// 出错返回:ATL_ENDPOINT_ERR
// NO_OPEN_ATL_TRANSFER
//功能描述:在传描述符数据结构列表中,查找空闲的传输描述符数据结构
//******************************************************************************************
transfer_instance *atl_open_transfer_instance( endpoint_info * epi_ptr)
{
int j;
unsigned char transfer_type = epi_ptr->transfer_type & 0x03;
OS_EVENT *os_event_ptr;
disable();
if(epi_ptr->ep_num==ENDPOINT_BE_FREE)
{
enable();
return ATL_ENDPOINT_ERR;
}
for ( j = 0; j < MAX_TRANSFER_LIST; j++ )
{
if ( (g_transfer_list[ j ]).lock == UNLOCK )
{
(g_transfer_list[ j ]).lock= LOCK; // 锁定该传输描述符数据结构,低7位为索引号
os_event_ptr = OSMboxCreate(NULL); // 创建一个消息事件
if(os_event_ptr)
(g_transfer_list[ j ]).os_event_ptr = os_event_ptr; // 保存OS事件指针
else
{
(g_transfer_list[ j ]).lock = UNLOCK; // 锁定该传输描述符数据结构,低7位为索引号
enable();
return NO_OPEN_ATL_TRANSFER ;
}
(g_transfer_list[ j ]).epi_ptr = epi_ptr; // 保存端点描述信息结构指针
(g_transfer_list[ j ]).endpoint_create_id = epi_ptr->endpoint_create_id;// 记录端点ID
insert_transfer_descriptor(&(g_transfer_list[ j ]), transfer_type);
insert_tr_to_ep_list(&epi_ptr->tr_instance_ptr, &(g_transfer_list[ j ]));
enable();
return &(g_transfer_list[ j ]) ;
}
}
enable();
return NO_OPEN_ATL_TRANSFER ;
}
//******************************************************************************************
//函数名称:atl_free_index,
//输入参数:tr_instance_ptr,传输描述符数据结构指针
//输出参数:无
//功能描述:释放传输索引
//******************************************************************************************
void atl_close_transfer_instance( transfer_instance *tr_instance_ptr )
{
unsigned char err;
OS_MBOX_DATA Mbox_data;
if(tr_instance_ptr->lock == UNLOCK)
return;
if(tr_instance_ptr->lock == DELETE)
return;
tr_instance_ptr->data_ptr_start = NULL;
tr_instance_ptr->lock = DELETE;
/*查询是否在任务在等待该消息*/
OSMboxQuery(tr_instance_ptr->os_event_ptr,
&Mbox_data );
if(Mbox_data.OSEventGrp) // 有任务在等待该消息
{
tr_instance_ptr->completion_code = OS_EVENT_DELETE; // 标记该传输描述符已被删除
OSMboxPost( tr_instance_ptr->os_event_ptr,
&tr_instance_ptr->completion_code); // 向等待消息的任务发送消息
return;
}
OSMboxDel( tr_instance_ptr->os_event_ptr, // 删除传输描述符使用的事件
OS_DEL_ALWAYS , &err );
tr_instance_ptr->os_event_ptr = NULL;
}
//******************************************************************************************
// 函数名称:atl_set_transfer
// 输入参数:tr_inst_ptr,传输描述符数据结构指针
// buffer_ptr,数据缓冲区指针
// length,传输数据长度
// direction,传输方向
// callback,传输完成回调函数
// 输出参数:正常返回TRUE,出错返回FALSE。
// 功能描述:设置传输处理。
//******************************************************************************************
unsigned char atl_set_transfer( transfer_instance *tr_inst_ptr,
unsigned char *buffer_ptr,
unsigned short length,
unsigned char direction,
void (*callback)( transfer_instance *tr_inst_ptr ) )
{
unsigned char schedule_rate;
if( tr_inst_ptr->lock != LOCK) // 校验传输描述符是否有效
return FALSE ;
if( tr_inst_ptr->epi_ptr == NULL) // 校验端点描述符是否有效
return FALSE ;
if( tr_inst_ptr->epi_ptr->ep_num == ENDPOINT_BE_FREE)// 校验端点描述符是否有效
return FALSE ;
if( tr_inst_ptr->endpoint_create_id != // 校验端传输描述符与端点描述符是否一致
tr_inst_ptr->epi_ptr->endpoint_create_id)
return FALSE;
schedule_rate = tr_inst_ptr->epi_ptr->endpoint_descriptor.bInterval;
tr_inst_ptr->data_ptr_base = buffer_ptr; // 该传输数据缓冲区基地址指针
tr_inst_ptr->data_ptr_end = buffer_ptr + length; // 该传输数据缓冲区结束地址指针
tr_inst_ptr->direction = direction; // 设置传输方向(SETUP、IN、OUT)
tr_inst_ptr->callback = callback; // 保存回调函数结构指针
tr_inst_ptr->readout_position = NULL; // 初始化为空
tr_inst_ptr->transferred_size = 0; // 初始化传输数据长度为0
tr_inst_ptr->fatal_error = 0; // 初始化出错记录为0
tr_inst_ptr->completion_code = 0; // 初始化完成代码为0
tr_inst_ptr->schedule_rate = schedule_rate; // 设置调度时间间隔
tr_inst_ptr->poll_timing_timer = g_sof_counter + tr_inst_ptr->schedule_rate;
// 设置data_ptr_start指针,当该指针成员被设置,中断中将会处理该传输
tr_inst_ptr->data_ptr_start = tr_inst_ptr->data_ptr_base; // This should be last. ISR detects the list enabled by this pointer setting.
return TRUE;
}
//******************************************************************************************
//函数名称:re_enable_interrupt_transfer
//输入参数:tr_inst_ptr,中断传输描述信息结构指针
//输出参数:无
//功能描述:重新使能中断传输。
//******************************************************************************************
void re_enable_interrupt_transfer( transfer_instance *tr_inst_ptr )
{
// data_ptr_start,不为空指针时,该传输将被调度
tr_inst_ptr->data_ptr_start = tr_inst_ptr->data_ptr_base;
}
/* interrupt service routines */
//***********************************************************************
//函数名称:atl_ATL_transfer_mixer
//输入参数:无
//输出参数:无
//功能描述:ATL传输处理
//***********************************************************************
void atl_ATL_transfer_mixer( void )
{
unsigned short atl_stat;
unsigned short atl_full;
unsigned short atl_done;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -