Skip to content

Conversation

vincent-d
Copy link
Member

@vincent-d vincent-d commented Jul 19, 2017

The goal of this PR was to fix stm32 pm_set implementation. The clock needs to be reinitialized after leaving stop mode.

I also added a simple test app for pm_layered, then I had to fix kinetis build issues. moved to #7666

@vincent-d vincent-d added Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation labels Jul 19, 2017
@vincent-d vincent-d added this to the Release 2017.10 milestone Jul 19, 2017
Copy link
Member

@jnohlgard jnohlgard left a comment

Choose a reason for hiding this comment

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

Please add a Readme for the new test application. The expected behavior of the test and how to use it needs to be stated somewhere. Even better would be if there was an expect script for it like a few of the other tests have, though I won't reject this PR if you don't have it.
The kinetis changes are OK from a functionality view point, but do you think there is another way that avoids adding an identical one line file to each kinetis CPU?
I am thinking about the ease of maintenance in the future, for us maintainers.

Copy link
Member

@jnohlgard jnohlgard left a comment

Choose a reason for hiding this comment

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

Is not the RTT a better choice for setting alarms x seconds from now? The RTC calendar handling looks messy.

@vincent-d
Copy link
Member Author

Please add a Readme for the new test application. The expected behavior of the test and how to use it needs to be stated somewhere.

OK, I will. The purpose was first to be sure to compile the pm_layered somewhere and have a simple app to unblock modes and measure power consumption.

but do you think there is another way that avoids adding an identical one line file to each kinetis CPU?

I don't know. The feature needs to be 'exported' in a way to the global makefiles. The kinetis common one seemed to not be included in any other makefile. The simplest way was then to include from every kinetis.

Is not the RTT a better choice for setting alarms x seconds from now?

Indeed, could be a better choice, but I had no board with an working RTT. I'll try to add the option with some #ifdef.

@vincent-d
Copy link
Member Author

Well, RTT support turns out to be a hell if I want to have an app which is compatible with both RTC and RTT.

Some cpus implement the RTC and RTT with the same hardware periph, then are mutually exclusive. When using FEATURES_OPTIONAL in the Makefile, if both periphs are available, they are compiled. And shared code does not build.

@vincent-d
Copy link
Member Author

Readme added

@kaspar030
Copy link
Contributor

thanks a lot, I was hitting this issue on a customer board. I'll be AFK for the next two weeks, if this is still open, I'll test asap.

/* Set SLEEPDEEP bit of system control block */
deep = 1;
break;
}
#endif

cortexm_sleep(deep);

#if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
Copy link
Contributor

Choose a reason for hiding this comment

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

if done here, doesn't this delay reinitialization until idle is scheduled after the isr that triggered wakeup and any possibly scheduled threads?

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't think about that...but it looks like it could be more complicated that what I expected.

I guess the solution would be to re-initialize the PLL from the interrupt which triggered the wake-up...but this would imply more code impact.

Copy link

@pwillem pwillem Jul 25, 2017

Choose a reason for hiding this comment

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

Interrupts are disabled in pm_set_lowest so I guess interrupts are only handled after executing the clock init code and re-enabling interrupts in pm_set_lowest
edit:
It seems that I was wrong. cortexm_sleep also disables and enables interrupts

Copy link
Member Author

Choose a reason for hiding this comment

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

I ran another test.

With the current code, it works as @kaspar030 pointed out: another thread can be scheduled before PLL is reinitialized.

If we change cortexm_sleep() from

static inline void cortexm_sleep(int deep)
{
    if (deep) {
        SCB->SCR |=  (SCB_SCR_SLEEPDEEP_Msk);
    }
    else {
        SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
    }

    /* ensure that all memory accesses have completed and trigger sleeping */
    __disable_irq();
    __DSB();
    __WFI();
    __enable_irq();
}

to:

static inline void cortexm_sleep(int deep)
{
    if (deep) {
        SCB->SCR |=  (SCB_SCR_SLEEPDEEP_Msk);
    }
    else {
        SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk);
    }

    /* ensure that all memory accesses have completed and trigger sleeping */
    unsigned state = irq_disable();
    __DSB();
    __WFI();
    irq_restore(state);
}

i.e. replacing __disable_irq()/__enable_irq() by irq_disable()/irq_restore(state).
Then the issue is no longer present: the clock is initialized, then the irq are restored and the interrupt is served, then only after threads can be scheduled.

So there are 2 choices: either we change cortexm_sleep as proposed here, or we remove disabling/re-enabling interrupt from cortexm_sleep and let the layers above taking care of interrupts.

@kaspar030 @gebart @haukepetersen what's your opinion on that?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've discussed this offline with @haukepetersen, and the latter solution (replace __disable_irq/__enable_irq with irq_disable/irq_restore) seems the most elegant to us. It only changes these two lines, and it should work with both boards using pm_layered and with boards that don't.

@vincent-d would you mind updating the PR accordingly?

Copy link
Member Author

Choose a reason for hiding this comment

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

Seems to me it's the best, indeed.

Done.

@vincent-d vincent-d added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Aug 7, 2017
@vincent-d
Copy link
Member Author

  • Fixed build for stm32f1

Should be OK for a final review

@kaspar030
Copy link
Contributor

Needs a rebase.

IMO it makes sense to split up this PR into stm32 fix, test application and kinetis fixes.

@vincent-d
Copy link
Member Author

rebased

I could split in 2 PR, but kinetis fixes are needed for the test app

@kaspar030
Copy link
Contributor

I could split in 2 PR

please do! I can test nucleos, but not kinetis...

@jnohlgard
Copy link
Member

Kinetis in current master has disabled all PM modes, so there's not much to test. I have a WIP branch for implementing low power in the periph drivers on Kinetis, not yet PRed though.

@vincent-d
Copy link
Member Author

I can test nucleos, but not kinetis...

kinetis fix is really only a build issue when compiling the test app, I guess it could stay in one PR. The test app is more convenient to test pm modes IMO.

@vincent-d vincent-d changed the title pm_layered: add test app and fix stm32 + kinetis cpu/stm32_common: fix stm32f1/2/4/7 pm Oct 2, 2017
@vincent-d vincent-d changed the title cpu/stm32_common: fix stm32f1/2/4/7 pm cpu/stm32_common: fix stm32f1/2/4 pm Oct 2, 2017
@vincent-d
Copy link
Member Author

I split the stm32 code and test app/kinetis in 2 PRs. Hopefully, it will ease the review.

@kaspar030
Copy link
Contributor

Hopefully, it will ease the review.

It does. :) please squash!

@vincent-d
Copy link
Member Author

Squashed

@vincent-d
Copy link
Member Author

It does. :) please squash!

@kaspar030 does it mean you ack'ed? ;)

Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

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

ACK.

@kaspar030 kaspar030 merged commit 508547d into RIOT-OS:master Oct 16, 2017
@haukepetersen
Copy link
Contributor

When debugging #7687 git bisect brought me back around to this PR: apparently dd49f22 breaks the stm32l1 implementation (e.g. hard fault when sending a char to the shell using tests/shell).

When doing s/irq_restore(state);/__enable_irq();/, everything is working (again). The difference seems to be __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
vs
__ASM volatile ("cpsie i" : : : "memory");
I have currently no idea why this is showing up for the stm32l1 (Cortex-M3) and not for any other board so far... Any ideas?

@haukepetersen
Copy link
Contributor

opened an issue for this -> #8024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants