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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Оператор "printf" и функция "putchar" для работы с символьным LCD
zltigo
сообщение Mar 19 2010, 18:52
Сообщение #16


Гуру
******

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



Цитата(Буратино @ Mar 19 2010, 21:45) *
Что касается разрешения прерывания, то пересмотрю источник (не помню какая апликуха атмела) возможно я уже что-то на пакостил в тексте. Справедливости ради хочу заметить что этот код уже гигибайта три прокачалsmile.gif

Я сказал не кошерно, а не не халяльно smile.gif. Другими словами просто не красиво(полезно) sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 19 2010, 21:20
Сообщение #17


Гуру
******

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



Цитата(zltigo @ Mar 19 2010, 20:37) *
Некошерно смотрится дергание бита разрешения прерывания sad.gif
Нормально смотрится. Нужны прервания - разрешаем, не нужны - запрещаем. Флаг-то аппаратно торчит всегда, когда свободен буфер передачи. Это вам не '550.
Цитата(zltigo @ Mar 19 2010, 20:37) *
Ну и volatile для UART_TxHead0 лишнее - только warning вызывает.
Формально - не лишняя. Переменная меняется в другой относительно прерывания нити.
Цитата(zltigo @ Mar 19 2010, 20:37) *
tmptail0 лишняя сущность...
Вовсе нет. Без нее получаем предупреждение компилятора на неопределенный порядок чтения двух volatile в сравнении.


--------------------
На любой вопрос даю любой ответ
"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
сообщение Mar 19 2010, 21:53
Сообщение #18


Гуру
******

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



Цитата(Сергей Борщ @ Mar 20 2010, 00:20) *
Нормально смотрится. Нужны прервания - разрешаем, не нужны - запрещаем. Флаг-то аппаратно торчит всегда, когда свободен буфер передачи.

Свободен сдвиговый регистр - записываем прямо в UART, не свободен в буфер и по прерыванию уже вычитываем, либо по анализу указателей, либо флаг можно завести.
Цитата
Формально - не лишняя. Переменная меняется в другой относительно прерывания нити.

Абсолютно лишняя, ибо пока выполняется обработчик она измениться за его пределами не может. для Tail volatile нужен, Head - нет.
Цитата
Вовсе нет. Без нее получаем предупреждение компилятора на неопределенный порядок чтения двух volatile в сравнении.

Два volatile, повторяю, ну совсем не нужны, а warning, гарантировано при if ( UART_TxHead0 != UART_TxTail0 ) вылезет хоть есть tmptail0, хоть нет.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 20 2010, 09:54
Сообщение #19


Гуру
******

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



Цитата(zltigo @ Mar 19 2010, 23:53) *
Свободен сдвиговый регистр - записываем прямо в UART, не свободен в буфер и по прерыванию уже вычитываем, либо по анализу указателей, либо флаг можно завести.
И все эти телодвижения только ради того, чтобы не запрещать/разрешать прерывание? Нафиг. Хорошо, пусть даже идем вашим путем. В прерывании вычитываем из буфера. Буфер пуст - все данные переданы. Что делать дальше? Флаг прерывания сбросить невозможно - для этого нужно что-то начать передавать. Если выйдем из прерывания не запретив его - тут же попадем в это же прерывание снова. Что мы можем сделать кроме как запретить это прерывание? Еще раз повторяю - это не '550, тут не получается начать генерить прерывания положив первый байт в передатчик. И такая реализация дает более компактный код, без всяких лишних проверок "свободен/не свободен сдвиговый регистр".
Цитата(zltigo @ Mar 19 2010, 23:53) *
Абсолютно лишняя, ибо пока выполняется обработчик она измениться за его пределами не может.
Ну хорошо, тут соглашусь.
Цитата(zltigo @ Mar 19 2010, 23:53) *
Два volatile, повторяю, ну совсем не нужны, а warning, гарантировано при if ( UART_TxHead0 != UART_TxTail0 ) вылезет хоть есть tmptail0, хоть нет.
Тюю... Невнимательно посмотрел исходник. Рассмотрел только TransmitByte, увидел, что она очень похожа на один из вариантов используемого мной кода и экстраполировал этот вывод и на обработчик прерывания. Виноват. У автора ветки действительно лишний.
Код
void uart_t::send(uint8_t byte)
{
    uint8_t Tmp = (TxHead + 1) & (UART_TX_BUFF_SIZE - 1);
    while(Tmp == TxTail)
       ;       // Buffer full
    TxBuffer[ TxHead ] = byte;
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
}

inline void  uart_t::UDRE_handler(void)
{
    uint8_t Tmp = TxTail;
    UDR = TxBuffer[ Tmp ];
    TxTail = Tmp = (Tmp + 1) & (UART_TX_BUFF_SIZE - 1);
    if(Tmp == TxHead)
        UCSRB &= ~(1<<UDRIE);
}


--------------------
На любой вопрос даю любой ответ
"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
сообщение Mar 20 2010, 10:34
Сообщение #20


Гуру
******

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



Цитата(Сергей Борщ @ Mar 20 2010, 12:54) *
И все эти телодвижения....

Это не все, это на вскидку три разных варианта. Каждый из 3x не сложнее суммарного дергания периферии с целью разрешения/запрещения прерывания в функции передачи и обработчике.
Цитата
И такая реализация дает более компактный код, без всяких лишних проверок "свободен/не свободен сдвиговый регистр".

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

Цитата
У автора ветки действительно лишний.
Код
inline void  uart_t::UDRE_handler(void)
{
    uint8_t Tmp = TxTail;
    UDR = TxBuffer[ Tmp ];
    TxTail = Tmp = (Tmp + 1) & (UART_TX_BUFF_SIZE - 1);
    if(Tmp == TxHead)
        UCSRB &= ~(1<<UDRIE);
}

Ну вообще-то и у тебя лучше обойтись smile.gif без.

Код
union {
volatile uint8_t TxTail;
uint8_t TxTail_int;
};

inline void  uart_t::UDRE_handler(void)
{
    UDR = TxBuffer[ TxTail_int ];
    TxTail_int = (TxTail_int + 1) & (UART_TX_BUFF_SIZE - 1);
    if(TxTail_int == TxHead)
        UCSRB &= ~(1<<UDRIE);
}

Меньше указивок, меньше думать и больше свободы компилятору.
P.S.
Кстати, в таких случаях я предпочитаю НЕ накладывать маску на индексы при их наращивании - пусть крутятся по полному циклу, а маска накладывается при использовании индекса. В этом случае одними действием вычитания индексов можно узнать сколько байтов в буфере - бывает нужно при пакетной передаче.


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


Гуру
******

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



Цитата(zltigo @ Mar 20 2010, 12:34) *
Очень очень зависит от конкретики и железа. Компактность кода, тоже не всегда синоним скорости - для тех контроллеров, у которых периферия находится на медленной шине безусловное действие прочитать-изменить-записать флаг в при каждом вызове передачи байта катострофически проигрывает по времени, например, анализу софтового флага.
В данном случае код был под конкретный контроллер - AVR. В котором, во-первых, периферия висит на быстрой шине (других просто нет), а во-вторых - без сброса разрешения прерывания просто не получится.
Цитата(zltigo @ Mar 20 2010, 12:34) *
Кстати, в таких случаях я предпочитаю НЕ накладывать маску на индексы при их наращивании - пусть крутятся по полному циклу, а маска накладывается при использовании индекса. В этом случае одними действием вычитания индексов можно узнать сколько байтов в буфере - бывает нужно при пакетной передаче.
Так я же написал - это один из вариатнтов. Опять же, речь идет об AVR, у которого FIFO нет (двойная буферизация не считается), и толку от знания "сколько конкретно байт в буфере" нет никакого.
Код
void uart_t::send(uint8_t byte)
{
    uint8_t Tmp = TxHead;
    while((uint8_t)(Tmp - TxTail) >=  (uint8_t) UART_TX_BUFF_SIZE)
    ; // Buffer full
    TxBuffer[ Tmp++ & (UART_TX_BUFF_SIZE - 1) ] = byte;
    TxHead = Tmp;
    UCSRB |= (1<<UDRIE);
}

inline void uart_t::UDRE_Handler()
{
    uint8_t Tmp = TxTail;
    UDR = TxBuffer[ Tmp++ & (UART_TX_BUFF_SIZE - 1) ];
    TxTail = Tmp;
    if(Tmp == TxHead)
        UCSRB &= ~(1<<UDRIE);
}
Но результирующий код получается длинее на 6 байт. И чего я на него перешел? Надо вернуться к первому - память кода может пригодиться.

Цитата(zltigo @ Mar 20 2010, 12:34) *
Меньше указивок, меньше думать и больше свободы компилятору.
Фу. union в таком применении - грязный хак. Как раз таки и не дающий никакой дополнительной свободы компилятору, но чреватый какими-нибудь граблями если компилятор окажется черезчур умным. А думать надо всегда smile.gif

Впрочем, мы уклонились от темы ветки.


--------------------
На любой вопрос даю любой ответ
"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
сообщение Mar 20 2010, 11:14
Сообщение #22


Гуру
******

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



Цитата(Сергей Борщ @ Mar 20 2010, 14:08) *
Опять же, речь идет об AVR, у которого FIFO нет (двойная буферизация не считается), и толку от знания "сколько конкретно байт в буфере" нет никакого.

А причем тут наличие или отсутствие FIFO и AVR??? Это уже конкретные проблемы верхнего уровня - надо ему знать сколько есть места в софтовом буфере передачи, или нет. При необходимости поместить в буфер за один вызов функции не один байт, а фрейм - весьма не лишняя возможность.
Цитата
Но результирующий код получается длинее на 6 байт.

Это уже конкретные заморочки компилятора sad.gif, кстати, возможно, и из-за неоптимальных volatile. То,что я описал, это просто тот вариант работы с индексами который я реализовывал "для начала". В случае каких-то дополнительных/особых требований, условий - естественно никаких догм.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Mar 20 2010, 12:57
Сообщение #23


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Кстати, можно вопрос по поводу UARTов микроконтроллеров?

Мне пока доводилось поработать с двумя реализациями их передатчиков:
1. как только сдвиговый регистр передатчика становится пуст - устанавливается соответствующее прерывание.
Сбросить его невозможно до тех пор, пока передатчик пуст.

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

2. в LPC1768 другая система (так называемый 550-ый?) - триггер прерывания "передатчик пуст" устанавливается только после завершения передачи данных (а не присутствует постоянно).
То есть изначально его нет (хотя передачтик пуст!), и после вызова обработчика он сбрасывается.

Здесь уже погеморройнее - загрузку FIFO приходится делать как в обработчике прерывания, так и снаружи (для инициирования передачи).
Причём дополнительно есть какой-то механизм откладывания прерывания:

The UARTn THRE interrupt (UnIIR[3:1] = 001) is a third level interrupt and is activated
when the UARTn THR FIFO is empty provided certain initialization conditions have been
met. These initialization conditions are intended to give the UARTn 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 UnTHR at one time
since the last THRE = 1 event. This delay is provided to give the CPU time to write data to
UnTHR without a THRE interrupt to decode and service. A THRE interrupt is set
immediately if the UARTn THR FIFO has held two or more characters at one time and
currently, the UnTHR is empty. The THRE interrupt is reset when a UnTHR write occurs or
a read of the UnIIR occurs and the THRE is the highest interrupt (UnIIR[3:1] = 001).


Здесь я до конца не понял конкретику, лишь то, что флаг THRE может устанавливаться не сразу по опустошению передатчика, а спустя какое-то время.

То есть проанализировав в регистре статуса бит Transmitter Empty (TEMT), в случае, если он установлен, нельзя однозначно понять, был ли уже вызов прерывания, или только ещё будет - из-за one character delay?

В общем, некоторый гиморрой получается sad.gif

Может, кто нибудь более популярно разъяснит механику работы LPCшного UART?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 20 2010, 13:10
Сообщение #24


Гуру
******

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



Цитата(sonycman @ Mar 20 2010, 15:57) *
В общем, некоторый гиморрой получается sad.gif

Пальцем покажите:
Код
//----------------------------------------------------------------------------
void boutchar( char ch )
{
    if(    status_word & STW_THR_BUSY )
    {    tbuf.buf[tbuf.tail & TBUF_SIZE_MSK] = ch;
              tbuf.tail++;
    }
    else
    {
        status_word |= STW_THR_BUSY;
        U0THR = ch;
    }
}
//----------------------------------------------------------------------------
__irq __arm  void uart_isr(void)
{
bint ch;

    while( !((ch = (U0IIR&IIR_MASK)) & IIR_IP) )        // Check Pending Bit
    {
        // What caused the interrupt?
        switch( ch )
        {

        case IIR_THRE:    // The THRE+TEMPT+FIFO is empty. If there is another
                        //    characters in the TX buffer, load its now to FIFO->THRE.
            if( tbuf.tail != tbuf.head )
            {   for( int ii=0; ( tbuf.tail != tbuf.head )&&( ii < TR_FIFO_SIZE ); ii++ )
                    U0THR = tbuf.buf[(tbuf.head++) & TBUF_SIZE_MSK];
            }
            else
                status_word &= (~STW_THR_BUSY);
            break;

.......


Цитата
Тут получается весьма простой обработчик - надо передавать данные - разрешаем прерывания и в обработчике происходит загрузка.
Данные закончились - запрещаем прерывание.

Если выкинуть работу с FIFO отсутствующим у AVR, то получаем вот такой "сложный" обработчик прерывания для LPC:
Код
if( tbuf.tail != tbuf.head )
                    U0THR = tbuf.buf[(tbuf.head++) & TBUF_SIZE_MSK];
            else
                status_word &= (~STW_THR_BUSY);

И такой "простой" ( © Сергея ) для AVR:
Код
    
    uint8_t Tmp = TxTail;
    UDR = TxBuffer[ Tmp++ & (UART_TX_BUFF_SIZE - 1) ];
    TxTail = Tmp;
    if(Tmp == TxHead)
        UCSRB &= ~(1<<UDRIE);


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Mar 20 2010, 14:00
Сообщение #25


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Mar 20 2010, 17:10) *
Пальцем покажите:

Спасибо за пример.
У Вас используется софтовый флаг (STW_THR_BUSY) для исключения коллизии при загрузке данных.
На AVR, благодаря "упрощённому" железу он совсем не нужен.

Наверное, тоже введу такой флаг, вместо принудительного вызова прерывания установкой pending бита...

Цитата(zltigo @ Mar 20 2010, 17:10) *
void boutchar( char ch )
{
if( status_word & STW_THR_BUSY )
{ tbuf.buf[tbuf.tail & TBUF_SIZE_MSK] = ch;
tbuf.tail++;
}
else
{
status_word |= STW_THR_BUSY;
U0THR = ch;
}
}

Кстати, у Вас в этой функции потенциальная проблема с опросом флага status_word.
Для корректной работы необходимо запрещать прерывание THRE перед обращением к status_word.
Жаль, не хотелось бы этого...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 20 2010, 14:41
Сообщение #26


Гуру
******

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



Цитата(sonycman @ Mar 20 2010, 17:00) *
У Вас используется софтовый флаг (STW_THR_BUSY) для исключения коллизии при загрузке данных.

Прежде всего из-за много более медленного доступа к железным флагам.
Цитата
Кстати...

Да, в реальности я байтовое занесение даже в буфер печати не использую - просто болталась неиспользуемая функция sad.gif.
Используется свой xprintf() в котором в том числе оптимизирован контроль за флагом, который контролируется только в конце заполнения буфера.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 20 2010, 15:08
Сообщение #27


Гуру
******

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



Цитата(zltigo @ Mar 20 2010, 13:14) *
При необходимости поместить в буфер за один вызов функции не один байт, а фрейм - весьма не лишняя возможность.
А если весь фрейм не лезет, что будем делать? Ждать, пока влезет или все же запихаем сколько сможем, чтобы избежать пауз в потоке? Будет кошерный вариант для AVR без дерганья флага?
Цитата(zltigo @ Mar 20 2010, 13:14) *
Это уже конкретные заморочки компилятора sad.gif
С чего бы это? В одном случае сравниваются две переменные, во втором - их разность сравнивается с константой. Очевидно, что второй вариант требует больше команд.


--------------------
На любой вопрос даю любой ответ
"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
сообщение Mar 20 2010, 15:35
Сообщение #28


Гуру
******

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



Цитата(Сергей Борщ @ Mar 20 2010, 18:08) *
А если весь фрейм не лезет, что будем делать?

Лично у меня в большинстве случаев буфера разумно-большие и отсутствие места для фрейма это аварийное состояние. Предпринимаются разборки, торможение уровней и встечной стороны... Если это просто отладочная печать захлебывается, то тем более, ждать нечего - как мы начали идти до жизни такой уже видно в начале буфера, остальное в мусорник.
Цитата
..чтобы избежать пауз в потоке?

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

На ШЕСТЬ байт больше??? Кроме вышеуказанного сравнения остальные действия достаточно равнозначны, даже для AVR различие в 6 байт это проблемы компилятора sad.gif. Для ARM, полагаю, как минимум, что в лоб, что по лбу.


P.S.
Глянул для AVR IAR.
"Плохой" вариант с константой
Код
     82          void send1( BYTE ch )
   \                     send1:
     83          {
   \   00000000   ....               LDI     R30, LOW(TxTail)
   \   00000002   ....               LDI     R31, (TxTail) >> 8
   \   00000004   8121               LDD     R18, Z+1
     84              while( (BYTE)(TxHead - TxTail) >=  UART_TX_BUFF_SIZE)
   \                     ??send1_0:
   \   00000006   8130               LD      R19, Z
   \   00000008   2F12               MOV     R17, R18
   \   0000000A   1B13               SUB     R17, R19
   \   0000000C   3410               CPI     R17, 64
   \   0000000E   F7D8               BRCC    ??send1_0
     85; // Buffer full
     86          
     87              TxBuffer[ TxTail++ & (UART_TX_BUFF_SIZE - 1) ] = ch;
   \   00000010   8120               LD      R18, Z
   \   00000012   2F12               MOV     R17, R18
   \   00000014   9513               INC     R17
   \   00000016   8310               ST      Z, R17
   \   00000018   E0F0               LDI     R31, 0
   \   0000001A   732F               ANDI    R18, 0x3F
   \   0000001C   2FE2               MOV     R30, R18
   \   0000001E   ....               SUBI    R30, LOW((-(TxBuffer) & 0xFFFF))
   \   00000020   ....               SBCI    R31, (-(TxBuffer) & 0xFFFF) >> 8
   \   00000022   8300               ST      Z, R16
     88          }
   \   00000024   9508               RET



"Хороший" вариант:
Код
     91          void send2( BYTE ch )
   \                     send2:
     92          {
   \   00000000   2F3B               MOV     R19, R27
   \   00000002   2F4A               MOV     R20, R26
     93          BYTE Tmp = ( TxTail + 1 )&(UART_TX_BUFF_SIZE - 1);    
   \   00000004   ....               LDI     R30, LOW(TxTail)
   \   00000006   ....               LDI     R31, (TxTail) >> 8
   \   00000008   8110               LD      R17, Z
   \   0000000A   9513               INC     R17
   \   0000000C   731F               ANDI    R17, 0x3F
   \   0000000E   8121               LDD     R18, Z+1
     94          
     95              while( TxHead == Tmp )
   \                     ??send2_0:
   \   00000010   1721               CP      R18, R17
   \   00000012   F3F1               BREQ    ??send2_0
     96; // Buffer full
     97          
     98              TxBuffer[ TxTail ] = ch;
   \   00000014   81A0               LD      R26, Z
   \   00000016   E0B0               LDI     R27, 0
   \   00000018   ....               SUBI    R26, LOW((-(TxBuffer) & 0xFFFF))
   \   0000001A   ....               SBCI    R27, (-(TxBuffer) & 0xFFFF) >> 8
   \   0000001C   930C               ST      X, R16
     99              TxTail = Tmp;
   \   0000001E   8310               ST      Z, R17
    100          }
   \   00000020   2FA4               MOV     R26, R20
   \   00000022   2FB3               MOV     R27, R19
   \   00000024   9508               RET


Где 6 байт проигрыша?

P.P.S.
Это была оптимизация по скорости. При оптимизации по размеру "Плохой" выиграл два байта у "Хорошего"
Код
     82          void send1( BYTE ch )
   \                     send1:
     83          {
   \   00000000   ....               LDI     R30, LOW(TxTail)
   \   00000002   ....               LDI     R31, (TxTail) >> 8
     84              while( (BYTE)(TxHead - TxTail) >=  UART_TX_BUFF_SIZE)
   \                     ??send1_0:
   \   00000004   8111               LDD     R17, Z+1
   \   00000006   8120               LD      R18, Z
   \   00000008   1B12               SUB     R17, R18
   \   0000000A   3410               CPI     R17, 64
   \   0000000C   F7D8               BRCC    ??send1_0
     85        ; // Buffer full
     86          
     87              TxBuffer[ TxTail++ & (UART_TX_BUFF_SIZE - 1) ] = ch;
   \   0000000E   8120               LD      R18, Z
   \   00000010   2F12               MOV     R17, R18
   \   00000012   9513               INC     R17
   \   00000014   8310               ST      Z, R17
   \   00000016   E0F0               LDI     R31, 0
   \   00000018   732F               ANDI    R18, 0x3F
   \   0000001A   2FE2               MOV     R30, R18
   \   0000001C   ....               SUBI    R30, LOW((-(TxBuffer) & 0xFFFF))
   \   0000001E   ....               SBCI    R31, (-(TxBuffer) & 0xFFFF) >> 8
   \   00000020   8300               ST      Z, R16
     88          }
   \   00000022   9508               RET


Код
     91          void send2( BYTE ch )
   \                     send2:
     92          {
   \   00000000   2F3B               MOV     R19, R27
   \   00000002   2F4A               MOV     R20, R26
     93          BYTE Tmp = ( TxTail + 1 )&(UART_TX_BUFF_SIZE - 1);    
   \   00000004   ....               LDI     R30, LOW(TxTail)
   \   00000006   ....               LDI     R31, (TxTail) >> 8
   \   00000008   8110               LD      R17, Z
   \   0000000A   9513               INC     R17
   \   0000000C   731F               ANDI    R17, 0x3F
     94          
     95              while( TxHead == Tmp )
   \                     ??send2_0:
   \   0000000E   8121               LDD     R18, Z+1
   \   00000010   1721               CP      R18, R17
   \   00000012   F3E9               BREQ    ??send2_0
     96        ; // Buffer full
     97          
     98              TxBuffer[ TxTail ] = ch;
   \   00000014   81A0               LD      R26, Z
   \   00000016   E0B0               LDI     R27, 0
   \   00000018   ....               SUBI    R26, LOW((-(TxBuffer) & 0xFFFF))
   \   0000001A   ....               SBCI    R27, (-(TxBuffer) & 0xFFFF) >> 8
   \   0000001C   930C               ST      X, R16
     99              TxTail = Tmp;
   \   0000001E   8310               ST      Z, R17
    100          }
   \   00000020   2FA4               MOV     R26, R20
   \   00000022   2FB3               MOV     R27, R19
   \   00000024   9508               RET

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Буратино
сообщение Mar 20 2010, 16:49
Сообщение #29


Профессионал
*****

Группа: Свой
Сообщений: 1 433
Регистрация: 27-10-08
Из: Украина, Киев
Пользователь №: 41 215



blink.gif


--------------------
Брак - это такой вид отношений, в которых один всегда прав, - а другой - муж.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 20 2010, 17:01
Сообщение #30


Гуру
******

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



Цитата(Буратино @ Mar 20 2010, 19:49) *
blink.gif

А что? Просто обмен опытом и жизненными наблюдениями.


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

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

 


RSS Текстовая версия Сейчас: 7th July 2025 - 20:27
Рейтинг@Mail.ru


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