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

 
 
> Трассировка процесса
juvf
сообщение Dec 10 2010, 11:32
Сообщение #1


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



MSP430F2418
есть в мэйне основной цыкл while(1). в теле цыкла вызываются всякие процедуры и функции которые по глобальным флагам делают те или иные действия. Есть обработчик прерываний который прерывает этот вайл и выставляет всякие флажки, которые обрабатываются в главном цыкле. обычно цыкл прохонит за несколько мс с учётом времени потраченное в перываниях. но иногда процесс где-то шляется больше секунды. в обработчике прерывания выставляю флаг. в главном цыкле должен по этому флагу запустить процедуру. так вот между выставлением флага в прерывании и проыеркой этого флага в гл. цыкле может пройти больше секунды. из прерывания выход мгновенный. 100%. а вот где потом процесс шляется целую секунду не могу найти. узнать бы в каком месте была прервана программа прерыванием и куда вернулась? Как бы трассировкку процесса устроить? Как это можно решить с помошью IAR EW IDE? или какими еще способами можно выяснить где мы были целую секунду?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Shread
сообщение Dec 10 2010, 11:47
Сообщение #2


иногда заглядывающий
****

Группа: Свой
Сообщений: 900
Регистрация: 18-05-05
Из: Зеленоград
Пользователь №: 5 170



Что-то похожее наблюдал, когда были включены прерывания, а обработчик NMI отсутствовал. Разберитесь с тем что у вас включено из прерываний, а что нет, после чего добавьте обработчики тех прерываний, которые включены. Просто так "шляться" программа в 2хх не может - в этом семействе есть аппаратный модуль сброса на этот случай.
Go to the top of the page
 
+Quote Post
juvf
сообщение Dec 10 2010, 15:11
Сообщение #3


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

Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045



Цитата(Shread @ Dec 10 2010, 16:47) *
Разберитесь с тем что у вас включено из прерываний, а что нет, после чего добавьте обработчики тех прерываний, которые включены. Просто так "шляться" программа в 2хх не может - в этом семействе есть аппаратный модуль сброса на этот случай.

да вроде всё что нужно включено, всё что не нужно выключено. Может какой нибудь прерывание не нужное раз в 3 дня включается и процесс постоянно ныряет в него около минуты. потом опять всё нормально. Но я ме могу понять где процесс находится? в каком прерывании или где застревает в мэйне?

И всё же, есть у кого-нибудь опыт трассировки процесса? Может кто-нибудь подсказать в какую сторону глянуть?

Цитата
Исходник обработчика прерывания приведите. Мнится мне, что именно там собака порылась.
Ну тут адский код. Черт ногу сломит. Но мож на вскидку кто увидет потенциальную багу.
Код
#pragma vector=TIMERB1_VECTOR
__interrupt void TimerB_Int1(void) {

  switch(__even_in_range(TBIV, 14)) {
    case 2: break; //Прерывание по модулю сравнения 1 (Высший приоритет)
    case 4:  TBCCTL2=0; InvalidIntCNT++; return;        
    case 6:  TBCCTL3=0; InvalidIntCNT++; return;
    case 8:  TBCCTL4=0; InvalidIntCNT++; return;
    case 10: TBCCTL5=0; InvalidIntCNT++; return;
    case 12: TBCCTL6=0; InvalidIntCNT++; return;
    case 14: Tic2sCounter++; return; //Прерывание по переполнению таймера B. Период 32768/65536=0.5 Гц (2 с)
    default: return;
  }
  

  TBCCR1+=Value32kHz1sCCR;
  //Цифровая коррекция хода часов
  //Изменение на 3 такта каждые 79 сек дает 0,1 сек/сут
  if(++DTC79Cnt>=79) {
    DTC79Cnt=0;
    TBCCR1-=(EEPROM.RTC_Correct*3)-60;  //60 - отставание на 2 сек/сут
  }
  //Если нужно, считаем длительность заряда АКБ
  if(ChargeCnt) if(gFlags.ExtPower) {
    if(++ChargeSticks>4) ChargeSticks=0;
    if(!--ChargeCnt) EndCharge();
  }

  if(P3State != P3_Off) {
    //Если нужно, считаем секундный тайм-аут
    if(Sec_TimeOut) --Sec_TimeOut;
    //Если нужно, проверим время автовыключения
    if(gFlags.ExtPower) {AutoOffCnt=EEPROM.AutoOff; BLAutoOffCnt=EEPROM.BLAutoOff;}
    else{
      if(AutoOffCnt)   if(!--AutoOffCnt)   gFlags.AutoOff=1;
      if(BLAutoOffCnt) if(!--BLAutoOffCnt) InitBackLight();
    }
    //Синхронизируем индикацию с часами
    if((Cnt20ms>1) && (Cnt20ms<18)) Cnt20ms++;
    if((Cnt1S>1)   && (Cnt1S<48))   Cnt1S++;
  }
  //Если идет ожидание окончания измерения, считать секунды
  if(MeasWait) MeasWait--;
  //Если часы остановлены, выход
  if(gFlags.ClockStop) return;
  _EINT();
  //Прибавление секунды к текущему времени
  //NewSec++;
  if( GsmCheckTimeOut != 0)
      --GsmCheckTimeOut;
  ++CurDT.Sec;
  if((CurDT.Sec >= 1) && gFlags.TimeBeginConnect)
  {
      gFlags.TimeBeginConnect = 0;
//PORT_UART_PC &= ~Bit_UART_PC_FOF;//порт сбросим для наблюдения в осцилографе
  }
#ifdef RADIO
  if(CurDT.Sec == 58)
  {//включим питание RFD21733
      UARTAdOn();
      Power4On();
  }
#endif
  
//if(CurDT.Sec == 3)///!!!
//    CurDT.Sec = 56;
    
  if(CurDT.Sec>59) {
    
        
    CurDT.Sec=0;
    //Если есть нормальное питание (EP2), проснуться
    if(!PowerIsLi())
    {
        _BIC_SR_IRQ(LPM3_bits);
        InitUART1();
        IdleDelay=1;
    }
    BCSCTL1 &= ~XT2OFF;
    BCSCTL2 |= SELS;
    gFlags.TimeBeginConnect = 1;
    gFlags.isTest = 1;
    BeginSysTimer(); //сброс дебажного счетчика
    gFlags.Synchronization = 1;
    if(--timeCheckBattary == 0)
    {
        gFlags.CheckBattary = 1; // флаг проверки батареи
        timeCheckBattary = 10;
    }
    //PORT_UART_PC |= Bit_UART_PC_FOF;
    if(++CurDT.Min>59) {
      CurDT.Min=0;
      if(++CurDT.Hour>23) {
        CurDT.Hour=0; CurDT.Day++;
        if(CurDT.Day>CalcDayInMonth(&CurDT)) {  //Месяц закончился
          CurDT.Day=1;
          if(++CurDT.Month>12) {
            CurDT.Month=1;
            CurDT.Year++;
          }
        }
      }
    }
  }  
  //Проверка будильника
  if((AlarmAct != AA_Off) &&                      //Будильник включен,
     (AlarmAct != AA_ProcStop) &&                 //Не требуется окончание процесса
     (*(WORD*)&AlarmDT.Sec==*(WORD*)&CurDT.Sec) &&      //..секунды, минуты совпадают,..
     (*(WORD*)&AlarmDT.Hour==*(WORD*)&CurDT.Hour) &&    //..час, день,..
     (*(WORD*)&AlarmDT.Month==*(WORD*)&CurDT.Month))    //..месяц, год
  {
    //Будильник сработал, установить флаг
    regFlags.Alarm=1; MeasStep=MS_Wait;
    //Если есть нормальное питание (EP2), проснуться
    if(!PowerIsLi()) {_BIC_SR_IRQ(LPM3_bits); IdleDelay=1;}
    //При отсутствии нормального питания установить флаг потенциальной ошибки
    else {InitPower(); regFlags.PotencError=1;}
  }
  //Если при отсутствии нормального питания (EP2) разрешено включение, разобраться
  if((IE_PowerIn & Bit_PowerIn) && PowerIsLi()) {InitPower(); _BIC_SR_IRQ(LPM3_bits); regFlags.PotencError=1;}
  //Программный WDT
  if((P3State != P3_Off) && !--SoftWDT) {regFlags.PotencError=1; regFlags.ResultWrite=0; WarmReset();}
  asm("nop");
  msTime[0] = EndSysTimer(); фиксация дебажного счетчика
}


А вот еще возник вопрос, может здесь грабля лежит. Как работает "многопоточность" в мсп430 + иар?
например есть код и есть обработчик прерывания
Код
///main.cpp
bool happy;
int main()
{
happy = false;
while(1)
{
    if(happy)
    {
         divHappySmb();
         happy = false;
    }
}
}

//обработчик прерывания
#pragma vector=TIMERB1_VECTOR
__interrupt void TimerB_Int1()
{
    happy = checkMyMoney();
}


так вот, крутимся постоянно в main. по прерываниям порадаем в TimerB_Int1(). Можно сказать что тут 2 потока - главный и обработчик прерывания. Но ни какой системы синхранизации. Допустим мэйне мы читаем или пишим happy, в это время происходит прерывание. прцессор передает управление обработчику, сохраняется "портрет" состояния мэин и выполняется обработчик TimerB_Int1(). Потом востанавливается картина и передается управление мэйну. Так вот получается как-бы одновременное обращение из двух "потоков" к переменной happy. Не косяк ли это? может ли оператор "=" быть прерван по среди выполнения?
Понятно, что оператор "=" для bool скорее всего одна инструкция и её прервать на середине невозможно, но если happy это int, или какойнибудь тяжелый class MyHappyClass? Нужно ли защищять переменные в мэйне, которые используются в прерывании, типа

Код
int main()
{
happy = false;
while(1)
{
    dInt();//запрет прерывания
    if(happy)
    {
         eInt();//разрешение прерывания
         divHappySmb();
         dInt();//запрет прерывания
         happy = false;
    }
    eInt();//разрешение прерывания
    
}
}
Go to the top of the page
 
+Quote Post



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

 


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


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