Как отладить ядро ​​ARM Linux (msleep ())? - PullRequest
3 голосов
/ 11 марта 2012

Я в первую очередь ищу советы по отладке. Если кто-то может указать одну строку кода, которую нужно изменить, или один периферийный бит конфигурации, чтобы установить, чтобы исправить проблему, это было бы потрясающе. Но это не то, на что я надеюсь; Я больше ищу, как мне отладить его.

Поиск в Google "msleep hang linux site kernel: stackoverflow.com" дает 13 ответов, и ни один из них не подходит, поэтому я думаю, что я могу спросить.

Я перестраиваю ядро ​​ARM Linux для встроенного процессора TI AM1808 ARM (Sitara / DaVinci?). Я вижу весь загрузочный журнал вплоть до приглашения login:, поступающего из последовательного порта, но попытка входа не получает ответа, даже не повторяет то, что я напечатал.

После многих отладок я прибыл в ядро ​​и добавил код отладки между строками 828 и 830 (да, версия ядра - 2.6.37). В этот момент в режиме ядра перед вызовом 'sbin / init':

http://lxr.linux.no/linux+v2.6.37/init/main.c#L815

Прямо перед строкой 830 я добавил printk цикла навсегда, и я вижу результаты. Я дал ему поработать около пары часов, и он составляет около 2 миллионов. Пример строки:

dbg:init/main.c:1202: 2088430

Так что без проблем выплыл 60 миллионов байт.

Однако, если я добавляю msleep (1000) в цикл, он печатается только один раз, то есть msleep () не возвращается.

Подробнее: Добавление условного printk в строку 4073 в планировщике, которое устанавливает условие для флага, который устанавливается в начале цикла проверки навсегда, описанного выше, показывает, что schedule () больше не вызывается, когда он зависает:

http://lxr.linux.no/linux+v2.6.37/kernel/sched.c#L4064

В разделе .config / «Драйверы устройств» доступны только следующие параметры: Блочные устройства Поддержка I2C Поддержка SPI

Ядро и его ramdisk загружаются с помощью uboot / TFTP. Я не верю, что он пытается использовать Ethernet. Поскольку все это происходило до '/ sbin / init', очень мало должно происходить.

Подробнее: У меня очень похожая плата с тем же процессором. Я могу запустить тот же uImage и тот же ramdisk, и он прекрасно работает там. Я могу войти и делать обычные вещи.

Я запустил тест памяти (всего 64 МБ, ограничил ядро ​​32M и протестировал остальные 32M; это DDR2 с одним чипом) и не нашел никаких проблем. На одной плате используется UART0, а на другой - UART2, но журнал загрузки загружен обоими, поэтому проблем не должно быть.

Любые советы по отладке приветствуются. У меня нет подходящего JTAG, поэтому я не могу его использовать.

Ответы [ 2 ]

0 голосов
/ 13 марта 2012

Эта проблема была решена.

При свободном использовании prink было определено, что schedule () действительно переключается на другую задачу, задачу ожидания.В данном случае, будучи встроенным Linux, исходная кодовая база, из которой я скопировал, установила простаивающую задачу.Эта неработающая задача, кажется, не подходит для моей платы и заблокировала процессор, что привело к сбою.Закомментирование вызова в режиме ожидания

http://lxr.linux.no/linux+v2.6.37/arch/arm/mach-davinci/cpuidle.c#L93

обходит проблему.

0 голосов
/ 11 марта 2012

Если msleep не возвращается или не доходит до schedule, то для отладки мы можем следить за стеком вызовов.

msleep вызывает schedule_timeout_uninterruptible(timeout), который вызывает schedule_timeout(timeout), который в случае по умолчанию завершается без расписания вызовов, если время ожидания в jiffies, переданное ему, составляет

Если timeout положительно, то вызывается setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);, затем __mod_timer(&timer, expire, false, TIMER_NOT_PINNED); перед вызовом schedule.

Если мы не доходим до schedule, тогда что-то должно происходить либо в setup_timer_on_stack, либо в __mod_timer.

Calltrace для setup_timer_on_stack - это setup_timer_on_stack, звонки setup_timer_on_stack_key, которые звонят init_timer_on_stack_key, либо внешние, если CONFIG_DEBUG_OBJECTS_TIMERS включена, либо звонки init_timer_key(timer, name, key);, которые звонят debug_init, за которым следует __init_timer(timer, name, key).

__mod_timer сначала вызовы timer_stats_timer_set_start_info(timer);, а затем множество других вызовов функций.

Я бы посоветовал начать с ввода printk или двух в schedule_timeout, вероятно, с любой стороны вызова setup_timer_on_stack или с любой стороны вызова __mod_timer.

...