|
Nios II Uart прерывания по приему байта |
|
|
|
Jun 26 2016, 07:29
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Организованы в системе на Nios II прерыывания Uart по приему одного байта на скорости 115200 Байты приходят короткими пакетами по 72 байта с периодом 0.5 сек. Если количество принятых байт равно 72 и первый байт равен 0х55 то Start = 1; В основном цикле main все сбрасывается (uart_count, Start). ... Код alt_u8 Start = 0; alt_u8 buf_uart[256]; alt_u16 uart_count = 0; ... // Инициализация прерываний по UART void Uart_irq_init() { // Регистрация обработчика прерываний alt_irq_register(UART_0_IRQ, (void*)UART_0_IRQ, uart_isr); } ... // прерывания по UART static void uart_isr(void* context, alt_u32 id) { alt_u32 status; // Чтение регистра статуса для определения причины прерываний status = IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE); // Очистка всех флагов ошибок IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE, 0); // Процесс чтения irq if (status&ALTERA_AVALON_UART_STATUS_RRDY_MSK) { buf_uart[uart_count] = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE); uart_count++; } if(uart_count == 72 && buf_uart[0] == 0x55) { Start = 1; uart_count = 0; } } Main Код int main (void) { alt_u8 led = 0x2; alt_u8 dir = 0;
Uart_irq_init(); alt_irq_enabled();
// главный цикл while(1) { if(Start == 1) { Start = 0; // бегущий светодиод if(led & 0x81) dir = (dir ^ 0x1); if(dir) led = led >> 1; else led = led << 1; // запись в PIO_0_BASE (0x00000000) led IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, led); } } return 0; } Данный тест проводится на Циклоне 4 (DE0Nano Terasic). Проблема в том, что если количество байт в пакете небольшое (~40) то все работает нормально. С увеличением количества байт в пекете очевидно сбивается счетчик uart_count и первый синхробайт 0x55 уже не определяется. Код простейший. Подскажите пожалуйста что в нем не так?
Сообщение отредактировал Acvarif - Jun 26 2016, 07:37
|
|
|
|
|
 |
Ответов
|
Jun 26 2016, 10:20
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Немного переделал код. Заработало. CODE #include "system.h" #include "altera_avalon_pio_regs.h" #include "alt_types.h" #include "stdio.h" #include "sys/alt_irq.h" #include "altera_avalon_uart_regs.h" #include <unistd.h> #include <io.h>
//--------------------------------------------------------------------------------------------- // Константы
#define BAUD_RATE 115200
//--------------------------------------------------------------------------------------------- // Объявления функций
void UartIsr(void* context, alt_u16 id); void InitUart(alt_u32 BaudRate);
//--------------------------------------------------------------------------------------------- // Глобальные переменные
alt_u8 Start = 0; alt_u8 Buf_uart[256]; alt_u16 Uart_count = 0;
//--------------------------------------------------------------------------------------------- // Функции
//--------------------------------------------------------------------------------------------- // прерывания по UART
void UartIsr(void* context, alt_u16 id) { alt_u16 status; // Чтение регистра статуса для определения причины прерываний status = IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE); // Процесс чтения irq if (status & ALTERA_AVALON_UART_STATUS_RRDY_MSK) { Buf_uart[Uart_count] = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE); Uart_count++; // Очистка всех флагов ошибок IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE, 0); } if(Uart_count >= 72 && Buf_uart[0] == 0x55) { Start = 1; Uart_count = 0; } }
//--------------------------------------------------------------------------------------------- // инициализация Uart
void InitUart(alt_u32 BaudRate) { alt_u16 context_uart; alt_u16 divisor;
divisor = (ALT_CPU_FREQ/BaudRate) + 1; IOWR_ALTERA_AVALON_UART_DIVISOR(UART_0_BASE, divisor); IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK); // регистрация прерываний UART_0_IRQ alt_irq_register(UART_0_IRQ, &context_uart, UartIsr); // alt_irq_enable (UART_0_IRQ); }
//---------------------------------------------------------------------------------------------
int main (void) { alt_u8 led = 0x2; alt_u8 dir = 0;
InitUart(BAUD_RATE); alt_irq_enabled();
// main while while(1) { if(Start == 1) { Start = 0; // running led if(led & 0x81) dir = (dir ^ 0x1); if(dir) led = led >> 1; else led = led << 1; // write in PIO_0_BASE led IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, led); } } return 0; } Далее в SOPC в модуле UART убраз птичку с "Fixed baud rate" для возможности программного назначения частоты бод. Код (или SOPC система) не работает. Можно-ли программно корректировать частоту бод в модуле UART Nios?
Сообщение отредактировал Acvarif - Jun 27 2016, 09:26
|
|
|
|
|
Jun 27 2016, 12:17
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(gridinp @ Jun 27 2016, 13:05)  в статусе надо ещё проверять ALTERA_AVALON_UART_STATUS_PE_MSK и ALTERA_AVALON_UART_STATUS_FE_MSK
очистку флагов надо делать в IOWR_ALTERA_AVALON_UART_CONTROL, хотя может адреса со статусом и совпадают, не помню
смена скорости: IOWR_ALTERA_AVALON_UART_DIVISOR(base, div); С флагами вроде все нормально. Хотя еще проверю... А вот с установкой скорости все тоже. Не работает. Код: Код alt_u16 context_uart; alt_u16 divisor;
divisor = (ALT_CPU_FREQ/BaudRate) + 1; IOWR_ALTERA_AVALON_UART_DIVISOR(UART_0_BASE, divisor); IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK); Работатает только при Код #define UART_0_FIXED_BAUD 1 Странно. Думал имеется возможность немного корректировать скорость... модуль UART Quartus 11.0 Sp1. Может кто тоже сталкивался с таким казусом?
|
|
|
|
|
Jun 27 2016, 18:18
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Цитата(gridinp @ Jun 27 2016, 16:40)  ну в общем, чтобы по пунктам не обьяснять, смотрите в своем bsp файлы:
*_bsp/drivers/src/altera_avalon_uart_*.c
в частности функцию altera_avalon_uart_rxirq Да, есть такая функция CODE /* * altera_avalon_uart_rxirq() is called by altera_avalon_uart_irq() to * process a receive interrupt. It transfers the incoming character into * the receive circular buffer, and sets the apropriate flags to indicate * that there is data ready to be processed. */ static void altera_avalon_uart_rxirq(altera_avalon_uart_state* sp, alt_u32 status) { alt_u32 next; /* If there was an error, discard the data */
if (status & (ALTERA_AVALON_UART_STATUS_PE_MSK | ALTERA_AVALON_UART_STATUS_FE_MSK)) { return; }
/* * In a multi-threaded environment, set the read event flag to indicate * that there is data ready. This is only done if the circular buffer was * previously empty. */
if (sp->rx_end == sp->rx_start) { ALT_FLAG_POST (sp->events, ALT_UART_READ_RDY, OS_FLAG_SET); }
/* Determine which slot to use next in the circular buffer */
next = (sp->rx_end + 1) & ALT_AVALON_UART_BUF_MSK;
/* Transfer data from the device to the circular buffer */
sp->rx_buf[sp->rx_end] = IORD_ALTERA_AVALON_UART_RXDATA(sp->base);
sp->rx_end = next;
next = (sp->rx_end + 1) & ALT_AVALON_UART_BUF_MSK;
/* * If the cicular buffer was full, disable interrupts. Interrupts will be * re-enabled when data is removed from the buffer. */
if (next == sp->rx_start) { sp->ctrl &= ~ALTERA_AVALON_UART_CONTROL_RRDY_MSK; IOWR_ALTERA_AVALON_UART_CONTROL(sp->base, sp->ctrl); } } Находится в файле altera_avalon_uart_init.c Как она связана с тем, что uart не работает при софт установке скорости бод Код #define UART_0_FIXED_BAUD 0
Сообщение отредактировал Acvarif - Jun 27 2016, 18:19
|
|
|
|
Сообщений в этой теме
Acvarif Nios II Uart прерывания по приему байта Jun 26 2016, 07:29      Acvarif Цитата(gridinp @ Jun 27 2016, 22:46) да э... Jun 28 2016, 11:05       gridinp а, что вы кладете в делитель?
должно быть примерн... Jun 28 2016, 18:20       arpa-net Цитата(Acvarif @ Jun 28 2016, 12:05) Спас... Jun 29 2016, 00:01        Acvarif Цитата(arpa-net @ Jun 29 2016, 03:01... Jun 29 2016, 10:28         gridinp Цитата(Acvarif @ Jun 29 2016, 13:28) То р... Jun 29 2016, 13:59         arpa-net Цитата(Acvarif @ Jun 29 2016, 11:28) Поня... Jun 29 2016, 17:48
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|