2012-08-27 3 views
1

Gumstix Overo Fire 용 Angstrom Linux 2.6.36 용 SPI 드라이버를 작성하려고합니다. 내 드라이버가 인터럽트 처리기에서 계속 충돌합니다. 내가이 선 모든 것이 잘 실행하지만 물론 데이터가 SPI에서 읽을하지 주석 경우 다음 인터럽트 핸들러가 라인Linux SPI 드라이버 문제집

status = spi_async(spike_dev.spi_device, &spike_ctl.msg); 

에 충돌 전체 코드

#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/ioctl.h> 
#include <linux/fs.h> 
#include <linux/device.h> 
#include <linux/err.h> 
#include <linux/errno.h> 
#include <linux/mutex.h> 
#include <linux/slab.h> 
#include <linux/smp_lock.h> 
#include <linux/cdev.h> 
#include <linux/spi/spi.h> 
#include <linux/string.h> 
#include <asm/uaccess.h> 
#include <linux/kernel.h> 
#include <mach/gpio.h> 
#include <linux/interrupt.h> 
#include <linux/delay.h> 
#include <linux/kthread.h> 
#include <linux/hrtimer.h> 

#define IRQ_PIN 10 

#define SPI_BUFF_SIZE 4 
#define USER_BUFF_SIZE 128 

#define SPI_BUS 1 
#define SPI_BUS_CS1 1 
#define SPI_BUS_SPEED 1500000 

unsigned char *buff_even = 0; 
unsigned char *buff_odd = 0; 
unsigned char *temp_buff = 0; 
unsigned int sample_counter = 0; 
unsigned int buff_counter = 0; 
unsigned int current_buffer = 0; 
unsigned int local_current_buffer = 0; 
unsigned int local_sample_counter = 0; 
unsigned int num_reads = 0; 
unsigned int num_miss_samples = 0; 
unsigned int regval = 0; 

#define LIMIT (4000) 
#define BUFF_SIZE (4*LIMIT) 

#define MAJOR_NUM 100 
#define READ_CURR_COUNTER _IOWR(MAJOR_NUM, 1, int) 
#define READ_BUFF  _IOWR(MAJOR_NUM, 2, int) 
#define READ_CURR_BUFF_NO _IOWR(MAJOR_NUM, 3, int) 
#define READ_REGISTER _IOWR(MAJOR_NUM, 4, unsigned char) 
#define WRITE_REGISTER _IOWR(MAJOR_NUM, 5, int) 
#define START_READ _IOWR(MAJOR_NUM, 6, int) 
#define STOP_READ _IOWR(MAJOR_NUM, 7, int) 

const char this_driver_name[] = "adc"; 

static int running = 0; 
static int resetting = 0; 
static int reading = 0; 

struct spike_control 
{ 
    struct spi_message msg; 
    struct spi_transfer transfer; 
    u8 *tx_buff; 
    u8 *rx_buff; 
}; 

static struct spike_control spike_ctl; 

struct spike_dev 
{ 
    struct semaphore spi_sem; 
    struct semaphore fop_sem; 
    dev_t devt; 
    struct cdev cdev; 
    struct class *class; 
    struct spi_device *spi_device; 
    char *user_buff; 
    u8 test_data; 
    int irq;  
}; 

static struct spike_dev spike_dev; 

static DEFINE_MUTEX(list_lock); 
static DEFINE_MUTEX(count_lock); 

static int status; 

static void spike_completion_handler(void *arg) 
{ 
    local_sample_counter++; 

    if (sample_counter >= local_sample_counter + 1) 
     num_miss_samples++; 

    if (current_buffer == 0) 
    { 
     buff_even[buff_counter++] = spike_ctl.rx_buff[0]; 
     buff_even[buff_counter++] = spike_ctl.rx_buff[1]; 
     buff_even[buff_counter++] = spike_ctl.rx_buff[2]; 
     buff_even[buff_counter++] = spike_ctl.rx_buff[3]; 
    } 
    else if (current_buffer == 1) 
    { 
     buff_odd[buff_counter++] = spike_ctl.rx_buff[0]; 
     buff_odd[buff_counter++] = spike_ctl.rx_buff[1]; 
     buff_odd[buff_counter++] = spike_ctl.rx_buff[2]; 
     buff_odd[buff_counter++] = spike_ctl.rx_buff[3]; 
    } 

    memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); 

    if (sample_counter == LIMIT) 
    { 
     buff_counter = 0; 
     mutex_lock(&count_lock); 
     if (current_buffer == 0) 
      current_buffer = 1; 
     else 
      current_buffer = 0; 
     sample_counter = 0; 
     mutex_unlock(&count_lock); 
     local_sample_counter = 0; 
    } 

} 

static irqreturn_t adc_handler(int irq, void *dev_id) 
{ 
    sample_counter++; 

    spi_message_init(&spike_ctl.msg); 

    spike_ctl.msg.complete = spike_completion_handler; 
    spike_ctl.msg.context = NULL; 

    spike_ctl.transfer.tx_buf = NULL; 
    spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; 
    spike_ctl.transfer.len = 4; 

    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_async(spike_dev.spi_device, &spike_ctl.msg); 

    return IRQ_HANDLED; 
} 

static void resetbuffers(void) 
{ 
    local_sample_counter = 0; 
    sample_counter = 0; 
    num_miss_samples = 0; 
    current_buffer = 0; 
    buff_counter = 0; 
    memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); 
    memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); 
    memset(buff_even, 0, BUFF_SIZE); 
    memset(buff_odd, 0, BUFF_SIZE); 
    memset(temp_buff, 0, BUFF_SIZE); 
} 

static int read_register(unsigned char addr) 
{ 
    if (down_interruptible(&spike_dev.spi_sem)) 
     return -ERESTARTSYS; 

    if (!spike_dev.spi_device) 
    { 
     up(&spike_dev.spi_sem); 
     return -ENODEV; 
    } 

    memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); 
    memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); 

    spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; 
    spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; 
    spike_ctl.transfer.len = 1; 

    spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP1:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP1\n\t"); 

    spike_ctl.tx_buff[0] = 0x20 + addr;//Address of register 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP2:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP2\n\t"); 

    spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP3:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP3\n\t"); 

    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP4:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP4\n\t"); 

    printk(KERN_ALERT "%x\n",spike_ctl.rx_buff[0]); 
    regval = spike_ctl.rx_buff[0]; 

// spike_ctl.tx_buff[0] = 0x10;//Start read data continuous 
// spi_message_init(&spike_ctl.msg); 
// spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
// status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 

    up(&spike_dev.spi_sem); 

    return status; 
} 

static int write_register(unsigned char addr, unsigned char val) 
{ 
    if (down_interruptible(&spike_dev.spi_sem)) 
     return -ERESTARTSYS; 

    if (!spike_dev.spi_device) 
    { 
     up(&spike_dev.spi_sem); 
     return -ENODEV; 
    } 

    memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); 
    memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); 

    spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; 
    spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; 
    spike_ctl.transfer.len = 1; 

    spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP5:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP5\n\t"); 

    spike_ctl.tx_buff[0] = 0x40 + addr;//Address of register 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP6:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP6\n\t"); 

    spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP7:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP7\n\t"); 

    spike_ctl.tx_buff[0] = val;//Value to write 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 
    __asm__ __volatile__("ldr r0,=0x2710\n\t" 
         ".LOOP8:\n\t" 
         "subs r0,r0,#1\n\t" 
         "bne .LOOP8\n\t"); 

    spike_ctl.tx_buff[0] = 0x10;//Start read data continuous 
    spi_message_init(&spike_ctl.msg); 
    spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
    status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 

// spike_ctl.tx_buff[0] = 0x10;//Start read data continuous 
// spi_message_init(&spike_ctl.msg); 
// spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); 
// status = spi_sync(spike_dev.spi_device, &spike_ctl.msg); 

    up(&spike_dev.spi_sem); 

    return status; 
} 

static long adc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
{ 
    unsigned char addr; 
    switch(cmd) 
    { 
    case READ_CURR_COUNTER: 
     mutex_lock(&count_lock); 
     local_current_buffer = current_buffer; 
     local_sample_counter = sample_counter; 
     mutex_unlock(&count_lock); 
     copy_to_user((void *)arg, &local_sample_counter, sizeof(unsigned int)); 
     printk(KERN_ALERT "Read current counter %d\n",local_sample_counter); 
     break; 
    case READ_BUFF: 
     mutex_lock(&count_lock); 
     local_current_buffer = current_buffer; 
     local_sample_counter = sample_counter; 
     mutex_unlock(&count_lock); 
     if (local_current_buffer == 0) 
     { 
      memcpy(temp_buff,buff_odd, BUFF_SIZE); 
//   memset(temp_buff, 'Q', BUFF_SIZE);   
     } 
     else 
     { 
      memcpy(temp_buff,buff_even, BUFF_SIZE); 
//   memset(temp_buff, 'T', BUFF_SIZE);   
     } 
     copy_to_user((void *)arg, temp_buff, BUFF_SIZE); 
     num_reads++; 
     break; 
    case READ_CURR_BUFF_NO: 
     mutex_lock(&count_lock); 
     local_current_buffer = current_buffer; 
     local_sample_counter = sample_counter; 
     mutex_unlock(&count_lock); 
     copy_to_user((void *)arg, &local_current_buffer, sizeof(int)); 
     break; 
    case READ_REGISTER: 
     get_user(addr, (unsigned char *)arg); 
     disable_irq(spike_dev.irq); 
     read_register(addr); 
     enable_irq(spike_dev.irq); 
     copy_to_user((void *)arg, &regval, sizeof(int)); 
     break; 
    case WRITE_REGISTER:  
     disable_irq(spike_dev.irq); 

     enable_irq(spike_dev.irq); 
     //copy_to_user((void *)arg, &local_current_buffer, sizeof(int)); 
     break; 

    default: 
     return -ENOTTY; 
    } 
    return 1; 

} 

static int spike_open(struct inode *inode, struct file *filp) 
{ 
    int status = 0; 

    if (down_interruptible(&spike_dev.fop_sem)) 
     return -ERESTARTSYS; 

    if (!spike_dev.user_buff) { 
     spike_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL); 
     if (!spike_dev.user_buff) 
      status = -ENOMEM; 
    } 

    up(&spike_dev.fop_sem); 

    return status; 
} 

static int spike_probe(struct spi_device *spi_device) 
{ 
    if (down_interruptible(&spike_dev.spi_sem)) 
     return -EBUSY; 

    spike_dev.spi_device = spi_device; 

    printk(KERN_ALERT "SPI[%d] max_speed_hz %d Hz\n", spi_device->chip_select, spi_device->max_speed_hz); 

    up(&spike_dev.spi_sem); 

    return 0; 
} 

static int spike_remove(struct spi_device *spi_device) 
{ 
    if (down_interruptible(&spike_dev.spi_sem)) 
     return -EBUSY; 

    spike_dev.spi_device = NULL; 

    up(&spike_dev.spi_sem); 

    return 0; 
} 

static int __init add_spike_device_to_bus(void) 
{ 
    struct spi_master *spi_master; 
    struct spi_device *spi_device; 
    struct device *pdev; 
    char buff[64]; 
    int status = 0; 

    spi_master = spi_busnum_to_master(SPI_BUS); 
    if (!spi_master) 
    { 
     printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n", 
      SPI_BUS); 
     printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n"); 
     return -1; 
    } 

    spi_device = spi_alloc_device(spi_master); 
    if (!spi_device) 
    { 
     put_device(&spi_master->dev); 
     printk(KERN_ALERT "spi_alloc_device() failed\n"); 
     return -1; 
    } 

    spi_device->chip_select = SPI_BUS_CS1; 

    /* Check whether this SPI bus.cs is already claimed */ 
    snprintf(buff, sizeof(buff), "%s.%u", 
      dev_name(&spi_device->master->dev), 
      spi_device->chip_select); 

    pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff); 
    if (pdev) 
    { 
     /* We are not going to use this spi_device, so free it */ 
     spi_dev_put(spi_device); 

     /* 
     * There is already a device configured for this bus.cs 
     * It is okay if it us, otherwise complain and fail. 
     */ 
     if (pdev->driver && pdev->driver->name && strcmp(this_driver_name, pdev->driver->name)) 
     { 
      printk(KERN_ALERT 
       "Driver [%s] already registered for %s\n", 
       pdev->driver->name, buff); 
      status = -1; 
     } 
    } 
    else 
    { 
     spi_device->max_speed_hz = SPI_BUS_SPEED; 
     spi_device->mode = SPI_MODE_0; 
     spi_device->bits_per_word = 8; 
     spi_device->irq = -1; 
     spi_device->controller_state = NULL; 
     spi_device->controller_data = NULL; 
     strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE); 

     status = spi_add_device(spi_device);   
     if (status < 0) 
     { 
      spi_dev_put(spi_device); 
      printk(KERN_ALERT "spi_add_device() failed: %d\n", 
       status);   
     }    
    } 

    put_device(&spi_master->dev); 

    return status; 
} 

static struct spi_driver spike_driver = { 
    .driver = { 
     .name = this_driver_name, 
     .owner = THIS_MODULE, 
    }, 
    .probe = spike_probe, 
    .remove = __devexit_p(spike_remove),  
}; 

static int __init spike_init_spi(void) 
{ 
    int error; 

    spike_ctl.tx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); 
    if (!spike_ctl.tx_buff) 
    { 
     error = -ENOMEM; 
     goto spike_init_error; 
    } 

    spike_ctl.rx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); 
    if (!spike_ctl.rx_buff) 
    { 
     error = -ENOMEM; 
     goto spike_init_error; 
    } 

    error = spi_register_driver(&spike_driver); 
    if (error < 0) 
    { 
     printk(KERN_ALERT "spi_register_driver() failed %d\n", error); 
     goto spike_init_error; 
    } 

    error = add_spike_device_to_bus(); 
    if (error < 0) 
    { 
     printk(KERN_ALERT "add_spike_to_bus() failed\n"); 
     spi_unregister_driver(&spike_driver); 
     goto spike_init_error; 
    } 

    spike_dev.irq = OMAP_GPIO_IRQ(IRQ_PIN); 

    return 0; 

spike_init_error: 

    if (spike_ctl.tx_buff) { 
     kfree(spike_ctl.tx_buff); 
     spike_ctl.tx_buff = 0; 
    } 

    if (spike_ctl.rx_buff) { 
     kfree(spike_ctl.rx_buff); 
     spike_ctl.rx_buff = 0; 
    } 

    return error; 
} 

static ssize_t spike_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) 
{ 
    size_t len; 
    ssize_t status = 0; 

    if (!buff) 
     return -EFAULT; 

    if (*offp > 0) 
     return 0; 

    if (down_interruptible(&spike_dev.fop_sem)) 
     return -ERESTARTSYS; 

    printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples); 

    up(&spike_dev.fop_sem); 

    return status; 
} 

static ssize_t spike_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos) 
{ 
    size_t len; 
    ssize_t status = 0; 

    if (down_interruptible(&spike_dev.fop_sem)) 
     return -ERESTARTSYS; 

    memset(spike_dev.user_buff, 0, 16); 
    len = count > 8 ? 8 : count; 

    if (copy_from_user(spike_dev.user_buff, buff, len)) 
    { 
     status = -EFAULT; 
     goto spike_write_done; 
    } 

    /* we'll act as if we looked at all the data */ 
    status = count; 

    /* but we only care about the first 5 characters */ 
    if (!strnicmp(spike_dev.user_buff, "inc", 3)) 
    { 
     disable_irq(spike_dev.irq); 
     write_register(1,0x62); 
     resetbuffers(); 
     printk(KERN_ALERT "4000 samples per second\n"); 
     enable_irq(spike_dev.irq); 
    } 

    if (!strnicmp(spike_dev.user_buff, "dec", 3)) 
    { 
     disable_irq(spike_dev.irq); 
     write_register(1,0x52); 
     resetbuffers(); 
     printk(KERN_ALERT "1000 samples per second\n"); 
     enable_irq(spike_dev.irq); 
    } 

    if (!strnicmp(spike_dev.user_buff, "stop", 4)) 
    { 
     disable_irq(spike_dev.irq); 
     resetbuffers(); 
     printk(KERN_ALERT "Driver stopped\n"); 
    } 

spike_write_done: 

    up(&spike_dev.fop_sem); 

    return status; 
} 

static const struct file_operations spike_fops = { 
    .owner   = THIS_MODULE, 
    .open   = spike_open, 
    .read   = spike_read, 
    .write   = spike_write, 
    .unlocked_ioctl = adc_ioctl,  
}; 

static int __init spike_init_cdev(void) 
{ 
    int error; 

    spike_dev.devt = MKDEV(0, 0); 

    error = alloc_chrdev_region(&spike_dev.devt, 0, 1, this_driver_name); 
    if (error < 0) 
    { 
     printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n", 
      error); 
     return -1; 
    } 

    cdev_init(&spike_dev.cdev, &spike_fops); 
    spike_dev.cdev.owner = THIS_MODULE; 

    error = cdev_add(&spike_dev.cdev, spike_dev.devt, 1); 
    if (error) 
    { 
     printk(KERN_ALERT "cdev_add() failed: %d\n", error); 
     unregister_chrdev_region(spike_dev.devt, 1); 
     return -1; 
    } 

    return 0; 
} 

static int __init spike_init_class(void) 
{ 
    spike_dev.class = class_create(THIS_MODULE, this_driver_name); 

    if (!spike_dev.class) 
    { 
     printk(KERN_ALERT "class_create() failed\n"); 
     return -1; 
    } 

    if (!device_create(spike_dev.class, NULL, spike_dev.devt, NULL, this_driver_name)) 
    { 
     printk(KERN_ALERT "device_create(..., %s) failed\n", 
      this_driver_name); 
     class_destroy(spike_dev.class); 
     return -1; 
    } 

    return 0; 
} 

static int __init spike_init(void) 
{ 

    int result; 
    memset(&spike_dev, 0, sizeof(spike_dev)); 
    memset(&spike_ctl, 0, sizeof(spike_ctl)); 

    sema_init(&spike_dev.spi_sem, 1); 
    sema_init(&spike_dev.fop_sem, 1); 

    buff_even = kmalloc(BUFF_SIZE, GFP_KERNEL); 
    buff_odd = kmalloc(BUFF_SIZE, GFP_KERNEL); 
    temp_buff = kmalloc(BUFF_SIZE, GFP_KERNEL); 

    if (buff_even == 0) 
     printk(KERN_ALERT "Failed to allocate buffer even\n"); 

    if (buff_odd == 0) 
     printk(KERN_ALERT "Failed to allocate buffer odd\n"); 

    if (temp_buff == 0) 
     printk(KERN_ALERT "Failed to temp buffer\n"); 

    if (spike_init_cdev() < 0) 
     goto fail_1; 

    if (spike_init_class() < 0) 
     goto fail_2; 

    if (spike_init_spi() < 0) 
     goto fail_3; 

    result = request_irq(spike_dev.irq, adc_handler, IRQF_TRIGGER_RISING, "adc", &spike_dev); 

    if (result < 0) 
    { 
       printk(KERN_ALERT "request_irq failed: %d\n", result); 
       return -1; 
    } 

    return 0; 

fail_3: 
    device_destroy(spike_dev.class, spike_dev.devt); 
    class_destroy(spike_dev.class); 

fail_2: 
    cdev_del(&spike_dev.cdev); 
    unregister_chrdev_region(spike_dev.devt, 1); 

fail_1: 
    return -1; 
} 
module_init(spike_init); 

static void __exit spike_exit(void) 
{ 

    disable_irq(spike_dev.irq); 
    free_irq(spike_dev.irq, &spike_dev); 
    gpio_free(IRQ_PIN); 

    spi_unregister_device(spike_dev.spi_device); 
    spi_unregister_driver(&spike_driver); 

    device_destroy(spike_dev.class, spike_dev.devt); 
    class_destroy(spike_dev.class); 

    cdev_del(&spike_dev.cdev); 
    unregister_chrdev_region(spike_dev.devt, 1); 

    if (spike_ctl.tx_buff) 
     kfree(spike_ctl.tx_buff); 

    if (spike_ctl.rx_buff) 
     kfree(spike_ctl.rx_buff); 

    if (spike_dev.user_buff) 
     kfree(spike_dev.user_buff); 

    if (buff_even != 0) 
     kfree(buff_even); 

    if (buff_odd != 0) 
     kfree(buff_odd); 

    if (temp_buff != 0) 
     kfree(temp_buff); 

    printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples); 

} 
module_exit(spike_exit); 

입니다.

답변

1

무하마드, 아마도이 문제는 시간에 따라 해결했을 것입니다.

그러나 내가 본 것은 잠을 잘 수없는 상황에서 실행되는 SPI 완료 핸들러 (spike_completion_handler)에서 뮤텍스를 사용하고 있다는 것입니다. 따라서 대신 스핀 록을 사용하는 것이 좋습니다. count_lock은 항상 잠자기 상태가 아닌 코드를 보호하기 때문에 안전합니다.

문제의 원인이 아닐 수도 있지만 (전체 코드를 읽지는 않았 음)이 방법을 사용하는 것이 좋습니다.

관련 문제