Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: затыкается stdout в NiosII
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
torik
Возникла проблема.

В программе под NiosII используется вывод в консоль fprintf. Очень удобно для отладки.

Добавил в систему VIC и написал обработчик прерываний для таймера. Таймер генерит прерывание с периодом 1мс.

И тут у меня начал затыкаться вывод в stdout (в функции main в бесконечном цикле). Как только я закоментил код обработчика прерываний, все заработало:

Код
//********************** ISR functions **************************************************
//void timer_interrupt_init (void* base, alt_u32 irq_controller_id, alt_u32 irq)
//{
//  /* Register the interrupt */
//  alt_ic_isr_register(irq_controller_id, irq, timer_interrupt_irq, base, NULL);
//
//  irq_cnt = 0;
//
//  /* Start timer */
//  IOWR_ALTERA_AVALON_TIMER_CONTROL(base, ALTERA_AVALON_TIMER_CONTROL_ITO_MSK
//  | ALTERA_AVALON_TIMER_CONTROL_START_MSK);
//}
//
//void timer_interrupt_irq (void* base)
//{
//  /* Clear TO bit in status register */
//  IOWR_ALTERA_AVALON_TIMER_STATUS (base, 0);
//
//  if (irq_cnt < 1000) {
//      irq_cnt++;
//  } else {
//      irq_cnt = 0;
//      send_tx_buffer(&tx);
//  }
//
//  /*Start timer */
//  IOWR_ALTERA_AVALON_TIMER_CONTROL(base, ALTERA_AVALON_TIMER_CONTROL_ITO_MSK
//  | ALTERA_AVALON_TIMER_CONTROL_START_MSK);
//
//}


Это как-то лечится, не? Отчего происходят такие сбои?
vadimuzzz
точно помню, делал и тут выкладывал. а найти не могу laughing.gif
похоже, что прерывание начинает срабатывать слишком часто. например, в регистре period таймера 0, и он на каждом такте кидает прерывание. буквально пару недель назад такую штуку делал и те же симптомы наблюдал. завтра на работе поищу.
воткните в обработчик прерывания дамп регистров таймера, может прояснит ситуацию.
vadimuzzz
во, нашел. ваш косяк, думаю, видно где:
Код
#include <stdio.h>
#include "alt_types.h"
#include "system.h"
#include <sys/alt_irq.h>
#include "altera_avalon_timer_regs.h"

void timer_interrupt_latency_irq()
{
    IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE,0);
    alt_ic_irq_disable(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ);
    printf("Hello timer!\n");
    alt_ic_irq_enable(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ);
    printf("IRQ enabled!\n");
}

int main()
{
    printf("Hello from Nios II!\n");
    /* Register the interrupt */
    alt_ic_isr_register(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ, timer_interrupt_latency_irq, TIMER_0_BASE, NULL);
    /* Start timer */
    IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE,10000);
    IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE,10000);
    IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE,1000);
    IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE, ALTERA_AVALON_TIMER_CONTROL_ITO_MSK
            | ALTERA_AVALON_TIMER_CONTROL_CONT_MSK
            | ALTERA_AVALON_TIMER_CONTROL_START_MSK);
    while (1);//Event Loop
    return 0;
}
torik
Не вкурил, где конкретно?
Прерывания срабатывают с нужным периодом - сейчас 10 мс.
vadimuzzz
Цитата(torik @ Feb 25 2011, 12:34) *
Не вкурил, где конкретно?

Код
alt_ic_irq_disable(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ);
...
alt_ic_irq_enable(TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID, TIMER_0_IRQ);
torik
Да, да, заметил уже. Но... не помогло. Несколько printf проходит, а затем снова затыкается.
vadimuzzz
а что в main? есть ли другие прерывания? есть ли зависимость от периода таймера?
torik
Других прерываний нет.

А не может ли это быть из-за того, что одна и та же функция используется в прерываниях и в main?
функция записи в SPI используется и в main и в прерываниях.



Ага, вот пробую. не fprint затыкается похоже, а именно функция где используется запись SPI!
vadimuzzz
Цитата(torik @ Feb 25 2011, 13:22) *
функция записи в SPI используется и в main и в прерываниях.

не хорошо, прерывание ведь может произойти во время транзакции по SPI. что будет - хз - зависит от контроллера. м.б. вообще зависнет
torik
Запретил прерывания в main на момент выполнения функций, которые используются и в прерываниях. Стало работать.
Побочный эффект - неточность вызова прерывания таймера. И вообще тут надо осторожно...
vadimuzzz
Цитата(torik @ Feb 25 2011, 13:36) *
И вообще тут надо осторожно...

я бы сказал, что надо саму идею пересмотреть. может озвучите задачу?
torik
пока еще в стадии формирования
vetal
Цитата
Побочный эффект - неточность вызова прерывания таймера. И вообще тут надо осторожно...

Неточность - это нормально. При доступе из двух разных мест надо решать неопределенность rmw операций.
Прерывания можно запрещать не на все время выполнения функции, а только при доступе к общим ресурсам.
Если у вас в системе более одного прерывания, то неточность все равно будет иметь место.
Reanimator++
Можно в прерывании взводить семафор (есть отправка на SPI) а потом вызывать функцию отправки которая его проверяет, тогда неточность вызова таймера заменится на неточность во времени отправки данных.
Впрочем тот же микриум должен это дело достаточно быстро обработать (вытесняющая ос все-таки).
torik
Спасибо!
Я еще вернусь к теме, когда алгоритм как следует продумаю.
gosu-art
А при выполнении подпрограммы обработки прерывания остальные IRQ маскируются? У меня сейчас 2 прерывания в системе:от таймера и от внешнего устройства (VIC пока не использую). Если не заблокировать прерывание от таймера, во время обработки другого, может ли оно "выстрелить"? Или все же не ленится и запрещать все остальные прерывания во время обработок?
WitFed
Ох, мужики, это опасное дело -- вызывать файловые операции в обработчике прерываний.
Всё зависит от реентерабельности этих самых функций -- если они на середине вывода имеют половину служебных переменных в стеке, половину глобальных, и тут влазит новый вызов, который окончится ранее продолжения старого, х.з. что там по окончании обоих намешается... В мануалах надо искать положительные разрешения, и вряд ли Альтерцы закладывали много мозгов в свой детский проц.
В каких-то конкретных проверенных нечастых случаях для отладки может и можно, но осторожно, и потом сразу лучше наложить табу обратно wink.gif Ведь если число желаемых символов по каналу за 1 с превысит его пропускную способность, где-то кого-то кто-то перетрёт в буферах или отбросится в лучшем случае.
В настоящих многозадачных ОС обычно для обработчиков семафоры ждать запрещается, файлы трогать тем более, надо сигналить куда-то семафором или в переменную, записывать всю ситуацию в глобальные переменные, тикать побыстрее, а потом снаружи в нормальном потоке разбираться и сливать инфу без спешки. А если сама функция вывода использует прерывания для обратной сигнализации, то фиг вообще первое прерывание закончится с принтфом wink.gif
Если прерываний несколько разных, то обычно они отсортированы по приоритету, и то же самое произойти не может уже в обработчике, но более крутое запросто. И такие хитроглюки могут прятаться редкие... Я у себя в проектах стараюсь обходиться без прерываний -- поллинг вполне годится для 99% задач, плюс верифицируется и отлаживается на порядки проще.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.