gunahmt
Posts: 15
Joined: Mon Jun 25, 2018 12:31 pm
Location: Turkey

Spi Kernel Module

Tue Jul 24, 2018 8:44 am

Hi everyone,

I am trying to write kernel module working with spi. I try to catch data with interrupt. I found some interrupt example and i used. it works fine. But i cant configuration spi. there is my code ;

Code: Select all

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h> // for the GPIO functions
#include <linux/interrupt.h> // for the IRQ code
#include <linux/fcntl.h>
#include <linux/ioctl.h>
//#include <linux/stdint.h>

#include <linux/spi/spidev.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Derek Molloy");
MODULE_DESCRIPTION("A Button/LED test driver for the RPi");
MODULE_VERSION("0.1");

/*button for interrupt*/
static unsigned int gpioButton = 27; // pin 13 (GPIO27)
static unsigned int irqNumber; // share IRQ num within file
/*spi variables*/
static const char *spiDev0 	= "/dev/spidev0.0";
static const uint8_t spiBPW	= 8;
static uint32_t spiSpeeds	= 500000;

static irq_handler_t erpi_gpio_irq_handler(unsigned int irq, void
									*dev_id, struct pt_regs *regs);


static int __init erpi_gpio_init(void) {int result = 0;
	printk(KERN_INFO "GPIO_TEST: Initializing the GPIO_TEST LKM\n");
	
	// false prevents in/out change
	gpio_request(gpioButton, "sysfs"); // set up gpioButton
	gpio_direction_input(gpioButton); // set up as input
	gpio_export(gpioButton, false); // appears in /sys/class/gpio
	
	irqNumber = gpio_to_irq(gpioButton); // map GPIO to IRQ number
	printk(KERN_INFO "GPIO_TEST: button mapped to IRQ: %d\n", irqNumber);
	
	open(spiDev0,O_RDWR);
	ioctl(0,SPI_IOC_WR_MODE,0);
	ioctl(0,SPI_IOC_WR_BITS_PER_WORD,&spiBPW);
	ioctl(0,SPI_IOC_WR_MAX_SPEED_HZ,&spiSpeeds);
	
	
	// This next call requests an interrupt line
	result = request_irq(irqNumber, 				// interrupt number requested
			(irq_handler_t) erpi_gpio_irq_handler,	// handler function
			IRQF_TRIGGER_RISING, 					// on rising edge (press, not release)
			"erpi_gpio_handler", 					// used in /proc/interrupts
			NULL); 									// *dev_id for shared interrupt lines
	
	
	
	return result;
}



static void __exit erpi_gpio_exit(void) {
	free_irq(irqNumber, NULL); // free the IRQ number, no *dev_id
	gpio_unexport(gpioButton); // unexport the Button GPIO
	
	gpio_free(gpioButton); // free the Button GPIO
	
	printk(KERN_INFO "GPIO_TEST: Goodbye from the LKM!\n");
}



static irq_handler_t erpi_gpio_irq_handler(unsigned int irq, void *dev_id,
											struct pt_regs *regs) 
{
	printk(KERN_INFO "GPIO_TEST: Interrupt! (button is %d)\n",
			gpio_get_value(gpioButton));
	return (irq_handler_t) IRQ_HANDLED; // announce IRQ handled
}
module_init(erpi_gpio_init);
module_exit(erpi_gpio_exit);
spi-test.c

Code: Select all

obj-m+=spi-test.o

all: 
	make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean: 
	make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
Makefile

I got a error about open and ioctl function like that ;

Code: Select all

make -C /lib/modules/4.14.56-v7+/build/ M=/home/pi/kdeneme/spi-test modules
make[1]: Entering directory '/home/pi/linux'
  CC [M]  /home/pi/kdeneme/spi-test/spi-test.o
/home/pi/kdeneme/spi-test/spi-test.c: In function ‘erpi_gpio_init’:
/home/pi/kdeneme/spi-test/spi-test.c:40:2: error: implicit declaration of function ‘open’ [-Werror=implicit-function-declaration]
  open(spiDev0,O_RDWR);
  ^~~~
/home/pi/kdeneme/spi-test/spi-test.c:41:2: error: implicit declaration of function ‘ioctl’ [-Werror=implicit-function-declaration]
  ioctl(0,SPI_IOC_WR_MODE,0);
  ^~~~~
cc1: some warnings being treated as errors
scripts/Makefile.build:334: recipe for target '/home/pi/kdeneme/spi-test/spi-test.o' failed
make[2]: *** [/home/pi/kdeneme/spi-test/spi-test.o] Error 1
Makefile:1522: recipe for target '_module_/home/pi/kdeneme/spi-test' failed
make[1]: *** [_module_/home/pi/kdeneme/spi-test] Error 2
make[1]: Leaving directory '/home/pi/linux'
Makefile:4: recipe for target 'all' failed
make: *** [all] Error 2
I followed the instructions for kernel header files. ; https://www.raspberrypi.org/documentati ... /README.md

juj
Posts: 26
Joined: Sat Nov 18, 2017 10:51 pm

Re: Spi Kernel Module

Wed Jul 25, 2018 4:43 pm

I experimented with building a kernel side SPI driver a while ago for https://github.com/juj/fbcp-ili9341. The test code still exists at https://github.com/juj/fbcp-ili9341/tree/master/kernel , although will not build out of the box anymore, since I abandoned the approach.

Perhaps you may find it useful for reference. If you look into git history of that repository, you may be able to find a time in the past where it still built.

The reason that I abandoned using a SPI kernel module is that using interrupt based communication for SPI turned out to be too heavy weight for a Pi Zero to handle at high SPI bus speeds. If there is a lot of data to transmit, and the SPI bus speed is relatively high (> 40 MHz gut estimate), the SPI interrupts will fire too often that the overhead of entering and exiting the interrupt handler in Linux will be too heavy that the Pi has little time for other realtime tasks. In my case I needed to have smooth audio playback happen at the same time, and was not able to get enough breathing time for that.

It is possible that one might be able to optimize interrupt handling from the version I used, perhaps my approach was not fast enough or had a performance bug. Although this is still an aspect worth keeping in mind if you need to do really fast transfers while keeping CPU usage % low.

But using interrupts in conjunction with DMA will be a super smooth approach, so for low CPU usage, that's definitely the direction to look at.

gunahmt
Posts: 15
Joined: Mon Jun 25, 2018 12:31 pm
Location: Turkey

Re: Spi Kernel Module

Wed Aug 01, 2018 9:44 am

Thank you :o :)

Return to “C/C++”

Who is online

Users browsing this forum: No registered users and 5 guests