📄 spi.c
字号:
//-------------------------------------------------------------------------------------------------------------------------
// 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 S3C6400 CPU
//
// Environment : Samsung S3C6400 / WinCE6.0
//
// 2007/06/
//
//-------------------------------------------------------------------------------------------------------------------------
#include <windows.h>
//#include <types.h> //
#include <nkintr.h>
#include <ceddk.h> //For DMA Buffer Alloc
#include <memory.h>
//#include <bsp_cfg.h>
#include <s3c6400.h> // for 6400
#include <DrvLib.h>
#include "spi.h"
#include "oal_intr.h"
#include "s3c6400_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
//#define TEST_MODE
//#define POLLING
// MSG
#define SPI_MSG 0
#define SPI_INIT 1
volatile S3C6400_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 //1024
//Memory Physical Address
PHYSICAL_ADDRESS g_PhysDmaDstBufferAddr;
PHYSICAL_ADDRESS g_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;
if ( !pPublicSpi )
{
return FALSE;
}
// GPIO Virtual alloc
pPublicSpi->pGPIOregs = (volatile S3C6400_GPIO_REG *)DrvLib_MapIoSpace(S3C6400_BASE_REG_PA_GPIO, sizeof(S3C6400_GPIO_REG), FALSE);
if (pPublicSpi->pGPIOregs == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] For pGPIOregs: DrvLib_MapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// HS-SPI Virtual alloc
pPublicSpi->pSPIregs = (volatile S3C6400_SPI_REG *)DrvLib_MapIoSpace(S3C6400_BASE_REG_PA_SPI0, sizeof(S3C6400_SPI_REG), FALSE);
if (pPublicSpi->pSPIregs == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSPIregs: DrvLib_MapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// Syscon Virtual alloc
pPublicSpi->pSYSCONregs = (volatile S3C6400_SYSCON_REG *)DrvLib_MapIoSpace(S3C6400_BASE_REG_PA_SYSCON, sizeof(S3C6400_SYSCON_REG), FALSE);
if (pPublicSpi->pSYSCONregs == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] For pSYSCONregs: DrvLib_MapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// DMAC0 Virtual alloc
pPublicSpi->pDMAC0regs = (volatile S3C6400_DMAC_REG *)DrvLib_MapIoSpace(S3C6400_BASE_REG_PA_DMA0, sizeof(S3C6400_DMAC_REG), FALSE);
if (pPublicSpi->pDMAC0regs == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC0regs: DrvLib_MapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
// DMAC1 Virtual alloc
pPublicSpi->pDMAC1regs = (volatile S3C6400_DMAC_REG *)DrvLib_MapIoSpace(S3C6400_BASE_REG_PA_DMA1, sizeof(S3C6400_DMAC_REG), FALSE);
if (pPublicSpi->pDMAC1regs == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] For pDMAC1regs: DrvLib_MapIoSpace failed!\r\n")));
bResult = FALSE;
goto CleanUp;
}
CleanUp:
if (!bResult)
{
if (pPublicSpi->pGPIOregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pGPIOregs);
pPublicSpi->pGPIOregs = NULL;
}
if (pPublicSpi->pSPIregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSPIregs);
pPublicSpi->pSPIregs = NULL;
}
if (pPublicSpi->pDMAC0regs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC0regs);
pPublicSpi->pDMAC0regs = NULL;
}
if (pPublicSpi->pDMAC1regs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pDMAC1regs);
pPublicSpi->pDMAC1regs = NULL;
}
if (pPublicSpi->pSYSCONregs)
{
DrvLib_UnmapIoSpace((PVOID)pPublicSpi->pSYSCONregs);
pPublicSpi->pSYSCONregs = NULL;
}
return FALSE;
}
//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 TRUE;
}
BOOL InitializeBuffer()
{
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, &g_PhysDmaDstBufferAddr, FALSE);
//RETAILMSG(TRUE, (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")));
return FALSE;
}
pVirtDmaSrcBufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter2, Buffer_Mem_Size, &g_PhysDmaSrcBufferAddr, FALSE);
//RETAILMSG(TRUE, (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")));
return FALSE;
}
//DMA Address
DmaDstAddress = (UINT)(g_PhysDmaDstBufferAddr.LowPart);
DmaSrcAddress = (UINT)(g_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")));
return TRUE;
}
PSPI_PUBLIC_CONTEXT SPI_Init(PVOID Context)
{
LPTSTR ActivePath = (LPTSTR) Context; // HKLM\Drivers\Active\xx
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")));
return NULL;
}
if ( !(pRestoreSPIregs = (PS3C6400_SPI_REG)LocalAlloc( LPTR, sizeof(S3C6400_SPI_REG) )) )
{
return NULL;
}
if(!HW_Init(pPublicSpi))
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] HW_Init is failed\n")));
return NULL;
}
else
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] HW_Init is completed\n")));
}
if(!InitializeBuffer())
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] InitializeBuffer is failed\n")));
return NULL;
}
else
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] InitializeBuffer is completed\n")));
}
// Request DMA Channel
// DMA context have Virtual IRQ Number of Allocated DMA Channel
// You Should initialize DMA Interrupt Thread after "Request DMA Channel"
DMA_request_channel(&g_OutputDMA, DMA_SPI0_TX);
DMA_request_channel(&g_InputDMA, DMA_SPI0_RX);
do
{
InitializeCriticalSection(&(pPublicSpi->CsRxAccess));
InitializeCriticalSection(&(pPublicSpi->CsTxAccess));
//Rx Thread
pPublicSpi->hRxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
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);
pPublicSpi->hRxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//Tx Thread
pPublicSpi->hTxEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
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 Dma Thread creation error!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hTxDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pPublicSpi->hTxIntrDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//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)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI ISR Thread creation error!!!\n")));
bResult = FALSE;
break;
}
//Tx DMA Done ISR
pPublicSpi->dwTxDmaDoneSysIntr = SYSINTR_NOP;
dwHwIntr = g_OutputDMA.dwIRQ;
pPublicSpi->hTxDmaDoneDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pPublicSpi->hTxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwTxDmaDoneSysIntr, sizeof(DWORD), NULL))
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI_DMA sysintr.\n")));
pPublicSpi->dwTxDmaDoneSysIntr = SYSINTR_UNDEFINED;
bResult = FALSE;
break;
}
if (!InterruptInitialize(pPublicSpi->dwTxDmaDoneSysIntr, pPublicSpi->hTxDmaDoneEvent, NULL, 0))
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hTxDmaDoneThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForTxDmaDone, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwTxDmaDoneThreadId);
if (pPublicSpi->hTxDmaDoneThread == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Dma Thread creation error!!!\n")));
bResult = FALSE;
break;
}
//Rx DMA Done ISR
pPublicSpi->dwRxDmaDoneSysIntr = SYSINTR_NOP;
dwHwIntr = g_InputDMA.dwIRQ;
pPublicSpi->hRxDmaDoneDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
pPublicSpi->hRxDmaDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwHwIntr, sizeof(DWORD), &pPublicSpi->dwRxDmaDoneSysIntr, sizeof(DWORD), NULL))
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] Failed to request the SPI_DMA sysintr.\n")));
pPublicSpi->dwRxDmaDoneSysIntr = SYSINTR_UNDEFINED;
bResult = FALSE;
break;
}
if (!InterruptInitialize(pPublicSpi->dwRxDmaDoneSysIntr, pPublicSpi->hRxDmaDoneEvent, NULL, 0))
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] DMA Interrupt Initialization failed!!!\n")));
bResult = FALSE;
break;
}
pPublicSpi->hRxDmaDoneThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadForRxDmaDone, (LPVOID)pPublicSpi, 0, (LPDWORD)&pPublicSpi->dwRxDmaDoneThreadId);
if (pPublicSpi->hRxDmaDoneThread == NULL)
{
RETAILMSG(SPI_INIT,(TEXT("[SPI] SPI Dma Thread creation error!!!\n")));
bResult = FALSE;
break;
}
} while (0);
RETAILMSG(SPI_INIT,(TEXT("--[SPI] HSP_Init Function\r\n")));
if(bResult)
{
return pPublicSpi;
}
else
{
return NULL;
}
}
DWORD
SPI_Open(
DWORD pContext,
DWORD AccessCode,
DWORD ShareMode)
{
PSPI_PUBLIC_CONTEXT pSpiPublic = (PSPI_PUBLIC_CONTEXT) pContext;
PSPI_PRIVATE_CONTEXT pSpiPrivate = NULL;
BOOL bResult = TRUE;
if ( !(pSpiPrivate = (PSPI_PRIVATE_CONTEXT)LocalAlloc( LPTR, sizeof(SPI_PRIVATE_CONTEXT) )) )
{
RETAILMSG(SPI_MSG,(TEXT("[SPI] Can't not allocate for SPI Context\n")));
return (DWORD)NULL;
}
do
{
pSpiPrivate->State = STATE_INIT;
pSpiPrivate->pSpiPublic = pSpiPublic;
pSpiPrivate->bUseRxDMA = FALSE;
pSpiPrivate->bUseRxIntr = FALSE;
pSpiPrivate->bUseTxDMA = FALSE;
pSpiPrivate->bUseTxIntr = FALSE;
} while(FALSE);
if(bResult)
{
return (DWORD) pSpiPrivate;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -