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

 
 
> ADuC7128 + IAR C 5.11, Help!!! Как такое может быть? Кто глючит: я или компилер?
Dir
сообщение Feb 18 2008, 08:36
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830



Итак, ADuC7128 + C от IAR v5.11. Тестовая и программирующая аппаратура J-Link v3.78d (JetLink-5) . Проблема с отработкой обычного кольцевого буфера по прерываниям. Одна программа putBYTE() пишет в этот буфер, а по прерыванию от таймера этот буфер выгребается и посылается на UART. Период прерываний от таймера 50мкс, UART настроен на скорость 115200.
Вот ее текст:

Код
typedef unsigned char BYTE;
#define TX_BUFFER_SIZE0 64
#define    COM_TEMP 6    // COMxTX Empty
volatile BYTE tx_buffer0[TX_BUFFER_SIZE0];
volatile char tx_wr_index0, tx_rd_index0, tx_counter0;

void putBYTE0(BYTE c)
{
    while (tx_counter0 == TX_BUFFER_SIZE0);
    tx_buffer0[tx_wr_index0] = c;
    if (++tx_wr_index0 == TX_BUFFER_SIZE0)
        tx_wr_index0=0;
    tx_counter0++;
}

__arm __irq void IRQ_Handler(void)
{
    if (IRQSTA & (1 << INT_T0))            // сброс прерывания от таймера
        T0ICLR = 0;

BYTE status;
    status = COM0STA0;
    if (status & (1 << COM_TEMP))
    {
        if (tx_counter0)
        {
           tx_counter0--;                                                        // 1
           COM0TX = tx_buffer0[tx_rd_index0];
           if (++tx_rd_index0 == TX_BUFFER_SIZE0)               // 2
               tx_rd_index0=0;
// test -------
           if (!tx_counter0 && (tx_rd_index0 != tx_wr_index0))
                   LED_OFF;
// test -------
        }
    }
}

Глюк в том, что в передатчик UART иногда посылается на 1 байт больше! Этот факт отражен в тестовом фрагменте между двумя // test. Т.е. при уменьшении tx_counter до 0, tx_rd_index0 становится больше (на 1), чем tx_wr_index0.
Так реально и происходит. ПК получает лишний байт, стоящий за буфером. Бряк, останавливающий Jet-Lin и поставленный на макрос LED_OFF, показывает в Watch, что tx_rd_index = tx_wtr_index+1 (с учетом, естественно закольцовки буфера). Дальше идет, как и положено, полная ерунда sad.gif
Что тут не так? В п/п putBYTE() инкремент tx_counter0 идет самым последним, так что, вроде, ни о какой атомарности и необходимости запрещать прерывания речи не идет. Хотя ХЗ.
HELP!!!
PS. Вся оптимизация выключена. Даже не LOW, а NO. Хотя при LOW-уровне было тоже самое.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aaarrr
сообщение Feb 18 2008, 08:40
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Dir @ Feb 18 2008, 11:36) *
В п/п putBYTE() инкремент tx_counter0 идет самым последним, так что, вроде, ни о какой атомарности и необходимости запрещать прерывания речи не идет. Хотя ХЗ.

Почему это? Прерывание вполне может случиться в момент, когда tx_counter0 уже ++, но еще не записан - получите лишний байт.
Go to the top of the page
 
+Quote Post
Dir
сообщение Feb 18 2008, 08:55
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830



Цитата(aaarrr @ Feb 18 2008, 10:40) *
Почему это? Прерывание вполне может случиться в момент, когда tx_counter0 уже ++, но еще не записан - получите лишний байт.


Вообще то не лишний, а наоборот одного байта не будет до поры до времени. Но, ИМХО, не в этом проблема.

Цитата(vmp @ Feb 18 2008, 10:42) *
На ARM'е инкремент операция не атомарная, состоит из 3 команд - загрузка, инкремент, сохранение. Если прерывание вклинится между ними - получаем рассогласование.


И это нужно делать руками (т.е. запрещать прерывания)? Встроенных средств в компилере для этого нет?
Go to the top of the page
 
+Quote Post
vmp
сообщение Feb 18 2008, 09:03
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070



Цитата(Dir @ Feb 18 2008, 11:55) *
И это нужно делать руками (т.е. запрещать прерывания)? Встроенных средстd в компилере для этого нет?

Есть ключевое слово __monitor. Но оно запрещает прерывание на всю функцию.

Кстати, светодиод может гаснуть, если прерывание пройдет между инкрементом tx_wr_index0 tx_counter0.
Go to the top of the page
 
+Quote Post
Dir
сообщение Feb 18 2008, 09:14
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 201
Регистрация: 6-01-05
Пользователь №: 1 830



Цитата(vmp @ Feb 18 2008, 11:03) *
Есть ключевое слово __monitor. Но оно запрещает прерывание на всю функцию.

Кстати, светодиод может гаснуть, если прерывание пройдет между инкрементом tx_wr_index0 tx_counter0.


Спасибо, vmp и aaarrr!
Заработало biggrin.gif
Go to the top of the page
 
+Quote Post



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

 


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


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