控制TI OMAP l138频率导致内核"除以零#34;

时间:2015-01-05 16:21:19

标签: linux division omap

我的团队正在努力控制德州仪器OMAP l138的频率。默认频率为300 MHz,我们希望将其置于374 MHz的“完整”状态。 form:我们不仅希望将默认值更改为所需的值(或者至少在启动时配置它),而且还能够在运行时更改该值。

在网上搜索有关如何执行此操作的内容,我们发现了一篇文章,其中指出其中一种方法是通过" echo"命令:

echo 372000 /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

我们使用此命令进行了一些测试,它运行正常,出现一个问题:有时第一次调用此echo命令会导致错误消息"在内核中除以零":

PrintScreen with error message

在我的个人测试中,此错误始终出现在第一次调用echo命令中。所有后来的调用都没有错误。如果,然后,我重置我的处理器并再次调用该命令,则会出现同样的问题:第一次调用导致此错误,稍后调用工作没有问题。

所以我的问题是:导致这个问题的原因是什么?我怎么能解决它? (显然答案是"总是输入两次"不算数!)

(请随时提及实时控制OMAP l138频率的其他方法!)

1 个答案:

答案 0 :(得分:1)

在我看来,就像你在 davinci_spi_cpufreq_transition()函数中除以零一样。在这个函数的某个地方(或者在 davinci_spi_cpufreq_transition 中调用的某个函数中)有一个错误的除法运算,它试图除以某个变量(在你的例子中)的值为0。这是显然应该在代码中正确处理的错误情况,但事实上并非如此。

很难说出哪个代码确切地导致了这一点,因为我不知道您使用的是哪个内核。如果您可以提供到内核存储库的链接,那将会容易得多。虽然我在上游内核中找不到 davinci_spi_cpufreq_transition ,但我找到它here

davinci_spi_cpufreq_transition()功能似乎位于drivers/spi/davinci_spi.c。它调用davinci_spi_calc_clk_div() function。那里有两个师。首先是:

prescale = ((clk_rate / hz) - 1);

第二是:

if (hz < (clk_rate / (prescale + 1)))

其中一个可能导致“除以零”错误。我建议你通过以下方式修改 davinci_spi_calc_clk_div()函数来追踪哪一个(只需添加标记为“+”的行):

    static void davinci_spi_calc_clk_div(struct davinci_spi *davinci_spi)
    {
        struct davinci_spi_platform_data *pdata;
        unsigned long clk_rate;
        u32 hz, cs_num, prescale;

        pdata = davinci_spi->pdata;
        cs_num = davinci_spi->cs_num;
        hz = davinci_spi->speed;
        clk_rate = clk_get_rate(davinci_spi->clk);
+       printk(KERN_ERR "### hz = %u\n", hz);
        prescale = ((clk_rate / hz) - 1);
        if (prescale > 0xff)
            prescale = 0xff;

+       printk("### prescale + 1 = %u\n", prescale + 1UL);
        if (hz < (clk_rate / (prescale + 1)))
            prescale++;

        if (prescale < 2) {
            pr_info("davinci SPI controller min. prescale value is 2\n");
            prescale = 2;
        }

        clear_fmt_bits(davinci_spi->base, 0x0000ff00, cs_num);
        set_fmt_bits(davinci_spi->base, prescale << 8, cs_num);
    }

我的猜测 - 它是“hz”变量,在你的情况下为0。如果是这样,您还可能希望将下一个调试行添加到 davinci_spi_setup_transfer()功能:

        if (!hz)
                hz = spi->max_speed_hz;

+       printk(KERN_ERR "### setup_transfer: setting speed to %u\n", hz);
        davinci_spi->speed = hz;
        davinci_spi->cs_num = spi->chip_select;

通过所有这些修改,重建你的内核,你可能会得到线索为什么你有“div by zero”错误。只需在内核启动日志中查找以“###”开头的行。如果您不知道下一步该做什么 - 附上这些调试行,我会尽力帮助您。