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

📄 usbhost.c

📁 USB Host在嵌入式系统中的实现.包括所有源代码.
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "standard.h"
#include "nucleus.h"
#include "syt.h"
#include "usbhost.h"
#include "usbpriv.h"
#include "xtime.h"
#include "usbh.h"

//#define HOSTPRINTF logprintf
#define HOSTPRINTF if(0) printf

#define PIPE_IN		0x01
#define PIPE_OUT	0x02
#define PIPE_INT	0x03

#define USBHOST_PRIORITY     10
#define FS_CTRL_PKCT_SIZE    64
#define FS_BULK_PKCT_SIZE    64
/*
 * Start-of-Frame byte-count-times threshold for starting a worst-case
 * transfer followed by ACK or NAK without colliding with next SOF.
 */
#define SOF_THRESHOLD  100
#define PTPTASK_STACKSIZE	1024
#define USBHTASK_STACKSIZE 1024


/* Insertion delay - 100ms. min USB spec.: 9.1.2, #3, pg. 243 */
#define USB_DEBOUNCE_DELAY          (105*1000)
/* Reset delay (TDRSTR) - 50ms. min, USB spec.: 7.1.7.5, pg. 153 */
#define USB_RESET_DELAY             (55*1000)
/* Reset recovery time (TRSTRCY) - 10ms. min, USB spec.: 7.1.7.5, pg. 153 */
#define USB_RESET_RECOVERY_DELAY    (15*1000)


#define MICROSECONDS_PER_TICK	(1000000 / (NU_PLUS_Ticks_Per_Second))
#define MILLISECONDS_PER_TICK	(1000 / (NU_PLUS_Ticks_Per_Second))
#define TICKS_PER_SECOND	(NU_PLUS_Ticks_Per_Second)

/*
**  Notes on time conversion:
**	    1. We round microseconds to the nearest tick.
**	    2. Max TaskSleep time is ~497 days.
*/
#define TIMEVAL_TO_TICKS(tvp) \
	(tvp->secs * TICKS_PER_SECOND + \
	 (tvp->usecs + MICROSECONDS_PER_TICK/2) / MICROSECONDS_PER_TICK)
	 
//typedef enum {
//    PTP_USB_OK,
//    PTP_USB_NAK,
//    PTP_USB_INT_DATA_ABORT,
//    PTP_USB_D_CANCEL,
//    PTP_USB_H_CANCEL,
//    PTP_USB_ERROR,
//    PTP_USB_GONE
//} PTPIO_RETN;

typedef struct {
    Boolean needClass;
    int Config;
    int iface;
    int ifaceAlt;
    int MaxLUN;
    int ep_in;
    int ep_in_pksize;
    int ep_out;
    int ep_out_pksize;
    int ep_intr;
    int ep_intr_pksize;
    int ep_intr_pollms;
} USB_CLASS;

typedef struct {
    Uint8 process;
	Uint8 istate;
	Uint8 error;
	Uint8 regstate;
	Uint32 TID;	
	Uint32 bw3;
	Uint32 bw4;
}MSG_Q;

typedef struct {
	/*Curr State Info*/
	HOST_QUEUE_HEAD	*curr_QH;
    TRANSACTION_STRUCT *curr_TD;
    TRANSACTION_STRUCT *prve_TD;
        
    /*USB Device Info DataBase*/
    Uint8 dev_total;   
	DEV_INFO *dev_info[128];
	Uint32 USB_addr;
	/*USBH HW Setting Info*/
    Boolean even_odd_OUT;
    Boolean even_odd_IN;
    int DeviceReady;
} HOST_STATE_STRUCT;


static NU_TASK TaskPTPLayerID;
static NU_TASK TaskUSBH_ID;
static NU_QUEUE USBH_CTRL_Queue;
static NU_QUEUE USBH_BIN_Queue;
static NU_QUEUE USBH_BOUT_Queue;
static NU_QUEUE USBH_INTIN_Queue;
static NU_SEMAPHORE USBH_READ_Semaphore;
static NU_SEMAPHORE USBH_WRITE_Semaphore;
static NU_SEMAPHORE USBH_INT_Semaphore;
static Uint32 TaskUSBH_stack[USBHTASK_STACKSIZE*2];
static Uint32 TaskPTPLayer_stack[PTPTASK_STACKSIZE*4];
static DEVICE_DESC DeviceDesc;    
static CONFIG_DESC ConfigDesc;    
static INTERFACE_DESC InterfaceDesc;
static ENDPOINT_DESC EndpointDesc;
static USB_CLASS MassStorage;
static USB_CLASS StillImage;
static TimeVal debounce_delay = {0, USB_DEBOUNCE_DELAY};
static TimeVal reset_delay   = {0, USB_RESET_DELAY};
static TimeVal recover_delay = {0, USB_RESET_RECOVERY_DELAY};

int *USBHOST_READY_FLAG;
Uint8 *Setup, *dev_request_buffer;
Uint32 *Ctrl_Queue_buff;
Uint32 *BulkIN_Queue_buff;
Uint32 *BulkOUT_Queue_buff;
Uint32 *IntIN_Queue_buff;
HOST_STATE_STRUCT usb_host;

extern EP_DATA *Ctrl_ep;
extern DEV_INFO *device_info;
extern HOST_QUEUE_HEAD	ISO_QH,INT_QH,CONTROL_QH,BULK_QH;


void PTP_Layer_Task(UNSIGNED argc, VOID *argv);
PTPIO_RETN PTP_USB_ReadInterrupt(Uint32 UniqueDeviceID, Uint8 *Buf, Uint32 Size, Uint32 *retCount);



///*****************************************************************************
// * Synopsis:    Sint32 TaskSleep(pTV)
// * Description: Put the task to sleep, making it ready after the time 'pTV'.
// * Arguments:   (TimeVal *) pTV -- pointer to the timeval structure.
// * Return:      0 always
// *****************************************************************************/
//Sint32 TaskSleep(TimeVal * pTV)
//{
//    /* Note: NU_Sleep(n) sleeps for between n-1 and n ticks, that's why we
//    **	     add the 1 at the end of the equation.
//    */
//    UNSIGNED ticks;
//
//    ASSERT(pTV != NULL);
//
//    ticks = TIMEVAL_TO_TICKS(pTV) + 1;
//
//    NU_Sleep(ticks);
//
//    return 0;
//}

Uint8 debug_log_workreport[400];
Uint16 debug_log_workreport_count=0;
void USBH_work_report(Uint8 code, Uint32 PROCESS_ID, Uint32 rstatus)
{
	STATUS status;
	MSG_Q Msg;

	Msg.process = code;
	Msg.istate	= (Uint8)(rstatus>>16);	
	Msg.error	= (Uint8)(rstatus>>8);
	Msg.regstate= (Uint8) rstatus;
	Msg.TID		= PROCESS_ID;
	Msg.bw3		= 0;
	Msg.bw4		= 0;
	
	if(code==USBH_DONE){
		if(debug_log_workreport_count>400)
			debug_log_workreport_count=0;
		debug_log_workreport[debug_log_workreport_count]=PROCESS_ID;
		debug_log_workreport_count++;
	}
	
	if(((PROCESS_ID&0xF0)==CTRL_TRANSACTION)||(PROCESS_ID==0)){
		status = NU_Send_To_Queue(&USBH_CTRL_Queue, &Msg, 4, NU_NO_SUSPEND);
		if(status!=NU_SUCCESS){
			while(1);
		}
		return;
	}
	if(PROCESS_ID==(BULK_TRANSACTION|PROCESS_IN)){
		status = NU_Send_To_Queue(&USBH_BIN_Queue, &Msg, 4, NU_NO_SUSPEND);
		if(status!=NU_SUCCESS){
			while(1);
		}
		return;
	}
	if(PROCESS_ID==(BULK_TRANSACTION|PROCESS_OUT)){
		status = NU_Send_To_Queue(&USBH_BOUT_Queue, &Msg, 4, NU_NO_SUSPEND);
		if(status!=NU_SUCCESS){
			while(1);
		}
		return;
	}
	if(PROCESS_ID==INT_TRANSACTION|PROCESS_IN){
		status = NU_Send_To_Queue(&USBH_INTIN_Queue, &Msg, 4, NU_NO_SUSPEND);
		if(status!=NU_SUCCESS){
			while(1);
		}
		return;
	}
//	status = NU_Broadcast_To_Queue(&USBH_CTRL_Queue, &Msg, 4,NU_NO_SUSPEND);	
//	if(status!=NU_SUCCESS){
//		while(1);
//	}
}











Sint32 IObf_2_BDT(TRANSACTION_STRUCT *TD,Uint8 *ep_iobf)
{
    Uint8  reg8;
    Uint32 reg32;
    
	reg32=(Uint32)ep_iobf;	//Get Buffer Address
	
	reg8=(Uint8)(reg32>>24);//MSB	
	TD->BUFBASEH=reg8;
	reg8=(Uint8)(reg32>>16);
	TD->BUFBASEL=reg8;
	reg8=(Uint8)(reg32>>8);	
	TD->bdt_ADDRH=reg8;	
	reg8=(Uint8)reg32;
	TD->bdt_ADDRL=reg8;	//LSB
	

}



static void reset_the_device(void)
{
    /* Disable and clear all interrupts */
    *regINT_ENB = 0;
    *regINT_STAT = 0xFF;

    /* Reset the device */
    Ctrl_ep->pksize = FS_CTRL_PKCT_SIZE;
    usb_host.USB_addr = 0;
    *regADDR = 0;

    /* Assert reset on the USB */
    *regCTL = CTRL_HOST_NO_SOF | CTRL_RESET;

    /* Delay 55 msec. for the reset process to complete */
    TaskSleep(&reset_delay);

    /* Set the ODD/EVEN BDT to even */
    usb_host.even_odd_OUT = BDT_OUT_BIT;
    usb_host.even_odd_IN  = BDT_IN_BIT;

    /*
     * Set SOF threshold so we are guaranteed to have enough time for
     * any transaction to complete (including ACK or NAK) without reaching
     * the time to send the next Start-of-frame packet.
     */
    *regSOF_THLD = SOF_THRESHOLD;

    /* End the reset , clear ODD bit and enable host */
    *regCTL = CTRL_ODD_RST | CTRL_HOST_SOF;

    /* Delay 15 msec. for the reset recovery period */
    TaskSleep(&recover_delay);


}

void TD_add2QH(HOST_QUEUE_HEAD *QH, TRANSACTION_STRUCT *TD)
{
	TRANSACTION_STRUCT *TDtail;
	
	//Disable USBH Interrupt
    *(unsigned long *)EXMSK1A &= ~(1 << USB1_INTERRUPT_BIT);
    
	if(QH->TD_tail!=NULL)
	{
		TDtail=QH->TD_tail;	//Get Tail TD
		TD->TD_next=NULL;
		TDtail->TD_next=TD;	//Add Curr TD After TD Tail
		QH->TD_tail=TD;		//Update QH Tail
		/****************************************/
		/*	QH->TD_head->TD1->TD2->TDtail->TD	*/
		/*									/|\	*/
		/*	QH->TD_tail----------------------|	*/
		/****************************************/
	}
	else
	{
		TD->TD_next=NULL;
		QH->TD_head=TD;
		QH->TD_tail=TD;
		/********************/
		/*	QH->TD_head->TD	*/
		/*				/|\	*/
		/*	QH->TD_tail--|	*/
		/********************/
	}
	//Enable USB HOST INT
    *(unsigned long *)EXMSK1A |= (1 << USB1_INTERRUPT_BIT);
}


Sint32 USBH_INTIN_FCT(DEV_INFO *dev, EP_DATA *ep, Uint8 *Buf, Uint32 Size)
{
	TRANSACTION_STRUCT *CurrTD, *Tmp_TD;
	
	ep->curr_count=0;
	//4.Create Transfer
	CurrTD=(TRANSACTION_STRUCT*)calloc(sizeof(TRANSACTION_STRUCT),1);
	
	CurrTD->state=INT_TRANSACTION|PROCESS_IN;
	CurrTD->QH=(Uint32*)&INT_QH;
	CurrTD->curr_DEV=dev;
	CurrTD->curr_EP=ep;
	CurrTD->io_bf=Buf;
	CurrTD->length=Size;
		
	//EP Transfer Setting
	CurrTD->bdt_PID		=	BDT_PID_OWN | ep->DATAx;
	CurrTD->bdt_BC		=	ep->pksize;
	
	//Data Buffer Address Setting
	IObf_2_BDT(CurrTD,CurrTD->io_bf);
	
	//USB HOST Control Register Setting
	CurrTD->EP0CTL		=	ep->type;
	CurrTD->ADDR		=	dev->addr;
	CurrTD->TOKEN		=	ep->pid_ep;
    
    TD_add2QH(&INT_QH,CurrTD);
}

Sint32 USBH_BulkIN_FCT(DEV_INFO *dev, EP_DATA *ep, Uint8 *Buf, Uint32 Size)
{
	Uint8 PROCESS_ID;
	Uint8 process_msg;
	Uint8 istate_msg;
	Uint8 regstate_msg;
	Uint8 error_msg;
	TRANSACTION_STRUCT *CurrTD, *Tmp_TD;
	
	ep->curr_count=0;
	//4.Create Transfer
	CurrTD=(TRANSACTION_STRUCT*)calloc(sizeof(TRANSACTION_STRUCT),1);
	
	CurrTD->state=BULK_TRANSACTION|PROCESS_IN;
	CurrTD->QH=(Uint32*)&BULK_QH;
	CurrTD->curr_DEV=dev;
	CurrTD->curr_EP=ep;
	CurrTD->io_bf=Buf;
	CurrTD->length=Size;
		
	//5.EP Transfer Setting
	CurrTD->bdt_PID		=	BDT_PID_OWN | ep->DATAx;
	CurrTD->bdt_BC		=	ep->pksize;
	
	//Data Buffer Address Setting
	IObf_2_BDT(CurrTD,CurrTD->io_bf);
	
	//USB HOST Control Register Setting
	CurrTD->EP0CTL		=	ep->type;
	CurrTD->ADDR		=	dev->addr;
	CurrTD->TOKEN		=	ep->pid_ep;
   
    TD_add2QH(&BULK_QH,CurrTD); 
}

Sint32 USBH_BulkOUT_FCT(DEV_INFO *dev, EP_DATA *ep, Uint8 *Buf, Uint32 Size)
{
	Uint32 left_to_send;
	TRANSACTION_STRUCT *CurrTD;
	
	ep->curr_count=0;
	//4.Create Transfer
	CurrTD=(TRANSACTION_STRUCT*)calloc(sizeof(TRANSACTION_STRUCT),1);
	
	CurrTD->state=BULK_TRANSACTION|PROCESS_OUT;
	CurrTD->QH=(Uint32*)&BULK_QH;
	CurrTD->curr_DEV=dev;
	CurrTD->curr_EP=ep;
	CurrTD->io_bf=Buf;
	CurrTD->length=Size;
		
    left_to_send = Size;
	if (left_to_send > ep->pksize)
		left_to_send = ep->pksize;
	//5.EP Transfer Setting
	CurrTD->bdt_PID		=	BDT_PID_OWN | ep->DATAx;
	CurrTD->bdt_BC		=	left_to_send;
	
	//Data Buffer Address Setting
	IObf_2_BDT(CurrTD,CurrTD->io_bf);
	
	//USB HOST Control Register Setting
	CurrTD->EP0CTL		=	ep->type;
	CurrTD->ADDR		=	dev->addr;
	CurrTD->TOKEN		=	ep->pid_ep;

    TD_add2QH(&BULK_QH,CurrTD);
}


PTPIO_RETN PTP_USB_Read(Uint32 UniqueDeviceID,Uint8* Buf,Uint32 Size,Uint32 *retCount)
{
	Uint8 i;
	Sint32 ret;
    EP_DATA *ep;
	DEV_INFO dev;
	MSG_Q RDMsg;
	Uint32 actual_size;

⌨️ 快捷键说明

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