📄 lib_uhp.c
字号:
/*************************************** Copyright (c) *************************************************
*
* POLAR STAR
* 北天星国际有限公司
* http://www.po-star.com
*
*文 件 名: lib_uhp.c
*文件描述:uhp test
*编译环境:ADS1.2
*
********************************************************************************************************/
#include "main.h"
#include "ohci.h"
#include "timeout.h"
#undef LOW_SPEED
int g_port;
// =====================================
// Memory allocation for UHP:
// =====================================
// UHP HCCA memory location:
__align(32) AT91S_UHP_HCCA HCCA;
// UHP transfer descriptors:
__align(32) AT91S_UHP_ED pUHPEd[1];
__align(32) AT91S_UHP_ED pUHPTd[4];
// UHP data area
#ifdef LOW_SPEED
const char pUHPSetup[8] = {
0x80,
0x06,
0x00,
0x01,
0x00,
0x00,
0x40,
0x00
};
#else
const char pUHPSetup[8] = {
0x08,
0x06,
0x00,
0x01,
0x00,
0x00,
0x40,
0x00
};
#endif
#define DataSIZE 0x12
char pUHPData[DataSIZE];
// =====================================
// Memory allocation for UDP:
// =====================================
// UDP data area
char pUDPSetup[8];
const char pUDPData[DataSIZE] = {
0x12,
0x01,
0x00,
0x01,
0x00,
0x00,
0x00,
0x08,
0x7B,
0x05,
0x00,
0x00,
0x04,
0x03,
0x01,
0x02,
0x00,
0x01
};
#define AT91C_PRDSTRTVAL 0x2240
#define AT91C_FRINTERVAL 0x2710
#define AT91C_FSMAXPKTSZ (((AT91C_FRINTERVAL * 6) / 7) - 180)
#define AT91C_PRDSTRT AT91C_PRDSTRTVAL
#define AT91C_FMINTERVAL ((AT91C_FSMAXPKTSZ << 16) | AT91C_FRINTERVAL)
//*----------------------------------------------------------------------------
//* \fn main
//* \brief
//*----------------------------------------------------------------------------
int AT91F_testUHP()
{
AT91PS_UHP pUhp = AT91C_BASE_UHP;
AT91PS_UDP pUdp = AT91C_BASE_UDP;
unsigned int i;
AT91S_TIMEOUT timeout;
/* ************************************************ */
/* Deactivate UDP pull up */
/* ************************************************ */
// AT91F_PIO_CfgOutput(AT91C_BASE_PIOB, AT91C_PIO_PB30);
// AT91F_PIO_ClearOutput(AT91C_BASE_PIOB, AT91C_PIO_PB30);
AT91C_BASE_UDP->UDP_TXVC &= (~AT91C_UDP_PUON);
/* ************************************************ */
/* Open UDP+UHP clocks */
/* ************************************************ */
AT91F_UHP_CfgPMC();
AT91F_UDP_CfgPMC();
AT91C_BASE_PMC->PMC_SCER = (AT91C_PMC_UHP | AT91C_PMC_UDP); // AT91C_PMC_HCK0
/* ************************************************ */
/* Configure the UHP */
/* ************************************************ */
// Desactivate all IT
pUdp->UDP_IDR = (unsigned int) -1;
// Disable all pending IT
pUdp->UDP_ICR = (unsigned int) -1;
// RESET UDP
pUdp->UDP_RSTEP = 0;
pUdp->UDP_GLBSTATE = 0;
// Forcing UHP_Hc to reset
pUhp->UHP_HcControl = 0;
// Writing the UHP_HCCA
pUhp->UHP_HcHCCA = (unsigned int) &HCCA;
// Enabling list processing
pUhp->UHP_HcControl = 0;
// Set the frame interval
pUhp->UHP_HcFmInterval = AT91C_FMINTERVAL;
pUhp->UHP_HcPeriodicStart = AT91C_PRDSTRT;
// Create a default endpoint descriptor
#ifdef LOW_SPEED
AT91F_CreateEd(
(unsigned int) pUHPEd, // ED Address
8, // Max packet
0, // TD format
0, // Skip
1, // Speed = 1 (Low) 0 (Full)
0x0, // Direction
0x0, // Endpoint
0x0, // Func Address
(unsigned int) &pUHPTd[3], // TDQTailPointer
(unsigned int) &pUHPTd[0], // TDQHeadPointer
0, // ToggleCarry
0x0); // NextED
#else
AT91F_CreateEd(
(unsigned int) pUHPEd, // ED Address
8, // Max packet
0, // TD format
0, // Skip
0, // Speed = 1 (Low) 0 (Full)
0x0, // Direction
0x0, // Endpoint
0x0, // Func Address
(unsigned int) &pUHPTd[3], // TDQTailPointer
(unsigned int) &pUHPTd[0], // TDQHeadPointer
0, // ToggleCarry
0x0); // NextED
#endif
// Setup PID
AT91F_CreateGenTd(
(unsigned int) &pUHPTd[0], // TD Address
2, // Data Toggle
0x7, // DelayInterrupt
0x0, // Direction
1, // Buffer Rounding
(unsigned int) pUHPSetup, // Current Buffer Pointer
(unsigned int) &pUHPTd[1], // Next TD
8); // Buffer Length
// Data IN
AT91F_CreateGenTd(
(unsigned int) &pUHPTd[1], // TD Address
0, // Data Toggle
0x7, // DelayInterrupt
0x2, // Direction
1, // Buffer Rounding
(unsigned int) pUHPData, // Current Buffer Pointer
(unsigned int) &pUHPTd[2], // Next TD
DataSIZE); // Buffer Length
// Status OUT
AT91F_CreateGenTd(
(unsigned int) &pUHPTd[2], // TD Address
3, // Data Toggle
0x7, // DelayInterrupt
0x1, // Direction
1, // Buffer Rounding
0x0, // Current Buffer Pointer
(unsigned int) &pUHPTd[3], // Next TD
0x0); // Buffer Length
AT91F_CreateGenTd(
(unsigned int) &pUHPTd[3], // TD Address
3, // Data Toggle
0x7, // DelayInterrupt
0x1, // Direction
1, // Buffer Rounding
0x0, // Current Buffer Pointer
(unsigned int) 0, // Next TD
0x0); // Buffer Length
// Programming the BHED
pUhp->UHP_HcControlHeadED = (unsigned int) pUHPEd;
// Programming the BCED
pUhp->UHP_HcControlCurrentED = (unsigned int) pUHPEd;
// Initializing the UHP_HcDoneHead
pUhp->UHP_HcBulkDoneHead = 0x00;
HCCA.UHP_HccaDoneHead = 0x0000;
// Forcing UHP_Hc to Operational State
pUhp->UHP_HcControl = 0x80;
// Enabling port power
pUhp->UHP_HcRhPortStatus[0] = 0x00000100;
pUhp->UHP_HcRhPortStatus[1] = 0x00000100;
pUhp->UHP_HcRhStatus = 0x00010000;
/* ************************************************ */
/* Activate UDP pull up PIOB30 */
/* ************************************************ */
// UDP: Connect a pull-up
// AT91F_PIO_SetOutput(AT91C_BASE_PIOB, AT91C_PIO_PB30);
AT91C_BASE_UDP->UDP_TXVC |= (AT91C_UDP_PUON);
/* ************************************************ */
/* Detect a connected deviced, generate a reset... */
/* ************************************************ */
// UHP: Detect the device on one port, generate a reset and enable the port
AT91F_InitTimeout(&timeout, 2);
while (1) {
if ( (pUhp->UHP_HcRhPortStatus[0] & 0x01) ) {
g_port = 0;
AT91F_DBGU_Printk("# USB A ");
pUhp->UHP_HcRhPortStatus[0] = (1 << 4); // SetPortReset
while (pUhp->UHP_HcRhPortStatus[0] & (1 << 4)); // Wait for the end of reset
pUhp->UHP_HcRhPortStatus[0] = (1 << 1); // SetPortEnable
break;
}
else if ( (pUhp->UHP_HcRhPortStatus[1] & 0x01) ) {
g_port = 1;
AT91F_DBGU_Printk("# USB B ");
pUhp->UHP_HcRhPortStatus[1] = (1 << 4); // SetPortReset
while (pUhp->UHP_HcRhPortStatus[1] & (1 << 4)); // Wait for the end of reset
pUhp->UHP_HcRhPortStatus[1] = (1 << 1); // SetPortEnable
break;
}
else if ( !AT91F_TestTimeout(&timeout) ) {
goto error;
}
}
// UHP: UHP is now operational and control list processing is enabled
pUhp->UHP_HcControl = 0x90;
// UDP: Wait for end bus reset
AT91F_InitTimeout(&timeout, 2);
while ( !(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES)) {
if ( !AT91F_TestTimeout(&timeout)) {
goto error;
}
}
pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
/* ************************************************ */
/* Generate traffic between UHP and UDP */
/* ************************************************ */
// UHP: Notify the Hc that the Control list is filled
pUhp->UHP_HcCommandStatus = 0x02;
// UDP: Wait for a Setup packet
AT91F_InitTimeout(&timeout, 2);
while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP)) {
if ( !AT91F_TestTimeout(&timeout)) {
goto error;
}
}
for (i = 0; i < 8; ++i)
pUDPSetup[i] = pUdp->UDP_FDR[0];
pUdp->UDP_CSR[0] |= AT91C_UDP_DIR; // Data stage will be DATA IN transactions
while ( !(pUdp->UDP_CSR[0] & (AT91C_UDP_DIR)) );
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RXSETUP);
while ( pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP );
// UDP: Send several Data packets
for (i = 0; i < DataSIZE; ++ i) {
pUdp->UDP_FDR[0] = pUDPData[i];
// UDP: Detect a packet frontier, send it and wait for the end of transmition
if ( !((i+1) % 8) || (i == (DataSIZE - 1))) {
pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
AT91F_InitTimeout(&timeout, 2);
while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP)) {
if ( !AT91F_TestTimeout(&timeout)) {
goto error;
}
}
pUdp->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;
while ( pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP );
}
}
// UDP: Wait for the status sent by the host
AT91F_InitTimeout(&timeout, 2);
while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0)) {
if ( !AT91F_TestTimeout(&timeout)) {
goto error;
}
}
pUdp->UDP_CSR[0] = ~AT91C_UDP_RX_DATA_BK0;
while ( pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0 );
/* ************************************************ */
/* Compare data sent and received */
/* ************************************************ */
for (i = 0; i < 8; ++i) {
if (pUHPSetup[i] != pUDPSetup[i]) {
goto error;
}
}
for (i = 0; i < DataSIZE; ++i) {
if (pUHPData[i] != pUDPData[i]) {
goto error;
}
}
AT91F_DBGU_Printk("-I- Test OK\n\r");
return 0;
error:
AT91F_DBGU_Printk("-E- FAIL ***\n\r");
return -1;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_TestUHP
//* \brief
//*----------------------------------------------------------------------------
int AT91F_TestUHP()
{
int err_0 = 0, err_1 = 0, err = 0;
AT91F_DBGU_Printk("\n\r-I- Step 10. Test USB UHP/UDP\n\r");
AT91F_DBGU_Printk("-I- Please connect the USB cable onto the first plug\n\r");
AT91F_DBGU_Printk("-I- Hit a key when ready !!!\n\r");
AT91F_Wait4KeyPressed();
// Perform first test on first connector
err = AT91F_testUHP();
if (g_port == 0)
err_0 = err;
else
err_1 = err;
AT91F_DBGU_Printk("-I- Please connect the USB cable onto the second plug\n\r");
AT91F_DBGU_Printk("-I- Hit a key when ready !!!\n\r");
AT91F_Wait4KeyPressed();
// Perform second test on second connector
err = AT91F_testUHP();
if (g_port == 0)
err_0 = err;
else
err_1 = err;
if ((err_0 < 0 ) || (err_1 < 0))
return -1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -