Перейти к содержанию
    

BF527 UART0 UART1 одновременная работа

На BF527 использую оба UART одновременно.

Большая часть данных это выдача из процессора и немного прием данных.

Есть исходный код который без проблем работал на BF533 (там только один UART).

Немного его переделали добавив туда второй UART.

Иногда при старте в один из UART не выдаются данные.

Но чаще данные перестают идти через десятки секунд на одном из них (на любом)

А еще через некоторое время перестают выдаваться и на втором.

При этом остальная часть программы работает без каких-либо проблем.

Прием по обоим UART также продолжает работать.

Через JTAG вижу что перестают возникать прерывания по опустошению регистра THR.

Часто бывает так что там даже данные не нулевые. Записал туда а они не ушли.

Код прилагаю

 

/**
  * @brief  UART interface initialization
  *         GPIO function set, interrupts enable
  * @param     uartnum uart number 0 or 1
  *
  * @return baudrate uart baudrate bit per second
  */
int InitUart(u32 uartnum, u32 baudrate)
{
    int ret = 1;

    register_handler(ik_ivg10, UART_ISR);        // UART RX ISR       -> IVG 10
    register_handler(ik_ivg7, UART_ERR_ISR);    // UART Error ISR -> IVG 7
    
    baudrate = GetSCLK()/16/baudrate;

    if(uartnum == 0)
    {
        *pUART0_GCTL |= UCEN;               // enable clock
        *pUART0_LCR |= DLAB;                  // enable acces to DLL and DLH
                                                         //
        *pUART0_DLL = (char)baudrate;          // BAUD_RATE = (27MHz*10(MSEL))/(5*16*57600)
        *pUART0_DLH = (char)(baudrate>>8);     //
        *pUART0_LCR = 0x03;

        *pPORTG_FER |= (PG7 | PG8);

        *pPORTG_MUX |= (1<<5);
        *pPORTG_MUX &= ~(1<<4);

         *pUART0_IER |= ELSI;         //enable UART ERR interrupt

         *pUART0_IER = ERBFI | ETBEI;                // enable rx tx uart interrupt
         *pSIC_IMASK0 |= IRQ_DMA8 | IRQ_DMA9;        // enable UART RX, UART TX interrupt
    }
    else if(uartnum == 1)
    {
         *pUART1_GCTL |= UCEN;    // enable clock
         *pUART1_LCR |= DLAB;    // enable acces to DLL and DLH
                                                 //
         *pUART1_DLL = (char)baudrate;          // BAUD_RATE = (27MHz*10(MSEL))/(5*16*57600)
         *pUART1_DLH = (char)(baudrate>>8);     //
         *pUART1_LCR = 0x03;

         *pPORTF_FER |= 0xC000;
         *pPORTF_MUX |= 0x0800;

         *pUART1_IER |= ELSI;         //enable UART ERR interrupt

         *pUART1_IER = ERBFI | ETBEI;                // enable rx tx uart interrupt
         *pSIC_IMASK0 |= IRQ_DMA10 | IRQ_DMA11;        // enable UART RX, UART TX interrupt

         //xdev_out(putchar_UART1);
         //xdev_in(getchar_UART1);
         xdev_out(putchar_UART0);
         xdev_in(getchar_UART0);
         getchar_argon = getchar_UART1;
         putchar_argon = putchar_UART1;
    }
    else
    {
        ret = -1;    // uart number doesn't exists
    }

    return ret;
}

 

void putchar_UART0(char ch)
{
    unsigned int intr_mask;
    
    while (tx_counter_0 == TX0_BUFFER_SIZE);
    
    intr_mask = cli();            //disable interrupt, save IMASK register into intr_mask

    if (tx_counter_0 || ((*pUART0_LSR & THRE)==0))        // write into buffer if (tx_counter != 0) or UART is busy
    {
        tx_buffer_0[tx_wr_index_0] = ch;
        tx_wr_index_0++;
        if (tx_wr_index_0 == TX0_BUFFER_SIZE) tx_wr_index_0=0;
        tx_counter_0++;
    }
    else
    {    
        *pUART0_THR = ch;
    }
    
    sti(intr_mask);
}

 

void putchar_UART1(unsigned char ch)
{
    unsigned int intr_mask;
    
    while (tx_counter_1 == TX1_BUFFER_SIZE);
    
    intr_mask = cli();            //disable interrupt, save IMASK register into intr_mask

    if (tx_counter_1 || ((*pUART1_LSR & THRE)==0))        // write into buffer if (tx_counter != 0) or UART is busy
    {
        tx_buffer_1[tx_wr_index_1] = ch;
        tx_wr_index_1++;
        if (tx_wr_index_1 == TX1_BUFFER_SIZE) tx_wr_index_1=0;
        tx_counter_1++;
    }
    else
    {    
        *pUART1_THR = ch;
    }
    
    sti(intr_mask);                //enable interrupt    
}

 

EX_INTERRUPT_HANDLER(UART_ISR)
{
    
    char z,data_0, data_1;    
    unsigned short int_ident_0, int_ident_1;    //UART Interrupt identification register
    
///////////For Interrupt From UART0//////////////////////////////////
//    *pPORTGIO_TOGGLE = PG_GREEN_LED;
    
    int_ident_0 = *pUART0_IIR;
    int_ident_0 >>= 0x01;
    
    
    switch(int_ident_0)
    {
        case 0x00:
        {
        
            break;
        } // end case 0x00
        
        case 0x01:    // UART_THR is empty
        {
            if(tx_counter_0)
            {
                tx_counter_0--;
                *pUART0_THR = tx_buffer_0[tx_rd_index_0];
                tx_rd_index_0++;
                if (tx_rd_index_0 == TX0_BUFFER_SIZE) tx_rd_index_0=0;
            }
            break;
        } // end case 0x01
        
        case 0x02:    // receive data ready
        {
    
            while (!(*pUART0_LSR & DR));
            data_0 = *pUART0_RBR;
            ssync();
            rx_buffer_0[rx_wr_index_0] = data_0;
    
            rx_wr_index_0++;    
            if(rx_wr_index_0 == RX0_BUFFER_SIZE)    rx_wr_index_0 = 0;
    
            rx_counter_0++;
            if(rx_counter_0 == RX0_BUFFER_SIZE)
            {
                rx_counter_0 = 0;    
                printf_UART0("\n\rx_buffer_1 overflow\n\r");
            }
            break;
        } // end case 0x02    
    } // end switch(int_ident)
    
///////////For Interrupt From UART1//////////////////////////////////
/////////////////////////////////////////////////////////////////////
    
    int_ident_1 = *pUART1_IIR;
    int_ident_1 >>= 0x01;
    
    switch(int_ident_1)
    {
        case 0x00:
        {
        
            break;
        } // end case 0x00
        
        case 0x01:    // UART_THR is empty
        {
            if(tx_counter_1)
            {
                tx_counter_1--;
                *pUART1_THR = tx_buffer_1[tx_rd_index_1];
                tx_rd_index_1++;
                if (tx_rd_index_1 == TX1_BUFFER_SIZE) tx_rd_index_1=0;
            }
            break;
        } // end case 0x01
        
        case 0x02:    // receive data ready
        {
    
            while (!(*pUART1_LSR & DR));
            data_1 = *pUART1_RBR;
            ssync();
            rx_buffer_1[rx_wr_index_1] = data_1;
    
            rx_wr_index_1++;    
            if(rx_wr_index_1 == RX1_BUFFER_SIZE)    rx_wr_index_1 = 0;
    
            rx_counter_1++;
            if(rx_counter_1 == RX1_BUFFER_SIZE)
            {
                rx_counter_1 = 0;    
                debugi("rx_buffer_1 overflow");
            }
            break;
        } // end case 0x02    
    } // end switch(int_ident)    

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На передачу смогу использовать DMA. На прием нет.

Мне кажется проблема связана с вложенными прерываниями, только не понимаю что не так.

Вложенные прерывания запрещены.

Но я не вижу проблем обслужить второе прерывание сразу после первого.

Ведь событие все равно должно взвестись, а потом будет обслужено.

Из-за моих подозрений на вложенные прерывания проблема может быть и на прием тоже.

Просто я ее ни разу не видел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...