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

Дык у аффтара проблемы с передачей,значит руками флаги дергать ваще не надо.байт в UDR -и смотри

чего-там с прерываниями.И скачайте версию 4.13,там атымельцы здорово над переферией поработали.

 

Согласен. Я удивился, как он этих флагов не видел. Или мышой не ткнул?

А что нового в периферии в 4.13? У меня только нумерацию битов приходится всё время включать, больше новостей не заметил. Проц М16.

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


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

Ну в принципе даже разрешение TXC можно не дергать, если вы можете дать гарантию, что время реакции на UDRE не превысит времени передачи символа.
Ещё можно тупо в прерывании UDRE - если производится запись очередного байта в UDR, то не глядя заодно сбрасывать флаг TXC. В суме это даёт меньше кода, чем разрешение/запрещение TXCIE и защищает от задержки отработки UDRE.

Так как если были запрещены прерывания и UDRE не отработало своевременно, успел установиться флаг TXC, то при разрешении прерываний (выходе из другого прерывания) первым будет передано управление на UDRE_vect.

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


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

To defunct. Посмотрел на ваш код.

Пример написан под AT90S2313, чтобы переделать под Tiny2313 надо будет поменять таблицу векторов и возможно пару штрихов с настройкой UART'a

Одно место меня озадачило, в теле подпрограммы PutChar вы снова вызываете PutChar. Это что, такая рекурсия заложена, или как? Вроде не должно работать.

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


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

Одно место меня озадачило, в теле подпрограммы PutChar вы снова вызываете PutChar. Это что, такая рекурсия заложена, или как?

Спасибо что проявили интерес ;>

Да - там рекурсия.

посылаем строку "hello\n"

putchar автоматически добавит возврат каретки и терминал примет "hello\r\n".

 

Вроде не должно работать.

Попробуйте код. ;>

Какой резон мне выкладывать что-то нерабочее?

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


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

Да - там рекурсия

Посмотрел попристальнее - нет там никакой рекурсии. И вообще, проще было бы вызывать не rcall PutChar, a rcall __skip_add_cr (ну и названьице(:-)). И выполнение было бы быстрее, ведь рутина у вас и в прерывании вызывается...

 

Попробуйте код

А чего его пробовать, и так видно, что тяжеловесно и неоптимально. Например, фрагмент с кольцевым буфером можно написать в два раза короче. А что там за пляски с бубнами в PutChar: in AH,SREG cli + out SREG,AH? Не проще ли обойтись связкой cli/sei. Или вот: зачем стоит tst AL перед rcall PutChar в рутине Print?

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


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

Посмотрел попристальнее - нет там никакой рекурсии.

Смотрите пристальнее сразу. Ок?

Есть там рекурсия, коль скоро функция вызывает сама себя.

 

проще было бы вызывать не 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?

опечатка.

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


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

Есть там рекурсия, коль скоро функция вызывает сама себя.

Ну-ну, 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;
}

Кстати, цикл является частным видом рекурсии. У вас ни того, ни другого.

Не сомневаюсь что вы именно так и поступаете, у меня же все метки начинающиеся с "__" внутренние и я стараюсь их не вызывать, чтобы было меньше путаницы.

Дорогой мой, зачем метки тогда вообще писать. Я пишу программы так, чтобы они были эффективные и красивые, а не какие-то там крокозябры (это не вам).

Не проще. Потому что вызывается эта функция еще и в прерывании.

Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает. Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом.

И вообще прежде чем хаить хамоватым тоном - разберитесь с кодом

Прошу прощения, если кого-то обидел, но я никому не хамил и никого не хаял. Была выложена программа, идёт её обсуждение, ничего личного.

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


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

Ну-ну, tell it your sailors(:-). Рекурсии там нет. Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности. Вот пример классической рекурсии.

 

Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области.

 

рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи.

 

В программировании рекурсия — вызов функции или процедуры из неё же самой

 

источник:

http://ru.wikipedia.org/wiki/Рекурсия

 

Ну хорошо, не проще, так не проще. Сейчас я вам покажу как ваш код работает.

:lol:

 

Выполняется программа Print, перед brne возникает прерывание по приему с rx. Программа прерывания запишет принятый байт внутрь строки, которую программа Print собирается поместить в кольцевой буфер. В результате вы получите не ту строку, которую копировали из флеши, а несколько другую. Я бы назвал сиё скрытым (неявным) багом.

Теоретически возможно. Атомарность Print я не организовывал.

Но конструкция реализованная в PutChar не препятствует организации атомарности Print.

 

тем же самым in Rr, SREG - cli - out SREG, Rr

 

Дорогой мой, зачем метки тогда вообще писать.

Во-первых выбирайте выражения. Своему бойфренду можете говорить "дорогой мой".

Во-вторых, я не виноват что русский язык порождает неоднозначность ("не вызывать" - имелось в виду "call" не делать. )

в третьих - это такой стиль - для обозначения внутренних меток (локальных для функций) на которые осуществяется условный переход я применю "тэг" - "__".

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


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

=GM=, при всём уважении к Вашим знаниям давайте будем добрее друг к другу. Так вы отобъёте всякое желание выложить свою прогу, чтобы кому-то помочь. :)

Любая маломальски приличная прога содержит ошибки. Иногда их вылавливаешь годами. Плюс различные предпочтения у каждого программиста. Это как аккорды на гитаре. Один пользуется чаще такими а другой другими. Но если оба музыканта, то музыка всё равно звучит. :)

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


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

Рекурсия – это сведение вычисления задачи некоторой размерности N к вычислению аналогичных задач меньшей размерности

А откуда такое определение рекурмии,ссылку можно?

 

В программировании рекурсия — вызов функции или процедуры из неё же самой

Вот с этим не поспоришь.

И чего-вы к обозначению внутренних меток прицепились?По моему,нормальная идея визуально разделять локальные и глобальные метки.

З.Ы. вы кодер,не знающий ошибок?

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


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

Ваше определение рекурсии и пример - неверны. либо взяты не из той предметной области. рекурсия — частичное определение объекта через себя, определение объекта с использованием ранее определённых. Рекурсия используется, когда можно выделить самоподобие задачи.

Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию F на более заметную RECURRENCE).

long RECURRENCE(unsigned int n)
{
  return n <= 1 ? n : RECURRENCE(n-1) + RECURRENCE(n-2);
}

Напишите ваш код PutChar на си в таком же виде, тогда и будем говорить, что верно, а что неверно. Интересно, что у вас будет параметром рекурсии?

Теоретически возможно. Атомарность Print я не организовывал.

Но конструкция, реализованная в PutChar не препятствует организации атомарности Print.

тем же самым in Rr, SREG - cli - out SREG, Rr

Так я и сказал. что все эти примочки внутри PutChar не нужны, не решают они задачу до конца, а снаружи атомарность передачи строки вы не обеспечили. И не теоретически, а сугубо практически, поверьте.

Во-первых, выбирайте выражения. Своему бойфренду можете говорить "дорогой мой"

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

 

 

=GM=, при всём уважении к Вашим знаниям давайте будем добрее друг к другу. Так вы отобъёте всякое желание выложить свою прогу, чтобы кому-то помочь. :)

Знаний как раз маловато, спасибо форуму, много даёт в плане самообразования. Да я...белый и пушистый, defunct'а почти люблю (как брата, а то опять поймет не в той плоскости(:-)). Что касается проги, не собирался я её критиковать, с первого взгляда она мне понравилась, посмотрел по диагонали - в подпрограмме вывода символа вроде используется рекурсия, вот думаю, люди рекурсию применяют, а я от неё как чёрт от ладана, ну я и спросил спроста, а потом уж стал смотреть, а он мне отвечает, да, там рекурсия, да какая рекурсия, курам на смех

Любая мало-мальски приличная прога содержит ошибки. Иногда их вылавливаешь годами. Плюс различные предпочтения у каждого программиста. Это как аккорды на гитаре. Один пользуется чаще такими, а другой другими. Но если оба музыканта, то музыка всё равно звучит. :)

Согласен. Ошибок в любой программе полно, у самого так. Смотришь на программу годичной давности, и думаешь, неужели это я написал такое гуано? Ну посмотрел я его программу, ну высказал замечания, будь благодарен, что кто-то потратил своё время, разобрался, принял участие, ответил, что плохого? Почему сразу надо воспринимать как наезд, которого и в помине не было. Дефункту не надо было говорить, чтоб код испытал(:-). Да если б все мои программы так критиковали, это было бы здорово, и программы были бы в стократ лучше...

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


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

Мой пример классический, не я его выдумал, взгляните на него непредвзято (заменил там рекурсивную функцию 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: я и сейчас пытаюсь отвечать на ваши вопросы по-сущесту, с приведением ссылок и примеров. Может вы просто не замечаете?

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


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

Уж не пойму или у меня там полный бред в коде или у вас проблемы с прочтением алгоритма из асм программы. поменять 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 так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг.

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


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

Ну, это другое дело. Но тогда сохранение/восстановление статус-регистра в PutChar не нужно, о чём я и толкую последние две страницы.

Нужно! Т.к. PutChar автономная функция, и кроме Print может быть использована где угодно.

"Лучше перебдеть чем "недобдеть" ;>

 

Кстати, неплохо бы добавить проверку на переполнение буфера в подпрограмме обработки прерываний по приему.

Это так и было задумано..

Практика показывает что для консольных приложений (а пример относился как раз консоли) много лучше допускать опустошение Tx (при переполнении) чем притормаживать CPU ожиданием освобождения места.

 

UART_RX_ISR так и будет писать по кругу, никаких ограничений у вас нет, возможен скрытый баг.

RX_ISR в идеале должен работать со входной очередью.

Вывод "Эхо" по скорости заполнения не быстрее TX, переполнений по вине RX потока быть не должно. Ну а в случае когда полный overload, то деваться некуда или сбросить TX очередь или ждать окончания TX. Но мы не можем торчать в прерывании и ждать когда освободится место в очереди..

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


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

Открыл новую тему на предмет написания и использования циклических буферов, показал своё видение предмета. Приглашаю к обсуждению.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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