我的团队正在努力控制德州仪器OMAP l138的频率。默认频率为300 MHz,我们希望将其置于374 MHz的“完整”状态。 form:我们不仅希望将默认值更改为所需的值(或者至少在启动时配置它),而且还能够在运行时更改该值。
在网上搜索有关如何执行此操作的内容,我们发现了一篇文章,其中指出其中一种方法是通过" echo"命令:
echo 372000 /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
我们使用此命令进行了一些测试,它运行正常,出现一个问题:有时第一次调用此echo命令会导致错误消息"在内核中除以零":
在我的个人测试中,此错误始终出现在第一次调用echo命令中。所有后来的调用都没有错误。如果,然后,我重置我的处理器并再次调用该命令,则会出现同样的问题:第一次调用导致此错误,稍后调用工作没有问题。
所以我的问题是:导致这个问题的原因是什么?我怎么能解决它? (显然答案是"总是输入两次"不算数!)
(请随时提及实时控制OMAP l138频率的其他方法!)
答案 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”错误。只需在内核启动日志中查找以“###”开头的行。如果您不知道下一步该做什么 - 附上这些调试行,我会尽力帮助您。