|
|
  |
Работа TXC в USART, Не могу разобраться с флагом "окончание передачи", помогите |
|
|
|
Aug 22 2007, 06:13
|
Местный
  
Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101

|
Цитата(WHALE @ Aug 21 2007, 21:45)  Дык у аффтара проблемы с передачей,значит руками флаги дергать ваще не надо.байт в UDR -и смотри чего-там с прерываниями.И скачайте версию 4.13,там атымельцы здорово над переферией поработали. Согласен. Я удивился, как он этих флагов не видел. Или мышой не ткнул? А что нового в периферии в 4.13? У меня только нумерацию битов приходится всё время включать, больше новостей не заметил. Проц М16.
|
|
|
|
|
Aug 22 2007, 06:40
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Rst7 @ Aug 21 2007, 12:59)  Ну в принципе даже разрешение TXC можно не дергать, если вы можете дать гарантию, что время реакции на UDRE не превысит времени передачи символа. Ещё можно тупо в прерывании UDRE - если производится запись очередного байта в UDR, то не глядя заодно сбрасывать флаг TXC. В суме это даёт меньше кода, чем разрешение/запрещение TXCIE и защищает от задержки отработки UDRE. Так как если были запрещены прерывания и UDRE не отработало своевременно, успел установиться флаг TXC, то при разрешении прерываний (выходе из другого прерывания) первым будет передано управление на UDRE_vect.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Aug 22 2007, 12:55
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 22 2007, 13:09)  Одно место меня озадачило, в теле подпрограммы PutChar вы снова вызываете PutChar. Это что, такая рекурсия заложена, или как? Спасибо что проявили интерес ;> Да - там рекурсия. посылаем строку "hello\n" putchar автоматически добавит возврат каретки и терминал примет "hello\r\n". Цитата Вроде не должно работать. Попробуйте код. ;> Какой резон мне выкладывать что-то нерабочее?
|
|
|
|
|
Aug 23 2007, 09:19
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Aug 22 2007, 11:55)  Да - там рекурсия Посмотрел попристальнее - нет там никакой рекурсии. И вообще, проще было бы вызывать не rcall PutChar, a rcall __skip_add_cr (ну и названьице(:-)). И выполнение было бы быстрее, ведь рутина у вас и в прерывании вызывается... Цитата(defunct @ Aug 22 2007, 11:55)  Попробуйте код А чего его пробовать, и так видно, что тяжеловесно и неоптимально. Например, фрагмент с кольцевым буфером можно написать в два раза короче. А что там за пляски с бубнами в PutChar: in AH,SREG cli + out SREG,AH? Не проще ли обойтись связкой cli/sei. Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 12:49
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 23 2007, 12:19)  Посмотрел попристальнее - нет там никакой рекурсии. Смотрите пристальнее сразу. Ок? Есть там рекурсия, коль скоро функция вызывает сама себя. Цитата проще было бы вызывать не rcall PutChar, a rcall __skip_add_cr (ну и названьице(:-)). Не сомневаюсь что вы именно так и поступаете, у меня же все метки начинающиеся с "__" внутренние и я стараюсь их не вызывать, чтобы было меньше путаницы. Цитата А что там за пляски с бубнами в PutChar: in AH,SREG cli + out SREG,AH? Не проще ли обойтись связкой cli/sei. Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print? Не проще. Потому что вызывается эта функция еще и в прерывании. И вообще прежде чем хаить хамоватым тоном - разберитесь с кодом. Цитата Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print? опечатка.
|
|
|
|
|
Aug 23 2007, 16:14
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Aug 23 2007, 11:49)  Есть там рекурсия, коль скоро функция вызывает сама себя. Ну-ну, tell it your sailors(:-). Рекурсии там нет. Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности. Вот пример классической рекурсии. Код Задача заключается в том, чтобы найти по заданному n число последовательности Фибоначчи Fn. #include <stdio.h> #include <time.h> long F(unsigned int n) { return n <= 1 ? n : F(n-1) + F(n-2); } int main() { time_t begin, end; long res; for(int n = 0; n < 40; n++) { time(&begin); res = F(n); time(&end); printf("%-3i\t%-9li\t%-20.3f\n",n,res,difftime(end,begin)); } return 0; } Кстати, цикл является частным видом рекурсии. У вас ни того, ни другого. Цитата(defunct @ Aug 23 2007, 11:49)  Не сомневаюсь что вы именно так и поступаете, у меня же все метки начинающиеся с "__" внутренние и я стараюсь их не вызывать, чтобы было меньше путаницы. Дорогой мой, зачем метки тогда вообще писать. Я пишу программы так, чтобы они были эффективные и красивые, а не какие-то там крокозябры (это не вам). Цитата(defunct @ Aug 23 2007, 11:49)  Не проще. Потому что вызывается эта функция еще и в прерывании. Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает. Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом. Цитата(defunct @ Aug 23 2007, 11:49)  И вообще прежде чем хаить хамоватым тоном - разберитесь с кодом Прошу прощения, если кого-то обидел, но я никому не хамил и никого не хаял. Была выложена программа, идёт её обсуждение, ничего личного.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 17:54
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 23 2007, 19:14)  Ну-ну, tell it your sailors(:-). Рекурсии там нет. Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности. Вот пример классической рекурсии. Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области. рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи. В программировании рекурсия — вызов функции или процедуры из неё же самой источник: http://ru.wikipedia.org/wiki/РекурсияЦитата Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает.  Цитата Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом. Теоретически возможно. Атомарность Print я не организовывал. Но конструкция реализованная в PutChar не препятствует организации атомарности Print. тем же самым in Rr, SREG - cli - out SREG, Rr Цитата Дорогой мой, зачем метки тогда вообще писать. Во-первых выбирайте выражения. Своему бойфренду можете говорить "дорогой мой". Во-вторых, я не виноват что русский язык порождает неоднозначность ("не вызывать" - имелось в виду "call" не делать. ) в третьих - это такой стиль - для обозначения внутренних меток (локальных для функций) на которые осуществяется условный переход я применю "тэг" - "__".
|
|
|
|
|
Aug 23 2007, 18:42
|

Знающий
   
Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768

|
Цитата Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности А откуда такое определение рекурмии,ссылку можно? Цитата В программировании рекурсия — вызов функции или процедуры из неё же самой Вот с этим не поспоришь. И чего-вы к обозначению внутренних меток прицепились?По моему,нормальная идея визуально разделять локальные и глобальные метки. З.Ы. вы кодер,не знающий ошибок?
--------------------
"Hello, word!" - 17 errors 56 warnings
|
|
|
|
|
Aug 23 2007, 21:29
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Aug 23 2007, 17:54)  Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области. рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи. Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию F на более заметную RECURRENCE). Код long RECURRENCE(unsigned int n) { return n <= 1 ? n : RECURRENCE(n-1) + RECURRENCE(n-2); } Напишите ваш код PutChar на си в таком же виде, тогда и будем говорить, что верно, а что неверно. Интересно, что у вас будет параметром рекурсии? Цитата(defunct @ Aug 23 2007, 17:54)  Теоретически возможно. Атомарность Print я не организовывал. Но конструкция, реализованная в PutChar не препятствует организации атомарности Print. тем же самым in Rr, SREG - cli - out SREG, Rr Так я и сказал. что все эти примочки внутри PutChar не нужны, не решают они задачу до конца, а снаружи атомарность передачи строки вы не обеспечили. И не теоретически, а сугубо практически, поверьте. Цитата(defunct @ Aug 23 2007, 17:54)  Во-первых, выбирайте выражения. Своему бойфренду можете говорить "дорогой мой" Да что ж такое! Такое впечатление, что или у всех мозги такие извращенные, или все свихнулись на этой секссвободе, что ни скажешь, всё переводят в плоскость гениталий. Вы уж, уважаемый, тоже слова выбирайте. Цитата(SasaVitebsk @ Aug 23 2007, 18:16)  =GM=, при всём уважении к Вашим знаниям давайте будем добрее друг к другу. Так вы отобъёте всякое желание выложить свою прогу, чтобы кому-то помочь.  Знаний как раз маловато, спасибо форуму, много даёт в плане самообразования. Да я...белый и пушистый, defunct'а почти люблю (как брата, а то опять поймет не в той плоскости(:-)). Что касается проги, не собирался я её критиковать, с первого взгляда она мне понравилась, посмотрел по диагонали - в подпрограмме вывода символа вроде используется рекурсия, вот думаю, люди рекурсию применяют, а я от неё как чёрт от ладана, ну я и спросил спроста, а потом уж стал смотреть, а он мне отвечает, да, там рекурсия, да какая рекурсия, курам на смехЦитата(SasaVitebsk @ Aug 23 2007, 18:16)  Любая мало-мальски приличная прога содержит ошибки. Иногда их вылавливаешь годами. Плюс различные предпочтения у каждого программиста. Это как аккорды на гитаре. Один пользуется чаще такими, а другой другими. Но если оба музыканта, то музыка всё равно звучит.  Согласен. Ошибок в любой программе полно, у самого так. Смотришь на программу годичной давности, и думаешь, неужели это я написал такое гуано? Ну посмотрел я его программу, ну высказал замечания, будь благодарен, что кто-то потратил своё время, разобрался, принял участие, ответил, что плохого? Почему сразу надо воспринимать как наезд, которого и в помине не было. Дефункту не надо было говорить, чтоб код испытал(:-). Да если б все мои программы так критиковали, это было бы здорово, и программы были бы в стократ лучше...
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 21:57
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 24 2007, 00:29)  Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию F на более заметную RECURRENCE). Взглянул непредвзято.. будем считать, что вы взяли определение рекурсии не из той предметной области. Цитата Напишите ваш код PutChar на си в таком же виде, тогда и будем говорить, что верно, а что неверно. Интересно, что у вас будет параметром рекурсии? отправляемый char, а что еще может быть параметром? функциональный аналог ассемблерной функции: Код void put(U8 ch) { if (ch == 0x0A) // add CR char ahead of LF put(0x0D); { U8 IStatus = ILock() pRing->storage[ pRing->tail ] = ch; pRing->tail = RingNextTail( pRing ); IUnlock( IStatus ); } } Цитата Так я и сказал. что все эти примочки внутри PutChar не нужны, не решают они задачу до конца, Это вам так кажется. Примочки внутри putchar решают свои задачи: - атомарность выгрузки символа в очередь - добавление символа CR Цитата а снаружи атомарность передачи строки вы не обеспечили. И не теоретически, а сугубо практически, поверьте. Господи, да что вы цепляетесь к фантикам от конфет. Чес слово. Уж не пойму или у меня там полный бред в коде или у вас проблемы с прочтением алгоритма из асм программы. поменять Print так: Код /* * Print() * Выводит строки размещенные во флеш памяти через PutChar * ---> Z - указатель на строку оканчиваемую \0 во флеш * <--- ничего не возвращает */ Print: in AH, SREG push AH cli __do_output: lpm; // читаем данные флеш adiw Z, 1 // увеличим указатель на 1 (z++) mov AL, R0 rcall PutChar tst AL brne __do_output pop AH out SREG, AH ret и будет обеспечиваться атомарность. push/pop конечно же можно сократить если использовать какой-либо другой регистр для хранения SREG вместо AH, но поставил специально для наглядности. Цитата да какая рекурсия, курам на смех Маленькая простенькая - но рекурсия, т.к. функция вызывает сама себя. Прочитайте определение рекурсии на wiki. Цитата Ну посмотрел я его программу, ну высказал замечания, будь благодарен, что кто-то потратил своё время, разобрался, принял участие, ответил, что плохого? Я выразил вам благодарность и попытался нормально ответить на ваши вопросы вначале. PS: я и сейчас пытаюсь отвечать на ваши вопросы по-сущесту, с приведением ссылок и примеров. Может вы просто не замечаете?
|
|
|
|
|
Aug 23 2007, 22:22
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(defunct @ Aug 23 2007, 21:57)  Уж не пойму или у меня там полный бред в коде или у вас проблемы с прочтением алгоритма из асм программы. поменять Print так: Код /* * Print() * Выводит строки размещенный во флеш памяти через UART * ---> Z - указатель на строку оканчиваемую \0 во флеш * <--- ничего не возвращает */ Print: in AH, SREG push AH cli __do_output: lpm; // читаем данные флеш adiw Z, 1 // увеличим указатель на 1 (z++) mov AL, R0 rcall PutChar tst AL brne __do_output pop AH out SREG, AH ret и будет обеспечиваться атомарность Ну, это другое дело. Но тогда сохранение/восстановление статус-регистра в PutChar не нужно, о чём я и толкую последние две страницы. Кстати, неплохо бы добавить проверку на переполнение буфера в подпрограмме обработки прерываний по приему. UART_RX_ISR так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Aug 23 2007, 22:41
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(=GM= @ Aug 24 2007, 01:22)  Ну, это другое дело. Но тогда сохранение/восстановление статус-регистра в PutChar не нужно, о чём я и толкую последние две страницы. Нужно! Т.к. PutChar автономная функция, и кроме Print может быть использована где угодно. "Лучше перебдеть чем "недобдеть" ;> Цитата Кстати, неплохо бы добавить проверку на переполнение буфера в подпрограмме обработки прерываний по приему. Это так и было задумано.. Практика показывает что для консольных приложений (а пример относился как раз консоли) много лучше допускать опустошение Tx (при переполнении) чем притормаживать CPU ожиданием освобождения места. Цитата UART_RX_ISR так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг. RX_ISR в идеале должен работать со входной очередью. Вывод "Эхо" по скорости заполнения не быстрее TX, переполнений по вине RX потока быть не должно. Ну а в случае когда полный overload, то деваться некуда или сбросить TX очередь или ждать окончания TX. Но мы не можем торчать в прерывании и ждать когда освободится место в очереди..
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|