Hi, I bought a board simliar to the Mini2440 called the TQ2440. The two boards are almost exact replicas. I followed one of the threads on this forum to get the SPI driver to work and successfully tested the SPI with the test code. Everything works, but now I want to write code for my wireless module nrF24L01+ through SPI. Since you cannot access pins directly because Linux does not allow it, how exactly do I transmit and receive data through my module?
Using wireless modules through SPI
Oh, here is the link to my board: http://www.cutedigi.com/product_info.php?products_id=4238 Thanks in advance!
What do you mean can't access SPI pins directly? You need to write your own wifi driver and hook it to SPI for mini2440 and use SPI api to send and receive data. good luck, marek
Sure it's the easiest part ;). Try to search maybe something already existing. If you have spec & maybe some spare module I can help ;). marek
the module im using is the Nordic nrf24l01+. Here is the datasheet if you want more information: http://www.nordicsemi.com/files/Product/data_sheet/nRF24L01P_Product_Spe...
So I have found written driver for my module so I am gonna use that. Do I just need to copy the c file into the kernel "driver" folder and create a Makefile and do "make zImage" to make new image file to include the driver?
Well no so easy ;). In board file you need to hook driver to SPI and also add driver to kernel compilation (could be done out of kernel tree). If you have link to source I could help you with integration. marek
I found this on an chinese blog. I've also noticed that the pins defined in this source code is different than what I used, so I changed that accordingly(eg. S3C2410_GPE11, 12 and 13 for me. Here is the source code. The comments are in chinese but other than that, it is very readable. You can also use google translate. http://blog.163.com/jammy_lee/blog/static/101195478201016112945395/ Thanks again.
So it is working for you or? I would say this is not very clean way to write kernel module because it manipulate with SPI pins directly. Anyway you could use spidev module and write code in userspace instead in kernel (check kernel documentation). Will look @driver but currently I'm little busy maybe till end of next week ;). Marek
I haven't tested it. I wasn't sure how to put this in the kernel and so forth. But I will try your suggestion.
Hey Marek, You said that you could use spidev module in userspace code so I experimented with the spidev_test.c given in the tutorial. Looping back the MISO and MOSI works without the module. When the module is connected to the corresponding pins, I cannot receive the data I am trying to transmitted. My professor told me that since SPI transmit and receive data by byteswapping, you need to byteswap twice. I modified the code to call transfer() function twice in main(), but it still doesnt work. Am I on the wrong track? Thanks, Quang
Well no you can't call transfer 2 times. SPI bus works in way you send data and with every clock you also receive data (check connection and signals if they seems to be correct).
I notice when hooking SPI driver to board, the board file contains static struct spi_board_info __initdata tq2440_spi0_board_info[] = { // SPI Port 0 { .modalias = "spidev", .max_speed_hz = 8000000, //8 Mbps .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_1, }, }; static void tq2440_spi0_cs(struct s3c2410_spi_info *spi, int cs, int pol) { s3c2410_gpio_setpin(S3C2410_GPG2, pol); } static struct s3c2410_spi_info tq2440_spi0_platdata = { .num_cs = 1, .bus_num = 0, .set_cs = tq2440_spi0_cs, }; Since I am using in the driver above the pins are defined directly to the SPI, if i add this to board file, would it have the same parameters(eg. .max_speed_hz, .bus_num = 0,.chip_select,....etc). Not quite sure how to hook my new driver to board file. Thanks in advance.
Use this: http://open-nandra.com/2010/09/friendly-arm-2440-and-sca3000-accelerometer/ instead: .modalias = "sca3000_d01" use : .modalias = "spidev"
Hey open-nandra, I loaded the driver I found on the kernel and open the device using "mknod /dev/nrf24l01 c 241 0" since it is a character device driver. I tried running a test program that just is similar to the code below. But it does not work. Is the read() and write() function suppose to work for the SPI port? I tried looping back MISO and MOSI pins on the SPI and send/receive with write() and read() function and it does not work. It does work however when I use the spidev_test.c from the Linux Documentation(uses ioctl() function to transfer). unsigned char TxBuf[32] = {0x00}; int main(void) { int fd = -1; int count = 1; //fd = open("/dev/nrf24l01", 0); fd = open("/dev/nrf24l01", O_RDWR); //打开nrf24l01为可读写文件 if(fd < 0) { perror("Can't open /dev/nrf24l01 \n"); exit(1); } printf("open /dev/nrf24l01 success \n"); while(count <= 5) { write(fd, &TxBuf , sizeof(TxBuf)); printf("Sending %d time \n", count); usleep(100*1000); count++; } close(fd); }
Yes write and read methods are supported by spidev. In write you just send data which would like to send via SPI. Anyway you need to do initialization like in spidev example (missing in your code).
Are you referring to this section of the spidev example? struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = ARRAY_SIZE(tx), .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, }; Since I am not using ioctl(), would I use this from the spi.h? I am not really sure how to initialize this. spi_write(struct spi_device *spi, const u8 *buf, size_t len) { struct spi_transfer t = { .tx_buf = buf, .len = len, }; struct spi_message m; spi_message_init(&m); spi_message_add_tail(&t, &m); }
I think you can reuse all code from spidev_test. I refer to transfer function in example. So first configure device then use transfer to send/receive message. marek
i have same problem with you chan. i want to connect an IC transmitter CC2550 with my mini2440. can that source code be used universally?