I'm just beginning to understand the way the various STM headers files define the types and so on that are associated with the various memory mapped registers.
Something occurred to me as I was perusing this and that is that the entire set of memory mapped registers could be represented with one large, comprehensive typedef, with a pointer to that typedef initialized to the relevant base address. In fact we could define three "parent" typedefs one for AHB1, APB1 and APB2.
Each of these would themselves be decomposed into a hierarchy.
There's no runtime cost to this approach and the code we write might be more understandable, especially to a beginner or novice.
rather than simply:
GPIOA->MODER = 0x00000300;
we'd see
AHB1->GPIO[A].MODER[4] = ANALOG_MODE; // 'A' here being a constant, index into array of GPIO's
or
APB1->DAC |= 1;
we'd see
APB1->DAC[1].CONTROL.ENABLE = 1;
You get the idea, you can see that by making the structure more granular we eliminate the need for using OR ( | ) because the assignments are confined to the specific flags intended and do not touch flags either side of it.
None of the suggested code above carries any overhead in comparison to the conventional code.
Of course I guess that in some "real world" settings we may want to write a composite value to the entire DAC control register and that would still be possible but aside from that the code would be more readable, the structure of the peripheral would reflect its physical structure in memory.
The current stratgey defines APB1 as just a set of #defines:
completely masking the fact that the constant TIM2_BASE is in any way part of APB1.
The entire memory mapped IO looks like a tree and so representing it that way might lead to improved readability.
Thoughts? what do experienced STM32 developers think of this?
Something occurred to me as I was perusing this and that is that the entire set of memory mapped registers could be represented with one large, comprehensive typedef, with a pointer to that typedef initialized to the relevant base address. In fact we could define three "parent" typedefs one for AHB1, APB1 and APB2.
Each of these would themselves be decomposed into a hierarchy.
There's no runtime cost to this approach and the code we write might be more understandable, especially to a beginner or novice.
rather than simply:
GPIOA->MODER = 0x00000300;
we'd see
AHB1->GPIO[A].MODER[4] = ANALOG_MODE; // 'A' here being a constant, index into array of GPIO's
or
APB1->DAC |= 1;
we'd see
APB1->DAC[1].CONTROL.ENABLE = 1;
You get the idea, you can see that by making the structure more granular we eliminate the need for using OR ( | ) because the assignments are confined to the specific flags intended and do not touch flags either side of it.
None of the suggested code above carries any overhead in comparison to the conventional code.
Of course I guess that in some "real world" settings we may want to write a composite value to the entire DAC control register and that would still be possible but aside from that the code would be more readable, the structure of the peripheral would reflect its physical structure in memory.
The current stratgey defines APB1 as just a set of #defines:
completely masking the fact that the constant TIM2_BASE is in any way part of APB1.
The entire memory mapped IO looks like a tree and so representing it that way might lead to improved readability.
Thoughts? what do experienced STM32 developers think of this?
Last edited: