Maple ported to STM32

I am testing a code captured by pwm. The original code belongs to the core of Maple.
Because I only have a Nucleo F446RE board and my network cannot update the Maple core, I tried to port the code to the STM32 core.

This is original code for Malpe core

            #include <Arduino.h>
            int32_t channel_1_start, channel_1_stop, channel_1;
            void setup() {
            Serial.begin(57600);
            pinMode(PA0, INPUT);
            delay(250);

            Timer2.attachCompare1Interrupt(handler_channel_1);
            TIMER2_BASE->CR1 = TIMER_CR1_CEN;
            TIMER2_BASE->CR2 = 0;
            TIMER2_BASE->SMCR = 0;
            TIMER2_BASE->DIER = TIMER_DIER_CC1IE;
            TIMER2_BASE->EGR = 0;
            TIMER2_BASE->CCMR1 = TIMER_CCMR1_CC1S_INPUT_TI1;
            TIMER2_BASE->CCMR2 = 0;
            TIMER2_BASE->CCER = TIMER_CCER_CC1E;
            TIMER2_BASE->PSC = 71;
            TIMER2_BASE->ARR = 0xFFFF;
            TIMER2_BASE->DCR = 0;
            }

            void loop() {
            delay(1000);
            Serial.println(channel_1);
            }

            void handler_channel_1(void) {
            if (0b1 & GPIOA_BASE->IDR) {
                channel_1_start = TIMER2_BASE->CCR1;
                TIMER2_BASE->CCER |= TIMER_CCER_CC1P;
            }
            else {
                channel_1 = TIMER2_BASE->CCR1 - channel_1_start;
                if (channel_1 < 0)channel_1 += 0xFFFF;
                TIMER2_BASE->CCER &= ~TIMER_CCER_CC1P;
            }
            }

This is the code I modified for the stm32 core

#include <Arduino.h>
int32_t channel_1_start, channel_1_stop, channel_1;

void handler_channel_1(void) {
if (0b1 & GPIOA->IDR) {
    channel_1_start = TIM2->CCR1;
    TIM2->CCER |= TIM_CCER_CC1P;
}
else {
    channel_1 = TIM2->CCR1 - channel_1_start;
    if (channel_1 < 0)channel_1 += 0xFFFF;
    TIM2->CCER &= ~TIM_CCER_CC1P;
}
}

void setup() {
Serial.begin(57600);
pinMode(PA0, INPUT);
delay(250);

Timer2.attachCompare1Interrupt(handler_channel_1);
TIM2->CR1 = TIM_CR1_CEN;
TIM2->CR2 = 0;
TIM2->SMCR = 0;
TIM2->DIER = TIM_DIER_CC1IE;
TIM2->EGR = 0;
TIM2->CCMR1 = TIM_CCMR1_IC1PSC;
TIM2->CCMR2 = 0;
TIM2->CCER = TIM_CCER_CC1E;
TIM2->PSC = 71;
TIM2->ARR = 0xFFFF;
TIM2->DCR = 0;
}

void loop() {
delay(1000);
Serial.println(channel_1);
}

I’m not sure if my modification like this is feasible, because there was a compilation warning, I have never been able to compile successfully.

        Processing nucleo_f446re (platform: ststm32; board: nucleo_f446re; framework: arduino)
    ------------------------------------------------------------------------------------------------------------------------------------------------------
    Verbose mode can be enabled via `-v, --verbose` option
    CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/nucleo_f446re.html
    PLATFORM: ST STM32 (12.0.0) > ST Nucleo F446RE
    HARDWARE: STM32F446RET6 180MHz, 128KB RAM, 512KB Flash
    DEBUG: Current (stlink) On-board (stlink) External (blackmagic, cmsis-dap, jlink)
    PACKAGES: 
    - framework-arduinoststm32 4.10900.200819 (1.9.0) 
    - framework-cmsis 2.50501.200527 (5.5.1) 
    - toolchain-gccarmnoneeabi 1.90201.191206 (9.2.1)
    LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
    LDF Modes: Finder ~ chain, Compatibility ~ soft
    Found 18 compatible libraries
    Scanning dependencies...
    No dependencies
    Building in release mode
    Compiling .pio/build/nucleo_f446re/src/main.cpp.o
    src/main.cpp: In function 'void setup()':
    src/main.cpp:21:3: error: 'Timer2' was not declared in this scope
      21 |   Timer2.attachCompare1Interrupt(handler_channel_1);
          |   ^~~~~~
    *** [.pio/build/nucleo_f446re/src/main.cpp.o] Error 1

Timer 2 is not a global object that is available in the STM32 core. But there is the HardwareTimer class and APIs, that are documented at HardwareTimer library · stm32duino/wiki Wiki · GitHub.

You can try this code.

#include <Arduino.h>

volatile int32_t channel_1_start, channel_1_stop, channel_1;

HardwareTimer Timer2(TIM2);

void handler_channel_1(void)
{
  if (0b1 & GPIOA->IDR)
  {
    channel_1_start = TIM2->CCR1;
    TIM2->CCER |= TIM_CCER_CC1P;
  }
  else
  {
    channel_1 = TIM2->CCR1 - channel_1_start;
    if (channel_1 < 0)
      channel_1 += 0xFFFF;
    TIM2->CCER &= ~TIM_CCER_CC1P;
  }
}

void setup()
{
  Serial.begin(57600);
  pinMode(PA0, INPUT);
  delay(250);

  /* install Capture compare 1 event callback */
  Timer2.attachInterrupt(1, handler_channel_1);
  TIM2->CR1 = TIM_CR1_CEN;
  TIM2->CR2 = 0;
  TIM2->SMCR = 0;
  TIM2->DIER = TIM_DIER_CC1IE;
  TIM2->EGR = 0;
  TIM2->CCMR1 = TIM_CCMR1_IC1PSC;
  TIM2->CCMR2 = 0;
  TIM2->CCER = TIM_CCER_CC1E;
  TIM2->PSC = 71;
  TIM2->ARR = 0xFFFF;
  TIM2->DCR = 0;
}

void loop()
{
  delay(1000);
  Serial.println(channel_1);
}

You can also check out the “Examples” that are listed at the bottom of the page that I’ve linked to, they seem to be similiar to what you’re trying to do.

Thanks for your answer, I have tried the code you provided, but “channel_1” prints 0.

And the pointer is used, but the printing result is still incorrect

HardwareTimer *pTimer2 = new HardwareTimer(TIM2);

Timer2->attachInterrupt(1, handler_channel_1);

Is my prescaler misconfigured?