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

📄 spi.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 4 页
字号:
// Copyright (c) Samsung Electronics. Co. LTD.  All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Module Name :    SPI.C
//
// Abstract     :   SPI Interface Routines for Samsung S3C6410 CPU
//
// Environment :    Samsung S3C6410 / WinCE6.0
//
// 2008/10/
//
//-------------------------------------------------------------------------------------------------------------------------

#include <bsp.h>
#include <memory.h>
#include "spi.h"
#include "s3c6410_dma_controller.h"

#define MASTER_CS_ENABLE      pSPIregs->SLAVE_SEL = 0
#define MASTER_CS_DISABLE     pSPIregs->SLAVE_SEL = 1

#define TRAIL_CNT(n)          (((n)&0x3FF)<<19)

#define SPI_POWER_ON          (1<<21)
#define SPI_SCLK_ON           (1<<20)
#define SPI_USBHOST_ON        (1<<22)

#define PCLOCK                (0)
#define USB_HOST_CLOCK        (1)
#define EPLL_CLOCK            (2)
#define SPI_CLOCK             EPLL_CLOCK

#if (SPI_CLOCK == EPLL_CLOCK)
#define CLKSEL                CLKSEL_EPLL
#elif (SPI_CLOCK == USB_HOST_CLOCK)
#define CLKSEL                CLKSEL_USBCLK
#elif (SPI_CLOCK == PCLOCK)
#define CLKSEL                CLKSEL_PCLK
#endif

//#define TEST_MODE 

// MSG
#define    SPI_MSG      0
#define    SPI_INIT     1

S3C6410_SPI_REG     *pRestoreSPIregs    =    NULL;

#define    WRITE_TIME_OUT_CONSTANT      5000
#define    WRITE_TIME_OUT_MULTIPLIER    1

#define    READ_TIME_OUT_CONSTANT       5000
#define    READ_TIME_OUT_MULTIPLIER     1

DWORD HW_Init(PSPI_PUBLIC_CONTEXT pPublicSpi);

DWORD ThreadForTx(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForRx(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForSpi(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForRxDmaDone(PSPI_PUBLIC_CONTEXT pPublicSpi);
DWORD ThreadForTxDmaDone(PSPI_PUBLIC_CONTEXT pPublicSpi);


static DMA_CH_CONTEXT    g_OutputDMA;
static DMA_CH_CONTEXT    g_InputDMA;

//DMA
//UINT nDmaLen;
UINT DmaDstAddress;
UINT DmaSrcAddress;

//DMA Buffer Address Alloc
#define Buffer_Mem_Size   1504

//Memory Physical Address
PHYSICAL_ADDRESS    PhysDmaDstBufferAddr;
PHYSICAL_ADDRESS    PhysDmaSrcBufferAddr;

// DMA Buffer Address Alloc
PBYTE pVirtDmaDstBufferAddr = NULL;
PBYTE pVirtDmaSrcBufferAddr = NULL;

BOOL
DllEntry(
    HINSTANCE   hinstDll,
    DWORD       dwReason,
    LPVOID      lpReserved
    )
{
    if ( dwReason == DLL_PROCESS_ATTACH )
    {
        DEBUGMSG (1, (TEXT("[SPI] Process Attach\r\n")));
    }

    if ( dwReason == DLL_PROCESS_DETACH )
    {
        DEBUGMSG (1, (TEXT("[SPI] Process Detach\r\n")));
    }

    return(TRUE);
}

DWORD
HW_Init(
    PSPI_PUBLIC_CONTEXT pPublicSpi
    )
{
    BOOL bResult = TRUE;
    PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

    if ( !pPublicSpi )
    {
        bResult = FALSE;
        goto CleanUp;
    }

    // GPIO Virtual alloc
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_GPIO;
    pPublicSpi->pGPIOregs = (volatile S3C6410_GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_GPIO_REG), FALSE);
    if (pPublicSpi->pGPIOregs == NULL)
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] For pGPIOregs: MmMapIoSpace failed!\r\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    // HS-SPI Virtual alloc
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_SPI0;    
    pPublicSpi->pSPIregs = (volatile S3C6410_SPI_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_SPI_REG), FALSE);
    if (pPublicSpi->pSPIregs == NULL)
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSPIregs: MmMapIoSpace failed!\r\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    // Syscon Virtual alloc
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_SYSCON;      
    pPublicSpi->pSYSCONregs = (volatile S3C6410_SYSCON_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_SYSCON_REG), FALSE);
    if (pPublicSpi->pSYSCONregs == NULL)
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSYSCONregs: MmMapIoSpace failed!\r\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    // DMAC0 Virtual alloc
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_DMA0;      
    pPublicSpi->pDMAC0regs = (volatile S3C6410_DMAC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_DMAC_REG), FALSE);
    if (pPublicSpi->pDMAC0regs == NULL)
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC0regs: MmMapIoSpace failed!\r\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    // DMAC1 Virtual alloc
    ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_DMA1;      
    pPublicSpi->pDMAC1regs = (volatile S3C6410_DMAC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_DMAC_REG), FALSE);
    if (pPublicSpi->pDMAC1regs == NULL)
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC1regs: MmMapIoSpace failed!\r\n")));
        bResult = FALSE;
        goto CleanUp;
    }

CleanUp:

    if (!bResult)
    {
        if (pPublicSpi->pGPIOregs)
        {
            MmUnmapIoSpace((PVOID)pPublicSpi->pGPIOregs, sizeof(S3C6410_GPIO_REG));
            pPublicSpi->pGPIOregs = NULL;
        }

        if (pPublicSpi->pSPIregs)
        {
            MmUnmapIoSpace((PVOID)pPublicSpi->pSPIregs, sizeof(S3C6410_SPI_REG));
            pPublicSpi->pSPIregs = NULL;
        }

        if (pPublicSpi->pDMAC0regs)
        {
            MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs, sizeof(S3C6410_DMAC_REG));
            pPublicSpi->pDMAC0regs = NULL;
        }

        if (pPublicSpi->pDMAC1regs)
        {
            MmUnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs, sizeof(S3C6410_DMAC_REG));
            pPublicSpi->pDMAC1regs = NULL;
        }

        if (pPublicSpi->pSYSCONregs)
        {
            MmUnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs, sizeof(S3C6410_SYSCON_REG));
            pPublicSpi->pSYSCONregs = NULL;
        }

        bResult = FALSE;
    }

    //Configure HS-SPI Port Drive Strength
    pPublicSpi->pGPIOregs->SPCON = pPublicSpi->pGPIOregs->SPCON & ~(0x3<<28) | (2<<28);
    //Set GPIO for MISO, MOSI, SPICLK, SS
    pPublicSpi->pGPIOregs->GPCPUD = pPublicSpi->pGPIOregs->GPCPUD & ~(0xFF<<0);
    pPublicSpi->pGPIOregs->GPCCON = pPublicSpi->pGPIOregs->GPCCON & ~(0xFFFF<<0) | (2<<0) | (2<<4) | (2<<8) |(2<<12);

    // Clock On
    pPublicSpi->pSYSCONregs->PCLK_GATE |= SPI_POWER_ON;
#if    (SPI_CLOCK == EPLL_CLOCK)
    pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_SCLK_ON;
#elif (SPI_CLOCK == USB_HOST_CLOCK)
    pPublicSpi->pSYSCONregs->SCLK_GATE |= SPI_USBHOST_ON;
#endif

    DMA_initialize_register_address((void *)pPublicSpi->pDMAC0regs, (void *)pPublicSpi->pDMAC1regs, (void *)pPublicSpi->pSYSCONregs);

    return bResult;
}

BOOL InitializeBuffer()
{
    BOOL bResult = TRUE;

    DMA_ADAPTER_OBJECT Adapter1, Adapter2;

    RETAILMSG(SPI_INIT,(TEXT("+[SPI] InitializeBuffer\n")));
    memset(&Adapter1, 0, sizeof(DMA_ADAPTER_OBJECT));
    Adapter1.InterfaceType = Internal;
    Adapter1.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);

    memset(&Adapter2, 0, sizeof(DMA_ADAPTER_OBJECT));
    Adapter2.InterfaceType = Internal;
    Adapter2.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);

    // Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
    //
    pVirtDmaDstBufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter1, Buffer_Mem_Size, &PhysDmaDstBufferAddr, FALSE);
    RETAILMSG(FALSE, (TEXT("[SPIDD] InitializeBuffer() - pVirtDmaDstBufferAddr %x\r\n"),pVirtDmaDstBufferAddr));
    if (pVirtDmaDstBufferAddr == NULL)
    {
        RETAILMSG(SPI_INIT, (TEXT("[SPI] InitializeBuffer() - Failed to allocate DMA buffer for SPI.\r\n")));
        HalFreeCommonBuffer(0, 0, PhysDmaDstBufferAddr, pVirtDmaDstBufferAddr, FALSE);
        bResult = FALSE;
        goto CleanUp;
    }

    pVirtDmaSrcBufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter2, Buffer_Mem_Size, &PhysDmaSrcBufferAddr, FALSE);
    RETAILMSG(FALSE, (TEXT("[SPIDD] InitializeBuffer() - pVirtDmaSrcBufferAddr %x\r\n"),pVirtDmaSrcBufferAddr));
    if (pVirtDmaSrcBufferAddr == NULL)
    {
        RETAILMSG(SPI_INIT, (TEXT("[SPI] InitializeBuffer() - Failed to allocate DMA buffer for SPI.\r\n")));
        HalFreeCommonBuffer(0, 0, PhysDmaSrcBufferAddr, pVirtDmaSrcBufferAddr, FALSE);
        bResult = FALSE;
        goto CleanUp;
    }

    //DMA Address
    DmaDstAddress = (UINT)(PhysDmaDstBufferAddr.LowPart);
    DmaSrcAddress = (UINT)(PhysDmaSrcBufferAddr.LowPart);

    RETAILMSG(SPI_MSG, (TEXT("[SPI] pVirtDmaSrcBufferAddr 0x%x   DmaSrcAddress 0x%x \r\n"),pVirtDmaSrcBufferAddr, DmaSrcAddress));
    RETAILMSG(SPI_MSG, (TEXT("[SPI] pVirtDmaDstBufferAddr 0x%x   DmaDstAddress 0x%x \r\n"),pVirtDmaDstBufferAddr, DmaDstAddress));

    RETAILMSG(SPI_INIT,(TEXT("-[SPI] InitializeBuffer\n")));

CleanUp:
    return bResult;
}


PSPI_PUBLIC_CONTEXT SPI_Init(PVOID Context)
{
    LPTSTR                          ActivePath = (LPTSTR) Context;
    PSPI_PUBLIC_CONTEXT             pPublicSpi = NULL;
    BOOL                            bResult = TRUE;
    DWORD                           dwHwIntr=0;

    RETAILMSG(SPI_INIT,(TEXT("++[SPI] HSP_Init Function\r\n")));
    RETAILMSG(SPI_MSG,(TEXT("[SPI] Active Path : %s\n"), ActivePath));

    if ( !(pPublicSpi = (PSPI_PUBLIC_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PUBLIC_CONTEXT) )) )
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] Can't not allocate for SPI Context\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    if ( !(pRestoreSPIregs = (PS3C6410_SPI_REG)LocalAlloc( LPTR, sizeof(S3C6410_SPI_REG) )) )
    {
        bResult = FALSE;
        goto CleanUp;
    }


    if(!HW_Init(pPublicSpi))
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] HW_Init is failed\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    if(!InitializeBuffer())
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] InitializeBuffer is failed\n")));
        bResult = FALSE;
        goto CleanUp;
    }

    // Request DMA Channel
    // DMA context have Virtual IRQ Number of Allocated DMA Channel
    // You Should initialize DMA Interrupt Thread after "Request DMA Channel"
    if( DMA_request_channel(&g_OutputDMA, DMA_SPI0_TX) != TRUE )
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA SPI TX channel request is failed\n")));
        bResult = FALSE;
        goto CleanUp;   
    }
    if( DMA_request_channel(&g_InputDMA, DMA_SPI0_RX) != TRUE )
    {
        RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA SPI RX channel request is failed\n")));
        bResult = FALSE;
        goto CleanUp;   
    }

    do
    {
        InitializeCriticalSection(&(pPublicSpi->CsRxAccess));
        InitializeCriticalSection(&(pPublicSpi->CsTxAccess));

        //Rx Thread
        pPublicSpi->hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hRxEvent == NULL)
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Rx Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        pPublicSpi->hRxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForRx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwRxThreadId);
        if (pPublicSpi->hRxThread == NULL)
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Rx Thread creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        pPublicSpi->hRxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hRxDoneEvent == NULL)
        {
            RETAILMSG(SPI_INIT, (TEXT("[SPI] SPI Rx Done Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }
        
        pPublicSpi->hRxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hRxIntrDoneEvent == NULL)
        {
            RETAILMSG(SPI_INIT, (TEXT("[SPI] SPI Rx Interrupt Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        //Tx Thread
        pPublicSpi->hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hTxEvent == NULL)
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Tx Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        pPublicSpi->hTxThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForTx, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwTxThreadId);
        if (pPublicSpi->hTxThread == NULL)
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Tx Thread creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        pPublicSpi->hTxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hTxDoneEvent == NULL)
        {
            RETAILMSG(SPI_INIT, (TEXT("[SPI] SPI Tx Done Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }        

        pPublicSpi->hTxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (pPublicSpi->hTxIntrDoneEvent == NULL)
        {
            RETAILMSG(SPI_INIT, (TEXT("[SPI] SPI Tx Interrupt Event creation error!!!\n")));
            bResult = FALSE;
            break;
        }

        //Spi ISR
        pPublicSpi->dwSpiSysIntr = SYSINTR_NOP;
        dwHwIntr = IRQ_SPI0;        //HS-SPI

        pPublicSpi->hSpiEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

        if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwSpiSysIntr, sizeof(DWORD), NULL))
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI sysintr.\n")));
            pPublicSpi->dwSpiSysIntr = SYSINTR_UNDEFINED;
            bResult = FALSE;
            break;
        }

        if (!InterruptInitialize(pPublicSpi->dwSpiSysIntr, pPublicSpi->hSpiEvent, NULL, 0))
        {
            RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Interrupt Initialization failed!!!\n")));
            bResult = FALSE;
            break;
        }

        pPublicSpi->hSpiThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForSpi, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwSpiThreadId);
        if (pPublicSpi->hSpiThread == NULL)

⌨️ 快捷键说明

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