2009-06-16 08:00 PM
Wrong regs reading sequence from Cosmic
2011-05-17 06:03 AM
It seems to me that Cosmic compiler makes a wrong assembly sequence in compiling this:
return (u16)(((u16)TIM1->CNTRH << 8) | (u16)(TIM1->CNTRL)); In fact it should read CNTRH first, and then CNTRL (that has an offset greater than CNTRH). This cause a wrong reading sequence from the timer regs, as mentioned in the technical reference manual... 0ee7 c6525f ld a,21087 0eea 5f clrw x 0eeb 97 ld xl,a 0eec 1f01 ldw (OFST-1,sp),x 0eee c6525e ld a,21086 ---------------------------------- COSMIC STM8 C Compiler 16K Version Version: 4.2.8 Date: 03 Dec 2008 ----------------------------------2011-05-17 06:03 AM
the instruction (u16)(((u16)TIM1->CNTRH << 8) | (u16)(TIM1->CNTRL))
In my opinion has Two side the left side and Right side and the compiler according to its rules of converting to assembly will begin from the right or from the left, in or case here it begin from the right. So I think it's better to seperate this instruction in two instructions : u16 uiTemp; uiTemp = (u16)TIM1->CNTRH << 8); uiTemp |= (u16)(TIM1->CNTRL); return uiTemp; it's a little bit long but it don't cause a wrong reading sequence ciao2011-05-17 06:03 AM
I cut and paste below the answer from our C language expert.
Regards, Luca (Cosmic) ******* The priority grouping and the evaluation order are two different things. The C language clearly defines a left to right priority grouping for the OR operator (|) which simply implies that in an expression using several identical operators without any parenthese, the compiler adds internal grouping parentheses from the leftmost operator. So the expression e1 | e2 | e3 will be considered as (e1 | e2) | e3. The evaluation order defines which operand of an operator is evaluated first, and there is no such requirement in the C language for the OR operator (there are only a few operators with such a constraint in C, such as the comma, question mark, logical AND (&&) and OR (||), and function call), so when writing e1 | e2, there is no obligation to evaluate e1 first or e2 first. The compiler will behave depending on the operand types to produce the smallest code as possible. So in that example, the assembly sequence is absolutely correct regarding the standard behaviour, while it is not according to the special behaviour attached to the object accessed, but such a special behaviour is not matching any standard C feature. There is anyhow a simple way to get the expected behaviour by removing the (u16) cast on the right operand (CNTRL), because with that cast, the compiler is forced to implement a 16 bit operation between two 16 bit integers. Without that cast, the compiler will behave the same as there is an implicit char to int cast which must be operated, but then the construct can be implemented differently as the compiler can combine internally the OR operation and the implicit cast. You will get the expected result, but only because the way the compiler implements such a construct matches the special requirement, and not because of any strandard behaviour. Note that it would be nicer to declare an equivalent int object for the catenation of CNTRH:CNTRL in the structure (with an embedded union) to allow either an individual byte access or a global word access (a single LDW instruction in such a case) whose access order is garanteed by the processor hardware.2011-05-17 06:03 AM
Many thanks to COSMIC.
In fact the particular construct line was taken from the ST library stm8s_tim1.c, that I expected to be written in accordance with a standard C behaviour. I also think that the embedded union is the better way. ST should be informed about, and the libriries reissued. Many thanks again with regards Francesco