SPI sending data

Judau
Hello everyone,

I have a micro2440 board running Win CE 6.0. My CE image have SPI driver
from domodom.fr. I reconfigure to SPI channel 1 with frequecy 5 MHz. Now I
want to sending 10 bytes data. The problem is when I measure SCK pin from
oscilloscope, there are 10 waves. Each wave has 8 pulses 5 MHz(sending 1
byte data). But, there are different between each byte of data. Some of
waves have from 0 to 3.3V but some of waves have only from around 1.0-1.5V
to 2-2.5V. Can someone help me to solve this problem?

Thanks in advance!
Best regards

Judau

davef
I think it would very unlikely that there should any clock pulses that were
not switching between almost 0V and almost 3.3Volts.

I would expand the trace and insure that the rise time is say less than
10-20 nanoseconds, for a 5MHz (200nS period) clock.  Maybe, try reducing
the SPI speed and see if they "clean up" and behave as expected.

Can you trigger on the beginning of the data and display all 10 bytes? 
What type of oscilloscope?

Judau
thanks for replying me! It work fine now. I measured it in a wrong
parameter of time!

Once again thanks you!

Judau
I have another question! The micro2440 only have SPI channel 1, does it
support SPI channel 0? In the schematic, I can't find the pins of SPI
channel 0.

Please help me!

davef
I can see them.  GPE11, 12 and 13 and GPG2 and they are ones labelled as
SPI on the GPIO connector.  SPI1 pins are not quite as obvious.

Use the find facility in a .pdf reader

Judau
I'm using micro2440 not mini2440, so there is only SPI channel 1. I want to
use both spi channel.

Do you have any idea?

davef
I was looking at the micro2440 schematic.  Have you got the micro2440-sdk? 
I see they are not labelled as such on that schematic.

Could you look at the micro2440 schematic note which are the SPI1 pins and
hope that they are the same on the micro2440-sdk?

Just for my interest, do you want to run two SPI masters on the micro2440?

Judau
Hello davef!

I'm using pins EINT13,14,15 as SPI channel 1. I can't find pins GPE11,12
and 13. 
I want to use both SPI channel to communicate with temperature sensor and a
microcontroller in a same time.

Can you guilde me?

Thanks in advance!

davef
>I was looking at the micro2440 schematic.  Have you got the micro2440-sdk?

davef
GPE11 on the mini2440 and micro2440 is is labelled K9
GPE12 on the mini2440 and micro2440 is is labelled P9
GPE13 on the mini2440 and micro2440 is is labelled L9

But, I see there is no corresponding labeling on the micro2440-sdk.

Sorry, can't help you anymore.

Good luck!

davef
Have you got an oscilloscope?  Using the spi_test utility probe each GPIO
pin.

Have you modified the mach-mini2440.c file to run two SPI masters?

Judau
Attachment: IMG_0237.JPG (1.7 MB)
Hi Davef! 

I modified domodom driver to SPI channel 1 and rewrite application in C#
(based on his VB sample).

Now i have another problem, the delay time between 2 times sending data is
too long. You can see it in my attach image. I measure the MOSI pin, I only
send dummy data 0xFF (10 bytes).

How can I reduce this delay time?

Please help me,
Best regards,

davef
I'd have to look at the code you are using.  If you are sending 10 bytes
using a call to some driver then you could have significant delays. Your
operating system might decide to check your keyboard or execute something
else before sending the 2nd chunk of data.  

The mechanism for deciding what task should run is done by timer ticks in
Linux, ie 10ms.  I imagine it is similar in Windows.

Is there a method for disabling other system interrupts and run only one
task, ie the SPI task.

I think you would need to continuously execute your SPI application in a
while(1) loop and stop anything else happening to reduce that delay period.

Give me a link to domdom's SPI code.  Hopefully, someone with some real
Windows OS experience could set us both straight here!

Judau
Attachment: SPI.rar (12.16 KB)
Here is the code SPI that I downloaded from domodom.fr, I cannot connect to
his website. Hopefully someone can help us this problem!

I'm thankful to you for helping us!

Thanks Davef too,

Regards,

davef
(My) WinRAR won't extract that file.  I'll look for his site.

davef
Had a quick look around his code.  Looks very comprehensive.  I see there
are some calls to IOCTL (winioctl), which based on my limited Linux kernel
experience are calls to the kernel.

I see a comment <0 = POLLING, 1 = INTERRUPT>    I wonder if you can use a
polling method and just stay in a SPI sending task.  But then again I
imagine you want the OS to do other things, like read the SPI bus and maybe
even run some other applications.

What SPI transfer rate are you trying to achieve?  Do you need to send data
continuously at a high speed or is bursts of data OK?

Judau
I use INTERRUPT method (Domodom said that he didn't test POLLING mode), and
  transfer rate 12.5 MHz. I only want to send a few Kbytes of data then I
manage to do some other function. The important problem is how to send few
kbytes of data continuously at around transfer rate 10 MHz.

Thanks for helping me!

davef
In Linux one can use a bulk SPI transfer method (spi_transfer).  There must
be the equivalent in a Windows application.  Basically, you send data until
you are finished, nothing is allowed to interrupt that process.

You are only sending data, you don't have to stop and listen for a response
from the slave.

Seeing as no one is adding to this thread and I guess you want to use
Windows, maybe start another thread that draws the attention of Windows
users.

Judau
Thanks very much and have a nice day

Judau
Anyone can help me plz!!!

Sushant
Hello,
i am try to receive a data from ADC using SPI0 i found 2440-SPI driver and
i modified this driver but its return grbage value
  
#include <linux/miscdevice.h>   
#include <linux/kernel.h>   
#include <linux/module.h>   
#include <linux/init.h>   
#include <linux/fs.h>   
#include <linux/slab.h>   
#include <linux/pci.h>   
#include <linux/delay.h>   
#include <asm/uaccess.h>   
   
int loopChar=0x11;  
module_param(loopChar,int,S_IRUGO);  
                                                       
#define DEVICE_NAME "MINI2440"   
static void __iomem *base_addr0;  
static void __iomem *base_addr1;  
static void __iomem *base_addr2;  
static void __iomem *base_addr3;  
  
//稓义一烐测试用的要发送的数熭缓庢包   
static char *kbuf;  
static int  kbuf_size;  
  
#define S3C2440_CLKCON 0x4c00000c   
#define S3C2440_GPG    0x56000060   
#define S3C2440_GPE    0x56000040   
#define S3C2440_SPI    0x59000000   
  
/*****************************************************/  
//S3C2440_CLKCON 部分   
#define CLKCON      (*(volatile unsigned long *)(base_addr0 + 0x00))   
  
//GPG 控制屇庢器部分  GPG2溑对訆NSS 端口   
#define GPGCON      (*(volatile unsigned long *)(base_addr1 + 0x00))   
#define GPGDAT      (*(volatile unsigned long *)(base_addr1 + 0x04))   
#define GPGUP       (*(volatile unsigned long *)(base_addr1 + 0x08))   
  
//GPE 控制屇庢器部分    
//GPE 11、12、13 溑分别对訆SPI的MISO、MOSI、CLK 端口   
#define GPECON      (*(volatile unsigned long *)(base_addr2 + 0x00))   
#define GPEDAT      (*(volatile unsigned long *)(base_addr2 + 0x04))   
#define GPEUP       (*(volatile unsigned long *)(base_addr2 + 0x08))   
  
//SPI 控制屇庢器部分   
#define SPCON0      (*(volatile unsigned long *)(base_addr3 + 0x00))   
#define SPSTA0      (*(volatile unsigned long *)(base_addr3 + 0x04))   
#define SPPIN0      (*(volatile char *)(base_addr3 + 0x08))   
#define SPPRE0      (*(volatile char *)(base_addr3 + 0x0C))   
#define SPTDAT0     (*(volatile char *)(base_addr3 + 0x10))   
#define SPRDAT0     (*(volatile char *)(base_addr3 + 0x14))   
  
//SPI 输入输出的判脢讕态引溑   
#define SPI_TXRX_READY      (((SPSTA0) & 0x1) == 0x1)   
  
#define  SPNSS0_DISABLE()      (GPGDAT |=   (0x1 << 13))   
#define  SPNSS0_ENABLE()       (GPGDAT &= ~ (0x1 << 13))   
/********************************************************/  
union ADC_RESPONSE{
  unsigned char byte[4];
  unsigned long int count;  
};


union ADC_RESPONSE adc_response;


static int spi_open(struct inode *inode,struct file *filp)  
{  

    CLKCON |= (0x01 << 18);//0x40000;   
    printk("s3c2440_clkcon=%08ld\n",CLKCON);  
    GPGCON &= ~((3 << 4)|(3<<26)) ;  
    GPGCON |=  (1 << 4) | (1<<26);  
    
   SPNSS0_ENABLE();  
  
    // ENABLE SPI MISO,MOSI &CLK
    GPECON &= ~((3 << 22) | (3 << 24) | (3 << 26));  
    GPECON |=  ((2 << 22) | (2 << 24) | (2 << 26));  
      
    GPGUP &= ~(0x07 << 2);    
    GPEUP |=  (0x07 << 11);  
  
    //Baud Rate=PCLK/2/(Prescaler value+1)   
    SPPRE0 = 0x18;       //freq = 1M   
    printk("SPPRE0=%02X\n",SPPRE0);  
      
    //polling,en-sck,master,low,format A,nomal = 0 | TAGD = 1   
    SPCON0 = (0<<5)|(1<<4)|(1<<3)|(0<<2)|(0<<1)|(0<<0);  
    printk("SPCON1=%02ld\n",SPCON0);  
  
    //多主机庬误岇测使能   
    SPPIN0 = (0 << 2) | (1 << 1) | (0 << 0);  
    printk("SPPIN1=%02X\n",SPPIN0);  
  
    //初蕦化程序   
    SPTDAT0 = 0xff;  
    return 0;  
}  
   
   
static int spi_release(struct inode *inode,struct file *filp)  
{  
    //释放掉在袔函数操作里面申请的缓庢空屼   
    kfree(kbuf);  
    //printk("<1>release\n");   
    return 0;  
}  
   
//向SPI屇庢器SPI_SPTDAT1中袔数熭    
static void writeByte(const char data)  
{  
    int j = 0;  
    SPTDAT0 = data;
   for (j=0;j<0xFF;j++); 
    while(!SPI_TXRX_READY)  
   for (j=0;j<0xFF;j++);      
}

  
//幱SPI屇庢器SPI_SPRDAT1中读取数熭   
static char readByte(const char data)  
{  
    int j = 0;  
    SPTDAT0 = data;   
   for (j=0;j<0xFF;j++);      
    while(!SPI_TXRX_READY);  
   for (j=0;j<0xFF;j++);      
    

    return SPRDAT0;   
}


  
unsigned long int adc_get_count(void){
  int x;
  ssleep(1);

  do{
    adc_response.byte[0] = readByte(0xFF);    
    adc_response.byte[1] = readByte(0xFF);    
    adc_response.byte[2] = readByte(0xFF);    
    adc_response.byte[3] = readByte(0xFF);    
    printk("byte[0]=%lu byte[1]=%lu byte[2] =%lu byte[3]=%lu
\n",adc_response.byte[0],adc_response.byte[1],adc_response.byte[2],adc_resp
onse.byte[3]);
  }while(adc_response.count & 0x80000000);
  ssleep(1);  
  adc_response.count &=0x0FFFFFF0;
   adc_response.count =adc_response.count>>4;
  printk("adc  count =%lu\n",adc_response.count);
  return adc_response.count;

}

void adc_channel(char ch){
  SPNSS0_DISABLE();
  ssleep(1);
  writeByte(ch);
  ssleep(1);
  SPNSS0_ENABLE();
  ssleep(1);
}
//溣收数熭并把数熭发送禍訆用空屼   
static ssize_t spi_read(struct file *filp,char __user *buf,size_t
count,loff_t *f_ops)  
{  
#if 0   
    int   i = 0;  
    char *tab;  
    printk("<1>spi read!\n");  
    tab = kmal
loc(kbuf_size,GFP_KERNEL);  
  
    for(; i < kbuf_size; i++){  
        tab[i] = readByte(kbuf[i]);  
        printk("read data tab[%d] = %02X\n",i, tab[i]);  
    }  
    copy_to_user(buf, tab, kbuf_size);  
    kfree(tab);  
#endif 
 
   int  i=0;
    
     adc_channel(0x08);
          adc_get_count(); 
        copy_to_user(buf,&adc_response.count,sizeof(unsigned long int));  
  return 1;  
}
  
//发送数熭并把数熭幱用户空屼发送禍内核   
static ssize_t spi_write(struct file *filp,const char __user *buf,  
                                            size_t count,loff_t *f_ops)  
{  
    int i;  
    //char *kbuf;   
    kbuf_size = count;  
    printk("<1>spi write!,count=%d\n",count);  
    kbuf = kmalloc(count,GFP_KERNEL);  
      
    //送禍发用户空屼   
    if(copy_from_user(kbuf,buf,count))  
    {  
        printk("no enough memory!\n");  
        return -1;  
    }  
      
    //循环袔入屇庢器   
#if 0       
    for(i=0;i<count;i++)  
    {  
        writeByte(kbuf[i]);  
        printk("write 0x%02X!\n",*kbuf);  
    }  
      
#endif   
    return count;  
}  
   
   
/**********************************************************/  
static const struct file_operations spi_fops =  
{  
    .owner=THIS_MODULE,  
    .open=spi_open,  
    .read=spi_read,  
    .release=spi_release,  
    .write=spi_write,  
};  
static struct miscdevice misc = {  
    .minor = MISC_DYNAMIC_MINOR,  
    .name  = DEVICE_NAME,  
    .fops  = &spi_fops,  
};  
  
static int __init spi_init(void)  
{  
    int ret;  
      
    //映射时钟控制屇庢器CLKCON    
    base_addr0 = ioremap(S3C2440_CLKCON, 0x04);  
    //映射GPG部分   
    base_addr1 = ioremap(S3C2440_GPG, 0x10);  
    //映射GPE 屇庢器地址   
    base_addr2 = ioremap(S3C2440_GPE, 0x10);  
    //映射SPI 屇庢器地址   
    base_addr3 = ioremap(S3C2440_SPI, 0x20);  
  
    //瀻杂设睘的注册   
    ret = misc_register(&misc);  
    printk(DEVICE_NAME "\tinitialized\n");  
   
    return ret;  
}  
   
   
static void __exit spi_exit(void)  
{  
    iounmap(base_addr0);  
    iounmap(base_addr1);  
    iounmap(base_addr2);  
    iounmap(base_addr3);  
    misc_deregister(&misc);  
    printk("<1>spi_exit!\n");  
}  
   
module_init(spi_init);  
module_exit(spi_exit);  
   
MODULE_LICENSE("GPL");