Переназначение Timer1 вызывает сбой отладки на STM32F103

Я создаю проект Keil для своего микроконтроллера STM32F103 с помощью STM32CubeMx.

Моя цель - использовать канал 2 TIM1 для управления зуммером. Я хочу генерировать ШИМ на частоте 4 кГц через канал 2 TIM1. Я настроил с помощью STM32CubeMx TIM1_Channel2 как «Генератор ШИМ CH2».

Проблема касается сеанса отладки. В частности, когда я запускаю сеанс отладки и когда MCU выполняет макрос "__HAL_AFIO_REMAP_TIM1_ENABLE()", происходит сбой сеанса отладки.

Это код инициализации таймера, сгенерированный STM32CubeMx:

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(htim->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspPostInit 0 */

  /* USER CODE END TIM1_MspPostInit 0 */

    /**TIM1 GPIO Configuration   
    PE11     ------> TIM1_CH2
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_TIM1_ENABLE();

  /* USER CODE BEGIN TIM1_MspPostInit 1 */

  /* USER CODE END TIM1_MspPostInit 1 */
  }

}

Эта проблема связана с полным переназначением контакта Timer1.

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

Спасибо!

=== ОБНОВЛЕНИЕ ===

Наконец-то я нашел время протестировать решение, предложенное @SamGibson, и оно работает! И спасибо @Rafiq Rahman за его код!

Спасибо, ребята, за ваше время!

Это код, который я использовал для переназначения TIM1 и сохранения возможности генерировать код с помощью Stm32CubeMX.

if(htim->Instance==TIM1)
{
  /* USER CODE BEGIN TIM1_MspPostInit 0 */
  #undef __HAL_AFIO_REMAP_TIM1_ENABLE
  #define __HAL_AFIO_REMAP_TIM1_ENABLE()  (0)
  /* USER CODE END TIM1_MspPostInit 0 */

    /**TIM1 GPIO Configuration    
    PE11     ------> TIM1_CH2 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_TIM1_ENABLE();

  /* USER CODE BEGIN TIM1_MspPostInit 1 */
  /* Make a copy of AFIO register */
  volatile uint32_t afioRegisterCopy = AFIO->MAPR;

  /* Clear Timer1 remap bits and + JTAG/SWD bits */
  afioRegisterCopy &= ~((7 << 24) + (3 << 6));

  /* To perform a full remap Timer1, bit 6-7 of 
     AFIO->MAPR must be set. Mask is 3 (11b)    */
  afioRegisterCopy |= (3 << 6);

  /* Apply the new register configuration*/
  AFIO->MAPR = afioRegisterCopy; 
  /* USER CODE END TIM1_MspPostInit 1 */
}

Ответы (2)

STM32F103 [...] STM32CubeMx [...] когда я запускаю сеанс отладки и когда MCU выполняет макрос "__HAL_AFIO_REMAP_TIM1_ENABLE()", происходит сбой сеанса отладки.

Я не использую STM32CubeMX HAL, но могу объяснить проблему и обходной путь.

Проблема в том, что серия STM32F1 имеет один регистр AFIO_MAPR, который содержит настройки для переназначения различных периферийных устройств и для включения/отключения соединения JTAG/SWD с вашим отладчиком. И чтобы сделать это еще более сложным, биты в этом регистре, которые включают/отключают настройки JTAG/SWD ( bits 24-26), доступны только для записи, поэтому их текущее состояние не может быть прочитано .

См. этот отрывок из справочного руководства STM32F1 :


Выдержка из справочного руководства STM32F1


Это означает, что любая попытка изменить настройки различных битов «переназначения периферийных устройств» путем выполнения последовательности «чтение-изменение-запись» в этом регистре может привести к считыванию других значений вместо реальных текущих значений в битах JTAG/SWD. Затем, когда запись в регистр завершена, ваш доступ к отладчику прекращается, потому что все, что было прочитано из этих битов JTAG/SWD, записывается обратно в них. (Сообщалось и о других эффектах, но я не буду сейчас вдаваться в подробности).

Из того, что я смог найти без установки HAL, используются следующие макросы:

#define __HAL_AFIO_REMAP_TIM1_ENABLE() MODIFY_REG(AFIO->MAPR, AFIO_MAPR_TIM1_REMAP, AFIO_MAPR_TIM1_REMAP_FULLREMAP)

и MODIFY_REGэто:

#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

Итак, как вы видите, MODIFY_REGвыполняется чтение-изменение-запись, и вы не знаете, какие значения он будет считывать из JTAG/SWD bits 24-26и, следовательно, какие значения он будет записывать туда! Значения, считанные из этих битов, являются «неопределенными» (цитируя ST), и я знаю, что читал разные значения с одного и того же STM32F1 в разное время.

«Исправление», которое я использовал с SPL, состоит в том, чтобы изменить любой код переназначения, чтобы специально установить биты JTAG/SWD, которые вы хотите, всякий раз, когда вы записываете в регистр AFIO_MAPR. Вам нужно будет выяснить, как вы хотите сделать то же самое с кодом HAL. Один из способов — использовать временную переменную, чтобы из памяти последовательность выглядела так:

  • Считать регистр AFIO_MAPR во временную переменную
  • Измените нужные биты переназначения периферийных устройств в переменной temp.
  • Маскируйте биты 24-26 в переменной temp
  • Установите биты 24-26 в переменной temp на все, что я хотел (поэтому игнорируйте их, вероятно, неправильное значение «чтения»)
  • Записать временную переменную в AFIO_MAPR

К счастью, ST изменился на лучшее расположение регистров в более поздних моделях STM32 (например, STM32F4).

Спасибо за ваш ответ. Отличное объяснение! К сожалению, мои работы изменены в сторону проекта с высоким приоритетом. Когда я решил проблему, я возвращаюсь к проблеме Timer1. Еще раз спасибо

Вот рабочий фрагмент кода, иллюстрирующий шаги, предложенные @SamGibson. Это работает для меня как шарм. Первое, что нужно сделать, это закомментировать файл __HAL_AFIO_REMAP_TIM1_ENABLE();stm32f1xx_hal_msp.c и заполнить его кодом переназначения следующим образом:

//__HAL_AFIO_REMAP_TIM1_ENABLE();

/* USER CODE BEGIN TIM1_MspPostInit 1 */

volatile uint32_t map_copy = AFIO->MAPR;

map_copy &= ~((7 << 24) + (3 << 6)); // Clear desired bitfields + debug bits


// 5(101b) shifted left 24 for CoreSight SW-DP (What Keil Ulink2 and St-LinkV2
//use for debugging in either Keil IDE or SW4STM32 IDE)

// The (3 << 6) is me wanting to fully remap the TIM1 AF pins for 
//Complementary PWM Generation

map_copy |= (5 << 24) + (3 << 6);

AFIO->MAPR = map_copy;

/* USER CODE END TIM1_MspPostInit 1 */

Просто следите за другими вызовами MspPostInit...

Ваше здоровье.