Search code examples
cgccarmstm32f7

Using structs to centralize the hardware abstraction layers make the code execution slow


I'm trying to use the structure for centralizing my hardware configuration. However, this makes my codes slow later while the struct has been defined as a global variable in the RAM.

For example, I have defined.

typedef struct
{
    PeriphBus       TIM_Bus;
    uint32_t        TIM_Clk;
    uint16_t        TIM_Prescaler;
    uint32_t        TIM_CounterMode;
    uint32_t        TIM_Autoreload;
    uint32_t        TIM_ClockDivision;
    uint32_t        TIM_RepetitionCounter;
    TIM_TypeDef     *TIM_Peripheral;
    IRQn_Type       TIM_Interrupt;
    uint32_t        TIM_IPeriority;
} TIMHandler;

TIMHandler  TIMCCS = {
    .TIM_Bus                        = APB1,
    .TIM_Clk                        = LL_APB1_GRP1_PERIPH_TIM2,
    .TIM_Prescaler                  = (10000 - 1),
    .TIM_CounterMode                = LL_TIM_COUNTERMODE_UP,
    .TIM_Autoreload                 = (1000 - 1),
    .TIM_ClockDivision              = LL_TIM_CLOCKDIVISION_DIV1,
    .TIM_RepetitionCounter          = 0,
    .TIM_Peripheral                 = TIM2,
    .TIM_Interrupt                  = TIM2_IRQn,
    .TIM_IPeriority                 = 2,
};

And later in the code, I'm trying to reset the interrupt flag with this code.

void TIMCCS_IRQHandler (void)
{
    ... // some codes here are deleted to keep it simpler.
    LL_TIM_ClearFlag_UPDATE (TIMCCS->TIM_Peripheral);
}

Unfortunately, this last function to reset the interrupt flag is prolonged, while if I replace it with

LL_TIM_ClearFlag_UPDATE (TIM2);

It gets back to normal.

I'm wondering where I'm making a mistake. I'm using ARM GCC as the compiler for STM32F7 microcontrollers.


Solution

  • My first bit of advice is to review the assembly code produced between the two versions of code. Is it doing what you think it is?

    Next question, do you have the optimizer turned on?

    To me, at first glance it makes sense that one runs slower than the other. If you look at your first version, the ISR needs to load the address of the global struct. Then it needs to dereference that address to get the value stored in the TIM_Peripheral variable. Then it passes that value to the ClearFlag function. Whereas the second version just directly passes that value in, skipping all the memory accesses. But again, the assembly code is your friend.