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

Попробовал ИАР-МСП в3.20

Ошибка при работе с volatile (http://www.telesys.ru/wwwboards/mcontrol/703/messages/67032.shtml

), что была в v3.10a, исправлена, как минимум, в моем случае.

Есть глюк с оптимизацией, я использую полную по скорости - надо отключать "Code motion" - ошибочно выносит из цикла переменную (опять же в моем случае).

При других оптимизациях не проверял.

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


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

Пример, в котором проявляется ошибка оптимизатора

 

typedef struct
{ unsigned char *home;                  // указатель на начало буфера
 unsigned char *head;                  // указатель на голову буфера
 unsigned char *tail;                  // указатель на хвост буфера
 unsigned char *end;                   // указатель на конец буфера
 volatile int change;                    // 
} CIRCULAR_BUFFER;

int put_circle( unsigned char dat, CIRCULAR_BUFFER *buf )
{
CIRCULAR_BUFFER b;
istate_t i;
int c;
unsigned char *p;

 for ( b.home = buf->home, b.end = buf->end;; )
 { b.head = buf->head;
   b.tail = buf->tail;
   b.change = buf->change;

   c = 0;// это присваивание при "Code motion" выносится из цикла, хотя ниже с может стать -1, а при повторном прохождении цикла с должно опять стать нулем.

   if ( b.tail == NULL )
   { b.tail = b.head;                  // буфер полон,
     if ( ++b.head == b.end )           // сдвинем голову
       b.head = b.home;
   }
   p = b.tail;                         // Сюда надо положить dat
   if ( ++b.tail == b.end )
     b.tail = b.home;
   if ( b.tail == b.head )              // буфер заполнен ?
   { b.tail = NULL;                    // да
     c = -1;
   }
   if ( b.change == buf->change )     // фоновый процесс поработал с буфером в это-же время, придется все делать заново
     break;
 }

 i = __get_interrupt_state();          // сохраним статус прерываний
 __disable_interrupt();                // Запретим прерывания
 buf->change++;                        // мы поработали с буфером!
 buf->head = b.head;                   // обновим значения в буфере
 buf->tail = b.tail;
 *p = dat;
 __set_interrupt_state( i );           // востановим статус прерываний
 return( c );
}

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


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

Точна.. ошибка с volatile пофиксена..

а буфер у тебя какой-то зловещий.. похоже компилятор испугался..

Посмотри по адресу hubbard.engr.scu.edu/embedded/avr/avrlib/. Там в библиотеке есть универсальный circular byte buffer

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


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

Это я нагородил еще лет 5 назад для РС. С тех пор и сую везде, где можно не задумываясь. :-)

Спасибо, гляну avrlib.

А буфер у меня не страшный (см. ниже), страшна реализация одновременного доступа к буферу из нескольких фоновых приложений... Но со временем приведу в порядок. В отличии от avrlib у меня используется только ++, а там -деление (точнее остаток).

 

typedef struct
{ unsigned char *home;                  // указатель на начало буфера
 unsigned char *head;                  // указатель на голову буфера
 unsigned char *tail;                  // указатель на хвост буфера
 unsigned char *end;                   // указатель на конец буфера
} CIRCULAR_BUFFER;

/* --- put_circle() --------------------------------------------------------------------------------------- **
*  Помещает байт dat в кольцевой буфер, при заполнении буфера делает buf->tail = NULL и возвращает -1,
*  при уже заполненом буфере затирает байт в голове буфера.
* -------------------------------------------------------------------------------------------------------- */
int put_circle( unsigned char dat, CIRCULAR_BUFFER *buf )
{
int c = 0;

 if ( buf->tail == NULL )
 { buf->tail = buf->head;              // буфер полон,
   if ( ++buf->head == buf->end )       // сдвинем голову
     buf->head = buf->home;
 }
 *buf->tail = dat;                     // затрем первый байт
 if ( ++buf->tail == buf->end )
   buf->tail = buf->home;
 if ( buf->tail == buf->head )          // буфер заполнен ?
 { buf->tail = NULL;                   // да
   c = -1;
 }
 return( c );
}

/* --- get_circle() --------------------------------------------------------------------------------------- **
*  Возвращает в младшем байте байт из кольцевого буфера, если буфер пуст, возвращает -1
* -------------------------------------------------------------------------------------------------------- */
int get_circle( CIRCULAR_BUFFER *buf )
{
int c = -1;

 if ( buf->head != buf->tail )         // буфер пуст ?
 { if ( buf->tail == NULL )            // буфер был полон
     buf->tail = buf->head;
   c = *buf->head;
   if ( ++buf->head == buf->end )
     buf->head = buf->home;
 }
 return( c );
}

/* --- ini_circle() --------------------------------------------------------------------------------------- **
*  
* -------------------------------------------------------------------------------------------------------- */
void ini_circle( unsigned char *home, unsigned char *end, CIRCULAR_BUFFER *buf )
{
 buf->head = buf->tail = buf->home = home;
 buf->end = end;
}

/* --- flush_circle() ------------------------------------------------------------------------------------- **
*  Очистка буфера
* -------------------------------------------------------------------------------------------------------- */
void flush_circle( CIRCULAR_BUFFER *buf )
{
 buf->tail = buf->head;
}

/* --- status_circle() ------------------------------------------------------------------------------------ **
*  Проверка статуса буфера
* Возвращает -1 если буфер полон (нет места)
*             0 если в буфере есть место
*             1 если буфер пуст
* -------------------------------------------------------------------------------------------------------- */
int status_circle( CIRCULAR_BUFFER *buf )
{
 if ( buf->tail == NULL )              // буфер заполнен?
   return( -1 );                       // да
 if ( buf->head == buf->tail )         // буфер пуст ?
   return( 1 );                        // да
 return( 0 );                          // есть место
}

/* ---------------------------------------------( end of file )-------------------------------------------- */

 

что-то первый пробел в каждой строчке кода съедается...

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


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

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...