Firefly开源社区

123
发表新贴
打印 上一主题 下一主题

《小试》根据cpu温度控制风扇转速

1225

积分

1

威望

3

贡献

中级创客

Rank: 4

积分
1225
QQ

《小试》根据cpu温度控制风扇转速

发表于 2015-5-12 14:15:01      浏览:45755 | 回复:27        打印      只看该作者   [复制链接] 楼主
本帖最后由 madman 于 2015-5-12 14:15 编辑

    之前刚拿到的板,搭建好基本的环境之后就想着进一步学习一下,不过限于初学者能力有限,不知道做什么好。后面在论坛乱逛无意间看到一个根据cpu温度控制风扇开关的应用,觉得挺有意思的。不过这个应用只是测到温度使用io口控制开关。然后我就想着使用pwm达到平时我们电脑散热风扇的那种效果,然后以此对驱动进行学习。然后就有下面那么个东西~~
    首先我使用的是官方默认板的Android SDK ,然后对它进行了编译。其后我主要是修改了kernel中原来的驱动,然后给上层留了个接口作为开关,测量温度和控制pwm都在驱动中完成了。额。。还有就是原带的风扇是不带pwm的接口的,这也让我郁闷了下,然后使用了个简单的三极管开关电路把pwm接口加了进去。然后根据之前看到的帖子,我们可以cat板子上的sys/class/hwmon/hwmon0/device/temp0_input,然后它就会打印出温度。根据这个文件夹我找到了它对应的驱动,在sdk里的kernel/drivers/hwmon/rockchip-hwmon.c里。然后我就对rockchip-hwmon.c这个驱动进行了小小的添加。这个驱动里上层的接口函数是show_input,然后我复制了这个函数并把它的return buf部分去掉,然后把他定义成了外部函数,这样就可以在别的驱动里调用它读取温度。至于pwm,我是在原来的背光pwm里修改的。背光驱动在kernel/drivers/video/backlight/pwm_bl.c上。首先这是背光的dts,添加进kernel/ arch/arm/boot/dts/rk3288.dtsi里面就可以了

backlight {
          compatible = "pwm-backlight";
          pwms = <&pwm1 0 10000>;//0 10000
          rockchip,pwm_id= <1>;
          brightness-levels = <214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 179 178 177 176 175 174 173 172 171 170>;
          default-brightness-level = <180>;//180
          enable-gpios = <&gpio8 GPIO_A6 GPIO_ACTIVE_HIGH>;
      };
至于控制pwm占空比使用的是这个函数pwm_config(&w_pwm, 1000, 10000);至于功能的实现我使用了一个线程在线程里每隔一秒读取一次温度然后调整对应的pwm。原来使用的是定时器,然后发现定时器不能带参数,带了就崩溃~_~..最后使用proc_create创建了个简单的读写接口给上层调用控制开和关。
    好吧,大概就是这样,也不罗嗦了,下面是相关的图和部分代码
rockchip-hwmon.c
extern int show_input_pwm(struct device *dev,
              struct device_attribute *devattr)//显示温度功能的实现
{
    int  temp;
    struct rockchip_temp *data = dev_get_drvdata(dev);//获取数据
    struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
    u8 tsadc_addr = data->tsadc_addr[attr->index];

    temp = data->ops.read_sensor(tsadc_addr);

    hwmon_cpu_wendu = temp;
    return 0;
}
extern void show_cpu(void)
{
    show_input_pwm(&(fpdev->dev),&sensor_dev_attr_temp0_input.dev_attr);
}
pwm_bl.c
int func(void* data)  
{  
    int high_pwm;
      while(1)  
    {  
            if( kthread_should_stop())  return -1;  
        show_cpu();
        printk("%d\n",hwmon_cpu_wendu);

        if(hwmon_cpu_wendu > 0 )
        {   
            if(hwmon_cpu_wendu <= 40)
                pwm_config(&w_pwm, 100, 10000);
            else if((hwmon_cpu_wendu>40)||(hwmon_cpu_wendu<80))
            {
                high_pwm = hwmon_cpu_wendu*125;
                pwm_config(&w_pwm, high_pwm, 10000);
            }   
            else if(hwmon_cpu_wendu >= 80)
                pwm_config(&w_pwm, 9800, 10000);
        }
   
        
           printk(KERN_ALERT "func running\n");  

            set_current_state(TASK_UNINTERRUPTIBLE); //设置进程的状态
              schedule_timeout(1*HZ);  //在指定的时间到期后(timeout了)将进程唤醒
        if(out_pthread == 1)//退出
        {
            pwm_config(&w_pwm, 100, 10000);
            break;
        }
      }   
      return 0;  
}
probe里:
       proc_create("pwm",0666,NULL,&proc_fops);
       msg=kmalloc(GFP_KERNEL,FANBUFSIZE*sizeof(char));
       w_pwm = *(pb->pwm);
       mytask=kthread_create(func,0,"mykthread");  
       wake_up_process(mytask);


之后的话进一步会将pwm的驱动从背光里单独拿出来,做成一个单独的驱动
pwm.zip (14.44 KB, 下载次数: 106)


QQ截图20150512140911.png (791.33 KB, 下载次数: 1608)

QQ截图20150512140911.png
回复

使用道具 举报

2918

积分

56

威望

46

贡献

高级创客

Rank: 6Rank: 6

积分
2918

优秀版主论坛元老

发表于 2015-5-12 14:33:46        只看该作者  沙发
赞一个:)
回复

使用道具 举报

215

积分

0

威望

0

贡献

超级版主

Rank: 8Rank: 8

积分
215

最佳新人活跃会员热心会员推广达人宣传达人灌水之王突出贡献优秀版主荣誉管理论坛元老

发表于 2015-5-12 15:34:51        只看该作者  板凳
支持原创
回复

使用道具 举报

1225

积分

1

威望

3

贡献

中级创客

Rank: 4

积分
1225
QQ
发表于 2015-5-13 11:11:47        只看该作者  地板
经过进一步的修改,已经把程序的功能从背光当中单独抽取了出来,相对应的dts如下,然后把线程读取温度控制pwm改成了工作队列的方式实现

static void work_timer_function(int para)
{
        if(schedule_work(&work_work_q) == 0)//调度执行一个具体的任务
    {
            printk("<0> cannot schedule work !!!\n");
        }
        counter++;
}

static void work_timer_register(struct timer_list* ptimer)
{
        init_timer(&work_timer);
        work_timer.data = 250;
        work_timer.expires = jiffies + 50;
        work_timer.function = work_timer_function;
        add_timer(&work_timer);
}


static void work_fectch_thread(struct work_struct *work)
{
    int high_pwm;
    if((out_thread == 0)||(out_thread == 2))
    {
        if(out_thread == 2)
            pwm_enable(&w_pwm);
            show_cpu();
           printk("wendu: %d\n",hwmon_cpu_wendu);
            if(hwmon_cpu_wendu > 0 )
        {   
            if(hwmon_cpu_wendu <= 40)
                pwm_config(&w_pwm, 10, 10000);
            else if((hwmon_cpu_wendu>40)||(hwmon_cpu_wendu<80))
            {
                high_pwm = hwmon_cpu_wendu*125;
                if(high_pwm <= 10000)
                    pwm_config(&w_pwm, high_pwm, 10000);
            }   
            else if(hwmon_cpu_wendu >= 80)
                pwm_config(&w_pwm, 9999, 10000);
        }
   
    }
    else if(out_thread == 1)
    {
        pwm_config(&w_pwm, 0, 10000);
        pwm_disable(&w_pwm);
        del_timer(&work_timer);   
    }
    work_timer_register(&work_timer);
}


dts
   backlight {
          compatible = "pwm-backlight";
          pwms = <&pwm1 0 10000>;//0 10000
          rockchip,pwm_id= <1>;
      };

probe
    work_timer_register(&work_timer);
        //初始化工作队列并将工作队列与处理函数绑定
        INIT_WORK(&work_work_q,work_fectch_thread);
pwm_bl.c.zip (2.28 KB, 下载次数: 93)


回复

使用道具 举报

9

积分

0

威望

0

贡献

技术小白

积分
9
发表于 2015-5-17 22:13:41        只看该作者  5#
显示show-cpu函数定义不对呀
回复

使用道具 举报

1225

积分

1

威望

3

贡献

中级创客

Rank: 4

积分
1225
QQ
发表于 2015-5-18 09:00:25        只看该作者  6#
zhang1984 发表于 2015-5-17 22:13
显示show-cpu函数定义不对呀

额。。怎么不对法?这函数调用的时候去读取一次cpu温度值,使得变量hwmon_cpu_wendu 更新为当前温度。
回复

使用道具 举报

9

积分

0

威望

0

贡献

技术小白

积分
9
发表于 2015-5-18 13:00:48        只看该作者  7#
显示 “rk_headset_irq_hoot_adc.c(.text+142bc):undefined to 'show_cpu'”
回复

使用道具 举报

1225

积分

1

威望

3

贡献

中级创客

Rank: 4

积分
1225
QQ
发表于 2015-5-18 14:17:29        只看该作者  8#
zhang1984 发表于 2015-5-18 13:00
显示 “rk_headset_irq_hoot_adc.c(.text+142bc):undefined to 'show_cpu'”

你只是在rockchip-hwmon.c修改,没有在pwm声明的话就会出现这样的错误,我好像之前也试过。
回复

使用道具 举报

9

积分

0

威望

0

贡献

技术小白

积分
9
发表于 2015-5-18 14:29:40        只看该作者  9#
我下在的文件,没有做任何修改,直接替换的, 我的qq361899636加一下好向你请教
回复

使用道具 举报

1225

积分

1

威望

3

贡献

中级创客

Rank: 4

积分
1225
QQ
发表于 2015-5-18 15:02:45        只看该作者  10#
zhang1984 发表于 2015-5-18 14:29
我下在的文件,没有做任何修改,直接替换的, 我的qq361899636加一下好向你请教

ok
回复

使用道具 举报

返回列表
123
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表