📄 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 "platform.h"/****************************************************************************** <Macros>*****************************************************************************//****************************************************************************** <Typedefs>*****************************************************************************//* function declare *//* USB functions */static void setup_dTD(u32 base, u32 next_linkptr, u8 Terminate, u16 total_bytes, u8 ioc, u8 Status, u32 BufferPtr0, u16 CurrentOffset, u32 BufferPtr1, u32 BufferPtr2, u32 BufferPtr3, u32 BufferPtr4);/* 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;/****************************************************************************** <Local Variables>*****************************************************************************/#define WD_TIMEOUT 0x20static inline void watchdog_service(void){ if (*(volatile u16 *)WDOG_WCR & 0x04) { *(volatile u16 *)WDOG_WSR = 0x5555; *(volatile u16 *)WDOG_WSR = 0xAAAA; }}/*! * delay */static void delay(void){ int i; for (i=0;i<100;i++) { } }/*==================================================================================================FUNCTION: setup_dTDDESCRIPTION: This function is used to setup the dTDARGUMENTS PASSED: u32 base_dTD - Base Address of the dTD u32 NextLinkPtr - Next Link Pointer, u8 terminate - Terminate - TERMINATE; not Terminate - NOT_TERMINATE u16 total_bytes - Total Bytes to be transfered in this dQH u8 ioc - interrupt on complete, set - IOC_SET, not set - IOC_NOTSET u8 Status - Status u32 BuffPtr0 - Buffer Pointer page 0 u16 CurrentOffset - current offset u32 BuffPtr1 - Buffer Pointer page 1 u32 BuffPtr2 - Buffer Pointer page 1 u32 BuffPtr3 - Buffer Pointer page 1 u32 BuffPtr4 - Buffer Pointer page 1 RETURN VALUE: None IMPORTANT NOTES: None ==================================================================================================*/void setup_dTD(u32 base, u32 next_linkptr, u8 terminate, u16 total_bytes, u8 ioc, u8 status, u32 bufptr0, u16 offset, u32 bufptr1, u32 bufptr2, u32 bufptr3, u32 bufptr4){ volatile struct s_dTD_SETUP* dTD_word = (volatile struct s_dTD_SETUP*)base; // Bit31:5 Next Link Pointer ; Bit0 terminate dTD_word->dTD_WORD0 = (next_linkptr & 0xFFFFFFE0) | terminate; // Bit30:16 total_bytes, Bit15 ioc, Bit7:0 status dTD_word->dTD_WORD1 = (((u32)total_bytes & 0x7FFF) << 16)| ((u32)ioc <<15) | (status); // Bit31:12 Buffer Pointer Page 0 ; Bit11:0 Current Offset dTD_word->dTD_WORD2 = (bufptr0 & 0xFFFFF000) | (offset & 0xFFF); // Bit31:12 Buffer Pointer Page 1 ; Bit10:0 Frame Number dTD_word->dTD_WORD3 = (bufptr1 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 2 ; dTD_word->dTD_WORD4 = (bufptr2 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 3 ; dTD_word->dTD_WORD5 = (bufptr3 & 0xFFFFF000); // Bit31:12 Buffer Pointer Page 4 ; dTD_word->dTD_WORD6 = (bufptr4 & 0xFFFFF000);}/*==================================================================================================FUNCTION: setup_EP1outDESCRIPTION: This function is used to prepare the Setup command from PC and prime the endpointARGUMENTS PASSED: None RETURN VALUE: None IMPORTANT NOTES: None==================================================================================================*/void setup_EP1out(u32 read_byte){ // setup dTD // dTD for status of GET_DEVICE_DESCRIPTOR setup_dTD(dTD0_EP1OUT, dTD1_EP1OUT, TERMINATE, read_byte, IOC_SET, ACTIVE, BUFPTR_P0_EP1OUT,(BUFPTR_P0_EP1OUT & 0xFFF),0,0,0,0); // 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; }/*! * Function to setup the receive from host channel * * @buf_addr receive data buffer * @count receive data size * * @return */void setup_EP1out_rx(u32 buf_addr, u32 offset, u32 count){ u32 bufpage0, bufpage1, bufpage2, bufpage3, bufpage4; /* fill the buffer page address */ bufpage0 = buf_addr; bufpage1 = buf_addr + 0x1000; bufpage2 = buf_addr + 0x2000; bufpage3 = buf_addr + 0x3000; bufpage4 = buf_addr + 0x4000; /* Clear the EP1 OUT complete status if set */ if (*(u32 *)USB_OTG_ENDPTCOMPLETE & BIT1) *(u32 *)USB_OTG_ENDPTCOMPLETE = BIT1; /* setup dTD for status of GET_DEVICE_DESCRIPTOR */ setup_dTD(dTD0_EP1OUT, dTD1_EP1OUT, TERMINATE, count, IOC_SET, ACTIVE, bufpage0, offset, bufpage1, bufpage2, bufpage3, bufpage4); /* write dQH next ptr and dQH terminate bit to 0 */ *(u32 *)(dQH2_EP1OUT + 0x8)= (dTD0_EP1OUT); /* clear active & halt bit in dQH */ *(u32 *)(dQH2_EP1OUT + 0xC) &= ~0xFF; /* prime endpoint by writing '1' in ENDPTPRIME */ *(u32 *)USB_OTG_ENDPTPRIME |= EP1OUT_PRIME; /* Wait for the Complete Status */ while (!(*(volatile u32 *)USB_OTG_ENDPTCOMPLETE & BIT1)); /* clear the complete status */ *(volatile u32 *)USB_OTG_ENDPTCOMPLETE = BIT1; return;}/*! * Function to setup the transmit to host channel * * @buf_addr transmit data buffer * @count transmit data size * * @return */void setup_EP2in_tx(u32 buf_addr, u32 count){ u32 bufpage0, bufpage1, bufpage2, bufpage3, bufpage4; /* fill the buffer page address */ bufpage0 = buf_addr; bufpage1 = buf_addr + 0x1000; bufpage2 = buf_addr + 0x2000; bufpage3 = buf_addr + 0x3000; bufpage4 = buf_addr + 0x4000; /* setup the dTD with buffer page */ setup_dTD(dTD0_EP2IN, dTD1_EP2IN, TERMINATE, count, IOC_SET, ACTIVE, bufpage0, bufpage0 & 0xFFF, bufpage1, bufpage2, bufpage3, bufpage4); /* write dQH next ptr and dQH terminate bit to 0 */ *(u32 *)(dQH5_EP2IN + 0x8)= dTD0_EP2IN; /* clear active & halt bit in dQH */ *(u32 *)(dQH5_EP2IN + 0xC) &= ~0xFF; /* prime endpoint by writing '1' in ENDPTPRIME */ *(u32 *)USB_OTG_ENDPTPRIME = EP2IN_PRIME; /* wait for complete set and clear */ while (!(*(volatile u32 *)USB_OTG_ENDPTCOMPLETE & EP2IN_COMPLETE)); *(u32 *)USB_OTG_ENDPTCOMPLETE = EP2IN_COMPLETE; return;}/*! * Function to get a character from UART FIFO * * @return character value */static u8 uart_getchar(void){ return (*(volatile u32 *)UART1_URXD_1 & 0xFF);}/*! * Function to put a character into UART FIFO */static void uart_putchar(u8 c){ *(volatile u32 *)UART1_UTXD_1 = c;}/*! * Function to initial channel of USB or UART * * @ch channel type */void atk_channel_init(u8 ch){ /* disable watchdog */ watchdog_service(); //*(volatile u16 *)0x53FDC000 &= ~0x08; channel = ch; dbg("Initial the channel finish\n"); return;}/*! * Function to receive data from host through channel * * @buf buffer to fill in * @count read data size * * @return 0 */u32 atk_channel_recv(u8 *buf, u32 count){ u32 i = 0, len; u32 to = WD_TIMEOUT; if (channel == CHAN_USB) { while (count) { /* fix the size length to 16K due to HW limit */ if (count > MAX_USB_DATA_LEN) { len = MAX_USB_DATA_LEN; } else { len = count; } /* setup EP out rx channel */ setup_EP1out_rx((u32)&buf[i], (u32)(&buf[i]) & 0xFFF, len); count -= len; i += len; } } else { watchdog_service(); for (i=0; i < count; i++) { /* check the receive status */ while (!(*(volatile u32 *)UART1_USR2_1 & 0x1)) { if (--to <= 0) { watchdog_service(); to = WD_TIMEOUT; } } buf[i] = uart_getchar(); if (--to <= 0) { watchdog_service(); to = WD_TIMEOUT; } } } return 0;}/*! * Function to send data to host through channel * * @buf buf to send * @count send data size * * @return 0 */u32 atk_channel_send(const u8 *buf, u32 count){ u32 size; u32 i; u32 to = WD_TIMEOUT; if (channel == CHAN_USB) { while (count) { size = count > MAX_USB_DATA_LEN ? MAX_USB_DATA_LEN : count; /* FIXME: if the buffer is messed by the USB, use static buffer arrary */ /* setup EP2 Tx data channel */ setup_EP2in_tx((u32)buf, size); count -= size; buf += size; /* update buffer addr */ } } else { watchdog_service(); for (i = 0; i < count; i++) { delay(); /* put data to UART transmit fifo */ uart_putchar(buf[i]); /* wait for TF empty */ while (!(*(volatile u32 *)UART1_USR2_1 & 0x4000)){ if (--to <= 0) { watchdog_service(); to = WD_TIMEOUT; } } if (--to <= 0) { watchdog_service(); to = WD_TIMEOUT; } } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -