Die Neuzuordnung von Timer1 verursacht einen Debug-Absturz auf STM32F103

Ich baue ein Keil-Projekt für meine STM32F103-MCU mit STM32CubeMx.

Mein Ziel ist es, den TIM1-Kanal 2 zur Steuerung eines Summers zu verwenden. Ich möchte eine PWM mit 4 kHz über TIM1-Kanal 2 erzeugen. Ich habe mit STM32CubeMx den TIM1_Channel2 als "PWM-Generator CH2" konfiguriert.

Das Problem betrifft die Debug-Session. Insbesondere wenn ich die Debug-Sitzung starte und wenn die MCU das Makro "__HAL_AFIO_REMAP_TIM1_ENABLE()" ausführt, stürzt die Debug-Sitzung ab.

Dies ist der von STM32CubeMx generierte Timer-Initialisierungscode:

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

}

Dieses Problem hängt mit der vollständigen Neuzuordnung des Timer1-Pins zusammen.

Hat jemand das gleiche Problem?

Danke!

=== AKTUALISIEREN ===

Endlich habe ich Zeit gefunden, die von @SamGibson vorgeschlagene Lösung zu testen und sie funktioniert! Und danke an @Rafiq Rahman für seinen Code!

Danke Jungs für eure Zeit!

Dies ist der Code, den ich verwendet habe, um den TIM1 neu zuzuordnen und die Fähigkeit aufrechtzuerhalten, den Code mit dem Stm32CubeMX zu generieren.

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

Antworten (2)

STM32F103 [...] STM32CubeMx [...] wenn ich die Debug-Session starte und wenn die MCU das Makro "__HAL_AFIO_REMAP_TIM1_ENABLE()" ausführt, stürzt die Debug-Session ab.

Ich verwende die STM32CubeMX HAL nicht, aber ich kann das Problem und die Problemumgehung erklären.

Das Problem ist, dass die STM32F1-Serie ein Register hat AFIO_MAPR, das die Einstellungen zum Neuzuordnen verschiedener Peripheriegeräte und zum Aktivieren/Deaktivieren der JTAG/SWD-Verbindung zu Ihrem Debugger enthält. Um dies noch komplizierter zu machen, sind die Bits in diesem Register, die die JTAG/SWD-Einstellungen aktivieren/deaktivieren ( bits 24-26), schreibgeschützt, sodass ihr vorhandener Zustand nicht gelesen werden kann .

Siehe diesen Auszug aus dem STM32F1-Referenzhandbuch :


Auszug aus dem STM32F1-Referenzhandbuch


Dies bedeutet, dass jeder Versuch, die Einstellungen der verschiedenen "Peripherie-Neuzuordnungs"-Bits zu ändern, indem eine Lese-Modifizier-Schreib-Sequenz für dieses Register ausgeführt wird, andere Werte anstelle der tatsächlichen aktuellen Werte in den JTAG/SWD-Bits lesen könnte. Wenn das Schreiben in das Register abgeschlossen ist, stoppt Ihr Debugger-Zugriff, da alles, was aus diesen JTAG/SWD-Bits gelesen wurde, in sie zurückgeschrieben wird. (Andere Effekte wurden auch berichtet, aber ich werde jetzt nicht darauf eingehen).

Nach dem, was ich ohne Installation der HAL finden konnte, sind die verwendeten Makros:

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

und MODIFY_REGist:

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

Wie Sie sehen, MODIFY_REGwird also ein Lese-Änderungs-Schreibvorgang durchgeführt, und Sie wissen nicht, welche Werte von JTAG/SWD gelesen bits 24-26und daher auf welche Werte dort zurückgeschrieben wird! Die von diesen Bits gelesenen Werte sind "undefiniert" (um ST zu zitieren), und ich weiß, dass ich zu unterschiedlichen Zeiten unterschiedliche Werte aus demselben STM32F1 gelesen habe.

Der "Fix", den ich mit der SPL verwendet habe, besteht darin, jeden Neuzuordnungscode zu ändern, um die gewünschten JTAG / SWD-Bits speziell festzulegen, wenn Sie in das Register schreiben AFIO_MAPR. Sie müssen herausfinden, wie Sie dasselbe mit dem HAL-Code tun möchten. Eine Möglichkeit besteht darin, eine temporäre Variable zu verwenden, sodass die Sequenz aus dem Speicher zu Folgendem wird:

  • Lesen Sie das AFIO_MAPR-Register in die temporäre Variable
  • Ändern Sie die gewünschten Peripheral-Remap-Bits in der Temp-Variablen
  • Maskieren Sie die Bits 24-26 in der Temp-Variablen
  • Setzen Sie die Bits 24-26 in der temporären Variablen auf das, was ich wollte (daher ignorieren, was auch immer ihr wahrscheinlich falscher "gelesener" Wert war)
  • Schreiben Sie die temporäre Variable in AFIO_MAPR

Zum Glück hat ST in späteren STM32-Modellen (z. B. STM32F4) auf eine bessere Registeranordnung umgestellt.

Danke für deine Antwort. Tolle Erklärung! Leider ist meine Arbeit zu einem Projekt mit hoher Priorität geworden. Wenn ich das Problem gelöst habe, wechsle ich zurück zu Timer1 Problem. Danke noch einmal

Hier ist ein funktionierender Code, um die von @SamGibson vorgeschlagenen Schritte zu veranschaulichen. Es funktioniert für mich wie ein Zauber. Als erstes müssen Sie die in stm32f1xx_hal_msp.c auskommentieren __HAL_AFIO_REMAP_TIM1_ENABLE();und den Remap-Code wie folgt eingeben:

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

Halten Sie einfach Ausschau nach anderen MspPostInit-Aufrufen ...

Beifall.