天嵌 ARM开发社区

 找回密码
 注册
查看: 3044|回复: 4

温度传感器驱动不能加载(附源码,错误报告),请教高人指点!

[复制链接]
jjkwzy 发表于 2009-7-28 13:58:00 | 显示全部楼层 |阅读模式
/************************* s3c2440_ds18b20.c文件开始 **************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>

typedef unsigned char BYTE;

#define DS18B20_PIN   S3C2410_GPB1
#define DS18B20_PIN_OUTP S3C2410_GPB1_OUTP
#define DS18B20_PIN_INP   S3C2410_GPB1_INP
#define HIGH 1
#define LOW 0
#define DEV_NAME "DS18B20"
#define DEV_MAJOR 232
static BYTE data[2];

// DS18B20复位函数
BYTE DS18b20_reset (void)
{
    // 配置GPIOB0输出模式
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
   
    // 向18B20发送一个上升沿,并保持高电平状态约100微秒
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
    udelay(100);
   
    // 向18B20发送一个下降沿,并保持低电平状态约600微秒
    s3c2410_gpio_setpin(DS18B20_PIN, LOW);
    udelay(600);
   
    // 向18B20发送一个上升沿,此时可释放DS18B20总线
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
    udelay(100);
   
    // 以上动作是给DS18B20一个复位脉冲
    // 通过再次配置GPIOB1引脚成输入状态,可以检测到DS18B20是否复位成功
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);
   
    // 若总线在释放后总线状态为高电平,则复位失败
    if(s3c2410_gpio_getpin(DS18B20_PIN)){ printk("DS18b20 reset failed.\r\n"); return 1;}

    return 0;
}


void DS18b20_write_byte (BYTE byte)
{
    BYTE i;
    // 配置GPIOB1为输出模式
    s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);

    // 写“1”时隙:
    //     保持总线在低电平1微秒到15微秒之间
    //     然后再保持总线在高电平15微秒到60微秒之间
    //     理想状态: 1微秒的低电平然后跳变再保持60微秒的高电平
    //
    // 写“0”时隙:
    //     保持总线在低电平15微秒到60微秒之间
    //     然后再保持总线在高电平1微秒到15微秒之间
    //     理想状态: 60微秒的低电平然后跳变再保持1微秒的高电平
    for (i = 0; i < 8; i++)
    {
        s3c2410_gpio_setpin(DS18B20_PIN, LOW); udelay(1);
        if(byte & HIGH)
        {
             // 若byte变量的D0位是1,则需向总线上写“1”
             // 根据写“1”时隙规则,电平在此处翻转为高
             s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        }
        else
        {
             // 若byte变量的D0位是0,则需向总线上写“0”
             // 根据写“0”时隙规则,电平在保持为低
             // s3c2410_gpio_setpin(DS18B20_PIN, LOW);
        }
        // 电平状态保持60微秒
        udelay(60);

        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        udelay(15);

        byte >>= 1;
    }
    s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
}

BYTE DS18b20_read_byte (void)
{
    BYTE i = 0;
    BYTE byte = 0;
    // 读“1”时隙:
    //     若总线状态保持在低电平状态1微秒到15微秒之间
    //     然后跳变到高电平状态且保持在15微秒到60微秒之间
    //      就认为从DS18B20读到一个“1”信号
    //     理想情况: 1微秒的低电平然后跳变再保持60微秒的高电平
    //
    // 读“0”时隙:
    //     若总线状态保持在低电平状态15微秒到30微秒之间
    //     然后跳变到高电平状态且保持在15微秒到60微秒之间
    //     就认为从DS18B20读到一个“0”信号
    //     理想情况: 15微秒的低电平然后跳变再保持46微秒的高电平
    for (i = 0; i < 8; i++)
    {
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_OUTP);
        s3c2410_gpio_setpin(DS18B20_PIN, LOW);

        udelay(1);
        byte >>= 1;

        s3c2410_gpio_setpin(DS18B20_PIN, HIGH);
        s3c2410_gpio_cfgpin(DS18B20_PIN, DS18B20_PIN_INP);

        // 若总线在我们设它为低电平之后若1微秒之内变为高
        // 则认为从DS18B20处收到一个“1”信号
        // 因此把byte的D7为置“1”
        if (s3c2410_gpio_getpin(DS18B20_PIN)) byte |= 0x80;
        udelay(60);
    }
    return byte;      
}

void DS18b20_proc(void)         
{
    while(DS18b20_reset());
   
    udelay(120);
   
    DS18b20_write_byte(0xcc);
    DS18b20_write_byte(0x44);
   
    udelay(5);
   
    while(DS18b20_reset());
    udelay(200);
   
    DS18b20_write_byte(0xcc);
    DS18b20_write_byte(0xbe);
   
    data[0] = DS18b20_read_byte();
    data[1] = DS18b20_read_byte();
}

static ssize_t s3c2440_18b20_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
    DS18b20_proc();

    buf[0] = data[0];
    buf[1] = data[1];
   
    return 1;
}

static struct file_operations s3c2440_18b20_fops =
{
    .owner = THIS_MODULE,
    .read = s3c2440_18b20_read,
};

static int __init s3c2440_18b20_init(void)
{
    if (register_chrdev(DEV_MAJOR, DEV_NAME, &s3c2440_18b20_fops) < 0)
    {
        printk(DEV_NAME ": Register major failed.\r\n");
        return -1;
    }
   
    devfs_mk_cdev(MKDEV(DEV_MAJOR, 0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEV_NAME);
   
    while(DS18b20_reset());   
}

static void __exit s3c2440_18b20_exit(void)
{
    devfs_remove(DEV_NAME);
    unregister_chrdev(DEV_MAJOR, DEV_NAME);
}
module_init(s3c2440_18b20_init);
module_exit(s3c2440_18b20_exit);

/************************* s3c2440_ds18b20.c文件结束 **************************/




/************************* test_ds18b20.c文件开始 **************************/

#include "stdio.h"
#include "sys/types.h"
#include "sys/ioctl.h"
#include "stdlib.h"
#include "termios.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "sys/time.h"

main()
{
    int fd;
    unsigned char buf[2];
    float result;

    if ((fd=open("/dev/DS18B20",O_RDWR | O_NDELAY | O_NOCTTY)) < 0)
    {
        printf("Open Device DS18B20 failed.\r\n");
        exit(1);
    }
    else
    {
        printf("Open Device DS18B20 successed.\r\n");
        while(1)
        {
            read(fd, buf, 1);
            result = (float)buf[0];
            result /= 16;
            result += ((float)buf[1] * 16);
     
            printf("%.1f `C\r\n", result);
            sleep(1);
        }
        close(fd);
    }
}

/************************* test_ds18b20.c文件结束 **************************/



/************************* Makefile文件开始 **************************/

obj-m := s3c2440_ds18b20.o

KERNELDIR ?= ../../kernel/linux-2.6.13
PWD := $(shell pwd)
CC := arm-linux-gcc
CLEAN := rm -rf


all : s3c2440_ds18b20.c test_ds18b20
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

test_ds18b20 : test_ds18b20.c
    $(CC) test_ds18b20.c -o test_ds18b20

clobber :
    $(CLEAN) test_ds18b20 s3c2440_ds18b20.ko
clean :
    $(CLEAN) *.mod.* *.o *~ modules.order Module.symvers

/************************* Makefile文件结束 **************************/

这是网上参考的程序,是用硬件平台是友善之臂的QQ2440,我的平台是qt2440,linux内核是linux-2.6.13,原作者的内核采用的是linux-2.6.29,我把程序make后,得到了test_ds18b20和s3c2440_ds18b20.ko这两个文件,启动开发板的Linux后,用ftp下载到开发板的/home/sky目录,把s3c2440_ds18b20这个模块加载到内核:

    insmod s3c2440_ds18b20.ko
出现的报错为
root@EmbedSky sky]# insmod s3c2440_ds18b20.ko
Module len 4238 truncated
insmod: cannot insert `s3c2440_ds18b20.ko': Invalid module format (-1): Exec format error

当执行./test_ds18b20的时候出现的报错为
[root@EmbedSky sky]# ./test_ds18b20
./test_ds18b20: error while loading shared libraries: ./test_ds18b20: unsupported version 256 of Verneed record
请教高手,这些报错是什么原因,怎么解决
 楼主| jjkwzy 发表于 2009-7-28 14:20:20 | 显示全部楼层
root@EmbedSky sky]# insmod s3c2440_ds18b20.ko
Module len 4238 truncated
insmod: cannot insert `s3c2440_ds18b20.ko': Invalid module format (-1): Exec format error
[root@EmbedSky sky]# ./test_ds18b20
./test_ds18b20: error while loading shared libraries: ./test_ds18b20: unsupported version 256 of Verneed record
亚瑟王 发表于 2009-7-28 23:55:14 | 显示全部楼层
2.6.13和2.6.29的内核结构有很多不同,移植驱动时需要注意很多的方便的,然后注册机制也有不同,这点也需要注意。
 楼主| jjkwzy 发表于 2009-7-29 18:43:53 | 显示全部楼层
管理员,能帮我说一下具体怎么改吗?
谢谢?
亚瑟王 发表于 2009-8-4 01:06:10 | 显示全部楼层
http://bbs.embedsky.net/viewthread.php?tid=630&extra=page%3D1
我们已经提供了Linux-2.6.30.4的内核了,你在这个上面移植了试试。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2024-9-29 07:42 , Processed in 1.030313 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表