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

 
 
> Одноразовый UART в AVR, Отправляет данные корректно только 1 раз..
Dikoy
сообщение Aug 2 2012, 18:17
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



IAR 4.30, ATmega640.
Структура. Надо её всю слить в UART.
Беру указатель на начало и попёр. Вроде всё правильно. Но отправляется корректно она только первый раз, а потом идёт мусор.

CODE
#pragma pack(1)
typedef struct
{
unsigned char Length;
unsigned char Cmd;
unsigned char ADC1[ADCBUFSISE]; // ADCBUFSISE == 18
unsigned char ADC2[ADCBUFSISE];
unsigned char ADC3[ADCBUFSISE];
unsigned char crc_h;
unsigned char crc_l;
} Response_str;
#pragma pack()


Response_str TransmisionFrame;
unsigned char *pUart0_tx_pointer;


void USART0_Transmit( unsigned char data ) {
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}


// инициирую отправку пакета раз в 2 секунды, пакет отправляется 2 мс, по этому период огромен
void main( void ) {
while(1) {
pUart0_tx_pointer = &TransmisionFrame.Cmd;
USART0_Transmit( TransmisionFrame.Length );
__delay_cycles(8000000*8);

}
}


// прерывание
// USART0 Transmitter interrupt service routine
#pragma vector=(0x36*0x02)
__interrupt void USART0_TXC_isr(void) { //

if( pUart0_tx_pointer <= &TransmisionFrame.crc_l ) {
UDR0 = *pUart0_tx_pointer++;
}
}


Результат:

Код
223A0000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000A55A - верный пакет
1A606908A5019746581A058A58A58199C65F1A606908A5019746581A058A58A58199C65F1A606908
A5019746581A058A58A58199C65F1A606908 - лажа
1A626910A52197C6581A078A64A5A19906601A626910A52197C6581A078A64A5A19906601A626910
A52197C6581A078A64A5A19906601A626910 - лажа


Подумал, указатель сползает... Сделал так:

Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
    USART0_Transmit( TransmisionFrame.Length );  
    __delay_cycles(8000000*8);
    memset( &TransmisionFrame, 0xAA, sizeof(TransmisionFrame) );    
  }


Получил:

Код
223A0000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000A55A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Лага категорически не вижу sad.gif

Сообщение отредактировал IgorKossak - Aug 2 2012, 18:23
Причина редактирования: [codebox] для длинного кода!!!
Go to the top of the page
 
+Quote Post
4 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 50)
Сергей Борщ
сообщение Aug 2 2012, 21:34
Сообщение #2


Гуру
******

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



Что-то (стек?) затирает содержимое структуры после первой передачи. Можно заполнять какое-либо поле структуры константой непосредственно перед передачей, чтобы подтвердить или опровергнуть это предположение.


--------------------
На любой вопрос даю любой ответ
"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
kolobok0
сообщение Aug 2 2012, 21:41
Сообщение #3


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Dikoy @ Aug 2 2012, 22:17) *
...инициирую отправку пакета раз в 2 секунды, пакет отправляется 2 мс...
Код
..1A606908-A5019746581A058A58A58199C65F1A606908-A5019746581A058A58A58199C65F1A606908-A5019746581A058A58A58199C65F1A606908 - лажа
1A626910-A52197C6581A078A64A5A19906601A626910-A52197C6581A078A64A5A19906601A626910-A52197C6581A078A64A5A19906601A626910 - лажа
...


1) что то по времени не понятно. скорость какая порта? структура имеет 3*18+4=58 байт. за две милисекунды - дюже скорость не плохая...

2) у вас повтор идёт 18 байтовый в посылках которая лажа...

3) программа плохо написана. нигде не указано, что менять местами поля нельзя в структуре. особенно первые и последнии. не факт что кто то это будет знать через много дней. или вообще что такие поля будут существовать.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 3 2012, 02:59
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Да, скорее всего стек...
18 байт, это размер массивов ADCх[ADCBUFSISE]; в структуре.
У меня три порта USART в режиме SPI читают три АЦП и складывают байты в промежуточные буферы.
Потом эти буферы быстренько перекладываются в данную структуру и она уходит на отправку через UART0. Приложил проект, если кому интересно.
Сейчас полностью отключил эти SPI и их обработку, закомментировав adc_hardware_init();, и всё стало работать идеально.

Значит прерывания дерутся. Расширить стек?

2kolobok0: скорость мегабит, через FT232R. При тупом поллинге работает прекрасно, это далеко не первый прибор такой, дело не в железе.
Структура - стандартный протокол. Никто ничего менять и не будет wink.gif


Цитата(Сергей Борщ @ Aug 3 2012, 00:34) *
Что-то (стек?) затирает содержимое структуры после первой передачи. Можно заполнять какое-либо поле структуры константой непосредственно перед передачей, чтобы подтвердить или опровергнуть это предположение.

Ещё до отключения SPI провёл эксперимент.

CODE

do {
pUart0_tx_pointer = &(TransmisionFrame.Length);
TransmisionFrame.ADC1[0] = 0x01;
TransmisionFrame.ADC2[0] = 0x02;
TransmisionFrame.ADC3[0] = 0x03;
UDR0 = *pUart0_tx_pointer++;

__delay_cycles(8000000*8);

} while(1);

//***************************

223A01000000000000000000000000000000000002000000000000000000
0000000000000000030000000000000000000000000000000000A55A

5F1A016908A5119746581AD3895CA59199C65F1A026908A5119746581AD3
895CA59199C65F1A036908A5119746581AD3895CA59199C65F1A6169

5F1A016908A5119786581AEE8960A59199C65F1A026908A5119786581AEE
8960A59199C65F1A036908A5119786581AEE8960A59199C65F1A6069


Как видно, первый раз всё срабатывает, а потом кирдык.

Размер стека по умолчанию, 32 бутеса...



Go to the top of the page
 
+Quote Post
prottoss
сообщение Aug 3 2012, 04:09
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



2 Dikoy
Вы не верно строите прерывание. Как Вы знаете, в USART AVR при передаче работают два регистра - UDR (Доступен из программы пользователя) и Transmit Shift Register (будем для краткости называть его TSR). Когда Вы записываете данные в UDR, они, если TSR пуст, автоматически переписываются в него. Второй как раз занимается передачей последовательных данных на выход TXDx. О состоянии этих регистров можно судить по флагам UDRE (регистр данных пуст) и TXC (TSR пуст). Так вот, не нужно при передаче пакета данных использовать прерывание TXC, а нужно использовать прерывание UDRE. А вот окончание сеанса передачи всего пакета уже можно отследить по TXC, т.е. данных для отправки нет, и TSR освободился.


--------------------
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 3 2012, 08:44
Сообщение #6


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Может организуйте fifo для отправки данных?

CODE
unsigned char Rx0Buf[UART_0_RXBUFSIZE];// the receiver buffer.
unsigned char Rx0Head = 0;// the circular buffer index
unsigned char Rx0Tail = 0;
unsigned char Tx0Buf[UART_0_TXBUFSIZE];// the transmit buffer.
unsigned int Tx0Head = 0;// the circular buffer index
unsigned int Tx0Tail = 0;

signed int _getcharUART0()
{
__disable_interrupt();
signed int temp = -1;
if (Rx0Tail != Rx0Head)
{
temp = Rx0Buf[Rx0Tail++];
if (Rx0Tail >= UART_0_RXBUFSIZE) Rx0Tail = 0;
}
__enable_interrupt();
return(temp);
}

void _putcharUART0(signed char in_char)
{
__disable_interrupt();
if ((Tx0Head == Tx0Tail) && (UCSR0A & (1<<UDRE0)))
{
UDR0 = in_char;
}
else
{

Tx0Buf[Tx0Head++] = (unsigned char) in_char;
if (Tx0Head >= UART_0_TXBUFSIZE) Tx0Head = 0;
}
__enable_interrupt();
}


#pragma vector=USART0_RX_vect
__interrupt void USART0_RX_IRQ(void)
{
Rx0Buf[Rx0Head++] = UDR0;
if (Rx0Head >= UART_0_RXBUFSIZE) Rx0Head = 0;
}

#pragma vector = USART0_TX_vect
__interrupt void USART0_TX_IRQ(void)
{
if (Tx0Tail != Tx0Head)
{
UDR0 = Tx0Buf[Tx0Tail++]; // send a byte of data
if (Tx0Tail >= UART_0_TXBUFSIZE) Tx0Tail = 0;// check for wrap around.
}
}


Закидываете всю структуру сразу на передачу с помощью

Код
while(size--)
{
_putcharUART0(*pStruct++);
}


size - размер структуры
pStruct - указатель на первый её элемент

Подобное fifo 100% рабочее применялось во многих моих серийных проектах на AVR.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 10:51
Сообщение #7



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
...
  }

Посмотрите, во что компилятор оптимизирует эту строчку.
Есть волшебное слово volatile.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 11:02
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 13:51) *
Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
...
  }

Посмотрите, во что компилятор оптимизирует эту строчку.

Несоптимизировал компилятор строчку.

Цитата(xemul @ Aug 3 2012, 13:51) *
[code]while( 1 )
Есть волшебное слово volatile.

Кого здесь volatile делать?

Сообщение отредактировал IgorKossak - Aug 3 2012, 11:27
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 11:56
Сообщение #9



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 15:02) *
Несоптимизировал компилятор строчку.

У меня нет иара, чтобы проверить, но, имхо, любой компилятор вынесет указанную строку в init() при любом отличном от 0 уровне оптимизации.
Цитата
Кого здесь volatile делать?

Есть варианты?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 12:18
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 14:56) *
У меня нет иара, чтобы проверить, но, имхо, любой компилятор вынесет указанную строку в init() при любом отличном от 0 уровне оптимизации.

И что будет? Работать перестанет?

Цитата(xemul @ Aug 3 2012, 14:56) *
Есть варианты?

Как минимум два.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 12:25
Сообщение #11



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 16:18) *
И что будет? Работать перестанет?

Будет работать именно так, как написано - передавать по TransmisionFrame.Length байтов, начиная с pUart0_tx_pointer. Но pUart0_tx_pointer будет равен &TransmisionFrame.Cmd только единожды.
Без оптимизации будет работать как задумано, кроме, вероятно, __delay_cycles().
Цитата
Как минимум два.

Да ну? "Огласите, пожалуйста, весь список", и с комментами, если можно.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 12:43
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 15:25) *
Да ну? "Огласите, пожалуйста, весь список", и с комментами, если можно.


Код
volatile Response_str TransmisionFrame;
unsigned char * volatile  pUart0_tx_pointer;


Строчка
Код
__delay_cycles(8000*8);

вызывает варнинги
Цитата
Warning[Pe061]: integer operation result is out of range FirstChip\main.c 162
Warning[Pe068]: integer conversion resulted in a change of sign FirstChip\main.c 162

и программа дальше не идёт.

Если так:
Код
__delay_cycles(8000UL*8);

то идёт.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 12:48
Сообщение #13



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 16:31) *
Код
volatile Response_str TransmisionFrame;

Из приведённого ТС кода не следует, что TransmisionFrame имеет смысл объявлять volatile, но прокатит. Правда, потянет за собой оверхед при обращениях к TransmisionFrame.
Цитата
Код
unsigned char * volatile  pUart0_tx_pointer;

Йес-с-с, Вы угадали. Это единственная переменная, модифицируемая в прерывании, и только в прерывании.
Почти тот же эффект получится, если внутри while(1) {} pUart0_tx_pointer будет как-нибудь бесполезно изменяться, но так, чтобы компилятор не догадался, что оно бесполезно.

__delay_xxx() не использую, но в комментах к подобным функциям обычно оговаривается уровень оптимизации, достаточный, чтобы они не выдавали цену на дрова.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 13:07
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 3 2012, 15:48) *
Йес-с-с, Вы угадали. Это единственная переменная, модифицируемая в прерывании, и только в прерывании.

Прыз в студию...

Цитата(xemul @ Aug 3 2012, 15:48) *
Почти тот же эффект получится, если внутри while(1) {} pUart0_tx_pointer будет как-нибудь бесполезно изменяться, но так, чтобы компилятор не догадался, что оно бесполезно.

Обычно и без volatile работает. Хотя случаи могут быть разные.

Цитата(xemul @ Aug 3 2012, 15:48) *
__delay_xxx() не использую, но в комментах к подобным функциям обычно оговаривается уровень оптимизации, достаточный, чтобы они не выдавали цену на дрова.

Там только про то говорится что параметр - константа. И всё.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 3 2012, 13:19
Сообщение #15



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 3 2012, 17:07) *
Обычно и без volatile работает. Хотя случаи могут быть разные.

Вольному - воля.
Цитата
Там только про то говорится что параметр - константа. И всё.

Тогда скорее всего в иар в либах живёт что-то вроде void __delay(unsigned long), а __delay_xxx() выполнены её обёртками.
В gcc-avr, если склероз не врёт, подобное шло в сорцах и с оговорками.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 3 2012, 14:51
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Цитата(prottoss @ Aug 3 2012, 08:09) *
2 Dikoy
а нужно использовать прерывание UDRE.

Помимо передачи, у меня есть ещё и приём. UDRE будет возникать в обоих случаях. Насколько помню, для разделения процессов приёма и передачи TxC/RxC и были придуманы. По крайней мере до этого я использовал именно их, и сейчас, после отключения лишних прерываний, данный код отлично работает.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 15:01
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Dikoy @ Aug 3 2012, 17:51) *
Помимо передачи, у меня есть ещё и приём. UDRE будет возникать в обоих случаях.

Да ну?

Цитата
• Bit 5 – UDREn: USART Data Register Empty
The UDREn flag indicates if the transmit buffer (UDRn) is ready to receive new data. If UDREn is
one, the buffer is empty, and therefore ready to be written. The UDREn flag can generate a Data
Register Empty interrupt (see description of the UDRIEn bit).
UDREn is set after a reset to indicate that the Transmitter is ready.


Цитата(Dikoy @ Aug 3 2012, 17:51) *
Насколько помню, для разделения процессов приёма и передачи TxC/RxC и были придуманы.


RxC - флаг приёма.
TxC - байт передан, нужен для определения окончания передачи пакета (RS485 и тп)
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 3 2012, 15:34
Сообщение #18


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Цитата(xemul @ Aug 3 2012, 14:51) *
Код
while( 1 )
  {
    pUart0_tx_pointer = &TransmisionFrame.Cmd;
...
  }

Посмотрите, во что компилятор оптимизирует эту строчку.
Есть волшебное слово volatile.

Вы предполагаете, что компилятор засунул структуру в регистры? Зря. Даже если убрать #pragma pack(1), этого не будет.
Адрес берётся от расположения структуры или массива в ОЗУ, а нем от того, куда в итоге засунули данные.
Тем не менее, первое что я сделал, ещё до создания этой темы, это сделал волатайлом всё. Ничего не поменялось.

Цитата(_Артём_ @ Aug 3 2012, 19:01) *
Да ну?
RxC - флаг приёма.
TxC - байт передан, нужен для определения окончания передачи пакета (RS485 и тп)

Попробую, раз такая пьянка.
Но принимать данные то по RxC прерыванию?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 3 2012, 15:43
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Dikoy @ Aug 3 2012, 18:34) *
Вы предполагаете, что компилятор засунул структуру в регистры? Зря. Даже если убрать #pragma pack(1), этого не будет.
Адрес берётся от расположения структуры или массива в ОЗУ, а нем от того, куда в итоге засунули данные.
Тем не менее, первое что я сделал, ещё до создания этой темы, это сделал волатайлом всё. Ничего не поменялось.

Похоже так, volatile нипричом.
Указатель в прерывании правильно меняется.
Может delay_cycles заменить чем-нибудь синхронизированным от таймера.
И стеки увеличить.

Цитата(Dikoy @ Aug 3 2012, 18:34) *
Но принимать данные то по RxC прерыванию?

Да, приём в USART0_RXC_vect или проверкой бита RxC, передача в USART0_UDRE_vect или проверкой бита UDRE (если USART0 используется).
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 3 2012, 23:10
Сообщение #20


Гуру
******

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



QUOTE (Dikoy @ Aug 3 2012, 05:59) *
Ещё до отключения SPI провёл эксперимент.
Все верно. 01, 02, 03 остались на своих местах и передаются. Значит прерывание и передача работают, и работают правильно. Портится содержимое структуры. Либо стеком, либо при записи по указателю где-то за пределы массива улетаете.
Начните с увеличения DATA STACK - 32 байта как-то несерьезно для серьезной программы. Если виноват стек - то его надо увеличивать минимум на размер этой структуры, ибо она портится вся. И то - это если она последняя перед стеком, а ведь весьма вероятно, что портится не только она. Радикальное решение - подправить скрипт линкера, чтобы он размещал RSTACK и CSTACK от конца памяти. Тогда для CSTACK автоматически будет доступна вся свободная память и вопрос выделения памяти под него отпадет автоматически. Насколько помню, это достигалось заменой '=' на '#' в командах размещения этих сегментов (и размещение RSTACK должно идти в скрипте до размещения CSTACK).


--------------------
На любой вопрос даю любой ответ
"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
_Артём_
сообщение Aug 4 2012, 00:09
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Сергей Борщ @ Aug 4 2012, 02:10) *
Значит прерывание и передача работают, и работают правильно.

Запускал программу TC в симуляторе - данные только один раз передаются.
Но у меня ИАР 5.

Цитата(Сергей Борщ @ Aug 4 2012, 02:10) *
Портится содержимое структуры. Либо стеком,


А каким образом глобальные переменные стеком могут портится?
ИАР располагает их так(адреса увеличиваются):
СSTACK- RSTACK-глобальные переменные.
Стек растёт вниз.
В ИАР-е 3 и 4 по-другому что ли?

Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 4 2012, 01:01
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Почитал про UDRE.
Получается, прерывание оное надо держать всегда выключеным. Включать только когда пошёл первый байт, и отключать до ухода последнего. Иначе флаг будет всегда стоять и МК из прерывания не выйдет.
Угумс?

Увеличил стек ажно до FF. Не помогло
Код
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
5F1A016900A5F19686581ADA8958A59199465F1A026900A5F19686581ADA8958A59199465F1A0369
00A5F19686581ADA8958A59199465F1A5F69
5F1A0169F8A4C19686571AF68950A56199065F1A0269F8A4C19686571AF68950A56199065F1A0369
F8A4C19686571AF68950A56199065F1A5D69
5F1A0169FCA4E19606581AD88954A57199465F1A0269FCA4E19606581AD88954A57199465F1A0369
FCA4E19606581AD88954A57199465F1A5E69
5F1A0169FCA4D196C6571AE88958A56199065F1A0269FCA4D196C6571AE88958A56199065F1A0369
FCA4D196C6571AE88958A56199065F1A5D69


Отключаю АЦП и всё снова работает:
Код
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
223A0100000000000000000000000000000000000200000000000000000000000000000000000300
00000000000000000000000000000000A55A
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 4 2012, 01:17
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Почитал про UDRE.
Получается, прерывание оное надо держать всегда выключеным. Включать только когда пошёл первый байт, и отключать до ухода последнего. Иначе флаг будет всегда стоять и МК из прерывания не выйдет.
Угумс?

Из прерывания выйдет, выполнит одну команду и опять войдёт. Но в общем так - угумс .

Код
void StopUartTx()
{
    UCSR0B&=~(1<<UDRIE0);
}
#pragma vector=USART0_UDRE_vect
__interrupt void ExtUartTx()
{
    unsigned char i=TxBuffer.ReadByte();
    UDR0=i;
    if (TxBuffer.BufferNotEmpty()==0)
        StopUartTx();
}
void StartUartTx()
/*
Если есть данные для передачи
*/
{
    UCSR1B|=(1<<UDRIE1);
}



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Увеличил стек ажно до FF. Не помогло

Который стек? Или оба?

Цитата(Dikoy @ Aug 4 2012, 04:01) *
Отключаю АЦП и всё снова работает:

Потому чта АЦП - это зло, а DAC - добро.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 18:01
Сообщение #24


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676





Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 5 2012, 19:39
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Dikoy @ Aug 4 2012, 04:01) *
Отключаю АЦП и всё снова работает:

Возможно ошибка в чтении данных от АЦП:

Код
ADC1_temp = ADC1_RxC_counter;
   ADC1_temp--;  
    Buf_ADC1[ADC1_temp] = UDR2;

После того как ADC1_RxC_counter станет равным 0 прерывания по spi не запрещаются и если это прерывание как-нибудь возникнет, то оно начнет переписываться память вне массива Buf_ADC.
Нет ли возможности поставить data breakpoint на запись в TransmisionFrame?
Если есть то можно так выявить ошибку.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 20:32
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Я уже писал тут где-то, что у меня цепь из 2 чипов по JTAG и дракон категорически отказывается отлаживать эту цепь, настраиваясь всегда на 1 чип. И как это изменить я так и не понял.
По этому отлаживаюсь методом UART+осциллограф.
По осциллу прерывания АЦП отрабатывают верно. Но косяк явно в нём.
Сейчас просто выключил таймер, который инициирует чтение АЦП, оставив се тела функций и прерываний активными, и всё работает. В смысле, передача корректна.
Стоит запустить процесс - и всё падает.

Увеличил оба стека до FF, ибо не жалко. Не помогает. Но если б стек переполнился, то а) компилер бы об этом сказал, б) всё бы рушилось и с отключённым таймером, ибо компиллер же не знает что без него все прерывания бесполезны и никогда не сработают.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 5 2012, 21:00
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Dikoy @ Aug 5 2012, 23:32) *
Я уже писал тут где-то, что у меня цепь из 2 чипов по JTAG и дракон категорически отказывается отлаживать эту цепь, настраиваясь всегда на 1 чип. И как это изменить я так и не понял.
По этому отлаживаюсь методом UART+осциллограф.

Без jtag-а плохо.
А в симуляторе сбой возникает? Ведь у вас программа работает как spi-master и uart transmitter, значит ошибка возможно может проявится и в симуляторе.

Цитата(Dikoy @ Aug 5 2012, 23:32) *
Но если б стек переполнился, то а) компилер бы об этом сказал

Поставьте стеки CSTACK и RSTACK в 1-2 байта и увидите, что ИАР будет молчать как партизан.

Цитата(Dikoy @ Aug 5 2012, 23:32) *
всё бы рушилось и с отключённым таймером, ибо компиллер же не знает что без него все прерывания бесполезны и никогда не сработают.

Не обязательно рушилось бы: смотря что переполнилось: может и просто глючить непонятным образом.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 5 2012, 23:54
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



В общем, память однозначо перетирают прерывания от АЦП.
Код
volatile unsigned char laja; // TEST

#pragma vector=(0x48*0x02)
__interrupt void ADC3_RxC_isr(void) { //
    unsigned char ADC3_temp;
    
    ADC3_temp = ADC3_RxC_counter;
    ADC3_temp--;    
    laja = UDR1;
//   Buf_ADC3[ADC3_temp] = UDR1;

    if(ADC3_temp) {
        UDR1 = ADC3_temp;    
    } else {
        ADC3_CS_PASSIV;  
    }
    
    ADC3_RxC_counter = ADC3_temp;
     PORTA ^= ((1<<1));  
}


Как только слив данных поставил в volatile переменную вместо массивов, сразу всё стало пучкасто.
Провёл серию экспериментов, проинициализировал Buf_ADCx[], на выход идёт всё корректно. То есть цикл прерываний отрабатывается правильно, данные из временных буферов Buf_ADCx[] перекладываются во фрейм и т.д.
То есть рушит всё именно строчка Buf_ADCx[ADCx_temp] = UDRx;. Только непонятно почему - по лапе PORTA я вижу правильное число заходов в прерывание.
Go to the top of the page
 
+Quote Post
Petka
сообщение Aug 6 2012, 06:33
Сообщение #29


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

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(Dikoy @ Aug 6 2012, 03:54) *
В общем, память однозначо перетирают прерывания от АЦП.
Код
volatile unsigned char laja; // TEST

#pragma vector=(0x48*0x02)
__interrupt void ADC3_RxC_isr(void) { //
    unsigned char ADC3_temp;
    
    ADC3_temp = ADC3_RxC_counter;
    ADC3_temp--;    
    laja = UDR1;
//   Buf_ADC3[ADC3_temp] = UDR1;

    if(ADC3_temp) {
        UDR1 = ADC3_temp;    
    } else {
        ADC3_CS_PASSIV;  
    }
    
    ADC3_RxC_counter = ADC3_temp;
     PORTA ^= ((1<<1));  
}


Полный бред.
1) ADC3_temp = ADC3_RxC_counter;
2) ADC3_temp--;
3) Buf_ADC3[ADC3_temp] = UDR1;
4) ADC3_RxC_counter = ADC3_temp;
5) goto 1
Разумеется после обнуления ADC3_temp команда из п.2 сделает ADC3_temp==0xFF и тогда п.3 сломает память.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 6 2012, 11:12
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Petka @ Aug 6 2012, 09:33) *
Разумеется после обнуления ADC3_temp команда из п.2 сделает ADC3_temp==0xFF и тогда п.3 сломает память.

Но для этого нужно чтобы возникло прерывание.Оно возникнет?

Цитата(kolobok0 @ Aug 3 2012, 00:41) *
нигде не указано, что менять местами поля нельзя в структуре. особенно первые и последнии.

А как указать чтобы поля не менялись местами?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 6 2012, 12:25
Сообщение #31


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Вы б отложили чашку с кофейной гущей и гадали бы на Протеусе. Найти обращение к байту в интересующей структуре - дело 5 минут при помощи условных брекпоинтов. Тем более, что дефект у Вас стабильный и танцы с бубном не нада.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Aug 6 2012, 13:10
Сообщение #32


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(_Артём_ @ Aug 6 2012, 15:12) *
...А как указать чтобы поля не менялись местами?


код видоизменить так, что бы не было в нём первого поля, или последнего. структура как чёрный ящик - длина, начало буфера. тогда пофигу будет где в ней какие поля раскиданы.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 6 2012, 13:24
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(kolobok0 @ Aug 6 2012, 16:10) *
код видоизменить так, что бы не было в нём первого поля, или последнего. структура как чёрный ящик - длина, начало буфера. тогда пофигу будет где в ней какие поля раскиданы.

А что у вас были случаи когда компилятор менял местами поля в структуре?
Я таких случаев не помню.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 6 2012, 19:09
Сообщение #34


Гуру
******

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



QUOTE (_Артём_ @ Aug 6 2012, 16:24) *
Я таких случаев не помню.
Да и стандарт не позволяет. Но у страха-то глаза велики...


--------------------
На любой вопрос даю любой ответ
"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
Dikoy
сообщение Aug 6 2012, 20:18
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Цитата(Petka @ Aug 6 2012, 10:33) *
Полный бред.
1) ADC3_temp = ADC3_RxC_counter;
2) ADC3_temp--;
3) Buf_ADC3[ADC3_temp] = UDR1;
4) ADC3_RxC_counter = ADC3_temp;
5) goto 1
Разумеется после обнуления ADC3_temp команда из п.2 сделает ADC3_temp==0xFF и тогда п.3 сломает память.

Вы, как всегда, пишете быстрее чем думаете.
1 и 4 кпируют волатайл переменную в R16 и далее все операции идут с регистром, что экономит порядка 20 тактов.
5 - ваш глюк.
3 - для одноразовой операции нет разницы, используется указатель или индекс. Всё равно будет с нуля браться адрес и вычисляться смещение.
2 - даже не знаю что и сказать.

А про порчу памяти от прерывания вам уже всё сказали. Не возникает лишнего прерывания. И я это вижу в железке на осциллографе, а не в протеусе, что суть кофейная гуща. Да ещё и пиратская (да да, есть такое понятие).

Компилятор НИКОГДА не переставит поля структуры. На то она и структура. По крайней мере за 5 лет работы в IAR и 8 лет в CV я такого не видел.

Цитата(kolobok0 @ Aug 6 2012, 17:10) *
код видоизменить так, что бы не было в нём первого поля, или последнего. структура как чёрный ящик - длина, начало буфера. тогда пофигу будет где в ней какие поля раскиданы.

Это называется массив wink.gif
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 6 2012, 23:06
Сообщение #36


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Dikoy @ Aug 6 2012, 23:18) *
а не в протеусе, что суть кофейная гуща. Да ещё и пиратская (да да, есть такое понятие).

Как говорят братья-мусульмане, Аллах, когда ночью спит, через стенку не видит sm.gif
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Aug 7 2012, 06:05
Сообщение #37


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(_Артём_ @ Aug 6 2012, 17:24) *
...компилятор менял местами..


для тех кто начал читать топик с конца, даю справку:

речь шла не о компиляторах...


Цитата(Dikoy @ Aug 7 2012, 00:18) *
...Это называется массив..


в данном конкретном случае - не важно как это называется. важно как это воспринимается.
Go to the top of the page
 
+Quote Post
hd44780
сообщение Aug 7 2012, 06:27
Сообщение #38


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

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Возьмите реализацию очередей из CVAvr-а. Я её и на WinAVR-е "портировал" - работает.

Структуры в CvAVR-е передавал, как байтовые массивы:

CODE

// Отправка структуры measureData
pData = (byte *)&measureData;
for (Uint=0; Uint<sizeof(measureData); Uint ++)
{
uartBufferPutchar ( *pData );
pData ++;
} // for


На компе, в программе на C# принимается как часы ... Даже второй МК (мега8), которая из себя изображает USB, нормально принимает. Там правда свои глюки есть, но то уже издержки эмуляции USB...
Изделие - ваттметр на Мега16, стек - 350 байт.

Сообщение отредактировал hd44780 - Aug 7 2012, 06:31


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post
Petka
сообщение Aug 7 2012, 07:05
Сообщение #39


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

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(Dikoy @ Aug 7 2012, 00:18) *
...
1 и 4 кпируют волатайл переменную в R16 и далее все операции идут с регистром, что экономит порядка 20 тактов.
3 - для одноразовой операции нет разницы, используется указатель или индекс. Всё равно будет с нуля браться адрес и вычисляться смещение.

Не суть.
Цитата
5 - ваш глюк.

А что запретит прерывание по UART_RXC? Если прерывание не запрещены, то при следующем входном байте на UART будет снова вызван обработчик прерывания.
вы так упорото не хотите понять, что индекс массива у вас никак не защищён от переполнения вниз.
Цитата
А про порчу памяти от прерывания вам уже всё сказали.

так это или не так легко проверить: поставьте проверку на индекс массива
Код
if(ADC2_RxC_counter >= ADCBUFSISE){
    ERROR_LED_ON;
}
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 7 2012, 07:12
Сообщение #40


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

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(hd44780 @ Aug 7 2012, 09:27) *
Возьмите реализацию очередей из CVAvr-а. Я её и на WinAVR-е "портировал" - работает.


Советовал уже использовать fifo гдето в первых постах.
У автора топика проблема с заполнением структуры данных АЦП а не с передачей.
Как по мне проглядывается ещё одна проблема - автор пытается заполнять структуру в прерываниях от ацп и одновремененно отправлять её по uart. Возможно там есть временное разделение - т.е. сначала структура заполняется, потом передаётся и гарантированно она не изменится в процессе передачи, но в целом подход неверный.
Было бы правильней проверять флаг необходимости передачи, при обнаружении с запрещёнными прерываниями закинуть всю структуру данных в fifo uart, сбросить флаг необходимости передачи, разрешить прерывания. Заодно можно обнулять индекс массива данных и инкрементировать его по каждому прерыванию ацп.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 7 2012, 23:02
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Цитата(Petka @ Aug 7 2012, 11:05) *
А что запретит прерывание по UART_RXC?
}

UART в режиме SPI. Если байт не будет отправлен, то он не будет принят, и RxC не будет. Посмотрите тушку прерывания - последний байт принимается, но отправки (UDR1 = ADC3_temp;) нет.
Это про порты АЦП речь.
С передачей в комп уже всё определилось - не она виновата.

Цитата(hd44780 @ Aug 7 2012, 10:27) *
Возьмите реализацию очередей из CVAvr-а. Я её и на WinAVR-е "портировал" - работает.

У меня есть свой движок с очередью, пользую уже лет 5. Но в очереди есть смысл когда мы мониторим несколько портов и, главное, информация из этих портов может уйти произвольно.
В данном случае маршруты следования информации строго определены, делать очередь нет смысла.
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 8 2012, 02:35
Сообщение #42


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



Переписал прерывание через указатель, и всё заработало:
CODE

unsigned char *pADC3_rx_pointer = &(Buf_ADC3[0]);;
volatile unsigned char ADC3_rx_compl = 0;

//*********

#pragma vector=(0x48*0x02)
__interrupt void ADC3_RxC_isr(void) { //

*pADC3_rx_pointer = UDR1;
if(pADC3_rx_pointer < (&(Buf_ADC3[ADCBUFSISE - 1])) ) {
pADC3_rx_pointer++;
UDR1 = 0xff;
} else {
ADC3_rx_compl = 0xff;
}

}

// **********

while(1) {
if( ADC3_rx_compl == 0xff ) {

CopyBufFast( (char *)&TransmisionFrame.ADC3[0], (char *)&Buf_ADC3[0], (ADCBUFSISE) ); // êîïèðóåì âðåìåííûé áóôåð â âûõîäíîé ôðåéì

pADC3_rx_pointer = &(Buf_ADC3[0]);
ADC3_rx_compl = 0;
}
}


Результат:

Код
22BB00000002000000000000000000000000000000000003000000000000
0000000000000000DF1A584696F1A500695F1A5F469971A55889A55A
22BB00000003000000000000000000000000000000000004000000000000
00000000000000001A584696F1A4FC695E1A5F469981A55889EDA55A
22BB00000004000000000000000000000000000000000005000000000000
00000000000000001A580696F1A500695E1A5F469971A55889EEA55A
22BB00000005000000000000000000000000000000000006000000000000
00000000000000001A580696E1A4FC695C1A5EC69961A55489F2A55A


Пока сделал только для АЦП №3.

Теперь думаю, как соптимизировать прерывание. Пробовал избавиться от ADC3_rx_compl и в мейнлупе поставить проверку
if( pADC3_rx_pointer == (&(Buf_ADC3[ADCBUFSISE - 1])) ) {}
Прерывание долбит непрерывно и не останавливается.
Уже поздно и мозг не варит, по тому не могу понять почему blink.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 8 2012, 16:18
Сообщение #43


Гуру
******

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



QUOTE (Dikoy @ Aug 8 2012, 05:35) *
Прерывание долбит непрерывно и не останавливается.
Уже поздно и мозг не варит, по тому не могу понять почему
Если pADC3_rx_pointer изменяется в прерывании, а анлизируется в основном цикле - она должна быть объявлена как volatile-указатель: unsigned char * volatile pADC3_rx_pointer = &(Buf_ADC3[0]);


--------------------
На любой вопрос даю любой ответ
"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
Dikoy
сообщение Aug 9 2012, 02:33
Сообщение #44


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



В этом случае компилер ругается

Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
*pADC3_rx_pointer++ = UDR1;

Регистры в IAR все volatile и компилер какбЭ намекает, что не может одновременно извлечь две volatile переменные для операции.

Хотя в реале, конечно, работает.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 9 2012, 09:39
Сообщение #45



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Dikoy @ Aug 9 2012, 06:33) *
В этом случае компилер ругается

Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
*pADC3_rx_pointer++ = UDR1;

Вот так
*pADC3_rx_pointer = UDR1;
pADC3_rx_pointer++;
полегчает.
Цитата
Регистры в IAR все volatile и компилер какбЭ намекает, что не может одновременно извлечь две volatile переменные для операции.
Хотя в реале, конечно, работает.

Компилер намекает, что порядок выполнения присваивания и постинкремента не гарантирован.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 9 2012, 09:53
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 9 2012, 12:39) *
Вот так
*pADC3_rx_pointer = UDR1;
pADC3_rx_pointer++;
полегчает.

Нет, не полегчает - всё равно будет варнинг.
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 9 2012, 10:18
Сообщение #47



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(_Артём_ @ Aug 9 2012, 13:53) *
Нет, не полегчает - всё равно будет варнинг.

Обосновать сможете? Или привести скриншот такой иаровой странности?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 9 2012, 11:00
Сообщение #48


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(xemul @ Aug 9 2012, 13:18) *
Обосновать сможете? Или привести скриншот такой иаровой странности?

Прикрепленное изображение
Go to the top of the page
 
+Quote Post
xemul
сообщение Aug 9 2012, 11:41
Сообщение #49



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Спасибо.
Вероятно, предупреждение связано таки с двухбайтовостью указателя и неготовностью компилятора обеспечить атомарность доступа к нему на однобайтовой архитектуре.
Тогда "*Ptr++ = UDR0;" на авр получается даже чуть более безопасным вариантом, чем "*Ptr = UDR0; Ptr++;".
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Aug 9 2012, 17:13
Сообщение #50


Местный
***

Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676



инкремент указателя будет согласно типу. У нас это чар, значит на 1 байт независимо от условий.
Попробуйте выражение a = b+c; где все переменные волатайлы, тоже выскочит варнинг.

А причина как раз в том, что несмотря на чёткость последовательности операций ИАР предупреждает, что одновременно вынуть 2 переменные он не сможет. Значит между извлечением UDR0 и записью оного по адресу будет Н тактов, в которых может произойти страшное. Вдруг у нас вложенные прерывания разрешены или ещё какой ужас.
То есть варнинг не страшный, лишь указует на возможную проблему.

Сообщение отредактировал Dikoy - Aug 9 2012, 17:15
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 9 2012, 18:26
Сообщение #51


Гуру
******

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



QUOTE (Dikoy @ Aug 9 2012, 05:33) *
В этом случае компилер ругается

CODE
{
unsigned char * pTmp = *pADC3_rx_pointer;
*pTmp++ = UDR1;
pADC3_rx_pointer = pTmp;
}

можно попробовать также другие варианты, и выбрать наиболее удачно компилирующийся:
CODE
{
unsigned char * pTmp = *pADC3_rx_pointer++;
*pTmp = UDR1;
}

CODE
{
unsigned char * pTmp = *pADC3_rx_pointer;
*pTmp = UDR1;
pADC3_rx_pointer = ++pTmp;
}


--------------------
На любой вопрос даю любой ответ
"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

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

 


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


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