📄 channel.c
字号:
/******************************************************************************* channel.c**** Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.**** This file contains copyrighted material. Use of this file is** restricted by the provisions of a Freescale Software License** Agreement, which has either been electronically accepted by** you or has been expressly executed between the parties.**** Description: Explanation for the usage of this file.**** Revision History:** -----------------*****************************************************************************//*! * @file channel.c * * @brief the RAM Kernel channel source file * * @ingroup RAM Kernel *//****************************************************************************** <Includes>*****************************************************************************/#include "channel.h"#include "protocol.h"#include "debug.h"#include "string.h"/****************************************************************************** <Macros>*****************************************************************************//****************************************************************************** <Typedefs>*****************************************************************************//* function declare *//* USB functions */static void setup_dQH(struct s_dQH* qhead);static void setup_dTD(struct s_dTD* td);/* EP1out and EP2in rx/tx channel setup function */static void setup_EP1out_rx(u32 buf_addr, u32 offset, u32 count);static void setup_EP2in_tx(u32 buf_addr, u32 count);/* UART get/put functions */static u8 uart_getchar(void);static void uart_putchar(u8 c);/****************************************************************************** <Global Variables>*****************************************************************************/static u8 channel;cache_usb_t cache_usb = {{0},STATE_CLEAN};/*! * delay */static void delay(void){ int i; for (i=0;i<300;i++) { } }/*! * This function is used to clear the dQH * * @qhead receive data buffer * * @return */void ClearDQH(void){ u8 i = 0; volatile u32 * EP_QUEUE_HEADPtr; EP_QUEUE_HEADPtr = (volatile u32 *)((volatile u32 *)dQHBASE); // Clear the dQH Memory for ( i = 0; i < (64*6)/4 ; i++) { *EP_QUEUE_HEADPtr = 0; EP_QUEUE_HEADPtr++; }}/*! * This function is used to setup the dQH * * @qhead receive data buffer * * @return */ void setup_dQH(struct s_dQH* qhead){ volatile struct s_dQH_SETUP* dQH_word = (volatile struct s_dQH_SETUP*) qhead->dQHBase; //====== // 0x0 //====== //Bit31:30 Mult; Bit29 zlt; Bit26:16 MPS; Bit15 ios dQH_word->dQH_WORD0 = (((u32)(qhead->ZLT) << 29)|((u32)(qhead->MPS) <<16) | ((u32)(qhead->ios) <<15)); //====== // 0x4 //====== // Current dTD Pointer => for hw use, not modified by DCD software dQH_word->dQH_WORD1 = 0x0; //====== // 0x8 //====== // Next dTD Pointer dQH_word->dQH_WORD2 = (((qhead->NextLinkPtr) & 0xFFFFFFE0) | qhead->Terminate); //====== // 0xC //====== // Bit30:16 TotalBytes; Bit15 ioc; Bit11:10 MultO; Bit7:0 Status dQH_word->dQH_WORD3 = ((((u32)(qhead->TotalBytes) & 0x7FFF) << 16) | ((u32)(qhead->ioc) <<15) | (qhead->Status)); //====== // 0x10 //====== // Bit31:12 Buffer Pointer (Page 0) dQH_word->dQH_WORD4 = ((qhead->BuffPtr0 & 0xFFFFF000) | (qhead->CurrentOffset & 0xFFF)); //====== // 0x14 //====== // Bit31:12 Buffer Pointer (Page 1) dQH_word->dQH_WORD5 = (qhead->BuffPtr1 & 0xFFFFF000); //====== // 0x18 //====== // Bit31:12 Buffer Pointer (Page 2) dQH_word->dQH_WORD6 = (qhead->BuffPtr2 & 0xFFFFF000); //====== // 0x1C //====== // Bit31:12 Buffer Pointer (Page 3) dQH_word->dQH_WORD7 = (qhead->BuffPtr3 & 0xFFFFF000); //====== // 0x20 //====== // Bit31:12 Buffer Pointer (Page 4) dQH_word->dQH_WORD8 = (qhead->BuffPtr4 & 0xFFFFF000); //====== // 0x24 //====== // Reserved dQH_word->dQH_WORD9 = 0; //====== // 0x28 //====== // Setup Buffer 0 dQH_word->dQH_WORD10 = 0; //====== // 0x2C //====== // Setup Buffer 1 dQH_word->dQH_WORD11 = 0;}/*! * This function is used to setup the TD * * @td pointer to the TD structure * * @return */void setup_dTD(struct s_dTD* td){ volatile struct s_dTD_SETUP* dTD_word = (volatile struct s_dTD_SETUP*) td->dTDBase; // Bit31:5 Next Link Pointer ; Bit0 Terminate dTD_word->dTD_WORD0 = ((td->dTDNextLinkPtr & 0xFFFFFFE0) | td->Terminate); // Bit30:16 TotalBytes, Bit15 ioc, Bit7:0 status dTD_word->dTD_WORD1 = ((((u32)td->TotalBytes & 0x7FFF) << 16)| ((u32)td->ioc <<15) | (td->Status)); // Bit31:12 Buffer Pointer Page 0 ; Bit11:0 Current Offset dTD_word->dTD_WORD2 = ((td->BuffPtr0 & 0xFFFFF000) | (td->CurrentOffset & 0xFFF)); // Bit31:12 Buffer Pointer Page 1 ; Bit10:0 Frame Number dTD_word->dTD_WORD3 = (td->BuffPtr1 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 2 ; dTD_word->dTD_WORD4 = (td->BuffPtr2 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 3 ; dTD_word->dTD_WORD5 = (td->BuffPtr3 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 4 ; dTD_word->dTD_WORD6 = (td->BuffPtr4 & 0xFFFFF000);}/*! * This function is used to enable out * * @return */ void EnableEP1OUT(void){ u32 TotalBytes = 0x10; struct s_dQH qhead; qhead.dQHBase = dQH2_EP1OUT; qhead.ZLT = ZLT_DISABLE; qhead.MPS = MPS_64; qhead.ios = IOS_SET; qhead.NextLinkPtr = dTD0_EP1OUT; qhead.Terminate = TERMINATE; qhead.TotalBytes = TotalBytes; qhead.ioc = IOC_SET; qhead.Status = NO_STATUS; qhead.BuffPtr0 = BUFPTR_P0_EP1OUT; qhead.CurrentOffset = (BUFPTR_P0_EP1OUT & 0xFFF); qhead.BuffPtr1 = 0; qhead.BuffPtr2 = 0; qhead.BuffPtr3 = 0; qhead.BuffPtr4 = 0; // EP1 OUT command = 16 bytes setup_dQH(&qhead); // Endpoint 1 : MPS = 64, OUT (Rx endpoint) *(u32 *)USB_OTG_ENDPTCTRL1 = 0x00080048; // Enable EP1 OUT *(u32 *)USB_OTG_ENDPTCTRL1 |= EP1OUT_ENABLE;}/*! * This function is used to set up out command * * @return */void EP1OutCommandSetup(void){ u32 TotalBytes = COMMAND; struct s_dTD td;// OUT // setup dTD // dTD for status of GET_DEVICE_DESCRIPTOR td.dTDBase = dTD0_EP1OUT; td.dTDNextLinkPtr = dTD1_EP1OUT; td.Terminate = TERMINATE; td.TotalBytes = TotalBytes; td.ioc = IOC_SET; td.Status = ACTIVE; td.BuffPtr0 = BUFPTR_P0_EP1OUT; td.CurrentOffset = (BUFPTR_P0_EP1OUT & 0xFFF); td.BuffPtr1 = 0; td.BuffPtr2 = 0; td.BuffPtr3 = 0; td.BuffPtr4 = 0; setup_dTD(&td); // 1. write dQH next ptr and dQH terminate bit to 0 *(u32 *)(dQH2_EP1OUT+0x8)= (dTD0_EP1OUT); // 2. clear active & halt bit in dQH *(u32 *)(dQH2_EP1OUT+0xC) &= ~0xFF; // 3. prime endpoint by writing '1' in ENDPTPRIME *(u32 *)USB_OTG_ENDPTPRIME |= EP1OUT_PRIME;}/*! * This function is used to rx binary data for the download * @address * @offset * @bytecount * @return */void setup_EP1out_rx(u32 buf_addr, u32 offset, u32 count){ struct s_dTD td; // setting up the dTD buffer pointer depend on the ByteCounts // each page is 0x1000 and the max recommanded transfer is 0x4000 (16k bytes) u32 BufferPtrPage0 = buf_addr; u32 BufferPtrPage1 = (buf_addr + 0x1000); u32 BufferPtrPage2 = (buf_addr + 0x2000); u32 BufferPtrPage3 = (buf_addr + 0x3000); u32 BufferPtrPage4 = (buf_addr + 0x4000); // Clear the EP1 OUT complete status if set if (*(u32 *)USB_OTG_ENDPTCOMPLETE & BIT1) *(u32 *)USB_OTG_ENDPTCOMPLETE = BIT1; // OUT // setup dTD // dTD for status of GET_DEVICE_DESCRIPTOR td.dTDBase = dTD0_EP1OUT; td.dTDNextLinkPtr = dTD1_EP1OUT; td.Terminate = TERMINATE; td.TotalBytes = count; td.ioc = IOC_SET; td.Status = ACTIVE; td.BuffPtr0 = BufferPtrPage0; td.CurrentOffset = offset; td.BuffPtr1 = BufferPtrPage1; td.BuffPtr2 = BufferPtrPage2; td.BuffPtr3 = BufferPtrPage3; td.BuffPtr4 = BufferPtrPage4; setup_dTD(&td); // 1. write dQH next ptr and dQH terminate bit to 0 *(u32 *)(dQH2_EP1OUT+0x8)= (dTD0_EP1OUT); // 2. clear active & halt bit in dQH *(u32 *)(dQH2_EP1OUT+0xC) &= ~0xFF; // 3. prime endpoint by writing '1' in ENDPTPRIME *(u32 *)USB_OTG_ENDPTPRIME |= EP1OUT_PRIME; // 4. Wait for the Complete Status while (!(*(volatile u32 *)USB_OTG_ENDPTCOMPLETE & BIT1)); //clear the complete status *(volatile u32 *)USB_OTG_ENDPTCOMPLETE = BIT1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -