Теперь приехали боевые платы, ну и начал переносить проект на реальное железо.
Ну и как обычно, то что работало на ките не захотело работать на реальной плате (кто бы сомневался).
Но проблема оказалась ну очень какая-то странная.
Уже все идеи кончились! Требуются идеи в каком направлении смотреть.
По ходу поиска причин, написал максимально примитивный код, который не работает:
Код
volatile uint32_t flag = 0;
volatile uint32_t counter = 0;
void timeoutRestart(void);
static void handle_eth0_timeout(void* context)
{
IOWR_ALTERA_AVALON_TIMER_STATUS(ETH_TIMEOUT_TIMER_BASE, 0); // Clear TO bit in status register
printf("Hello from Nios II %d!\n", counter); // <- 1
counter++; // <- 2
flag = 1;
}
int main()
{
// Register timeout interrupt
alt_ic_isr_register(ETH_TIMEOUT_TIMER_IRQ_INTERRUPT_CONTROLLER_ID,
ETH_TIMEOUT_TIMER_IRQ,
handle_eth0_timeout,
NULL,
NULL
);
timeoutRestart();
while(1) {
if(flag) {
flag = 0;
timeoutRestart();
}
}
return 0;
}
//! \brief Функция перезапуска таймера в случае прихода запроса по Ethernet.
void timeoutRestart(void)
{
IOWR_ALTERA_AVALON_TIMER_PERIODL(ETH_TIMEOUT_TIMER_BASE,
(uint16_t)ETH_TIMEOUT_TIMER_LOAD_VALUE
);
IOWR_ALTERA_AVALON_TIMER_PERIODH(ETH_TIMEOUT_TIMER_BASE,
(uint16_t)(ETH_TIMEOUT_TIMER_LOAD_VALUE >> 16)
);
IOWR_ALTERA_AVALON_TIMER_CONTROL(ETH_TIMEOUT_TIMER_BASE,
ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK
); // Restart timer with interrupt
}
volatile uint32_t counter = 0;
void timeoutRestart(void);
static void handle_eth0_timeout(void* context)
{
IOWR_ALTERA_AVALON_TIMER_STATUS(ETH_TIMEOUT_TIMER_BASE, 0); // Clear TO bit in status register
printf("Hello from Nios II %d!\n", counter); // <- 1
counter++; // <- 2
flag = 1;
}
int main()
{
// Register timeout interrupt
alt_ic_isr_register(ETH_TIMEOUT_TIMER_IRQ_INTERRUPT_CONTROLLER_ID,
ETH_TIMEOUT_TIMER_IRQ,
handle_eth0_timeout,
NULL,
NULL
);
timeoutRestart();
while(1) {
if(flag) {
flag = 0;
timeoutRestart();
}
}
return 0;
}
//! \brief Функция перезапуска таймера в случае прихода запроса по Ethernet.
void timeoutRestart(void)
{
IOWR_ALTERA_AVALON_TIMER_PERIODL(ETH_TIMEOUT_TIMER_BASE,
(uint16_t)ETH_TIMEOUT_TIMER_LOAD_VALUE
);
IOWR_ALTERA_AVALON_TIMER_PERIODH(ETH_TIMEOUT_TIMER_BASE,
(uint16_t)(ETH_TIMEOUT_TIMER_LOAD_VALUE >> 16)
);
IOWR_ALTERA_AVALON_TIMER_CONTROL(ETH_TIMEOUT_TIMER_BASE,
ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK
); // Restart timer with interrupt
}
Запускаю программу - счётчик counter не наращивается, сообщение печатается.
Ставлю точку останова на метку (1) и на стартап. Запускаю на исполнение, срабатывают по очереди стартап и (1),
то есть понятно, система перегружается. Ладно идём дальше. Останавливаюсь на точке (1) иду по шагам через printf и counter++ -
счетчик наращивается нормально, printf тоже не вылетает(отрабатывает)! После этих двух шагов запускаю систему в динамике. Система перегружается (срабатывает стартап)!
А вот теперь самое интересное!
Останавливаюсь на точке (1). Открываю окно в отладчике (в эклипсе) Memory, чтобы посмотреть содержимое ячейки памяти
где лежит counter. Делаю шаг смотрю в памяти счетчик изменился, стал равен 1. Запускаю дальше систему в динамике.
Всё работает!!! Причём работает долго (больше часа точно!).
Путём разных манипуляций выяснил, что пока не открою окно просмотра памяти в эклипсе, система работать не хочет!
После того как в режиме просмотра содержимого памяти измениш counter с 0 на 1 (в пошаговом режиме), потом с системой
можно делать всё что угодно, останавливать, стартовать, шагать, всё работает.
Первая мысль была, что не тянет по частоте, но как тогда объяснить что после просмотра памяти она работает часами?
По стеку тоже не понятно, опять же почему работает потом?
Если printf с переменной, заменить на простой текст без параметров, тоже работает часами (не перегружается) счётчик наращивается.
Причём работает сразу без манипуляций с эклипсом. Правда в этом случае вызывается не честный printf, а puts.
Вобщем загадка природы! У меня идеи кончились!
Может кто-то, что-то подскажет? В каком направлении копать?
Квартус и ниос 9.1. Пробовал и в 10.1, тоже не работает, но с ним глубоко не копал. Проект написан на c++.
По частоте тоже вроде запас большой.
По ходу отладки выкинул из sopc 2/3 оборудования. Констрейны описаны. При требуемой частоте 50 МГц, квартус говорит допустимая 74 МГц.