Jump to content
    

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

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

Share this post


Link to post
Share on other sites

... а также запретить DMA (если есть), или любых других мастеров кроме CPU.

Share this post


Link to post
Share on other sites

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

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

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

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

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. В остальных поймать не получилось.

 

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

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++;
  }
}

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

Edited by LAS9891

Share this post


Link to post
Share on other sites

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

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

...

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

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

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

...

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

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

Share this post


Link to post
Share on other sites

10 hours ago, jcxz said:

Ужас

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

 

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

Edited by LAS9891

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...