La reasignación de Timer1 causa un bloqueo de depuración en STM32F103

Construí un proyecto Keil para mi MCU STM32F103 con STM32CubeMx.

Mi objetivo es usar el canal 2 de TIM1 para controlar un zumbador. Quiero generar un PWM a 4KHz a través del canal 2 del TIM1. Configuré, con STM32CubeMx, el TIM1_Channel2 como "PWM Generator CH2".

El problema se refiere a la sesión de depuración. En particular, cuando inicio la sesión de depuración y cuando la MCU ejecuta la macro "__HAL_AFIO_REMAP_TIM1_ENABLE()", la sesión de depuración falla.

Este es el código de inicialización del temporizador generado por 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 */
  }

}

Este problema está relacionado con la reasignación completa del pin Timer1.

¿Alguien tiene el mismo problema?

¡Gracias!

=== ACTUALIZAR ===

¡Finalmente encontré algo de tiempo para probar la solución propuesta por @SamGibson y funciona! ¡Y gracias a @Rafiq Rahman por su código!

¡Gracias chicos por su tiempo!

Este es el código que usé para reasignar el TIM1 y mantener la capacidad de generar el código con el 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 */
}

Respuestas (2)

STM32F103 [...] STM32CubeMx [...] cuando inicio la sesión de depuración y cuando la MCU ejecuta la macro "__HAL_AFIO_REMAP_TIM1_ENABLE()", la sesión de depuración falla.

No uso el STM32CubeMX HAL, pero puedo explicar el problema y la solución.

El problema es que la serie STM32F1 tiene un registro AFIO_MAPRque contiene la configuración para reasignar varios periféricos y para habilitar/deshabilitar la conexión JTAG/SWD a su depurador. Y para hacer esto más complicado, los bits en ese registro que habilitan/deshabilitan la configuración JTAG/SWD ( bits 24-26) son de solo escritura , por lo que su estado existente no se puede leer .

Consulte este extracto del Manual de referencia de STM32F1 :


Extracto del Manual de referencia de STM32F1


Esto significa que cualquier intento de cambiar la configuración de los diversos bits de "reasignación periférica", al hacer una secuencia de lectura, modificación y escritura en este registro, podría leer valores diferentes en lugar de los valores actuales reales en los bits JTAG/SWD. Luego, cuando finaliza la escritura en el registro, el acceso del depurador se detiene porque todo lo que se leyó de esos bits JTAG/SWD se vuelve a escribir en ellos. (También se han informado otros efectos, pero no entraré en eso ahora).

Por lo que pude encontrar sin instalar HAL, las macros utilizadas son:

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

y MODIFY_REGes:

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

Entonces, como puede ver, MODIFY_REGestá haciendo una lectura-modificación-escritura y no sabe qué valores leerá de JTAG/SWD bits 24-26y, por lo tanto, qué valores volverá a escribir allí. Los valores leídos de esos bits son "indefinidos" (para citar ST) y sé que he leído diferentes valores del mismo STM32F1 en diferentes momentos.

La "solución" que he usado con el SPL es cambiar cualquier código de reasignación para establecer específicamente los bits JTAG/SWD que desea, cada vez que escribe en el AFIO_MAPRregistro. Deberá averiguar cómo desea hacer lo mismo con el código HAL. Una forma es usar una variable temporal para que, de memoria, la secuencia se convierta en:

  • Lea el registro AFIO_MAPR en la variable temporal
  • Cambie los bits de reasignación de periféricos deseados en la variable temporal
  • Enmascare los bits 24-26 en la variable temporal
  • Establezca los bits 24-26 en la variable temporal a lo que yo quisiera (por lo tanto, ignorando cualquiera que sea su valor de "lectura", probablemente incorrecto)
  • Escribir variable temporal en AFIO_MAPR

Afortunadamente, ST cambió a una mejor disposición de registro en los modelos STM32 posteriores (por ejemplo, STM32F4).

Gracias por su respuesta. ¡Gran explicación! Desafortunadamente, mis trabajos se cambian hacia un proyecto de alta prioridad. Cuando resolví el problema, vuelvo al Problema del temporizador 1. Gracias de nuevo

Aquí hay una pieza de código funcional para ilustrar los pasos propuestos por @SamGibson. Funciona para mí como un encanto. Lo primero que debe hacer es comentar __HAL_AFIO_REMAP_TIM1_ENABLE();en stm32f1xx_hal_msp.c y completar con el código de reasignación de la siguiente manera:

//__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 */

Esté atento a otras llamadas de MspPostInit...

Salud.