Цитата(klen @ Oct 23 2006, 12:51)

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

.
Пользовательский код добавляет в циклический буфер символ по указателю вставки, курсору push. Прерывание выгребает тот-же буфер по мере ухода символов. Выгребает по другому указателю-курсору (pop). Когда при вставке указатели равны, то это значит, что буфер заполнен и приложение попадает в блокировку на вывод (здесь - крутится в цикле).
Проблема проявилась в том, что при работе функции записи в буфер сравнивание указателей-курсоров производится без учёта того, что один из них может меняться прерыванием.
Пользовательский код:
Код
//----uart.c--------
uint8_t debugBuffer[32]; //кольцевой буфер
uint8_t volatile *debugPushCursor; //_указатель_ для функции записи
uint8_t volatile *debugPopCursor; //_указатель_ для функции чтения
//запись символа в кольцевой буфер
void pushToDebugBuffer(uint8_t symbol){
DEBUG_TX_INT_LOCK(); //макрос, запрещающий прерывание и изменение курсора чтения
while(debugPushCursor == debugPopCursor){//если буфер полон, то ожидаем прерывания
DEBUG_TX_INT_UNLOCK(); //разрешаем прерывания и изменения курсора чтения
SLEEP(); //ожидание прерывания
DEBUG_TX_INT_LOCK(); //прерывание пришло, запрещаем изменение курсора чтения (может, можно убрать)
}
*debugPushCursor = symbol; //буфер не полон, записываем символ
debugPushCursor = nextAddress(debugPushCursor); //приращиваем курсор записи (из-за того, что быфер кольцевой, простая операция ++ не канает
DEBUG_TX_INT_UNLOCK(); //разрешаем работу прерывания и изменение курсора чтения
return;
}
//функция чтения из кольцевого буфера
//вызывается только из прерывания
void popFromDebugBuffer(void){
uint8_t *nextPopCursorPosition;
if((nextPopCursorPosition = nextAddress(debugPopCursor)) != debugPushCursor){
//если следующая позиция настроена на ожидание ввода от курсора pushCursor, то весь буфер передан (догнали курсор снизу), выходим.
//здесь оказываемся, если ещё есть чего передавать
globIntFlags.isDebugPortBusy=true;
UDR1 = *debugPopCursor; //передаём в UART из текущего курсора чтения
debugPopCursor = nextPopCursorPosition; //прибавлем курсор на будущее
} else {
globIntFlags.isDebugPortBusy=false;
}
return;
}
//приращение курсора, в данном примере просто для иллюстрации
//вычислитель следующего адреса в кольцевом буфере на основе заданного указателя
uint8_t *nextAddress (uint8_t *pointer){
pointer++;
if(pointer == debugBuffer + sizeof(debugBuffer)){ //если указатель вылез за верх. границу буфера, ставим на начало
pointer = debugBuffer; //здесь ставим на начало
}
return pointer;
}
Код прерывания:
Код
//-----interrupt.c-------
extern uint8_t debugBuffer[32]; //кольцевой буфер
extern uint8_t volatile *debugPushCursor; //_указатель_ для функции записи
extern uint8_t volatile *debugPopCursor; //_указатель_ для функции чтения
//прерывание по отправке байта в порт
INTERRUPT(SIG_USART1_TRANS){
popFromDebugBuffer(); //функция приращения курсора чтения и отправки байта в порт, здесь не важно, из чего она состоит. Кстати, код функции описан в первом файле. Наверное, это не принципиально ?
}
Так вот, я, конечно, понимаю, что повторился немного, но здесь старался прокомментировать подробнее.
Попробуйте, что получится. Если получится хорошо, то я тоже скомпилирую пример (сейчас смена кончается, не успеваю).
Ещё раз сенкс за участие. Надеюсь, не слишком сумбурно излагаю.