Перейти к содержанию
    

GD32F103RBT6. Пропуск прерываний в режиме захвата

На время отладки все остальные прерывания отключить, колбэки убрать. Добиться отсутствия пропусков и понемногу возвращать функционал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 2/19/2024 at 7:13 PM, VladislavS said:

Добиться отсутствия пропусков

Сделал специальный дебуговый проект. В нём делаю минимальную инициализацию для настройки тактирования, пинов, таймера 1. По завершении инициализации проект висит в while(1){;}. На 4 канала таймера 1 подаю одинаковые пачки импульсов.

Вот в таком варианте обработчика прерываний:

Spoiler
void TIMER1_IRQHandler (void)
{
//---Variables---//
uint8_t  ch       = 0; // Переменная определяет номер канала.
  
uint32_t INTF_regval   = TIMER_INTF(TIMER1);
uint32_t CHCTL2_regval = TIMER_CHCTL2(TIMER1);
uint32_t  polarity     = 0x00;

EdgeEnum edge                                                = FALLING;
         GPIO_PinState NewPinState [4] = {GPIO_PIN_RESET};
static   GPIO_PinState OldPinState [4] = {GPIO_PIN_SET, GPIO_PIN_SET, GPIO_PIN_SET, GPIO_PIN_SET};
         GPIO_PinState LoopCondition = GPIO_PIN_RESET;

//---------------//
  
//---If channel 0 capture/compare interrupt flag is set---//
if (INTF_regval & TIMER_INTF_CH0IF) // If channel 0 capture/compare interrupt flag is set.
  {
  ch       = 0; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH0P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    {
    edge          = RISING;
    LoopCondition = GPIO_PIN_RESET;
    }
  else // Если было настроено прерывание на фронт...
    {
    edge          = FALLING;
    LoopCondition = GPIO_PIN_SET;
    }

  do
    {
    EdgeChanging(TIMER1, ch, edge);
    edge          = (EdgeEnum)!edge;
    LoopCondition = (GPIO_PinState)!LoopCondition;
    do
      {
      TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; // Clear capture/compare interrupt flag.
      NewPinState[ch]    = GPIO_GetPinState(DALI_RX_Connect[ch].port, DALI_RX_Connect[ch].pin);
      }
    while(TIMER_INTF(TIMER1) & TIMER_INTF_CH0IF);
    }
  while(NewPinState[ch] == LoopCondition);
    
  if (NewPinState[ch] == OldPinState[ch])
    {;}//return;
  else
    OldPinState[ch] = NewPinState[ch];
  }
//--------------------------------------------------------//


//---If channel 1 capture/compare interrupt flag is set---//
if (INTF_regval & TIMER_INTF_CH1IF) // If channel 1 capture/compare interrupt flag is set.
  {
  // Аналогично channel 0 //
  }
//--------------------------------------------------------//
  
//---If channel 2 capture/compare interrupt flag is set---//
if (INTF_regval & TIMER_INTF_CH2IF) // If channel 2 capture/compare interrupt flag is set.
  {
  // Аналогично channel 0 //
  }
//--------------------------------------------------------//
  
//---If channel 3 capture/compare interrupt flag is set---//
if (INTF_regval & TIMER_INTF_CH3IF) // If channel 3 capture/compare interrupt flag is set.
  {
  // Аналогично channel 0, но всё равно выложу. Может чем-то отличается, чем я не вижу//
  ch       = 3; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH3P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    {
    edge          = RISING;
    LoopCondition = GPIO_PIN_RESET;
    }
  else // Если было настроено прерывание на фронт...
    {
    edge          = FALLING;
    LoopCondition = GPIO_PIN_SET;
    }

  do
    {
    EdgeChanging(TIMER1, ch, edge);
    edge          = (EdgeEnum)!edge;
    LoopCondition = (GPIO_PinState)!LoopCondition;
    do
      {
      TIMER_INTF(TIMER1) = ~TIMER_INTF_CH3IF; // Clear capture/compare interrupt flag.
      NewPinState[ch]    = GPIO_GetPinState(DALI_RX_Connect[ch].port, DALI_RX_Connect[ch].pin);
      }
    while(TIMER_INTF(TIMER1) & TIMER_INTF_CH3IF);
    }
  while(NewPinState[ch] == LoopCondition);
    
  if (NewPinState[ch] == OldPinState[ch])
    {;}//return;
  else
    OldPinState[ch] = NewPinState[ch];
  }
//--------------------------------------------------------//
}

//...//

void EdgeChanging (uint32_t timer, uint8_t channel, EdgeEnum edge)
{
uint32_t temp              = TIMER_CHCTL2(timer);
uint32_t TIMER_CHCTL2_CHxP = (TIMER_CHCTL2_CH0P << (channel * 4));

if (edge == FALLING)
  temp |= TIMER_CHCTL2_CHxP;
else
  temp &= (~TIMER_CHCTL2_CHxP);

TIMER_CHCTL2(timer) = temp;    // Change channel x capture/compare function polarity.
}
//------------------------------------------------------------------------------//

стабильно ловлю пропуски в канале 3. Даже если в обработчике ставлю обработку канала 3 в самое начало, всё равно ловлю пропуски в канале 3. В остальных поймать не получилось.

 

Вот в таком варианте обработчика прерываний:

Spoiler
void TIMER1_IRQHandler (void)
{
//---Variables---//
uint8_t  ch       = 0; // Переменная определяет номер канала.
  
uint32_t INTF_regval   = TIMER_INTF(TIMER1);
uint32_t CHCTL2_regval = TIMER_CHCTL2(TIMER1);
uint32_t  polarity     = 0x00;

EdgeEnum edge = FALLING;
//---------------//


if (INTF_regval & TIMER_INTF_CH0IF) // If channel 0 capture/compare interrupt flag is set.
  {
  ch       = 0; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH0P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    edge = RISING;
  else // Если было настроено прерывание на фронт...
    edge = FALLING;

  EdgeChanging(TIMER1, ch, edge);
  TIMER_INTF(TIMER1) = ~TIMER_INTF_CH0IF; // Clear capture/compare interrupt flag.
  i_ch0++;
  }


if (INTF_regval & TIMER_INTF_CH1IF) // If channel 1 capture/compare interrupt flag is set.
  {
  ch       = 1; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH1P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    edge = RISING;
  else // Если было настроено прерывание на фронт...
    edge = FALLING;

  EdgeChanging(TIMER1, ch, edge);
  TIMER_INTF(TIMER1) = ~TIMER_INTF_CH1IF; // Clear capture/compare interrupt flag.
  i_ch1++;
  }


if (INTF_regval & TIMER_INTF_CH2IF) // If channel 2 capture/compare interrupt flag is set.
  {
  ch       = 2; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH2P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    edge = RISING;
  else // Если было настроено прерывание на фронт...
    edge = FALLING;

  EdgeChanging(TIMER1, ch, edge);
  TIMER_INTF(TIMER1) = ~TIMER_INTF_CH2IF; // Clear capture/compare interrupt flag.
  i_ch2++;
  }


if (INTF_regval & TIMER_INTF_CH3IF) // If channel 3 capture/compare interrupt flag is set.
  {
  ch       = 3; // Выбор номера канала.
  polarity = (CHCTL2_regval & TIMER_CHCTL2_CH3P);

  //---Input capture event--------------------------------------------------------------//
  if (polarity) // Если было настроено прерывание на срез...
    edge = RISING;
  else // Если было настроено прерывание на фронт...
    edge = FALLING;

  EdgeChanging(TIMER1, ch, edge);
  TIMER_INTF(TIMER1) = ~TIMER_INTF_CH3IF; // Clear capture/compare interrupt flag.
  i_ch3++;
  }
}

пропусков поймать не удалось.

Изменено пользователем haker_fox
Длинный код спрятал под спойлер.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, LAS9891 сказал:

Вот в таком варианте обработчика прерываний:

...

Ужас - такого бурелома нагородить на ровном месте из простого алгоритма...  :shok:

7 часов назад, LAS9891 сказал:

Вот в таком варианте обработчика прерываний:

...

пропусков поймать не удалось.

Но они всё равно будут, просто реже.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 hours ago, jcxz said:

Ужас

Другой оценки мне не стоит ожидать. Предложите свой код, в котором не будет пропусков, а я проверю. Где найти достойный пример, если даже в STM работают говнокодеры?

 

На свежую голову (или что там вместо головы у говнокодеров) нашёл косяк. Теперь не ловлю пропуски в обоих вариантах, но надеюсь, что выложат неговнокодовый пример того, как надо делать.

Изменено пользователем LAS9891

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...