|
CodeVision+указатели+прерывание, Искажение указателя при прерывании |
|
|
|
Sep 25 2009, 06:53
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 12-01-09
Из: Донецк, Украина
Пользователь №: 43 218

|
Написал вот такой код: Код interrupt [TIM2_OVF] void timer2_ovf_isr(void) { // Stop timer TCCR2=0x00;
if(get_incoming_pkt()==3){ switch (check_command(myip)) { case 0: strcpyf(service_msg, "Micro_device#0:not_a_command"); service_msg[13]=device_id; send_to_server(service_msg, service_msg_len); break; case 1: init_ip_arp_udp(mymac,myip); strcpyf(service_msg, "Micro_device#0:IP_changed"); service_msg[13]=device_id; send_to_server(service_msg, service_msg_len); break; case 2: strcpyf(service_msg, "Micro_device#0:comm_2_done"); service_msg[13]=device_id; send_to_server(service_msg, service_msg_len); break; default: strcpyf(service_msg, "Micro_device#0:command_Error"); service_msg[13]=device_id; send_to_server(service_msg, service_msg_len); }; }; // Start timer TCCR2=0x07; TCNT2=0x00; } // end of interrupt
void main(void)
.... unsigned int* pointer; ......
pointer=get_adc_data(); for(i=0;i<6;i++){ data_msg[16+2*i]=(*(pointer+i))>>8; //MSB data_msg[16+2*i+1]=(*(pointer+i)) & 0xff; //LSB };
...... Проблема следующая: при возникновении прерывания во время работы с указателем, значения записываемые в data_msg[], искажаются. При запрете прерываний на этот кусок кода, всё работает нормально.
Сообщение отредактировал troy97 - Sep 25 2009, 07:20
|
|
|
|
|
 |
Ответов
(1 - 11)
|
Sep 25 2009, 14:03
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Цитата(troy97 @ Sep 25 2009, 09:53)  ...Проблема следующая... Функцию get_adc_data() покажите...
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Sep 25 2009, 16:39
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 12-01-09
Из: Донецк, Украина
Пользователь №: 43 218

|
1) pointer точно не используется в прерывании. i объявлена в начале main(), да и не на i подозрения т.к. сегодня отловил, что та же проблема, но реже, возникает если вырубать прерывания только на кусок с циклом for. Т.е. портится указатель даже на строке pointer=get_adc_data(); 2) нет, размер service_msg не превышаю. Привожу код get_adc_data(): CODE unsigned int* get_adc_data(void) { unsigned char i; unsigned int adc_data=0; unsigned int analog_vals_arr[6]={0,0,0,0,0,0};
// ADC Clock frequency: 130,156 kHz ADCSRA=0x86;// ADC enable; ADC int.disable; prescaler=64 TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; TCCR1B=0x03;// clk/64
do{ for (i=0; i<6; i++) { ADMUX&=0b11110000; ADMUX|=i; ADCSRA|=0x40; while(!(ADCSRA & (1<<ADIF))); ADCSRA|=(1<<ADIF); adc_data=ADCW; check(adc_data, i); }; // check timer1 overflow flag if (TIFR &= (1<<TOV1)) { TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; TIFR |= (1<<TOV1); timer1(analog_vals_arr); break; }; } while(1); ADCSRA clrb(ADEN);//stop ADC return (analog_vals_arr); } функция timer1 получает указатель analog_vals_arr и заполняет массив необходимыми значениями
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Sep 25 2009, 19:06
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581

|
Попробуйте так: Код ... #asm("cli") TCNT1H=0x00; TCNT1L=0x00; #asm("sei") ... #asm("cli") adc_data=ADCW; #asm("sei") ... ЗЫ. И что за while(1) ? Как программа оттуда выходит (если флаг не будет стоять)? А стек увеличивать пробовали?..
--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
|
|
|
|
|
Sep 26 2009, 06:15
|
Участник

Группа: Участник
Сообщений: 70
Регистрация: 22-04-07
Из: Poltava/Kharkov
Пользователь №: 27 243

|
get_adc_data возвращает указатель на локальную переменную (созданую с стеке), естественно при входе в прерывание по тем адресам (где были значения analog_vals_arr) создаются другие локальные переменные. Нужно объявить analog_vals_arr как static, либо переделать get_adc_data так чтобы она заполняла переданый ей (указателем) массив. p.s. ладно, попробую поменять порядок слов
Сообщение отредактировал Sergey Reva - Sep 26 2009, 06:36
|
|
|
|
|
Sep 26 2009, 06:26
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 12-01-09
Из: Донецк, Украина
Пользователь №: 43 218

|
Goodefine, попробую, но определено, что проблема не возникает, если перед самым return'ом из get_adc_data(), сбросить TCNT2, т.е. чтобы прерывание точно не попало на кусок с указателями. Из while(1), если TOV1 не установлен... никак не выходит... признаю свою вину. "А стек увеличивать пробовали?.." - нет, а как?  _Pasha, можно и так, а что это даст, если я правильно понимаю, то просто добавится ещё один прыжок, а время обработки прерывания останется тем же? Sergey Reva, очень логично, сделаю, спасибо.
Сообщение отредактировал troy97 - Sep 26 2009, 06:29
|
|
|
|
|
Sep 27 2009, 18:40
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Sergey Reva @ Sep 26 2009, 09:15)  get_adc_data возвращает указатель на локальную переменную (созданую с стеке), естественно при входе в прерывание по тем адресам (где были значения analog_vals_arr) создаются другие локальные переменные. Нужно объявить analog_vals_arr как static, либо переделать get_adc_data так чтобы она заполняла переданый ей (указателем) массив. +1. Причём надо отметить, что это не "неточность", а грубая ошибка. С формальной точки зрения, вы передаёте указатель на несуществующие данные. Прогнозировать дальнейшее поведение системы не представляется возможным. Оно будет меняться от компиляции к компиляции. То есть будет зависеть от распределения памяти компилятором. Иными словами изменения в другой части программы, логически совершенно не связанной, может изменить поведение этого куска. Я бы не применял static, так как выглядит неестественно. Я бы либо сделал массив глобальным, либо объявил его в месте использования и передавал процедуре на неё указатель, как рекомендовал Sergey Reva.
|
|
|
|
|
Sep 28 2009, 06:53
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 12-01-09
Из: Донецк, Украина
Пользователь №: 43 218

|
Объявил массив в месте его использования, функции передаю указатель. Сегодня утром прошился, уже 1,5 часа полёт нормальный, надо ещё погонять, потом отпишусь.
|
|
|
|
|
Sep 29 2009, 09:53
|
Участник

Группа: Участник
Сообщений: 20
Регистрация: 12-01-09
Из: Донецк, Украина
Пользователь №: 43 218

|
Работает уже сутки без сбоев, всем большое спасибо за помощь!
Сообщение отредактировал troy97 - Sep 29 2009, 09:54
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|