STM32F103 приоритеты для обработки вложенных прерываний - PullRequest
0 голосов
/ 10 декабря 2018

Я мог найти проблему, связанную с NVIC_Init в библиотеке STM32F10x, связанную с приоритетами для обработки вложенных прерываний.Мы знаем, что любое прерывание со значением приоритета, равным или превышающим BASEPRI (в нашем случае 11), может вызывать функции FromISR () FreeRTOS API.

FreeRTOS использует 15 уровень (самый низкий приоритет).

#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY    15

Другими словами, FreeRTOS позволяет нам вызывать функции API (см. XQueueSendToBackFromISR) из ISR с приоритетом 15-11.Когда мы инициализируем NVIC, мы используем уровень # 11

#define    WRTU2_DMA1_SPI2_IRQ_PRIORITY     (configLIBRARY_KERNEL_INTERRUPT_PRIORITY-4*)
    /* DMA1 Channel4 interrupt setting */
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = WRTU2_DMA1_SPI2_IRQ_PRIORITY;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = WRTU2_DMA1_SPI2_IRQ_PRIORITY;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

Итак, мы должны быть в порядке.Но проблема существует.Я решил проверить NVIC_Init.

Согласно информации из таблицы данных STM32 приоритетным регистром является 0xe000e40e (канал 14 NVIC принадлежит DMA1_Channel4 прерывания).

И я мог прочитать 0x00 из этого регистра после инициализации NVIC.Это означает, что канал NVIC № 14 имеет самый высокий приоритет в системе.

И это вызывает все проблемы.

Я добавил простейшее исправление NVIC-> IP [DMA1_Channel4_IRQn] = 0xF0; И система больше не выходит из строя.Итак, наша текущая проблема решена.

Конечно, я попытался проанализировать, что происходит в NVIC_Init

**
  * @brief  Initializes the NVIC peripheral according to the specified
  *         parameters in the NVIC_InitStruct.
  * @param  NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
  *         the configuration information for the specified NVIC peripheral.
  * @retval None
  */
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;

  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));

  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/    
    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
    tmppre = (0x4 - tmppriority);
    tmpsub = tmpsub >> tmppriority;

    tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    tmppriority = tmppriority << 0x04;

    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;

    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}

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

uint32_t NVIC_IRQChannelPreemptionPriority=0xFF,NVIC_IRQChannelSubPriority=0xFF;
int32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
tprintf("\n\rSCB->AIRCR=0x%08x",SCB->AIRCR);

 tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
 tprintf("\n\rtmppriority=0x%08x",tmppriority);
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;

 tprintf("\n\rtmppre=0x%08x",tmppre);
 tprintf("\n\rtmpsub=0x%08x",tmpsub);


tmppriority = (uint32_t)NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |=  NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
tprintf("\n\rtmppriority=0x%08x",tmppriority);    

Есть журнал

SCB->AIRCR=0xfa050000
tmppriority=0x00000007
tmppre=0xfffffffd
tmpsub=0x00000000
tmppriority=0x00000000

Заметьте, даже если я указываю 0xFF для обоих входных параметров, он возвращает 0x00.

Я действительно удивлен этимповедение.Это библиотечная функция.

Люди используют ее много лет.Итак, я действительно запутался, я могу найти проблему с этой функцией.

Возможно, это связано с регистром управления прерываниями и сбросом приложения (SCB_AIRCR). Смещение адреса: 0x0C. Значение сброса: 0xFA05 0000. Требуемая привилегия: Privileged.AIRCR обеспечивает управление группировкой приоритетов для модели исключений, порядковый номер для доступа к данным и управление сбросом системы.

Обратите внимание, в источниках библиотеки я вижу #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)

Итак, этопохоже, у нас есть какой-то порядок байтов BIG vs LITTLE ENDIAN в 16-битном куске.

Есть ли у вас какие-либо предположения или сведения о проблеме?

1 Ответ

0 голосов
/ 12 декабря 2018

Я нашел проблему, проблема в том, что я должен использовать NVIC_SetPriorityGrouping (3);как 3 для cortex-m3.

, тогда он обеспечивает 4-битный приоритетный приоритет и 0 бит для приоритета.В конце, когда я начинаю так, он работает так, как я ожидал.

  /* DMA1 Channel4 interrupt setting */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 11;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
...