General header file question (bit access)...
Hi all!
This is a general question regarding port access and the provided header file. I'm using the "stm32f10x.h" file that contains all the "defines" etc for the pins/ports etc for the STM32 chip.
I noticed that everything is defined as a "define" along with the "mask" value...This seems to me alittle "unfriendly"...let me explain.
If I want to set the "TIM1_CCMR1_OUTPUT_COMPARE_MODE_OC1M_BIT" bit to "1", I need to do the following...
TIM1_CCMR1_OUTPUT_COMPARE_MODE = (TIM1_CCMR1_OUTPUT_COMPARE_MODE & ~TIM1_CCMR1_OUTPUT_COMPARE_MODE_OC1M_MASK) |
(0 << TIM1_CCMR1_OUTPUT_COMPARE_MODE_OC1M_BIT);
This is AFTER I located the correct Defines needed. Simple enough...
Is there a reason why a structure could not have been provided for this? For example, you could use
<code>
typedef struct
{
union
{
uint16_t value;
struct
{
unsigned CC1S: 2;
unsigned OC1FE: 1;
unsigned OC1PE: 1;
unsigned OC1M: 3;
unsigned OC1CE: 1;
unsigned CC2S: 2;
unsigned OC2FE: 1;
unsigned OC2P: 1;
unsigned OC2M: 3;
unsigned OC2CE: 1;
} output;
struct
{
unsigned CC1S: 2;
unsigned IC1PSC: 2;
unsigned IC1F: 4;
unsigned CC2S: 2;
unsigned IC2PSC: 2;
unsigned IC2F: 4;
} input;
}data;
} TIM_CCMR1;
main()
.
.
TIM_CCMR1 *ccmr1=TIM1_CCMR1_OUTPUT_COMPARE_MODE; <--- This should be a generic "TIM1_CCMR" pointer
ccmr1->data.output.OC1M=1;
.
.
}
</code>
Now I have a struct that can be input, output etc...
Is it an issue with memory? I'm sure I'm missing the obvious!
Thanks all!
~Kam (^8*
-
Hi Kam,
The problem with Bit Fields is that they are not always portable between platforms/compilers
- integers may be signed or unsigned
- Many compilers limit the maximum number of bits in the bit field to the size of an integer which may be either 16-bit or 32-bit varieties.
- Some bit field members are stored left to right others are stored right to left in memory.
- If bit fields too large, next bit field may be stored consecutively in memory (overlapping the boundary between memory locations) or in the next word of memory.
For uP registers, the most important issue is clearly getting the left-to-right / right-to-left thing correct.
I agree some of the names in 'stm32f10x.h' get a bit long, but they at least match well and consistently to the STM32 User Manual, so if you program with that open (like I do) you can have a pretty good stab at guessing them.
We did make structures for the individual peripherals so we could write (for example):
TIM1->CCMR1 |= 1 << TIM1_CCMR1_OUTPUT_COMPARE_MODE_OC1M_BIT;
This is how ST's original STM32 Firmware Library did it too. And this will work nicely with code completion once Rowley get around to implementing it ;-)
Hope that helps.
Cheers,
Wolf
-
Hi Wolf,
Thanks for the reply.
I understand what you are saying; not sure I agree, but understand. The part that is REALLY frustrating is that the names of the "defines" somewhat match the reference manual, but not really. For example, there is a define called "SysTick_Reload_Value". I need to check the manual to get a better understanding of what are valid values etc., and I just cannot locate it! If in the defines you mentioned the REAL name of the field in a comment etc that would help.
~Kam (^8*
-
Hi Kam,
Of course if portability is not an issue for you, then by all means use bit-fields. We did use them in one instance in my last job. I'm just saying that's why a lot of people don't use them.
The 'SysTick_Reload_Value' register is a Cortex-M3 core register - not a ST peripheral one. Rowley appear to have followed the naming convention in the ARM Cortex-M3 Technical Reference Manual for ARM-core registers. You may need both that AND the STM32 User Manual open.
I agree it looks a bit ugly to have 2 different naming conventions in the one file (ARM's CamelCase style and ST's ALL_CAPS style), but at least they've tried to be somewhat consistent.
Cheers,
Wolf
-
I see your point. I too was a bit miffed at having to create my own headers after:
a) purchasing CrossWorks
b) downloading ST's firmware library (which I ended up just using as example code)
Try here for the ARM doc:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf
Google is your friend ;)
Cheers,
Wolf
-
I can assure you that we don't invent names for any of this stuff - we use the names provided in the documentation. The ARM CM3 documentation appears to have avoided naming registers - since this is the definitive document for the NVIC block we had to take a best guess. Hopefully the CMSIS work will mean that we don't have ship our own header files for CM devices however this stuff is changing from release to release and we have what we have.
Regarding bitfields we don't use these because GCC can (and does) do byte/short access to byte/short aligned,byte/short sized bitfields - which may or may not work depending on the device.
Regards
Michael
-
I agree there is no good, universal solution. And don't get me wrong, I'm more than happy with Rowley's approach. You chose a convention, and you stuck to it and applied it consistently. That's all we can ask for.
Our code actually uses 'stm32f10x.h' unmodified - straight from the CPU Support Package. That way we don't have to muck around with anything if it gets updated. We created our own version of the ST Firmware Library's 'stm32f10x_map.h' 'cos it suited our firmware implementation to do so. I.e. - not better, not worse, just right for our particular architecture and coding style.I fully understand why you didn't use bitfields. I think your approach is perfectly fine (and if I didn't we would still use your Memory Map xml's with some Python code and Cheetah templates to generate our own anyway).
Keep up the good work :)
Wolf
-
I'm just starting out with ARM & CrossWorks and I also find it surprising that there's no bitfield access to the peripherals since I've had this "luxury" on most other platforms in the past. Aside from portability it seems like the biggest hurdle is the fact that when using bitfields, gcc will do byte/short access on registers which can only be accessed as longs. I noticed that in June 2010 there was a new option added to gcc "-fstrict-volatile-bitfields" which supposedly changes this behavior. Is there any way to try this patch with CrossWorks?
Please sign in to leave a comment.
Comments
12 comments