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

📄 spi.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 4 页
字号:

    case SPI_IOCTL_START:
        if(pSpiPrivate->State == STATE_ERROR)
        {
            RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI_IOCTL_START ERROR\n")));
            bResult = FALSE;
            break;
        }
        pSpiPrivate->State = STATE_IDLE;
        RETAILMSG(SPI_MSG,(TEXT("[SPI] SPI STATE : SPI_IOCTL_START\n")));
        break;

    default:
        break;
    }

    if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, lpInBuf, nInBufSize, ARG_I_PTR)))
    {
        RETAILMSG(1, (TEXT("SPI_IOControl: CeCloseCallerBuffer failed for input buffer.\r\n")));
        return FALSE;
    }

CleanUp:
    return bResult;
}


DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
    volatile S3C6410_SPI_REG    *pSPIregs  = NULL;
    PSPI_PRIVATE_CONTEXT        pSpiPrivate;

    DWORD     dwTxCount;
    PBYTE     pTxBuffer;

    PBYTE     pTestBuffer;
    DWORD     dwTestCount;

    ULONG    TimeOut;
    ULONG    TotalTimeOut;
    ULONG    WaitReturn;

    INT      TimeOutCount;

    if(pSpiPublic != NULL)
    {
        pSPIregs       = pSpiPublic->pSPIregs;
    }

    do
    {
        WaitForSingleObject(pSpiPublic->hTxEvent, INFINITE);

        pSpiPrivate     = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;

        if(pSpiPrivate->dwTxCount != 0)
        {
            dwTestCount     = dwTxCount = pSpiPrivate->dwTxCount;
        }

        pTestBuffer     = pTxBuffer = pSpiPrivate->pTxBuffer;

        RETAILMSG(SPI_MSG,(TEXT("[SPI] pTxBuffer : 0x%X, dwTxCount : %d \r\n"), pTxBuffer, dwTxCount));

        //Reset
        pSPIregs->CH_CFG |= SW_RST;
        while(!(pSPIregs->CH_CFG & SW_RST));
        RETAILMSG(SPI_MSG,(TEXT("[SPI] HS SPI reset\n")));
        pSPIregs->CH_CFG &= ~SW_RST;

        if(pSpiPrivate->bUseTxIntr)
        // INT  + TX
        {
            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE INT \r\n")));
            pSpiPrivate->State = STATE_TXINTR;

            pSPIregs->CH_CFG     = pSpiPrivate->TxSPIregs.CH_CFG;
            pSPIregs->CLK_CFG      = pSpiPrivate->TxSPIregs.CLK_CFG;
            pSPIregs->MODE_CFG    = pSpiPrivate->TxSPIregs.MODE_CFG|(TX_TRIG_LEVEL<<5);

            pSPIregs->SPI_INT_EN        =    TX_FIFORDY;
            pSPIregs->PENDING_CLEAR        =    TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
            pSPIregs->CH_CFG            |=    TX_CH_ON;

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
                MASTER_CS_ENABLE;
            }
            else
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
            }

            //Timeout value setting
            TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
            TimeOut    =    TotalTimeOut;
            WaitReturn = WaitForSingleObject(pSpiPublic->hTxIntrDoneEvent, TimeOut);

            if ( WAIT_TIMEOUT == WaitReturn )
            {
                // Timeout
                RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
                goto LEAVEWRITE;
            }

            TimeOutCount = 1000;
            while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE)) 
                || (TimeOutCount>0))
            {
                TimeOutCount--;
            }

        }
        else if(pSpiPrivate->bUseTxDMA)
        // DMA + TX
        {
            DWORD dwDmaLen            = dwTxCount & 0xFFFFF ;

            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE DMA (TxCount : %d) \r\n"),dwDmaLen));

            pSpiPrivate->State = STATE_TXDMA;
            //VirtualCopy((PVOID)pSpiPrivate->pTxBuffer, (PVOID)((ULONG) pSpiPrivate->pTxDMABuffer>>8), sizeof(dwTxCount), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                pSPIregs->CH_CFG     = pSpiPrivate->TxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->TxSPIregs.CLK_CFG;
                pSPIregs->MODE_CFG  = pSpiPrivate->TxSPIregs.MODE_CFG;
            }
            else
            {
                pSPIregs->CH_CFG     = pSpiPrivate->TxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->TxSPIregs.CLK_CFG;
                pSPIregs->MODE_CFG  = pSpiPrivate->TxSPIregs.MODE_CFG;
            }

            if(dwDmaLen > 0)
            {
                pSPIregs->MODE_CFG        |=    TX_DMA_ON|DMA_SINGLE;
                pSPIregs->CH_CFG         |=    TX_CH_ON;

                {
                    RETAILMSG(SPI_MSG,(TEXT("[SPI] pSpiPrivate->pTxDMABuffer : 0x%X \r\n"), pSpiPrivate->pTxDMABuffer));
                    DMA_initialize_channel(&g_OutputDMA, TRUE);
                    DMA_set_channel_source(&g_OutputDMA, (UINT)pSpiPrivate->pTxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
                    DMA_set_channel_destination(&g_OutputDMA, (UINT)SPI_TX_DATA_PHY_ADDR, BYTE_UNIT, BURST_1, FIXED);
                    DMA_set_channel_transfer_size(&g_OutputDMA, dwDmaLen);
                    DMA_initialize_LLI(&g_OutputDMA, 0);
                }

                if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
                {
                    RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
                    MASTER_CS_ENABLE;
                }
                else
                {
                    RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
                }

                DMA_channel_start(&g_OutputDMA);

                //Timeout value setting
                TotalTimeOut = WRITE_TIME_OUT_CONSTANT + (WRITE_TIME_OUT_MULTIPLIER/1000)*dwTxCount;
                TimeOut    =    TotalTimeOut;
                WaitReturn = WaitForSingleObject(pSpiPublic->hTxDmaDoneDoneEvent, TimeOut);

                if ( WAIT_TIMEOUT == WaitReturn )
                {
                    // Timeout
                    RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
                    // Stop output DMA
                    DMA_channel_stop(&g_OutputDMA);
                    goto LEAVEWRITE;
                }

                pSpiPrivate->dwTxCount -= dwDmaLen;
                pSpiPrivate->pTxBuffer = (((PUINT) pSpiPrivate->pTxBuffer) + dwDmaLen);
            }
            //VirtualFree((PVOID)pTxBuffer, 0, MEM_RELEASE);

            TimeOutCount = 1000;
            while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE)) 
                || (TimeOutCount>0))
            {
                TimeOutCount--;
            }
        }
        else
        // POLLING + TX
        {
            ULONG Count;
            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : USE Polling (TxCount : %d) \r\n"), dwTxCount));

            pSPIregs->CH_CFG     = pSpiPrivate->TxSPIregs.CH_CFG;
            pSPIregs->CLK_CFG     = pSpiPrivate->TxSPIregs.CLK_CFG;
            pSPIregs->MODE_CFG  = pSpiPrivate->TxSPIregs.MODE_CFG;

            pSPIregs->CH_CFG         |=    TX_CH_ON;

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : MASTER MODE \r\n")));
                MASTER_CS_ENABLE;
            }
            else
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for TX : SLAVE MODE \r\n")));
            }

            TotalTimeOut = WRITE_TIME_OUT_CONSTANT*100*50 + (WRITE_TIME_OUT_MULTIPLIER)*dwTxCount;
            Count = 0;
            do
            {
                while(((pSPIregs ->SPI_STATUS>>6) & 0x7f)==FIFO_FULL)
                {
                    Count++;
                    if(TotalTimeOut == Count)
                    {
                        // Timeout
                        RETAILMSG (TRUE, (TEXT("Write timeout!!!\r\n")));
                        goto LEAVEWRITE;
                    }
                }
                pSPIregs->SPI_TX_DATA = *(PBYTE)pSpiPrivate->pTxBuffer;
            } while(--pSpiPrivate->dwTxCount > 0 && ++(PBYTE)pSpiPrivate->pTxBuffer);

            TimeOutCount = 1000;
            while((((pSPIregs ->SPI_STATUS>>6) & 0x7f) && !(pSPIregs ->SPI_STATUS & TX_DONE)) 
                || (TimeOutCount>0))
            {
                TimeOutCount--;
            }
        }

        LEAVEWRITE:

#ifdef TEST_MODE
        do
        {
            RETAILMSG(SPI_MSG,(TEXT("[SPI] WRITE BYTE : %02X(dwTxCount : %d)\n"), *pTestBuffer, dwTestCount));
        } while( (--dwTestCount > 0) && ++pTestBuffer);
#endif

        RETAILMSG(FALSE,(TEXT("[SPI] TX_CH_OFF \n")));
        pSPIregs->CH_CFG     &= ~TX_CH_ON;    
        if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
        {
            MASTER_CS_DISABLE;
        }

        SetEvent(pSpiPublic->hTxDoneEvent);
    } while(TRUE);

    return 0;
}

DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pSpiPublic)
{
    volatile S3C6410_SPI_REG    *pSPIregs   = NULL;
    PSPI_PRIVATE_CONTEXT        pSpiPrivate;

    DWORD     dwRxCount;
    PBYTE     pRxBuffer;

    PBYTE     pTestBuffer;
    DWORD     dwTestCount;

    ULONG    TimeOut;
    ULONG    TotalTimeOut;
    ULONG    WaitReturn;

    if(pSpiPublic != NULL)
    {
        pSPIregs       = pSpiPublic->pSPIregs;
    }

    do
    {
        WaitForSingleObject(pSpiPublic->hRxEvent, INFINITE);

        pSpiPrivate = (PSPI_PRIVATE_CONTEXT) pSpiPublic->pSpiPrivate;

        if(pSpiPrivate->dwRxCount != 0)
        {
            dwTestCount = dwRxCount = pSpiPrivate->dwRxCount;
        }

        pTestBuffer = pRxBuffer = pSpiPrivate->pRxBuffer;

        RETAILMSG(SPI_MSG,(TEXT("[SPI] pRxBuffer : 0x%X, dwRxCount : %d \r\n"), pRxBuffer, dwRxCount));

        //Reset
        pSPIregs->CH_CFG |= SW_RST;
        while(!(pSPIregs->CH_CFG & SW_RST));
        RETAILMSG(SPI_MSG,(TEXT("[SPI] HS SPI reset\n")));
        pSPIregs->CH_CFG &= ~SW_RST;

        if(pSpiPrivate->bUseRxIntr)
        //INT Mode + RX
        {
            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE INT \r\n")));
            pSpiPrivate->State = STATE_RXINTR;

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                pSPIregs->CH_CFG     = pSpiPrivate->RxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->RxSPIregs.CLK_CFG;
                pSPIregs->MODE_CFG  = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11);
                pSPIregs->PACKET_COUNT = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
            }
            else
            {
                pSPIregs->CH_CFG     = pSpiPrivate->RxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->RxSPIregs.CLK_CFG; 
                pSPIregs->MODE_CFG  = pSpiPrivate->RxSPIregs.MODE_CFG|TRAIL_CNT(0x3FF)|(RX_TRIG_LEVEL<<11); 
            }

            pSPIregs->SPI_INT_EN        =    RX_FIFORDY;
            pSPIregs->PENDING_CLEAR        =    TX_UNDERRUN_CLR|TX_OVERRUN_CLR|RX_UNDERRUN_CLR|RX_OVERRUN_CLR|TRAILING_CLR;
            pSPIregs->CH_CFG            |=     RX_CH_ON;

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
                MASTER_CS_ENABLE;
            }
            else
            {
                RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
            }

            //Timeout value setting
            TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
            TimeOut    =    TotalTimeOut;
            WaitReturn = WaitForSingleObject(pSpiPublic->hRxIntrDoneEvent, TimeOut);

            if ( WAIT_TIMEOUT == WaitReturn )
            {
                // Timeout
                RETAILMSG (TRUE, (TEXT("Read timeout!!!\r\n")));
                goto LEAVEREAD;
            }
        }

        else if(pSpiPrivate->bUseRxDMA)
        //DMA Mode + Rx
        {
            DWORD dwDmaLen    = (pSpiPrivate->dwRxCount & 0xFFFFF);

            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE DMA \r\n")));

            pSpiPrivate->State = STATE_RXDMA;
            //VirtualCopy((PVOID)pSpiPrivate->pRxBuffer, (PVOID)((ULONG) pSpiPrivate->pRxDMABuffer>>8), sizeof(dwRxCount), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL);

            //Reset
            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                pSPIregs->CH_CFG     = pSpiPrivate->RxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->RxSPIregs.CLK_CFG;
                pSPIregs->MODE_CFG  = pSpiPrivate->RxSPIregs.MODE_CFG;
                pSPIregs->PACKET_COUNT = PACKET_CNT_EN | (pSpiPrivate->dwRxCount) ;
            }
            else
            {
                pSPIregs->CH_CFG     = pSpiPrivate->RxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG      = pSpiPrivate->RxSPIregs.CLK_CFG;
                pSPIregs->MODE_CFG  = pSpiPrivate->RxSPIregs.MODE_CFG;
            }

            if(dwDmaLen > 0)
            {
                pSPIregs->MODE_CFG        |=    RX_DMA_ON|DMA_SINGLE;
                pSPIregs->CH_CFG         |=    RX_CH_ON;

                {
                    DMA_initialize_channel(&g_InputDMA, TRUE);
                    DMA_set_channel_source(&g_InputDMA, (UINT)SPI_RX_DATA_PHY_ADDR, BYTE_UNIT, BURST_1, FIXED);
                    DMA_set_channel_destination(&g_InputDMA, (UINT)pSpiPrivate->pRxDMABuffer, BYTE_UNIT, BURST_1, INCREASE);
                    DMA_set_channel_transfer_size(&g_InputDMA, dwDmaLen);
                    DMA_initialize_LLI(&g_InputDMA, 0);
                }

                if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
                {
                    RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : MASTER MODE \r\n")));
                    MASTER_CS_ENABLE;
                }
                else
                {
                    RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : SLAVE MODE \r\n")));
                }

                DMA_channel_start(&g_InputDMA);

                //Timeout value setting
                TotalTimeOut = READ_TIME_OUT_CONSTANT + (READ_TIME_OUT_MULTIPLIER/1000)*dwRxCount;
                TimeOut    =    TotalTimeOut;
                WaitReturn = WaitForSingleObject(pSpiPublic->hRxDmaDoneDoneEvent, TimeOut);

                if ( WAIT_TIMEOUT == WaitReturn )
                {
                    // Timeout
                    RETAILMSG (TRUE, (TEXT("Read timeout!!!\r\n")));
                    // Stop input DMA
                    DMA_channel_stop(&g_InputDMA);
                    goto LEAVEREAD;
                }

                pSpiPrivate->dwRxCount -= dwDmaLen;
                pSpiPrivate->pRxBuffer = (PBYTE) (((PUINT) pSpiPrivate->pRxBuffer) + dwDmaLen);
            }
            //VirtualFree((PVOID)pRxBuffer, 0, MEM_RELEASE);
        }
        else
        {
        //POLLING Mode + RX
            ULONG Count;
            RETAILMSG(SPI_MSG,(TEXT("[SPI] Thread for RX : USE Polling (RxCount : %d) \r\n"), dwRxCount));

            if(pSpiPrivate->dwMode == SPI_MASTER_MODE)
            {
                pSPIregs->CH_CFG     = pSpiPrivate->RxSPIregs.CH_CFG;
                pSPIregs->CLK_CFG     = pSpiPrivate->RxSPIregs.CLK_CFG;

⌨️ 快捷键说明

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