Межпроцессорные прерывания в ARM cortex A9 (как написать обработчик программно сгенерированного прерывания (ARM) в Linux?)

Я читал, что прерывания, генерируемые программным обеспечением в ARM, используются как межпроцессорные прерывания. Я также вижу, что 5 из этих прерываний уже используются. Я также знаю, что ARM предоставляет 16 прерываний, генерируемых программным обеспечением.

В моем приложении я запускаю голое железо на ядрах ARM-cortex и Linux на другом. Я хочу передать некоторые данные из ядра, на котором запущено «голое железо», в ядро, работающее под управлением Linux. Я планирую скопировать данные во встроенную память (которая является общей) и вызову SGI на ядре (под управлением Linux), чтобы указать, что некоторые данные доступны для обработки. Теперь я могу сгенерировать SGI из ядра (работающее на «голом железе»). Но для обработки прерывания на стороне Linux я не уверен в свободных номерах SGI IRQ, и я также не уверен, могу ли я использовать номер IRQ напрямую (обычно SGI от 0 до 15). Есть ли у кого-нибудь идеи, как написать обработчик для SGI в Linux?

Изменить: это новая формулировка приведенного выше текста, поскольку вопрос был закрыт по причинам SSCE < / а>. Процессоры Cortex-A используются в многопроцессорных системах. ARM общий контроллер прерываний (GIC) отслеживает все глобальные прерывания и отправляет их конкретному процессору. Чтобы отдельные процессоры могли сигнализировать друг другу, от одного ядра к другому отправляется программно сгенерированное прерывание (SGI); здесь используются частные периферийные прерывания (PPI). Этот вопрос,

Как реализовать драйвер ядра Linux, который может получать SGI как PPI?


person Nuetrino    schedule 06.12.2013    source источник


Ответы (2)


Есть ли у кого-нибудь идеи, как написать обработчик для SGI в Linux?

Поскольку вы не указали версию для Linux, я предполагаю, что вы работаете с последней (или, по крайней мере, последней). ARM GIC имеет привязки дерева устройств. Обычно вам нужно указать номер прерывания SGI в узле дерева устройств,

 ipc: ipc@address {
        compatible = "company,board-ipc"; /* Your driver */
        reg = <address range>;
        interrupts = <1 SGI 0x02>;  /* SGI is your CPU interrupt. */
        status = "enabled";
 };

Первое число в разделе прерывание обозначает PPI. SGI, вероятно, будет между 0-15, поскольку именно сюда маршрутизируются прерывания SGI (по крайней мере, на Cortex-A5).

Затем вы можете просто использовать platform_get_irq() в своем драйвере, чтобы получить PPI (частное периферийное прерывание). Я предполагаю, что адрес - это общая память (физическая), по которой вы хотите осуществлять обмен данными; возможно reg не подходит, но я думаю, что это сработает. Эта область будет переназначена MMU Linux, и вы можете использовать ее с

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem = devm_ioremap_resource(dev, res);

адрес в дереве устройств выше - это шестнадцатеричное значение физического адреса. platform_get_irq() должен возвращать номер IRQ, который можно использовать с семейством функций request_irq(). Просто свяжите это со своим распорядком.

Изменить: К сожалению, прерывания ниже 16 запрещены Linux irq-gic.c. Например, gic_handle_irq(), ограничивает обработчик прерываниями от 16 до 1020. Если SMP включен, то для интересующих прерываний вызывается handle_IPI(). gic_raise_softirq() можно использовать для сигнализации прерывания. Чтобы обрабатывать SGI с текущим Linux, smp.c требует дополнительных _ 10_ и код для их обработки в _ 11_. Похоже, что новые ядра (возможно, 3.14+?) Могут добавить set_ipi_handler() в smp.c, чтобы сделать такую ​​модификацию ненужной.

person artless noise    schedule 06.12.2013
comment
Спасибо за ваш ответ. У меня есть пара вопросов. как мне заполнить структуры pdev и dev ?. Полагаю, я не могу заполнить это с помощью функции проверки, поскольку это не аппаратное прерывание. И поле ‹reg› в записи дерева устройств будет начальным адресом моей общей физической памяти (reg) и количеством байтов, к которым должен быть получен доступ (диапазон). Я прав? - person Nuetrino; 07.12.2013
comment
И pdev, и dev отправляются в probe() функцию. static int probe(struct platform_device *pdev)..., static struct platform_driver driver = { .probe = probe }; и module_platform_driver(driver); и dev = &pdev->dev. - person artless noise; 09.12.2013
comment
См. источники и типы прерываний ARM Cortex. В разделе 4.3.15 документа GIC указано ICDSGIR. NSATT указывает trustzone безопасный или нет. Вы можете выбрать любое неиспользуемое прерывание (0-15). - person artless noise; 09.12.2013
comment
@artlessnoise, спасибо. Я решил эту проблему. У меня возникла ошибка (EINVaL = -22 недействительный аргумент), когда я попытался использовать номер irq в функции request_irq (для всех номеров irq SgI), поэтому я использовал другую функцию set_ipi_handlers (arch / arm / kernel / smp.c) для регистрации моего обработчик irq. Я полагаю, что request_irq нельзя использовать в этом контексте. - person Nuetrino; 11.12.2013

Я хотел бы добавить, что пример такого межъядерного взаимодействия можно найти в многоядерных SoC TI (то есть OMAP3530). Некоторое время назад, когда я использовал такой механизм, средства были предоставлены TI. В частности, такую ​​функциональность предоставлял драйвер устройства DSPLink Linux. В то время, к сожалению, это не было решением с открытым исходным кодом, но, возможно, есть техническая статья от TI, описывающая, как это работает ... Просто направление, которое вы могли бы изучить дальше :)

РЕДАКТИРОВАТЬ: Между тем, похоже, они сделали его с открытым исходным кодом. Итак, если это то, что вы ищете, вы можете посмотреть: DSPLink и SysLink (преемник DSPLink)

person Adi    schedule 10.12.2013
comment
Спасибо. Я взгляну. :) - person Nuetrino; 10.12.2013