Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/efm32/timer: add support for LETIMER #13357

Merged
merged 3 commits into from Aug 7, 2020

Conversation

benemorius
Copy link
Member

Contribution description

This PR adds support for low energy timers to efm32. The implementation supports one LETIMER running at 32kHz which (IIRC) is a limitation imposed by the peripheral hardware.

Testing procedure

Compile with CFLAGS="-DEFM32_USE_LETIMER=1" and confirm that the letimer works as intended and with CFLAGS="-DEFM32_USE_LETIMER=0" and confirm that the regular timer still works as intended.

@chrysn
Copy link
Member

chrysn commented Feb 13, 2020

As @dylad so kindly pointed out, this is almost the same as my #13344.

On first glance, your approach looks superior to mine, so I'll try this out and review it.

@benemorius
Copy link
Member Author

Sorry I didn't notice the duplication. I did this some while back and I didn't check recently enough to make sure it was still undone. Two days. That's some coincidental timing.

Copy link
Member

@chrysn chrysn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in a first review run, with some comments.

I don't know the PM layer well enough to say much there.

Tested so far with the micropython example on an stk3700, will later run more (especially timer-related; which of tests/* are generally recommended here?) on this board and the sltb001a.

boards/ikea-tradfri/include/periph_conf.h Outdated Show resolved Hide resolved
cpu/efm32/include/periph_cpu.h Outdated Show resolved Hide resolved
cpu/efm32/include/periph_cpu.h Show resolved Hide resolved
cpu/efm32/periph/timer.c Outdated Show resolved Hide resolved
cpu/efm32/periph/timer.c Outdated Show resolved Hide resolved
LETIMER_IntEnable(tim, LETIMER_IEN_COMP0);
break;
case 1:
LETIMER_IntClear(tim, LETIMER_IFC_COMP1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks straightforward enough, so take this more as a question of curiosity rather than a reviewer comment: Is this covered anywhere in tests?

@chrysn
Copy link
Member

chrysn commented Feb 13, 2020

Concerning testing: I've run the periph_timer test as make -C tests/periph_timer BOARD=stk3700 all flash test, and that worked after adding my board to the BOARDS_TIMER_32kHz list in the test's Makefile -- kind of to be expected when the timers can only do that frequency. In practice, that list should be extended by whichever boards wind up having the LETIMER as a default, evaluating both channels.

With CFLAGS=-DEFM32_USE_LETIMER=0, three channels were tested for TIMER0, but did not succeed -- but then again, neither does it on master as far as I can see without getting my branches tangled, will investigate further to confirm.

@chrysn
Copy link
Member

chrysn commented Feb 13, 2020

Correction: make -C tests/periph_timer BOARD=stk3700 TIMER_SPEED=32768 all flash test does work on master (that particular speed was a leftover from other tests, 28000 works just as 2000 or 1000000 does), whereas the same prefixed with CFLAGS=-DEFM32_USE_LETIMER=0 doesn't on this branch -- unlike on master, it ends with

TIMER_0: set channel 2 to 15000
TIMER_0: starting
Timeout in expect script at "child.expect('TEST SUCCEEDED')" (tests/periph_timer/tests/01-run.py:21)

I've tried stepping through the individual variants, but failed to find a precise culprit that way. I had suspicions about the power manager briefly, but even without the top commit, the test fails when EFM32_USE_LETIMER=0.

@chrysn
Copy link
Member

chrysn commented Feb 13, 2020

In happier news, I've tested this with the sltb001a (programming which is a pain for different reasons: an openocd 0.11 would be direly due). With the default (EFM32_USE_LETIMER=1) setting, it passes tests/periph_timer, and builts micropython with time.sleep() just fine.

@benpicco benpicco added Area: cpu Area: CPU/MCU ports Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Feb 13, 2020
@benemorius
Copy link
Member Author

With CFLAGS=-DEFM32_USE_LETIMER=0, three channels were tested for TIMER0, but did not succeed

Whoops, very sorry for the trouble. I just pushed a fix for that. It helps a lot if you actually start the timer...

@chrysn
Copy link
Member

chrysn commented Feb 14, 2020

Yes, that makes both EFM32_USE_LETIMER=[01] pass tests/periph_timer on stk3700 and sltb001a, the letimer=0 version also with TIMER_SPEED 2000 or 1000000.

(One could argue about the necessity to keep the prescaler running, but when it runs I figure it contributes little to the total power consumption; that can still be tuned later.)

@benemorius
Copy link
Member Author

Sorry for the delay. I finally made the drive to Ikea for a Tradfri platform I can test on. I'll get back to this soon.

cpu/efm32/periph/timer.c Outdated Show resolved Hide resolved
cpu/efm32/periph/timer.c Show resolved Hide resolved
cpu/efm32/periph/timer.c Outdated Show resolved Hide resolved
cpu/efm32/periph/timer.c Outdated Show resolved Hide resolved
boards/ikea-tradfri/include/board.h Outdated Show resolved Hide resolved
@basilfx
Copy link
Member

basilfx commented Jun 16, 2020

I gave this PR a quick test on the STK3600, SLSTK3401a and SLSTK3402a and that seems to work. I tried the xtimer example and some xtimer tests.

I think, with Kconfig, we can make the whole LETIMER even optional (as an optimization), just like I did with the LEUART driver. But that is definitely for later.

@basilfx
Copy link
Member

basilfx commented Jun 16, 2020

@benemorius The requested changes are small. Feel free to rebase + squash.

@benemorius
Copy link
Member Author

I guess I didn't recall travis was that stringent on documentation. I'll get that fixed up soon.

@benemorius
Copy link
Member Author

Nevermind, I just botched the doxygen while adapting for #13900. It should be good now.

@basilfx basilfx added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 24, 2020
@basilfx
Copy link
Member

basilfx commented Jun 24, 2020

@benemorius I think that part of your last commit should be squashed with the first commit (that whole #ifndef EFM32_USE_LETIMER that was added in the first commit, but removed in the last commit).

@benemorius
Copy link
Member Author

Rebased to include the new CI checks.

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good and from what I gathered this works - I think this PR was simply forgotten.

@benpicco benpicco added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Aug 7, 2020
@benpicco benpicco merged commit cc1ffc8 into RIOT-OS:master Aug 7, 2020
@fjmolinas
Copy link
Contributor

fjmolinas commented Aug 11, 2020

This PR broke tests/periph_timer on slstk3402a EDIT: or there is a missing configuration change for this board

2020-08-11 17:04:42,923 # main(): This is RIOT! (Version: 2020.10-devel-689-g57946c-pr/periph/timer_max)
2020-08-11 17:04:42,923 #
2020-08-11 17:04:42,924 # Test for peripheral TIMERs
2020-08-11 17:04:42,924 #
2020-08-11 17:04:42,932 # Available timers: 1
2020-08-11 17:04:42,932 #
2020-08-11 17:04:42,933 # Testing TIMER_0:
2020-08-11 17:04:42,934 # TIMER_0: initialization successful
2020-08-11 17:04:42,934 # TIMER_0: stopped
2020-08-11 17:04:42,935 # TIMER_0: set channel 0 to 5000
2020-08-11 17:04:42,937 # TIMER_0: set channel 1 to 10000
2020-08-11 17:04:42,937 # TIMER_0: starting
2020-08-11 17:06:30,324 # TIMER_0: channel 0 fired at SW count 429468906 - init: 429468906
2020-08-11 17:06:30,327 # TIMER_0: channel 1 fired at SW count 429488896 - diff:    19990
2020-08-11 17:06:30,327 #
2020-08-11 17:06:30,328 # TEST SUCCEEDED
2020-08-11 17:15:51,885 # Help: Press s to start test, r to print it is ready

@benemorius
Copy link
Member Author

@fjmolinas I'm confused so far. Is this with EFM32_USE_LETIMER 1 or 0?

Could this have anything to do with LETIMER being countdown-only and therefore having the value inverted when read and written?

@fjmolinas
Copy link
Contributor

@fjmolinas I'm confused so far. Is this with EFM32_USE_LETIMER 1 or 0?

Could this have anything to do with LETIMER being countdown-only and therefore having the value inverted when read and written?

Its the default, I think that is EFM32_USE_LETIMER 0

* @{
*/
#ifdef EFM32_USE_LETIMER
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is strange, since it uses #Ifdef if 0 or 1 this statement will evaluate as true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be enough to fix the timer on slstk3402a?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm no, something else must be off..

* @{
*/
#if EFM32_USE_LETIMER
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO IS_ACTIVE should be used here.

if (!(tim->STATUS & TIMER_STATUS_RUNNING)) {
pm_block(EFM32_TIMER_PM_BLOCKER);
}
TIMER_Enable(timer_config[dev].timer.dev, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toggling the prescaler timer fixed the issue for the test.

@fjmolinas
Copy link
Contributor

@fjmolinas I'm confused so far. Is this with EFM32_USE_LETIMER 1 or 0?

Could this have anything to do with LETIMER being countdown-only and therefore having the value inverted when read and written

@benemorius can you take a look at 32e112d in #14780. That fixed the issue for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants