GPIO SPI Driver

matt_Damon
Hello,

Does anyone have SPI driver for WINCE?  The SPI Pins are on the GPIO
connector.

Thanks.

Killerwatt
Here are some contributions to them.
As it stands, there are probably differences between the "Mini" and "micro"
in the pinout.
Just once you read through the Forum, through.

matt_Damon
Yes, I was looking for MINi2440 SPI drivers for WINCE.

Killerwatt
There are several ways an ARM-based embedded Linux programming machine.
Each programming technique requires a very specific expertise, places
special demands on the next to use development tools.

matt_Damon
Actually I was looking to use the SPI Driver on the MINI2440 with WINCE5.0.

matt_Damon
Hello,

Can anyone please check this SPI driver? 

#include <windows.h>


void SPIInit();
void Virtual_Alloc();

#define DLLEXPORT __declspec(dllexport)
#define EXTERNC    extern "C"


EXTERNC BOOL VirtualCopy(LPVOID dest, LPVOID src, DWORD size, DWORD flags);


#define SSP_BASE 0xB1900000  // 0x59000000

typedef struct  {
    unsigned int  rSPCON0;   // 00
    unsigned int  rSPSTA0;
    unsigned int  rSPPIN0;
    unsigned int  rSPPRE0;
    unsigned int  rSPTDAT0;  // 10
    unsigned int  rSPRDAT0;
    unsigned int  rPAD[2];
    unsigned int  rSPCON1;   // 20
    unsigned int  rSPSTA1;
    unsigned int  rSPPIN1;
    unsigned int  rSPPRE1;
    unsigned int  rSPTDAT1;   // 30
    unsigned int  rSPRDAT1;
}SSPreg ; 


bool memoryAlloced = false;

volatile SSPreg *s2440SPI = (SSPreg *)SSP_BASE;

EXTERNC DLLEXPORT void Config_SPI(void);
void Config_SPI(void)
{
SPIInit();
s2440SPI->rSPPRE0=199;  //baud rate = 6MHZ; PCLK = 60KHZ
s2440SPI->rSPCON0=63;  //interrupt Mode, SCK Enabled, Master, CPOL=1,
CPHA=1, TAGD =1
}


EXTERNC DLLEXPORT int Status_SPI(void);
int Status_SPI(void)
{
SPIInit();
int i;
i=s2440SPI->rSPSTA0;  //status
return i;
}


EXTERNC DLLEXPORT int Write_SPI(int data);
int Write_SPI(int data)
{
SPIInit();

s2440SPI->rSPTDAT0=data;  //status
return 0;
}

EXTERNC DLLEXPORT void Close_SPI(void);
void Close_SPI(void)
{
SPIInit();
s2440SPI->rSPPRE0=0;  //
s2440SPI->rSPCON0=0;  //
}

void Virtual_Alloc()
{

    // GPIO Virtual alloc
  s2440SPI = (volatile SSPreg *) VirtualAlloc(0,sizeof(SSPreg),MEM_RESERVE,
PAGE_NOACCESS);
  if(s2440SPI == NULL) 
  {
    RETAILMSG(1,(TEXT("For s2440SPI: VirtualAlloc faiLED!\r\n")));
    
  }
  else {
   
if(!VirtualCopy((PVOID)s2440SPI,(PVOID)(SSP_BASE),sizeof(SSPreg),PAGE_READWRITE
| PAGE_NOCACHE )) 
    {
      RETAILMSG(1,(TEXT("For s2440SPI: VirtualCopy faiLED!\r\n")));
    }
  }
 
  
}

void SPIInit() {
  if (!memoryAlloced) 
  {
    
    Virtual_Alloc();
    memoryAlloced = true;
    
  }

}

ambitious
Hi, 
Can any one help me in using the SPI driver in the mini2440 for Linux

Thanks

Andre
Hi Matt Damon,


I´m trying to make a SPI communication, too. It´s been quite hard!
I can access all GPIO´s pins (and ports), including changing their boolean
value. BUT, when I try to send data thought SPI, it doesn´t work!

Can someone help me? (my email: andre.pepino@gmail.com)

My DLL code that I include it on my C# code (some parts I copied from this
and others forums):

#include "StdAfx.h"
#include "SPIDLL.h"
#include "s2440.h"
#include <windows.h>
#include <time.h>
//#include <ceddk.h>

extern "C"
{
  __declspec(dllimport) BOOL   VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc,
DWORD cbSize, DWORD fdwProtect);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
           )
{
    switch (ul_reason_for_call)
  {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
      break;
    }
    return TRUE;
}


// This is an example of an exported variable
SPIDLL_API int nSPIDLL=0;

// This is an example of an exported function.
SPIDLL_API int fnSPIDLL(void)
{
  return 42;
}

// This is the constructor of a class that has been exported.
// see SPIDLL.h for the class definition
CSPIDLL::CSPIDLL()
{ 
  return; 
}

void spiInit();
void Virtual_Alloc_SPI();
void Virtual_Alloc_GPIO();

bool memoryAlloced_GPIO = false;
bool memoryAlloced_SPI = false;
bool SPI_configured = false;

volatile SSPreg *s2440SPI = (SSPreg *)SSP_BASE;
volatile IOPreg *s2440IOP = (IOPreg*) IOP_BASE;

extern "C" _declspec(dllexport) unsigned int WINAPI DLLreadSPI ()
{
  spiInit();
  if(s2440SPI->rSPSTA0 & 1 == 1)
    return s2440SPI->rSPRDAT0;
  return 0;
}

extern "C" _declspec(dllexport) int WINAPI DLLwriteSPI(unsigned int dado) 
{
  if(!SPI_configured)
  {
    if (!memoryAlloced_SPI) 
    {  
      Virtual_Alloc_SPI();
      memoryAlloced_SPI = true;  
    }
    if (!memoryAlloced_GPIO) 
    {  
      Virtual_Alloc_GPIO();
      memoryAlloced_GPIO = true;  
    }

    //Coloca 101010 a partir do bit 22 do registrador GPECON
    s2440IOP->rGPECON = (s2440IOP->rGPECON &~ (63 << 22)) | (42 << 22);

    //Função nSS0: É necessária?
    //s2440IOP->rGPGCON = (s2440IOP->rGPGCON &~ (3 << 4)) | (3 << 4);

    s2440SPI->rSPPRE0 = 99;  //Baud Rate padrão
    s2440SPI->rSPCON0 = 29;    //Ver pg. 505 do datasheet do processador s2440
                  //Binário 7bits: 0011100
                  //SPI Mode Select[6,5]: "00" = polling mode
                  //SCK Enable[4]: "1" = enable
                  //Master/Slave Select[3]: "1" = master
                  //Clock Polarity Select[2]: "1" = active low
                  //Clock Phase Select[1]: "0" = format A
                  //Tx Auto Garbage Data mode enable[0]: "1" = normal mode
    SPI_configured = true;
  }
  s2440SPI->rSPTDAT0 = dado;
  return 0;
}


extern "C" _declspec(dllexport) int WINAPI DLLsetPino(char porta, int pino,
bool on) 
{
  if (!memoryAlloced_GPIO) 
  {  
    Virtual_Alloc_GPIO();
    memoryAlloced_GPIO = true;  
  }

  switch (porta) 
  {
  case 'A':
    s2440IOP->rGPACON = (s2440IOP->rGPACON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPADAT = (s2440IOP->rGPADAT &~ (0x1 << pino));
    else
      s2440IOP->rGPADAT = (s2440IOP->rGPADAT | (0x1 << pino));
    break;
  case 'B':
    s2440IOP->rGPBCON = (s2440IOP->rGPBCON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPBDAT = (s2440IOP->rGPBDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPBDAT = (s2440IOP->rGPBDAT | (0x1 << pino));
    break;
  case 'C':
    s2440IOP->rGPCCON = (s2440IOP->rGPCCON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPCDAT = (s2440IOP->rGPCDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPCDAT = (s2440IOP->rGPCDAT | (0x1 << pino));
    break;
  case 'D':
    s2440IOP->rGPDCON = (s2440IOP->rGPDCON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPDDAT = (s2440IOP->rGPDDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPDDAT = (s2440IOP->rGPDDAT | (0x1 << pino));
    break;
  case 'E':
    s2440IOP->rGPECON = (s2440IOP->rGPECON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPEDAT = (s2440IOP->rGPEDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPEDAT = (s2440IOP->rGPEDAT | (0x1 << pino));
    break;
    
  case 'F':
    s2440IOP->rGPFCON = (s2440IOP->rGPFCON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPFDAT = (s2440IOP->rGPFDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPFDAT = (s2440IOP->rGPFDAT | (0x1 << pino));
    break;
  case 'G':
  
    s2440IOP->rGPGCON = (s2440IOP->rGPGCON &~ ( 3 << pino*2)) | ( 1<<
pino*2);  
    if (!on)
      s2440IOP->rGPGDAT = (s2440IOP->rGPGDAT &~ (0x1 << pino));
    else
      s2440IOP->rGPGDAT = (s2440IOP->rGPGDAT | (0x1 << pino));
    break;
  }
  
  return 0;
}


void Virtual_Alloc_GPIO()
{
    // GPIO Virtual alloc
  s2440IOP = (volatile IOPreg *)
VirtualAlloc(0,sizeof(IOPreg),MEM_RESERVE,PAGE_NOACCESS);
  if(s2440IOP == NULL) 
  {
    RETAILMSG(1,(TEXT("For s2440IOP: VirtualAlloc faiLED!\r\n")));  
  }
  else 
  {
   
if(!VirtualCopy((PVOID)s2440IOP,(PVOID)(IOP_BASE),sizeof(IOPreg),PAGE_READWRITE|

PAGE_NOCACHE )) 
    {
      RETAILMSG(1,(TEXT("For s2440IOP: VirtualCopy faiLED!\r\n")));
    }
  }
}



void Virtual_Alloc_SPI()
{
    // GPIO Virtual alloc
  s2440SPI = (volatile SSPreg *)
VirtualAlloc(0,sizeof(SSPreg),MEM_RESERVE,PAGE_NOACCESS);
  if(s2440SPI == NULL) {
    RETAILMSG(1,(TEXT("For s2440SPI: VirtualAlloc faiLED!\r\n")));
    
  }
  else {
   
if(!VirtualCopy((PVOID)s2440SPI,(PVOID)(SSP_BASE),sizeof(SSPreg),PAGE_READWRITE
| PAGE_NOCACHE )) 
    {
      RETAILMSG(1,(TEXT("For s2440SPI: VirtualCopy faiLED!\r\n")));
    }
  }
}

domdom
Hello, 

I developed a Windows CE 6.0 SPI driver and tested it with a SPI
temperature sensor tmp125. 

This driver supports only SPI interface 0, but it would not be difficult to
adapt the source code for SPI interface 1.

You can download the driver and the test application on my site :
http://www.domodom.fr/spip/spip.php?article27&lang=en

domdom

Errol
Very nice!

Thanks,
Errol

Jose
where can i download a driver for wince 5 or make my own driver?

Thanks

Saif
hello,

@domDom can u tell me how do I understand that Receivable data is
available?
And when interrupt is generated Data received or sent?

and SPSTA Transfer Ready flag becomes set when either data transmission is
ready or Receive Buffer is ready. So how do I known which has happened>