Управление частотой TI OMAP l138 приводит к делению на ноль в ядре

Моя команда пытается контролировать частоту Texas Instruments OMAP l138. Частота по умолчанию 300 МГц и мы хотим поставить ее на 372 МГц в "полном" виде: хотелось бы не только изменить значение по умолчанию на нужное (или хотя бы настроить при запуске), но и иметь возможность изменения значения во время выполнения.

Поискав в Интернете информацию о том, как это сделать, мы нашли статью, в которой говорится, что один из способов сделать это — использовать команду «echo»:

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

Мы провели несколько тестов с этой командой, и она работает нормально с одной проблемой: иногда первый вызов этой команды echo приводит к сообщению об ошибке «Деление на ноль в ядре»:

PrintScreen с сообщением об ошибке

В моих личных тестах эта ошибка всегда появлялась при первом вызове команды echo. Все последующие вызовы работали без ошибок. Если затем я перезагружаю свой процессор и снова вызываю команду, возникает та же проблема: первый вызов приводит к этой ошибке, а последующие вызовы работают без проблем.

Итак, мои вопросы: что вызывает эту проблему? И как я мог это решить? (Очевидно, что ответ «всегда печатать дважды» не считается!)

(Не стесняйтесь упоминать и другие способы управления частотой OMAP l138 в реальном времени!)


person Momergil    schedule 05.01.2015    source источник


Ответы (1)


Мне кажется, что у вас есть деление на ноль в функции davinci_spi_cpufreq_transition(). Где-то в этой функции (или в какой-то функции, которая вызывается в davinci_spi_cpufreq_transition) есть ошибочная операция деления, которая пытается разделить на некоторую переменную, которая (в вашем случае) имеет значение 0. И это очевидно, ошибка, которая должна быть правильно обработана в коде, но на самом деле это не так.

Трудно сказать, какой именно код приводит к этому, потому что я не знаю, какое ядро ​​вы используете. Было бы намного проще, если бы вы предоставили ссылку на репозиторий вашего ядра. Хотя я не смог найти davinci_spi_cpufreq_transition в основном ядре, я нашел его здесь.

функция davinci_spi_cpufreq_transition() находится в drivers/spi/davinci_spi.c. Он вызывает функцию davinci_spi_calc_clk_div(). Там действуют 2 дивизии. Во-первых:

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". Просто найдите строки, начинающиеся с "###" в журнале загрузки вашего ядра. Если вы не знаете, что делать дальше — прикрепите эти отладочные строки, и я постараюсь вам помочь.

person Sam Protsenko    schedule 27.01.2015
comment
спасибо за ответ, Сэм. Как только наши приоритеты исчезнут, мы поработаем над этой проблемой, и я вернусь с обратной связью. - person Momergil; 24.04.2015