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

Гарантия того, что по USART все данные ушли

Значит, не один я так делаю. Почему же советы: "перед выдачей - сбросьте ТХС"?

Думаю так делают все, кто работает с RS485. Я правда использую намного более низкие скорости 19200-38400, так что и по прерываниям все получается неплохо. Но и при 2-х мегабитах интервал передачи байта 80 тактов, так что если в критическую секцию обернуть и выдачу в UDR и сброс TXC, все должно работать нормально.

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


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

1. Данные загружаются в UDR по прерыванию USART Data Register Empty

2. Перед загругкой последнего байта сбрасывается флаг TXC; последний байт загружается в UDR; разрешаются прерывания от USART Tx Complete

3. Наступает прерывание по TXC - считаем, что все байты переданы, что не всегда верно (см. выше - сообщение #5).

 

1. Иниц. указателя и счетчика байт

2. Разрешение UDRIE

volatile uint8_t *tx_ptr;
volatile uint8_t tx_cnt;
void new_xmit(void *buff, uint8_t len)
{
  tx_ptr = buff;
  tx_cnt = len;
  UCSRB |= (1<<UDRIE); 
}

 

3. Прерывание подхватывает поток: (GCC)

// ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
UDR= *tx_ptr++;
UCSRA &= ~(1<<TXC);
//}
if(--tx_cnt==0)
{
  UCSRB &= ~(1<<UDRIE); 
  UCSRB |= (1<<TXCIE);
}

 

4. Программа смотрит, разрешено ли прерывание UDRE или TXC в зависимости от того что надо.

 

Если используем неблокирующие прерывания, приходится применять критическую секцию. :laughing:

 

Если надо непрерывную передачу, контроль правильности/непрерывности можно сделать проверкой TXC перед передачей.

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


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

И вот вопрос: контроллеру нужно заснуть, как убедится, что все данные отосланы? Будет ли нормально, если я перед каждой посылкой байта (неважно последний он или нет) буду сбрасывать этот флаг?

Не пойму почемуони не сделали, что бы, к примеру, при записи данных в UDR флаг TXC сбрасывался аппаратно?

Если взглюнуть на структурную схему USART можно увидеть , что флаг TXC установиться при условии , что установлен флаг UDR и закончена передача байта , собственно он и сигнализирует о том , что сдвиговый регистр пуст и новых данных в буфере передачи нет . А , что Вы будете делать с ним дальше - значение не имеет , можете сбросить , записав единицу и уйти спать

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


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

Прерывания я не использую, поэтому флаг TXC сам не сбросится. Придется его сбрасывать программно.

или придется начать использовать прерывания.

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


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

Объясню ситуацию...
Сделайте отправку целиком по TXC, без UDRE. При отправке данных в цикле и по флагам, по-моему, ничуть не тормознее получится, и гарантированно отправите данные...

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


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

Это-то - понятно. Интересует: как у Вас устроена программа, что по этому прерыванию Вы гарантировано знаете, что все байты переданы?

Ваш изначальный вопрос касался 485-го. Так вот в контексте 485-го все держится на модели "запрос-ответ". Драйверу UARTа попросту не дается следующий __пакет__ до тех пор пока нас об этот не попросят, либо до тех пор пока нам не ответят, либо до тех пор пока не завершится таймаут.

 

Из этого построение программы такое:

Есть кольцевой буфер и есть put() который пишет в этот буфер. TXC прерывание разрешено постоянно и управляет направлением трансивера 485-го. (По TXC драйвер переключается на прием.) Флаг TXC руками не трогается никогда.

 

В буфер помещается отправляемый пакет. Перед записью в UDR делается переключение трансивера 485 на передачу.. По UDRE - вычитка и отправка следующего байта из буфера.

 

В системе нет настолько тяжелых обработчиков прерываний чтобы UDRE прерывание откладывалось настолько долго, что за это время могло возникнуть TXC прерывание, (суммарная латентность всех прерываний не превышает интервала одного символа UART'а). Поэтому все прекрасно работает.

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


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

Флаг TXC руками не трогается никогда.

 

В системе нет настолько тяжелых обработчиков прерываний чтобы UDRE прерывание откладывалось настолько долго, что за это время могло возникнуть TXC прерывание, (суммарная латентность всех прерываний не превышает интервала одного символа UART'а). Поэтому все прекрасно работает.

Вот я - не понимаю:

1) откуда берется священная корова непрерывности данных в пакете, без тайм-аутов.

2) для чего TXC прерывание все время держать разрешенным.

Объясните, пожалуйста

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


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

RS485, скорости до 115200. Делаю так же: формирую сообщение в буфере, переключаю на передачу, записываю первый байт в UDR. Дальше работают только прерывания: UDRE досыпает следующий байт, TXC переключает интерфейс на приём.

 

Как я узнаю, что все байты ушли? А как я знаю, сколько байтов передавать? По счётчику! Пока он больше 0 (или, если строка ASCIIZ байт данных не равен 0) работаем на передачу. Я успеваю это делать в прерывании UDRE. Если бы не успевал, проверил бы счётчик и в TXC, пока не переключил на приём.

Изменено пользователем Maik-vs

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


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

1) откуда берется священная корова непрерывности данных в пакете, без тайм-аутов.

application драйверу его так передает. Я так строю программу и гарантирую эту непрерывность.

 

2) для чего TXC прерывание все время держать разрешенным.

А зачем его смыкать туда-сюда, код раздувать? Один раз при настройке уарта разрешили и забыли о нем вообще.

Ведь все что оно делает, это:

 

__interrupt void uart_TxCompleteHandler(void)

{

#if (UART0_RS485)

// handle 485 driver direction

PortX &= ~(1 << RS485_REDE_Pin);

#endif

}

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


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

admiral,

если "правильность" софта не пугает и это будет временной мерой, то достаточно будет перед засыпанием установить задержку в виде N*2 холостых циклов. где N - это к-во тактов необходимые для отправки одного байта по USART. а умножаем на 2, т к у USART'а двойная буферизация.

 

глупее не бывает, но вроде как временная мера сойдет

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


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

А зачем его смыкать туда-сюда, код раздувать? Один раз при настройке уарта разрешили и забыли о нем вообще.

Если есть возможность прогнозировать приход прерываний, то это работает. Если же нет, то RS485 идет в лес. :(

А ведь есть более приоритетные, нежели от UDRE, прерывания - INTx, абсолютно асинхронные. Тут прогнозы не всегда работают.

 

Ведь все что оно делает, это:

__interrupt void uart_TxCompleteHandler(void)

{

#if (UART0_RS485)

// handle 485 driver direction

PortX &= ~(1 << RS485_REDE_Pin);

#endif

}

А добавить туда еще проверку счетчика байт и проблема тоже решится. Не все передали - выходим из прерывания без переключения направления драйвера. ИМХО тоже вариант.

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


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

1) откуда берется священная корова непрерывности данных в пакете, без тайм-аутов.
Один из вариантов - канал RS-485 без растяжек (+ к питанию, - к земле). Если все абоненты молчат, то состояние линии не определено, и от помех появляется мусор, успешно принимающийся МК. Поэтому во время передачи пакета на приём переключаться нельзя до окончания передачи всего пакета ;(

Также, если более чем один мастер в канале...

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


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

Если все абоненты молчат, то состояние линии не определено, и от помех появляется мусор, успешно принимающийся МК. Поэтому во время передачи пакета на приём переключаться нельзя до окончания передачи всего пакета ;(

Вы неверно представляете этот вариант. Или я :)

Объясняю своими словами:

Если передающий встал на передачу, и между символами будет пауза, то эта пауза - не повод отключать TXE, если это все в пределах наперед заданного тайм-аута. Какого именно? Такого, чтобы в наихудшем случае программа успевала отослать данные. В этом случае мусор в линию не валится и на приемнике имеем красивый "1".

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


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

Объясняю своими словами...
Ммм.. да, я под непрерывностью имел в виду именно это :)

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


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

В системе нет настолько тяжелых обработчиков прерываний чтобы UDRE прерывание откладывалось настолько долго, что за это время могло возникнуть TXC прерывание, (суммарная латентность всех прерываний не превышает интервала одного символа UART'а). Поэтому все прекрасно работает.
Это - хорошо, когда нет тяжелых прерываний... "Тяжесть" - штука относительная. Число "лёгких" прерываний с приоритетом выше чем у USART может быть достаточно для того, чтобы в сумме они составили "одно тяжелое". Да и "тяжелость" отпределяет ещё и скоростью передачи, особенно на очень высоких скоростях (тут уж - как не облегчай прерывания, а при некотором числе высокоприоритетных прерываний они всё равно превращаются в "тяжелое").

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


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

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

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

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

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

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

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

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

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

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