sys/xtimer: allow frequencies multiple of 921600Hz#6507
sys/xtimer: allow frequencies multiple of 921600Hz#6507kYc0o wants to merge 4 commits intoRIOT-OS:masterfrom
Conversation
sys/include/div.h
Outdated
| /** | ||
| * @brief Operand for 576/625 | ||
| */ | ||
| #define MUL_576 576ul |
There was a problem hiding this comment.
pls drop these defines, they don't make sense.
sys/include/div.h
Outdated
| /** | ||
| * @brief Operand for 625/576 | ||
| */ | ||
| #define MUL_625 625ul |
There was a problem hiding this comment.
It was to avoid the "ul" everywhere (8 and 16 bit requirement), but I can remove it.
There was a problem hiding this comment.
for 625 you don't need UL. That only matters on the left-hand side of an expression (left-hand side defines type being used for calculation), or if the value is >16bit.
There was a problem hiding this comment.
Addressed. Thanks for the explanation.
| */ | ||
| static inline uint64_t div_u64_by_625div576(uint64_t val) | ||
| { | ||
| /* |
There was a problem hiding this comment.
did you measure this? or C&P?
There was a problem hiding this comment.
Oops, copy-paste, I'll check if it does but I think it makes exactly the same as before. Moreover, it makes sense to take care of the overflow, I can just remove the comment but the code seems ok for me.
| */ | ||
| static inline uint32_t div_u64_by_576div625(uint64_t val) | ||
| { | ||
| /* |
|
Ready? |
lebrush
left a comment
There was a problem hiding this comment.
I think the #ifs and #else are not matching and there is some dead code. Besides it would be great if you add some empty lines to improve readability.
sys/include/xtimer/tick_conversion.h
Outdated
| */ | ||
| #if (XTIMER_HZ % 576 == 0) | ||
| #if (XTIMER_SHIFT != 0) | ||
| #if (XTIMER_HZ % 576 != 0) |
There was a problem hiding this comment.
You will never run into this, since you first checked for the opposite, right?
#if (XTIMER_HZ % 576 == 0)
#if (XTIMER_HZ % 576 != 0)There was a problem hiding this comment.
Yes, I can remove it but I need a way to throw the error if shifting is enabled.
sys/include/xtimer/tick_conversion.h
Outdated
| inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) { | ||
| return div_u64_by_576div625(ticks) >> XTIMER_SHIFT; | ||
| } | ||
| #else /* (XTIMER_HZ < 921600ul) */ |
sys/include/xtimer/tick_conversion.h
Outdated
| inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) { | ||
| return div_u64_by_576div625(ticks) << XTIMER_SHIFT; | ||
| } | ||
| #endif /* defined(XTIMER_SHIFT) && (XTIMER_SHIFT != 0) */ |
There was a problem hiding this comment.
This is actually /* (XTIMER_HZ > 921600ul) */ or /* (XTIMER_HZ <= 921600ul) */ (depends on the notation you are using)
There was a problem hiding this comment.
Rather the first, and also XTIMER_SHIFT. Will fix.
sys/include/xtimer/tick_conversion.h
Outdated
| return div_u64_by_576div625(ticks) << XTIMER_SHIFT; | ||
| } | ||
| #endif /* defined(XTIMER_SHIFT) && (XTIMER_SHIFT != 0) */ | ||
| #elif (XTIMER_HZ == 921600ul) |
There was a problem hiding this comment.
Is here expected to be: (XTIMER_SHIFT == 0) && (XTIMER_HZ == 921600ul)? If that's the case then is correct
There was a problem hiding this comment.
Yes, that's what is expected. I tried to reproduce a similar behaviour than for the 1MHz case.
sys/include/xtimer/tick_conversion.h
Outdated
| return div_u64_by_576div625(ticks); | ||
| } | ||
| #endif /* (XTIMER_HZ == 921600ul) */ | ||
| #elif (XTIMER_SHIFT != 0) /* (XTIMER_HZ % 576 == 0) */ |
There was a problem hiding this comment.
I think this branch belongs to the #if (XTIMER_HZ % 576 == 0)... then the code will enter the first time you test for #if (XTIMER_SHIFT != 0) and not here.
There was a problem hiding this comment.
Yes I was trying to solve the issue. Actually I need a way on which we can detect, first, if we're using either 1MHz or 921600Hz clock based timer, then we need to know if the shifting is used, to finally choose the right functions.
The current code will check first if there's shifting activated, then if it's a 1MHz or 921600Hz based clock. The process is repeated to ensure that we can choose 1MHz clocks.
There was a problem hiding this comment.
The code will enter here if the clock is not a multiple of 576, for which I need to check again if shifting is used.
|
@lebrush I added more comments to clarify all those definitions. I still have no idea on how I can simplify them, so if you have suggestions they're welcomed (maybe I'm doing redundant things and I cannot see them by myself). |
|
Some thoughts @kaspar030 ? |
|
ping @kaspar030 ! |
sys/include/xtimer/tick_conversion.h
Outdated
| * If it uses shifting, just check if it's not multiple of 576, if so, | ||
| * throw an error | ||
| */ | ||
| #if (XTIMER_HZ % 576 != 0) |
There was a problem hiding this comment.
This will never be true, as you check above the opposite, or do I miss something?
There was a problem hiding this comment.
Yes I know, but then how to check this? I need to know if XTIMER_HZ is valid when using shifting, but I'll just remove this line...
55827a7 to
2e87e54
Compare
|
@lebrush comments addressed. |
lebrush
left a comment
There was a problem hiding this comment.
@kYc0o thanks for the heads up! I have some quick comments regarding the comments :-)
I've thought how to factorize the code and it's hard if we want to keep it readable. One possibility is to use some macro magic, despite of readability:
Example:
...
#define PASTER(len,low,high) div_u ## len ## _by ## low ## div ## high
#define EVALUATOR(len,low,high) PASTER(len,low,high)
...
#if (XTIMER_HZ % 576 == 0)
#if (XTIMER_SHIFT != 0)
#define LOW 625
#define HIGH 576
#if (XTIMER_HZ > 921600ul)
#if (XTIMER_HZ != (921600ul << XTIMER_SHIFT))
#error XTIMER_HZ != (921600ul << XTIMER_SHIFT)
#endif
#define USEC_SHIFT(len) DIVIDER(len) << XTIMER_SHIFT
#define TICKS_SHIFT(len) DIVIDER(len) >> XTIMER_SHIFT
#else
#if ((XTIMER_HZ << XTIMER_SHIFT) != 921600ul)
#error (XTIMER_HZ << XTIMER_SHIFT) != 921600ul
#endif
#define USEC_SHIFT(len) DIVIDER(len) >> XTIMER_SHIFT
#define TICKS_SHIFT(len) DIVIDER(len) << XTIMER_SHIFT
#endif
...
#define DIVIDER(len) EVALUATOR(len, LOW, HIGH)
...
inline static uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
return USEC_SHIFT(32); /* i.e. div_u32_by_625div576(usec) << XTIMER_SHIFT; */
}
inline static uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
return USEC_SHIFT(64);
}
inline static uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
return TICKS_SHIFT(32);
}
inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
return TICKS_SHIFT(64);
}| /* | ||
| * If it's not greater, check if it's lower (XTIMER_HZ < 921600ul). | ||
| */ | ||
| #else |
There was a problem hiding this comment.
I guess here /* (XTIMER_HZ <= 921600ul) */ should be enough. Mind the equality.
| * No more shifted multiple of 921600Hz frequencies to check | ||
| * (XTIMER_SHIFT != 0) | ||
| */ | ||
| #endif |
There was a problem hiding this comment.
Nitpick: /* (XTIMER_SHIFT != 0) */. I like documentation but I think it's clear enough with a one-liner. In my previous review I didn't mean that you include more comments regarding the code flow, simply that sometimes the one-liner where in the wrong place... :-)
There was a problem hiding this comment.
Ok no problem, I just wanted to be as clear as possible, even for me. I find this code a bit complicated to understand in itself, so a bit more of documentation won't hurt IMHO.
sys/include/xtimer/tick_conversion.h
Outdated
| * Check for the actual frequency without any shifting (921600Hz) | ||
| * (XTIMER_SHIFT == 0) | ||
| */ | ||
| #elif (XTIMER_HZ == 921600ul) |
There was a problem hiding this comment.
I don't think you need a special case for that, shifting to any side by 0 (XTIMER_SHIFT should be 0 here). Would give the same result.
There was a problem hiding this comment.
Yes you're right, I think I can do the same for the 1MHz frequency.
|
I somehow like your suggestion with the macros magic. However, we have an "unofficial" preference to keep macro usage as low as possible, thus very often we use static inline functions instead of macros. I can try to adapt your proposition with static inline functions to make it "standard", but I'd like to have @gebart opinion on this, since he was the contributor of this code. |
I'd strongly oppose this. Please rather try to find a solution without any macros. Most of the checks could be done in C-Code, being syntax checked, and optimized out by the compiler. |
That's what I meant when I said I could try to adapt those macros to static in line functions. |
|
@kYc0o feel free to go ahead with the macro magic -> static inline conversion. |
|
I agree that macro magic makes sometimes code difficult to follow :-) |
|
I was trying to convert the ifdefs to inline functions but at the end I was adding more complexity, when why that code is there is to optimise the conversions. I removed some unnecessary checks, I find now it's a bit more readable and works correctly. I tested with samr21-xpro and arduino-mega2560 with success. What is missing is a test for cc2538 but xtimer is broken for that platform due to different reasons. |
|
For the separate file, IMHO, maybe it would be required if the cases of different frequencies increase. For now I think it's manageable, even if it was hard to get it in a less confusing way. |
|
Ping! Can we maybe get this in for the Hack'n'ACK? |
|
Can I squash to get the CI working? |
|
ping @lebrush @kaspar030 |
|
Well, everything seems good here, just a review from @kaspar030 is missing... |
|
ping @kaspar030 |
|
re-ping @kaspar030 |
|
@kaspar030 any objections to get this into the release? I have 2 more PRs which are based on this one, so I think they won't make it for the release if we don't merge this first soon. |
|
@kaspar030 could you please spare some time to ACK (or/and comment on) this and approve changes done?! I'd rather not dismiss your review, but have your trusted ACK here 😉 |
|
@kaspar030 will you leave this PR open until the xtimer rework is done? in such case we can close it since it won't certainly be compatible with the new xtimer code. |
Hm, good question. ;) By using a 32khz as backend for xtimer (not new in this PR), all code throughout the codebase would need to be checked if it's still working. E.g., are usec values We need multiple timers edit in the API edit... |
Well, it will depend how much usec you need, since here we're certainly losing accuracy by shifting. |
|
What do we do with this one? It's needed to support xtimer on waspmote-pro... |
jnohlgard
left a comment
There was a problem hiding this comment.
I don't mind adding more specializations for the xtimer frequencies, but some changes are necessary:
- Needs rebase
- Minor comments above
- Add test cases to unittests/tests-div for the new div.h functions, along with smart choices for the test vector (try to catch rounding errors, errors with large numbers close to the overflow limit, test for numbers near the magic number 10485759996).
- It may be possible to reduce the very long preprocessor if block in xtimer.h for all different kinds of XTIMER_SHIFT. The special case of XTIMER_SHIFT == 0 is not necessary, a shift of constant literal 0 will be optimized away by the compiler, and worst case it would be a no-op machine instruction by shifting with 0.
| * @brief Approximation of (2**l)/d for d=15625, l=12, 32 bits | ||
| */ | ||
| #define DIV_H_INV_15625_32 0x431bde83ul | ||
| #define DIV_H_INV_15625_32 0x431bde83ul |
There was a problem hiding this comment.
It doesn't matter if you have parentheses or not here, these are just magic numbers and never any complex expressions. As for the letter case, I don't care either way, I tend to prefer lowercase for the suffixes, but I don't see any point in forcing it.
sys/include/xtimer/tick_conversion.h
Outdated
| */ | ||
| #endif | ||
| /* | ||
| * Now, check if XTIMER_HZ is a frequency multiple of 1MHz (or 15675, which is |
sys/include/xtimer/tick_conversion.h
Outdated
| #error Unknown hardware timer frequency (XTIMER_HZ), check board.h and/or add an implementation in sys/include/xtimer/tick_conversion.h | ||
| #endif | ||
| /* | ||
| * End of optimisations |
There was a problem hiding this comment.
I would prefer to have this comment on the line with the #endif on L275, and related to the if condition. Suggestion:
#endif /* XTIMER_HZ == xxx */|
Sorry for forgetting this PR since looong time, I was kind of waiting for big changes on xtimer but apparently that won't come soon. I want to update and if possible merge this PR to support another frequency for the mega-xplained board. |
|
Yes! I think that will be the way to go for supporting other clock sources in xtimer. |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
This PR will add xtimer compatibility for boards running at frequencies multiple of 576 (e.g. waspmote-pro running at 14.7456 MHz with timers prescaled to this frequency).
Partially (re) fixes #5597. An upcoming PR will fix the xtimer configuration on the waspmote.