i2c设备驱动程序。尝试发送数据时系统关闭

时间:2013-06-18 19:57:30

标签: c linux-kernel structure i2c

我试着编写i2c设备驱动程序,一切都很顺利:

  1. 设备检测成功
  2. sysfs类中的设备,也创建了value属性
  3. 然后我创建一个hrtimer并启动它
  4. 我正在尝试从属性的商店功能发送数据,并且工作正常
  5. 但是当我尝试从hrtimer回调函数发送数据时,我的系统会关闭。这是一些代码(我删除了incudes,定义和非重要代码):

    LED-indicator.h

    struct timer_job {
            ktime_t period;
            struct hrtimer timer;
            ...
    };
    
    struct ledindicator {
            struct i2c_client *client;
            struct device *device;
            struct timer_job job;
            int value;
    };
    

    LED-indicator.c

    include "led-indicator.h"
    static struct ledindicator *li;
    
    // device attribute [value] store function
    static ssize_t value_store(struct device *device, struct device_attribute *attr, const char *buffer, size_t count)
    {
        int val;
        kstrtoint(buffer, 10, &val);
        li->value = val;
        i2c_smbus_write_byte_data(li->client,  0xBA, 0x02); // this is work fine
        LOG("New value is %d \n", li->value);
        return count;
    }
    
    //timer callback, fire each timer_job.period
    static enum hrtimer_restart send_next(struct hrtimer * tim) {
        long start = jiffies;
        struct timer_job *job = container_of(tim, struct timer_job, timer);
        i2c_smbus_write_byte_data(li->client, 0xBA, 0x02); // this cause system fault
        hrtimer_forward_now(tim, job->period);
        return HRTIMER_RESTART;
    }
    
    //when device is detected I am create sysfs device and init timer. 
    enter code here//Also I am crate led_indicator structure and save i2c_client pointer for future use
    static int li_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
        int ret = 0;
        li = kmalloc(sizeof(*li), GFP_KERNEL);
        li->client = client;
        li->value = 0;
    
        ...
        // here creating device and attribute for it
        ...
    
        hrtimer_init(&(li->job.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    
        li->job.timer.function = send_next;
        li->job.period = ktime_set(1, 0); //1 sec
        hrtimer_start(&(li->job.timer), li->job.period, HRTIMER_MODE_REL);
    
        return ret;
    }
    

    有什么问题?

0 个答案:

没有答案