VAI 0 5 июля, 2004 Опубликовано 5 июля, 2004 · Жалоба Ошибка при работе с volatile (http://www.telesys.ru/wwwboards/mcontrol/703/messages/67032.shtml ), что была в v3.10a, исправлена, как минимум, в моем случае. Есть глюк с оптимизацией, я использую полную по скорости - надо отключать "Code motion" - ошибочно выносит из цикла переменную (опять же в моем случае). При других оптимизациях не проверял. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 5 июля, 2004 Опубликовано 5 июля, 2004 · Жалоба Пример, в котором проявляется ошибка оптимизатора 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 ); } Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kurt 0 6 июля, 2004 Опубликовано 6 июля, 2004 · Жалоба Точна.. ошибка с volatile пофиксена.. а буфер у тебя какой-то зловещий.. похоже компилятор испугался.. Посмотри по адресу hubbard.engr.scu.edu/embedded/avr/avrlib/. Там в библиотеке есть универсальный circular byte buffer Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 6 июля, 2004 Опубликовано 6 июля, 2004 · Жалоба Это я нагородил еще лет 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 )-------------------------------------------- */ что-то первый пробел в каждой строчке кода съедается... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться