реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> LPC2124 проблема с прерыванием на UART THRE
MALLOY2
сообщение Feb 21 2007, 14:51
Сообщение #1


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



При включении прерывания U0IER_bit.THREIE = 1 не происходит прерывание при этом в U0LSR бит THRE и TEMT установлины. Происходит только после того как что то запишеш в U0THR. Я уже замучялся...

Код инициализации:

Код
    ubuff = &u0buff;
       ubuff->tx_buff = u0_buff_tx;
       ubuff->rx_buff = u0_buff_rx;
    ubuff->tx_buff_size = sizeof(u0_buff_tx);
    ubuff->rx_buff_size = sizeof(u0_buff_rx);
    PCONP_bit.PCURT0 = 1; //UART power on
    PINSEL0_bit.P0_0 = 1;//select pin for UART0  
    PINSEL0_bit.P0_1 = 1;
    U0FCR = 0xC1;
    uart_bautrate(UART0,32);
    U0LCR = 0x03; //1-8-N
    INT_Plug(UART0_ISR,VIC_UART0,IRQ_int,IRQ_Slot0);
    VIC_IntEnable(BIT(VIC_UART0));
    U0IER_bit.RDAIE = 1;
    U0IER_bit.RXLSIE = 1;


код функции передачи


Код
int uart_send_str(TUartChanel dev, const char* data)
{
  TUART_BUFF* ubuff;
  int len,fsize,head,i;
  unsigned long old_irq;
  char *ptr;
  ubuff = &u0buff;
  fsize = 0;
  len = strlen(data);
  ptr = (char*)data;
  do
   {
    do fsize = uart_tx_free(dev); while(fsize == 0);
    if (fsize > len) fsize = len;
    head = ubuff->tx_head;
    for (i=0;i<fsize;i++)
     {
      ubuff->tx_buff[head] = *ptr++;
      if(++head == ubuff->tx_buff_size) head = 0;
     }
    ubuff->tx_head = head;
    old_irq = disable_IRQ();
    ubuff->tx_size = ubuff->tx_size+i;
    restore_IRQ(old_irq);
    U0IER_bit.THREIE = 1; //<= включаем прерывание и оно не происходит
    len = len - fsize;    
   }
  while((*ptr!='\0')&&(len > 0));
  return(0);
};


код main

Код
  //U0THR = 0x00;  //<- если включить эту строку UART начинает генерить прерывания
  while(1)
   {
     uart_send_str(UART0,"HELLO WORD");
   }





Код обработчика:

Код
void UART0_ISR (void)
{
unsigned int tmp;
TUART_BUFF* ubuff = &u0buff;  
switch((U0IIR>>1)&0x7)
  {
   case IIR_THRE:   // continue sending data
        if (ubuff->tx_size == 0)U0IER_bit.THREIE = 0;
        else
         {
          U0THR = ubuff->tx_buff[ubuff->tx_tail];  
          ubuff->tx_size--;
          if (++ubuff->tx_tail == ubuff->tx_buff_size) ubuff->tx_tail = 0;
         }  
        break;
   case IIR_RSL:    
        tmp = U0LSR;
        ubuff->last_error |= tmp & 0x9E;
        break;
   case IIR_RDA:    // receive data
   case IIR_CTI:    // time out
        tmp = U0RBR;
        if (ubuff->eho_state == ON)
         {
          while(!U0LSR_bit.THRE);
          U0THR = tmp;
         };    
        if ((tmp == 0x0D) || (tmp == 0x0A)) ubuff->str_flag = 1;
        if (ubuff->rx_size == (ubuff->rx_buff_size-1))
         {
          ubuff->last_error |= RC_FIFO_OVERRUN_ERR;
         }
        else
         {
          ubuff->rx_buff[ubuff->rx_head] = tmp;    
          ubuff->rx_size++;
          if (++ubuff->rx_head == ubuff->rx_buff_size) ubuff->rx_head = 0;
         }
        break;
   }//switch
}  //isr
Go to the top of the page
 
+Quote Post
DASM
сообщение Feb 21 2007, 15:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493



Читаем. Внимательно.
The UART0 THRE interrupt (U0IIR[3:1] = 001) is a third level interrupt and is activated
when the UART0 THR FIFO is empty provided certain initialization conditions have been
met. These initialization conditions are intended to give the UART0 THR FIFO a chance to
fill up with data to eliminate many THRE interrupts from occurring at system start-up. The
initialization conditions implement a one character delay minus the stop bit whenever THRE=1 and there have not been at least two characters in the U0THR at one time since
the last THRE = 1 event. This delay is provided to give the CPU time to write data to
U0THR without a THRE interrupt to decode and service. A THRE interrupt is set
immediately if the UART0 THR FIFO has held two or more characters at one time and
currently, the U0THR is empty.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2007, 15:13
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(MALLOY2 @ Feb 21 2007, 13:51) *
При включении прерывания U0IER_bit.THREIE = 1 не происходит прерывание при этом в U0LSR бит THRE и TEMT установлины. Происходит только после того как что то запишеш в U0THR. Я уже замучялся...
(разводя руками) Ну вот построен он так. Я тоже огорчен. В параллельной ветке выложил свои исходники с использованием FIFO. В простейшем же случае при входе в функцию отсылки проверяю, взведен ли THREIE и если не взведен - взвожу и кидаю байт сразу в THR, если взведен - складирую в буфер а по прерыванию забираю из буфера и если буфер пуст - сбрасываю THREIE.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Feb 21 2007, 15:43
Сообщение #4


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Вот кривизна, одно растройство, придется драйвер переписывать sad.gif, а что их привело к такому кривому решению ?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2007, 15:56
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(MALLOY2 @ Feb 21 2007, 14:43) *
а что их привело к такому кривому решению ?
16550
Причем признаки "цельнотянутости" есть в user manual:
Цитата
7:6 Rx Trigger Level Select
00: trigger level 0 (default=1 character or 0x01h)
01: trigger level 1 (default=4 characters or 0x04h)
10: trigger level 2 (default=8 characters or 0x08h)
11: trigger level 3 (default=14 characters or 0x0eh)
These two bits determine how many receiver UART0 FIFO characters must be written
before an interrupt is activated. The four trigger levels are defined by the user at
compilation
allowing the user to tune the trigger levels to the FIFO depths chosen.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Feb 21 2007, 16:19
Сообщение #6


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
7:6 Rx Trigger Level Select
00: trigger level 0 (default=1 character or 0x01h)
01: trigger level 1 (default=4 characters or 0x04h)
10: trigger level 2 (default=8 characters or 0x08h)
11: trigger level 3 (default=14 characters or 0x0eh)
These two bits determine how many receiver UART0 FIFO characters must be written
before an interrupt is activated. The four trigger levels are defined by the user at
compilation allowing the user to tune the trigger levels to the FIFO depths chosen.


а это к чему ? речь идет о передатчике.
Go to the top of the page
 
+Quote Post
Alex03
сообщение Feb 21 2007, 17:19
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(MALLOY2 @ Feb 21 2007, 17:43) *
Вот кривизна, одно растройство, придется драйвер переписывать sad.gif, а что их привело к такому кривому решению ?

К какому кривому?
Мой примерный перевод (ускоренным ПРОМПТом)
Цитата
UART0 THRE прерывание (U0IIR [3:1] = 001) - прерывание третьего уровня (приоритета), оно активизируется когда UART0 THR FIFO пуст и выполнены определенные условия.
Эти условия предназначены, чтобы дать UART0 THR FIFO шанс заполниться данными, чтобы устранить много прерываний THRE при запуске передачи.
Прерываний THRE имеет задержку на один символ минус СТОП-бит всякий раз, когда THRE=1 и не было по крайней мере двух символов в U0THR единовременно начиная с последнего THRE = 1 события. Эта задержка создана, чтобы дать время ЦПУ на запись данных в U0THR без прерывания THRE.
Прерывание THRE активизируется немедленно, если UART0 THR FIFO содержал как минимум два символа единовременно, а в настоящее время U0THR пуст.


Если плюёте пачками (в идеале по 16 байт) то прерывание когда очередь пуста, но ещё передаётся последний байт. Т.е. можно ещё 16 байт в ФИФО загонять.
Если шлёте по одному байту то прерывание когда передаётся стоповый бит.

Вот отсутствие прерывания по TEMP многие кто реализовывал 485 считают более существенным недостатком.
Но... Во времена создания 16550 считали каждый транзистор в чипе. smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2007, 17:23
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(MALLOY2 @ Feb 21 2007, 15:19) *
а это к чему ? речь идет о передатчике.
Это к тому, что UART исходно был в виде макрофункции, т.е. не собственная разработка или если собственная, то не конкретно под LPC. И его просто подцепили к ядру и скопировали документацию, документацию при этом даже не вычистив. Т.е. кривое решение не в том что так реализовано функционирование, а в том что прицепили именно этот готовый UART.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Alex03
сообщение Feb 21 2007, 17:30
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(Alex03 @ Feb 21 2007, 19:19) *
Если шлёте по одному байту то прерывание когда передаётся стоповый бит.

Вот отсутствие прерывания по TEMP многие кто реализовывал 485 считают более существенным недостатком.

Написал и подумал... А ведь это возможное решение.
Т.е. при передаче песледний символ отправлять всегда отдельно. Тогда прерывание будет уже во время передачи СТОП-бита, который единичный. Конечно нехорошо в это время выключать передатчик 485, но в ряде случаев видимо получим приемлимый вариант?
Подождать тем же полингом один бит всегда дешевле чем весь символ. Или например физический интерфейс типа к-лайна в авто, там оно видимо покатит.
Ктонить пробовал?

Раньше я про посимвольную передачу чтото и не думал, ФИФО по максимуму. smile.gif
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Feb 21 2007, 17:41
Сообщение #10


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
К какому кривому?
Мой примерный перевод (ускоренным ПРОМПТом)


UART0 THRE прерывание (U0IIR [3:1] = 001) - прерывание третьего уровня (приоритета), оно активизируется когда UART0 THR FIFO пуст и выполнены определенные условия.
Эти условия предназначены, чтобы дать UART0 THR FIFO шанс заполниться данными, чтобы устранить много прерываний THRE при запуске передачи.
Прерываний THRE имеет задержку на один символ минус СТОП-бит всякий раз, когда THRE=1 и не было по крайней мере двух символов в U0THR единовременно начиная с последнего THRE = 1 события. Эта задержка создана, чтобы дать время ЦПУ на запись данных в U0THR без прерывания THRE.
Прерывание THRE активизируется немедленно, если UART0 THR FIFO содержал как минимум два символа единовременно, а в настоящее время U0THR пуст.


кривизна в том, что при пустом передатчике и включении прерываний THRE прерывание не возникает пока не запишешь в THR хотя бы 1 символ. Не знаю откуда там они что сдирали или делали но у меня лежит плата с ST16C1550 и все он генерирует при включении прерывания.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 21 2007, 18:25
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(MALLOY2 @ Feb 21 2007, 16:41) *
но у меня лежит плата с ST16C1550 и все он генерирует при включении прерывания.

Вот именно он и "кривой", если так поступает.
У прародителя прерывание генерится при передаче стопового бита. Кроме того наличие "ложного" прерывания ничего не решает - ну разрешили прерывание, ну получили стартовый пинок. Ну а потом пауза в передаче и ..... кто пинок делать будет? 'Проблема' отсутствия прерывания
при его первом разрешении просто высосана из пальца.



Цитата(Alex03 @ Feb 21 2007, 16:30) *
Раньше я про посимвольную передачу чтото и не думал, ФИФО по максимуму. smile.gif

Так отключите FIFO и посимвольно с полным контролем над передачей.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Feb 21 2007, 18:38
Сообщение #12


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
Ну а потом пауза в передаче и ..... кто пинок делать будет? 'Проблема' отсутствия прерывания
при его первом разрешении просто высосана из пальца.


Это как раз и проблема, так я в процедуре отправки скопировал в буфе включил прерывание и он пошел колбасится, а тут еще и пинать надо smile.gif , так что это проблема не первого включения а проблема связана с тем что когда нечего передавать надо выключить прерывание, а когда надо что то передать приходится пинки раздавать разве это работа ?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 21 2007, 20:36
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(MALLOY2 @ Feb 21 2007, 17:38) *
Это как раз и проблема

Мне бы всегда такие "проблемы".
В "идеальном" с Вашей точки зрения железе дергать разрешение прерывания когда есть/нет чего передавать (разбираясь перед этим есть или нет чего)это типа "прямо" и правильно smile.gif. А глянуть на один флаг в момент начала передачи порции это "разве это работа".

Это гипотетический "идеальный" описанный Вами алгоритм.
Код
void print_zzz( char *string )
{
//"я в процедуре отправки скопировал в буфер"
    while( *string )
      {    tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++;
              tbuf.tail++;
    }
//"включил прерывание"
    U0IER |= IER_THREIE;

//"и он пошел колбасится"
}

После того, как отколбасился еще некая процедура должна по каим-то признакам запретить прерывание

Это "НЕПРАВИЛЬНЫЙ"
Код
void print_zzz( char *string )
{
    U0THR = *string++;
    while( *string )
      {    tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++;
              tbuf.tail++;
    }
}

Ну и где "проблема"???


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 21 2007, 22:22
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(zltigo @ Feb 21 2007, 19:36) *
После того, как отколбасился еще некая процедура должна по каим-то признакам запретить прерывание
само прерывание - если из буфера извлечен последний символ.

Цитата(zltigo @ Feb 21 2007, 19:36) *
Это "НЕПРАВИЛЬНЫЙ"
Код
void print_zzz( char *string )
{
    U0THR = *string++;
    while( *string )
      {    tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++;
              tbuf.tail++;
    }
}

Ну и где "проблема"???

print_zzz("Tipa ");
print_zzz("test");
В результате "Tt" попало в FIFO а "ipa est" в буфер. Неувязка.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 21 2007, 22:40
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ Feb 21 2007, 21:22) *
Неувязка.

Читаем внимательно - приводился текст ТОЧНО по предложенному возмущающимся заданию. В задании НЕ ПРЕДУСМОТРЕН вариант, когда вызов функции запонения буфера производится до его опустошения. Какие проблемы?
В противном случае - заводится флаг и реальная функция у меня выглядит так:
Код
void print_str( char *string )
{
    if( !(status_word & STW_THR_BUSY) )
    {   status_word |= STW_THR_BUSY;
        U0THR = *string++;
    }
    while( *string )
      {    tbuf.buf[tbuf.tail&(TBUF_SIZE_MSK)] = *string++;
              tbuf.tail++;
    }
}



Цитата(Сергей Борщ @ Feb 21 2007, 21:22) *
само прерывание - если из буфера извлечен последний символ.

Само - нет. Для "хорошего" UART придется еще написать:
U0ICR |= IER_THREIE;
Для "плохого" - ничего лишнего.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 04:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016