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
SPI sending data
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?
thanks for replying me! It work fine now. I measured it in a wrong parameter of time! Once again thanks you!
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!
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
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?
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?
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!
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!
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?
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,
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!
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,
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?
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!
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.
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");