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

📄 hdq.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 3 页
字号:
//  Function:  HDQ_Write
//
//  This function writes a byte of data in 8 bit mode to the specified address.
//
BOOL HDQ_Write(DWORD context, UCHAR address, USHORT data)
{
    BOOL rc=FALSE;
    HDQ_DEVICE* pDevice=(HDQ_DEVICE*)context;
    OMAP2420_HDQ_REGS* pHDQRegs;
    DWORD status, i, count;
    UCHAR buffer[3];

    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+++HDQ_Write(0x%08x, 0x%02x, 0x%x)\r\n", context, address, data));

// Check if we get correct context
    if(pDevice==NULL || pDevice->cookie!=HDQ_DEVICE_COOKIE)
    {
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
            L"Incorrect context parameter\r\n"));
        goto exit;
    };

// Get hardware
    pHDQRegs=pDevice->pHDQRegs;
    EnterCriticalSection(&pDevice->cs);

// Make sure that clock is present
    SetDevicePowerState(pDevice->hParentBus, D0, NULL);
    HDQ_PowerUp(context);

// Clear the interrupt
    status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
        L"Interrupt status (1) was 0x%02x\r\n", status));

// Need to notify InterruptDone right away
    InterruptDone(pDevice->sysIntr);

// Send initialization pulse in 1-wire mode
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_INITIALIZATION);
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);

// Wait on completion interrupt (not documented)
    if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->breakTimeout) == WAIT_TIMEOUT)
    {
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
            L"Timeout in init pulse\r\n"));
    }

// Clear the interrupt
    status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
        L"Interrupt status (2) was 0x%02x\r\n", status));

// Need to notify InterruptDone right away
    InterruptDone(pDevice->sysIntr);

// Back to HDQ mode.
    CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);

// We are going to do a write so set write bit in the address
    buffer[0]=address|0x80;
    buffer[1]=(UCHAR)data;
    switch(pDevice->mode)
    {
    case HDQ_MODE_HDQ8:
        count=2;
        break;
    case HDQ_MODE_HDQ16:
        buffer[2]=(UCHAR)(data >> 8);
        count=3;
        break;
    }
// Two write cycles required
    for(i=0; i < count; i++)
    {
// Write the value, set the direction and go
        OUTREG32(&pHDQRegs->ulHDQ_TX_DATA, buffer[i]);
        SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); //sr
        SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);

// Wait on TX complete interrupt.
        if (WaitForSingleObject(pDevice->hIntrEvent, pDevice->txTimeout)==WAIT_TIMEOUT)
        {
            DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
                L"Timeout in Tx\r\n"));
            goto cleanUp;
        }

// Clear the interrupt
        status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
        InterruptDone(pDevice->sysIntr);
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
            L"Interrupt status (%d) was 0x%x\r\n", 3 + i, status));

// Verify interrupt source
        if((status & HDQ_INT_STATUS_TXCOMPLETE)==0)
        {
            DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
                L"TX complete expected (0x%x)\r\n", status));
            goto cleanUp;
        }
    };

// Done
    rc=TRUE;

cleanUp:
    SetDevicePowerState(pDevice->hParentBus, D4, NULL);
    LeaveCriticalSection(&pDevice->cs);

exit:    
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"---HDQ_Write(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  HDQ_Read
//
//  This function reads from the specified address data in HDQ mode.
//
BOOL HDQ_Read(DWORD context, UCHAR address, USHORT* pData)
{
    BOOL rc=FALSE;
    HDQ_DEVICE* pDevice=(HDQ_DEVICE*)context;
    OMAP2420_HDQ_REGS* pHDQRegs=NULL;
    DWORD status, count, i;
    UCHAR buffer[2];
//

    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+++HDQ_Read(0x%08x, 0x%02x, 0x%08x)\r\n", context, address, pData));

    Sleep(cliDelay1); // tentaive
// Check if we get correct context
    if(pDevice==NULL || pDevice->cookie!=HDQ_DEVICE_COOKIE)
    {
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Read: "
            L"Incorrect context parameter\r\n"));
        goto exit;
    }

// Get hardware
    pHDQRegs=pDevice->pHDQRegs;
    EnterCriticalSection(&pDevice->cs);

// Make sure that clock is present
    SetDevicePowerState(pDevice->hParentBus, D0, NULL);
    HDQ_PowerUp(context);

    switch(pDevice->mode)
    {
    case HDQ_MODE_HDQ8:
        count=1;
        break;
    case HDQ_MODE_HDQ16:
        count=2;
        break;
    };

// Clear the interrupt.
    status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
        L"Interrupt status (1) was 0x%02x\r\n", status));

// Need to notify InterruptDone right away
    InterruptDone(pDevice->sysIntr);
// Step 0: send break pulse
// get into status mode; Send break pulse in HDQ mode
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_INITIALIZATION);
//    DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 1) Will Send out the break pulse and wait for %ld msec.\r\n",pDevice->breakTimeout));
//    DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 2) Next switch to Write mode, send out register Nr and wait for %ld msec.\r\n",pDevice->txTimeout));
//    DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 3) Then switch to Read mode and wait for %ld msec.\r\n",pDevice->rxTimeout));
// switch to go mode
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);

// Wait for completion of break pulse to be sent out
// there are no interrupts set on break pulse, so just wait for it to be sent out
    Sleep(cliDelay2); // was Sleep(pDevice->breakTimeout);  0.32 msec or so
// Back to HDQ mode.
    CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
// Step 1:
// Write the value, 
    OUTREG32(&pHDQRegs->ulHDQ_TX_DATA, address); // 
// Step 2: set the direction as Write and go
    CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); // was SET
    SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
//
// Wait on completion on transmit data 
    if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->txTimeout)==WAIT_TIMEOUT)
    {
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"ERROR !! HDQ_Read(): "
            L"Timeout in TX for %ld msec.\r\n",pDevice->txTimeout));
//      goto cleanUp;
    }

// Clear interrupt
    status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
        L"Interrupt status (3) was 0x%02x\r\n", status));

// Need to notify InterruptDone right away
    InterruptDone(pDevice->sysIntr);

// Verify that register address was sent out completely.
    if((status & HDQ_INT_STATUS_TXCOMPLETE)==0)
    { // sr further timing adjustment may be helpful. It works with current settings well so disregard this msg
        DEBUGMSG(ZONE_HDQ_1WIRE, (L"ERROR: HDQ_Read: "
            L"TX complete expected (0x%02x)\r\n", status));
//        goto cleanUp;
    }
    else
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"\tHDQ_Read: "
        L"TX completed (0x%02x) ok.\r\n", status));
// pre-Step 3:
    status=0; // INREG32(&pHDQRegs->ulHDQ_INT_STATUS);

    for(i=0; i<count; i++)
    {
// The RX is slave driven, if we are slow byte can be already done.
        if((status & HDQ_INT_STATUS_RXCOMPLETE)==0)
        {
// Indicate read & go: 0 to Read bit, 1 to GO bit
// Step 3:
            SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); // was CLR
            SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
            Sleep(cliDelay3);
// Wait on RX complete interrupt
            if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->rxTimeout)==WAIT_TIMEOUT)
            {
                DEBUGMSG(ZONE_ERROR, (L"ERROR: HDQ_Read: "
                    L"Timeout on RX at %ld msec\r\n",pDevice->rxTimeout));
                goto cleanUp;
            }
// Clear interrupt
            status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
            DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
                L"Interrupt status (5) was 0x%02x\r\n", status));

// Reenable interrupt
            InterruptDone(pDevice->sysIntr);
        }

// Verify interrupt source
        if((status & HDQ_INT_STATUS_RXCOMPLETE)==0)
        {
            DEBUGMSG(ZONE_HDQ_1WIRE, (L"ERROR: HDQ_Read: "
                L"RX complete expected (0x%02x)\r\n", status));
//            goto cleanUp;
        }
// Get data
        buffer[i]=(UCHAR)INREG32(&pHDQRegs->ulHDQ_RX_DATA);
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"\tHDQ_Read: "
            L"RX completed data=0x%02x\r\n", buffer[i]));
// Make sure we set GO bit on next byte
        status=0;
    };

    switch (pDevice->mode)
    {
    case HDQ_MODE_HDQ8:
        *pData=buffer[0];
        break;
    case HDQ_MODE_HDQ16:
        *pData=buffer[0]|(buffer[1] << 8);
        break;
    }

    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
        L"Address:=0x%02x, Data:=0x%02x\r\n", address, *pData));

// Done
    rc=TRUE;
//
cleanUp:
    SetDevicePowerState(pDevice->hParentBus, D4, NULL); // power off the hdq device
    LeaveCriticalSection(&pDevice->cs);
//
exit:    
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"---HDQ_Read(rc=%01ld)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  HDQ_SetMode
//
BOOL HDQ_SetMode(DWORD context, DWORD mode)
{
    BOOL rc = FALSE;
    HDQ_DEVICE *pDevice = (HDQ_DEVICE*)context;
    OMAP2420_HDQ_REGS *pHDQRegs;

    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+HDQ_SetMode(0x%08x, %d)\r\n", context, mode));

// Check if we get correct context
    if (pDevice == NULL || pDevice->cookie != HDQ_DEVICE_COOKIE)
    {
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_SetMode: "
            L"Incorrect context paramer\r\n"));
        goto cleanUp;
    };
    pHDQRegs = pDevice->pHDQRegs;

    switch (mode)
    {
    case HDQ_MODE_HDQ8:
        CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
        pDevice->mode = HDQ_MODE_HDQ8;
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_SetMode: "
            L"New mode HDQ8\r\n"));
        rc = TRUE;
        break;
    case HDQ_MODE_HDQ16:
        CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
        pDevice->mode = HDQ_MODE_HDQ16;
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_SetMode: "
            L"New mode HDQ16\r\n"));
        rc = TRUE;
        break;
    default:
        DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_SetMode: "
            L"Unsupported mode requested (mode = 0x%x)\r\n", mode));
    }

cleanUp:
    DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"-HDQ_SetMode(rc = 0x%x)\r\n", rc));
    return rc;
}

/*#ifdef RETAIL_DEBUG
#pragma optimize("", on)            // debug
#endif*/

⌨️ 快捷键说明

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