问题排查低版本内核驱动移植到高版本内核中编译报错,部分编译异常记录及解决(代码片段)

Evan_ZGYF丶 Evan_ZGYF丶     2022-10-20     262

关键词:

摘要:

将klsp移植到高版本内核中编译时,有可能会遇到一些编译报错。
原因一部分是因为新版本的内核加入了更多的代码检测,或者是打开了更多的代码检测选项,将以前的warning视为了error,
还有可能是因为内核之间的版本不兼容,有些函数已经被移除,或者是有些结构体成员发生变化...等等
这些都需要我们在移植的过程中去解决。
本文记录的是将klsp移植到4.19.90内核时,遇到的部分编译报错,及对应的解决办法。

【Makefile】

内核根目录下的Makefile内有很多的编译配置,有些时候我们可能需要关闭一部分的编译检查配置,以避免可能出现的编译报错。

报错:
    drivers/klsp/drivers/base/gpio_common.c:100:56: error: macro "__TIME__" might prevent reproducible builds [-Werror=date-time]
      GPIO_MSG("<%s, %d> %s\\n", __func__, __LINE__, __TIME__);
错误原因:
    新版本 gcc 编译包含 __DATE__ 或者 __TIME__ 宏的源程序时,会报下面的错误:
    error: macro "__DATE__" might prevent reproducible builds
    error: macro "__TIME__" might prevent reproducible builds
    编译驱动时遇到这个错误提示,表示当前编译环境中将关于 DATE 以及 TIME 的警告也作为错误来进行处理的。有如下几种方法可以参考:
    1. 在编译驱动的相应 Makefile 中增加一行:CFLAGS += -Wno-error=date-time,然后保存重新 make;
    2. 若 CFLAGS 不生效,将关键字替换为 EXTRA_FLAGS;
    3. 修改 /lib/modules/'uname -r'/build/Makefile 文件,找到包含 “-Werror=date-time” 这一行注释掉,然后保存退出。之后重新 make 即可
    4.修改根目录下的Makefile,将
        KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)
        改为
        KBUILD_CFLAGS   += $(call cc-option,-Wno-error=date-time)
解决办法:
    修改根目录下的Makefile,将
        KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)
        改为
        KBUILD_CFLAGS   += $(call cc-option,-Wno-error=date-time)


【隐式声明】

[-Werror=implicit-function-declaration]
很多函数,我们都是在代码中定义了,但没添加声明就在其他代码中互相调用,这样会出现报错。
还有的原因是,新的内核里去掉了相应的函数定义,需要我们自己添加进去 / 找新的替换函数

报错:
    drivers/klsp/common/klsp_timer.c:64:2: 
    error: implicit declaration of function ‘init_timer’ [-Werror=implicit-function-declaration]
错误原因:
    在4.15内核里,init_timer被移除了。需要换用新的timer_setup接口。
解决方法:
#include <linux/version.h>
    #if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
        /* Init timer */
        init_timer(&ptimer->timer);
        ptimer->timer.function = klsp_timer_process;
        ptimer->timer.data     = (unsigned long)ptimer;
    #else
        timer_setup(&ptimer->timer, klsp_timer_process, 0);
    #endif
        ptimer->timer.expires  = jiffies + timeout;
        add_timer(&ptimer->timer);
    -----------------------------
    #if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0)
    static void klsp_timer_process(unsigned long data)
    
            struct klsp_timer *ptimer = (struct klsp_timer *)data;
    #else
    static void klsp_timer_process(struct timer_list *t)
    
            struct klsp_timer *ptimer = from_timer(ptimer,t,timer);
    #endif


------------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:282:2: 
    错误:implicit declaration of function ‘init_timer’; did you mean ‘init_timers’?
解决办法:
    vi include/linux/timer.h
    添加:
    #define init_timer(timer)                        \\
    __init_timer((timer),NULL, 0)


一部分提示“implicit declaration”的报错是因为缺少头文件。添加上对应的头文件就好了。
报错:
    drivers/klsp/boards/kdv/jd4000/brd_ctrl.c:113:7: 
    error: implicit declaration of function ‘copy_to_user’
       if (copy_to_user(argp, &board_cfg, sizeof(board_cfg)))
解决办法:
vi drivers/klsp/boards/kdv/jd4000/brd_ctrl.c
    以前是:#include <asm/uaccess.h>
    现在需要添加:#include <linux/uaccess.h>


-------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/jd4000/brd_ctrl.c:203:3: 
    error: implicit declaration of function ‘msleep’ [-Werror=implicit-function-declaration]
       msleep(3000);
解决办法:
    drivers/klsp/boards/kdv/jd4000/brd_cfg.c
    drivers/klsp/boards/kdv/jd4000/brd_ctrl.c
        加上#include <linux/delay.h>


-------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/base/wd_common.c:506:7: 
    错误:implicit declaration of function ‘kernel_thread’; did you mean ‘kernel_read’? 
    原先的include/linux/sched.h里面缺少了相关的函数定义,该到了其他的函数里
    需要在文件中include其他头文件
解决办法:
    vi drivers/base/wd_common.c
    添加:
    #include <linux/sched/task.h>
    #include <linux/sched/types.h>

还有一部分隐式声明报错,是因为自己写的函数,没在头文件里添加声明。
-------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1127:2: 
    错误:implicit declaration of function ‘mc_config_idt’; did you mean ‘mc_config_pex’?
解决办法:
    vi drivers/mca/mca_v6/mca_jd4000.h
    添加:int mc_config_idt(void);


------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:201:8: 
    错误:隐式声明函数‘brd_hi35xx_reset’
解决办法:
    vi drivers/pcie_boot/hi35xx_pcie_x64_k.c
    添加:extern int brd_hi35xx_reset(u8 slot, u8 chip_type, u8 port);


------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/ceu2/slot.c:100:5: 
    错误:implicit declaration of function ‘copy_to_user’; did you mean ‘raw_copy_to_user’? 
    drivers/klsp/boards/kdv/ceu2/slot.c:114:5: 
    错误:implicit declaration of function ‘copy_from_user’; did you mean ‘raw_copy_from_user’?
解决办法:
    vi drivers/klsp/boards/kdv/ceu2/slot.c
    添加:#include <linux/uaccess.h>


------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/mca/mca_v6/mca_ms.c:548:4: 
    错误:implicit declaration of function ‘mca_i2c_pex_reset_port8’; did you mean ‘mca_i2c_pex_port_write’? 
    drivers/klsp/drivers/mca/mca_v6/mca_ms.c:204:11: 
    错误:implicit declaration of function ‘pciehp_xmpu5_3_init’; did you mean ‘pciehp_xmpu5_init’? 
解决办法:
    vi drivers/klsp/drivers/mca/mca_v6/mca_ms.c
    添加
    extern int mca_i2c_pex_reset_port8(void);
    extern int pciehp_xmpu5_3_init(int slot);


------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/jd4000/brd_cfg.c:185:3: 
    错误:implicit declaration of function ‘hi35xx_pcie_ep_setup’; did you mean ‘hi35xx_pcie_reinit’? 
解决办法:
    vi drivers/klsp/boards/kdv/jd4000/brd_cfg.c
    添加:extern int hi35xx_pcie_ep_setup(u32 id, chip_35xx_info *dev_p);


------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/ceu2/pcie/pcie_hotplug.c:967:8: 
    错误:implicit declaration of function ‘brd_slot_type_save’; did you mean ‘brd_slot_get’?
解决办法:
    vi drivers/klsp/boards/kdv/ceu2/pcie/pcie_hotplug.c
    添加:extern u8 brd_slot_type_save(u8 slot, u8 type);

【缺少头文件】

不同的内核版本,有可能出现将函数/结构体定义在不同的头文件中,
这样用老的驱动编译时就会报错,需要在代码中添加相应的新的头文件。

报错:
    ./arch/x86/include/asm/uaccess.h:32:9: error: dereferencing pointer to incomplete type ‘struct task_struct’
      current->thread.addr_limit = fs;
错误原因:
    出错原因主要在current上,宏current定义在arch/.../include/asm/current.h中。
    编译器不知道task_struct的具体定义,因此,无法解引用current,无法获知其成员pid、comm、flags的类型,
    才报“dereferencing pointer to incomplete type” 
    task_struct定义在<linux/sched.h>中。
    在源文件头,加上#include <linux/sched.h>,即可解决问题!
解决办法:
    在./arch/x86/include/asm/uaccess.h中加上
    #include <linux/sched.h>


【从不兼容的指针类型赋值】

[-Werror=incompatible-pointer-types]
这种一般都是因为语法错误,需要进行修改。
还有的需要做强制类型转换。

报错:
    drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c:1841:43: 
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
    priv->gbl                               = &jd6000_ceue_xmpu_layout;
    priv->xbl                               = &jd6000_ceue_xmpu5_layout;
    priv->xbl_3                             = &jd6000_xmpu5_3_layout;
解决办法:
    vi drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c
    改为:
    priv->gbl                               = jd6000_ceue_xmpu_layout;
    priv->xbl                               = jd6000_ceue_xmpu5_layout;
    priv->xbl_3                             = jd6000_xmpu5_3_layout;


------------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1224:15: 
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
      priv->mbl    = &jd4000_layout;
解决办法:
    改为:priv->mbl    = jd4000_layout;


------------------------------------------------------------------------------------
报错:
    ./include/linux/workqueue.h:262:17: 
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
       (_work)->func = (_func);    \\
    drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:275:5: 附注:in expansion of macro ‘INIT_WORK’
        INIT_WORK(&pend_event_work, brd_board_type_get);
解决办法:
    vi drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c
    改为:
    INIT_WORK(&pend_event_work, (void *)brd_board_type_get)


------------------------------------------------------------------------------------
报错:
    drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c:283:26: 
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
         input_timer.function =pulse_signal_give_out;
解决办法:
    vi drivers/klsp/boards/kdv/ceu2/brd_c612_gpio.c
    改为
    input_timer.function =(void *)pulse_signal_give_out;


------------------------------------------------------------------------------------
报错:
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
    drivers/klsp/drivers/watchdog/nct6106_wdt.c:422:17: 
      wd_obj_s.feed  = wdt_feed_dog;
    drivers/klsp/drivers/watchdog/nct6106_wdt.c:410:21: 
      wd_obj_s.wdgenable = wdt_open;
解决办法:
    vi drivers/klsp/drivers/watchdog/nct6106_wdt.c
    static int wdt_feed_dog(unsigned char val)
    改为
    static int wdt_feed_dog(int val)
    ------------
    static int wdt_open(struct inode *inode, struct file *file)
    wd_obj_s.wdgenable = wdt_open;
    改为
    static int wdt_open(struct inode *inode, struct file *file)
    static int wdt_enable(void)
    wd_obj_s.wdgenable = wdt_enable;


------------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:72:20: 
    错误:从不兼容的指针类型赋值 [-Werror=incompatible-pointer-types]
      g_hi35xx_info[id] = dev_p;
解决办法:
    int hi35xx_pcie_ep_setup(u32 id, struct chip_35xx_info *dev_p)
    改为
    int hi35xx_pcie_ep_setup(u32 id, chip_35xx_info *dev_p)


------------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/mca/mca_v6/mca_chan.c:84:15: 
    错误:传递‘atomic_read’的第 1 个参数时在不兼容的指针类型间转换 
       atomic_read(&chan->refcount.refcount));
报错原因:
    include/linux/kref.h中的
    struct kref atomic_t refcount;;
    变成了:
    struct kref refcount_t refcount;;
    对应
    typedef struct refcount_struct 
        atomic_t refs;
     refcount_t;
解决办法:
    vi drivers/mca/mca_v6/mca_chan.c
        判断内核版本,当大于 KERNEL_VERSION(4,19,0)时,添加上refcount_t.refs
    #if     defined(CONFIG_JD6100)
            refcount_read(&chan->refcount.refcount));
    #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)
            atomic_read(&chan->refcount.refcount.refs));
    #else
            atomic_read(&chan->refcount.refcount));
    #endif


------------------------------------------------------------------------------------
报错:
    drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:520:12: 
    警告:传递‘memcpy’的第 1 个参数时将整数赋给指针,未作类型转换 [-Wint-conversion]
         memcpy(g_hi35xx_ctrl.hpdev[devId].baseInfo[2].vmBase + HI3519_EP_INFO_OFFSET, &devId, sizeof(devId));
解决办法:
    vi drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c
    改为:memcpy((void *)g_hi35xx_ctrl.hpdev[devId].baseInfo[2].vmBase + HI3519_EP_INFO_OFFSET, &devId, sizeof(devId));


【函数声明不是一个原型】

[-Werror=strict-prototypes]
这个报错一般是在定义/声明的时候,没添加void,虽然函数不需要传参,但仍需要加上”void“去表示。

报错:
    drivers/klsp/drivers/mca/mca_v6/mca_e5_rc.c:1668:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
     extern int get_e2prom_userdata_ms_mode();
     drivers/klsp/drivers/mca/mca_v6/mca_i2c_pex.c:631:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
     static int i2c_pex_debug_init();
      drivers/klsp/drivers/mca/mca_v6/mca_ms.c:277:5: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
     int mca_wait_ms_notify_is_ready()
      drivers/klsp/drivers/mca/mca_v6/mca_ms.c:345:1: 错误:函数声明不是一个原型 [-Werror=strict-prototypes]
     extern int get_e2prom_userdata_ms_mode();
 解决办法:
     在函数里都加上:xxx(void)


【未定义函数】

以前我们可能在老的内核里定义了一些函数,做了一些特殊操作。
现在移植到新内核下之后,需要将那些函数也同样在新的系统下定义一次。

报错:
    kernel-4.19.90-2106.3.0/drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1278: 
    undefined reference to `pcie_reserve_mem_start'
    kernel-4.19.90-2106.3.0/drivers/klsp/drivers/mca/mca_v6/mca_jd4000_rc.c:1279: 
    undefined reference to `pcie_reserve_mem_size'
    kernel-4.19.90-2106.3.0/drivers/klsp/drivers/pcie_boot/hi35xx_pcie_x64_k.c:201: 
    undefined reference to `brd_hi35xx_reset'
解决办法:
    grep -rn "CONFIG_KDV9000A_CEU2"
    grep -rn "CONFIG_KDV9000A_CEU2E"
    grep -rn "CONFIG_JD4000"
    找到定制的代码,在新内核下将老的内核中的改动,移植进去
    在kernel下有很多针对内核版本里的改动,需要在openEuler里也修改过去
    drivers/i2c/busses/i2c-designware-platdrv.c:276:#ifdef CONFIG_JD4000
    drivers/i2c/busses/i2c-i801.c:1275:#if defined(CONFIG_JD4000)
    arch/x86/kernel/setup.c:917:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_JD4000) || defined (CONFIG_KDV9000A_CEU2E)
    arch/x86/kernel/setup.c:918:#if defined(CONFIG_JD4000)
    arch/x86/kernel/setup.c:1329:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_JD4000) || defined (CONFIG_KDV9000A_CEU2E)
    mm/mmap.c:1370:#if defined(CONFIG_KDV9000A_CEU2) || defined(CONFIG_KDV9000A_CEU2E) || defined(CONFIG_JD4000)
开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

backports移植rtlwifi驱动

...动也是越多,对于低版本*如何使用高版本中的驱动是个问题,左栋提醒使用backports来做移植,尝试一下。**2017-9-13深圳龙华樟坑村曾剑锋* 查看详情

一个linux内核模块移植到低版本时发生的异常(代码片段)

在3.10的内核版本下,有一个运行稳定的内核模块,移植到suse11的时候,编译正常,运行则直接出现crash:<4>[503.347297]CPU0<4>[503.347300]Moduleslinkedin:caq_sendmsg(EN)mysendmsg(EN)witdriver(EN)datalink(EN)w83627dhg(EN)tipc(EX)ossmod(E 查看详情

如何在 Linux 内核 3.10.0 版本中启用或反向移植蓝牙 BLE 功能?

...eatureinLinuxkernel3.10.0version?【发布时间】:2020-09-1706:19:56【问题描述】:我尝试在我的linux内核版本3.10.0中启用蓝牙LE,但可以在menuconfig中找到[*]蓝牙低功耗(LE)功能。我正在尝试为Linux内核版本3. 查看详情

已解决nvidia-smihasfailedbecauseitcouldn‘tcommunicatewiththenvidiadriver的报错(代码片段)

问题描述基于ubuntu16.04,本人在更换一次系统下载源后,误操作进行了内核升级。执行以下查看cuda命令:nvidia-smi出现如下提示:NVIDIA-SMIhasfailedbecauseitcouldn'tcommunicatewiththeNVIDIAdriver.MakesurethatthelatestNVIDIAdriverisinsta... 查看详情

内核编译与移植

...间都存在有很多差异,那下载哪一个版本好呢?其实这个问题很难有统一的答案,但作为嵌入式系统开发本身来说,坚持两个原则是没错的:一是够用就好,不要去追求“高大尚”;二是能够维护好一套内核就行,不要一... 查看详情

低版本gcc程序向高版本移植的兼容性问题

...cc编译过的程序移植到高版本GCC时,可能会出现一些兼容性问题.原因是,为了适应新的标准,一些旧的语法规则被废弃了.关于这方面的一些具体资料可从该处查询.这里只是自己遇到的其中一个问题.错误提示:Ininstantiationof‘intt(T)[... 查看详情

关于linux内核(3.0.8)编译移植中出现的问题总结

在编译linux内核3.0.8当中出现的问题  交叉编译器版本4.4.61.Infileincludedfromdrivers/usb/host/ehci-hcd.c:124:drivers/usb/host/ehci.h:747:warning:functiondeclarationisn‘taprototypedrivers/usb/host/ehci-hcd.c:1290 查看详情

类似的工具,如内核版本 2.6.9(或更低版本)的 inotify

...ifyforkernelversion2.6.9(orlower)【发布时间】:2013-03-0609:21:43【问题描述】:我必须在C++(Linux环境)中编写应用程序来监视文件更改并保持进程直到文件写入未关闭。我已经查看并安装了inotify但它没有工作,因为我有内核版本2.6.9。... 查看详情

linux驱动开发笔记:基于ubuntu的helloworld驱动源码编写makefile编写以及驱动编译加载流程测试(代码片段)

...拟机的过程请自行搜索查找完成。  步骤二:获取内核版本号  获取内核版本号是为了确认内核版本号一致。sudocat/proc/version  步骤三:校准编译器版本  前面获取了内核的编译器版本是gcc7.3.0,但是本机是gcc7.5,需要... 查看详情

低版本androidstudio项目升级到高版本

...新安装了新的as及相关插件,于是,打开旧项目就有很多问题了,最初是原项目gradle版本过低,新装的5.4.1,项目中用到的是3.5.3,编译时老提示最低编译版本为26,然后又是butterknife版本用了10.2.1,然后提示对应buildsdk要用28,于... 查看详情

linux内核移植编译时遇到的问题

...个交叉编译工具链.安装就ok了. 参考技术B我也遇到过这个问题,请参看这个博客内容。我就这样解决的参考资料:http://blog.csdn.net/sdwuyulunbi/article/details/6152437 查看详情

你好,我的在kalilinux安装rtl8192的驱动时编译遇到点问题

求大神帮忙看一下,我是新手他的书我也看过,你的问题应该是linux版本问题吧,记得编译驱动程序的内核和insmod时候使用的内核需要一样,例如:我当时使用ubuntu,里边自己编译的是linux-2.6.32.4吧(记不清楚了),编译完内核之后... 查看详情

2内核的配置和移植(代码片段)

...核源码目录结构1源码从哪里来之前讲过,我们使用2.6.35.7版本的内核。这个版本的内核有三种:第一种是kernel.org上的官方版本,第二种是三星移植过的,第三种是九鼎X210的移植版本。我们讲课时使用第三种内核来讲解,后面的... 查看详情

linux系统移植:内核获取和编译(代码片段)

...发布,Linux官网为https://www.kernel.org,选取合适的版本来使用就行本章的移植使用NXP提供的Linux源码二、Linux内核编译编译内核之前需 查看详情

linux为啥要编译内核

新手,不懂,希望讲的低级点,以下是几个问题。1:平时在linux下c编程,也没有用到编译内核什么的,经常看到“内核源码树”这个词汇,就不懂的。难道我正在使用的这个linux系统不是编译出来的一个系统吗?为什么还要再编... 查看详情

如何编译一个linux下的驱动模块

...具版本来构造一个内核(及其模块),可能导致许多奇怪的问题。另外也要注意,使用太新版本的编译器偶尔可能也会导致问题。一旦做好了上面的准备工作之后,其实给自己的模块创建一个makefile则非常简单。实际上,对于本章前面... 查看详情

openharmony内核学习[1]--单独编译openharmony标准系统内核(代码片段)

...ux内核作为标准系统内核。OpenHarmony标准系统从Linux内核LTS版本中选择合适的版本作为内核的基础版本,目前已完成对Linux-4.19及Linux-5.10的适配及支持。OpenHarmony的Linux内核基于开源Linux内核LTS4.19.y/5.10.y分支演进,在此基线基础上,... 查看详情

教你如何快速编译安装新内核

随着内核版本的更新换代,你是否有觉得自己的内核版本有些低了呢?如果有的话,没关系,今天小编就来教大家如何编译安装新的内核。在编译安装内核之前先检查我们的虚拟机所在的磁盘空间,预留空间10G以上,不然编译安... 查看详情