2020-08-20 05:49 AM
I'm using a Nucleo L152RE.
I've read the 900 pages manual multiple times but I still miss a clear view of what needs to be done to create a RTC Wakeup event.
I read in the manual:
"""
To enable the RTC Wakeup interrupt, the following sequence is required:
1. Configure and enable the EXTI Line 20 in interrupt mode and select the rising edge
sensitivity.
2. Configure and enable the RTC_WKUP IRQ channel in the NVIC.
3. Configure the RTC to generate the RTC wakeup timer event.
"""
But I don't understand what all that means.
Could you translate it for me in terms of operations that need to be done?
All of the three tasks I quoted start with "configure", this is way too vague for me. What does that mean, "configure" ? What needs to be done? I guess some registers, or bits somewhere must be modified. Which ones? How exactly do you "configure" those things?
Maybe all the 3 steps is too much, so, let's start with step 1:
"Configure and enable the EXTI Line 20 in interrupt mode"
What does that mean? What do I do?
"and select the rising edge sensitivity"
What is that? How do I select it?
Just step 1 will do for now.
Please help.
The whole manual is like that.
2020-08-20 02:04 PM
What does "ck_spre" stand for? I guess "ck" is for clock. I guess "pre" is for "prescaler". But what does the "s" mean?
It would be nice to have those names explained. It might help to understand. Why is there a "s" in "ck_spre"? What am I missing here? This name appears without explanation in the doc. It's just "ck_spre".
2020-08-20 02:29 PM
There's nothing in the doc about how to set "ck_spre". However there's a register called RTC_PRER in the section about RTC registers: https://www.st.com/resource/en/reference_manual/cd00240193-stm32l100xx-stm32l151xx-stm32l152xx-and-stm32l162xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page=533
This seems to correspond to this idea of dividing successively the frequency of the original clock by two successive divisors.
Bad news, I read:
"""
This register must be written in initialization mode only. The initialization must be performed in two separate write accesses. Refer to Calendar initialization and configuration on page 513
"""
This apparently will never end.
2020-08-21 09:18 AM
I asked the question about this RTC initialisation mode in the following thread: https://community.st.com/s/question/0D53W00000FzTCASA3/when-i-push-the-reset-button-of-my-nucleo-what-kind-of-reset-is-it
As you can see from my quote from the manual, and from the reply from TDK, we can conlude that it is necessary to:
1) Set the DBP bit from the PWR_CR register to 1
2) Successively set the value of register RTC_WPR to 0xca and then to 0x53
Once we have finally managed to program a wakeup event (if we ever manage to), I think it would be good to reset the DBP bit from PWR_CR to 0 and then also "reactivate the RTC registers protection" by writing a "wrong key" into RTC_WPR.
2020-08-21 09:32 AM
Now I have good hopes I have understood how to set "ck_spre" (still wondering what the "s" stands for):
We can move on to what should be (I hope) the last substep of step 3: "programming the wake up timer". Fortunately, it's written on page 512 that we have to read page 514 for this: https://www.st.com/resource/en/reference_manual/cd00240193-stm32l100xx-stm32l151xx-stm32l152xx-and-stm32l162xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf#page=514:
"""
Programming the wakeup timer
The following sequence is required to configure or change the wakeup timer auto-reload value (WUT[15:0] in RTC_WUTR):
1. Clear WUTE in RTC_CR to disable the wakeup timer.
2. Poll WUTWF until it is set in RTC_ISR to make sure the access to wakeup auto-reload counter and to WUCKSEL[2:0] bits is allowed. It takes 1 to 2 RTCCLK clock cycles (due to clock synchronization).
3. Program the wakeup auto-reload value WUT[15:0], and the wakeup clock selection (WUCKSEL[2:0] bits in RTC_CR).Set WUTE in RTC_CR to enable the timer again. The wakeup timer restarts down-counting. The WUTWF bit is cleared up to 2 RTCCLK clocks cycles after WUTE is cleared, due to clock synchronization.
"""
2020-08-21 09:36 AM
I note that there's an interesting info here. Clearing WUTE in RTC_CR disables the wakeup timer. That means that we should be able to use this timer to program a single wakeup. Once we catch the wakeup event, we'll clear that WUTE thing to disable the wakeup timer so that it doesn't wake us up periodically.
Edit: I just checked. WUTE is actually a bit, it's bit 10 of the RTC_CR register.
2020-08-21 09:51 AM
If I manage to set "ck_spre" to 1Hz, I'll set set WUCKSEL[2:0] to 0b10 and then I should be able to set a number of seconds into WUT[15:0]. Then I'll start the countdown by setting the WUTE bit back to 1 in RTC_CR.
2020-08-21 10:01 AM
I'm gonna do a recap of all these steps as soon as I have time.
And then I'll try to make it work.
2020-08-22 08:40 AM
Here is the recap. Sentences in quotes are the original sentences from the manual I had quoted in post 1, and that I could not understand.
Step 1:
Step 1.1: "Configure and enable the EXTI Line 20 in interrupt mode"
-> set bit 20 of EXTI_EMR register to 1
Step 1.2: "and select the rising edge"
-> set bit 20 of EXTI_RTSR register to 1
-> set bit 20 of EXTI_FTSR to 0
Step 2: "Configure and enable the RTC_WKUP IRQ channel in the NVIC"
-> write an interrupt handler routine and store the address of this routine at position 0x0000_004C of the code you're going to flash the microcontroller with
Step 3: "Configure the RTC to generate the RTC wakeup timer event."
Step 3.1: Unlock the RTC registers
-> Set bit DBP from the PWR_CR register to 1
-> Successively set the value of register RTC_WPR to 0xca and then to 0x53
Step 3.2: disable the wakeup timer (it can only be programmed when disabled)
-> set the WUTE bit of the RTC_CR register to 0
Step 3.3: wait for the timer to be programmable
-> loop until bit WUTWF of register RTC_ISR is 1
Step 3.4: Ensure "ck_spre" is 1Hz
-> set PREDIV_S to 255 (PREDIV_S is a 15 bits value stored in bits 0 to 14 of register RTC_PRER)
-> set PREDIV_A to 127 (PREDIV_A is a 7 bits value stored in bits 16 to 22 of register RTC_PRER)
Step 3.5: Set "ck_spre" as the clock frequency of the timer
-> set WUCKSEL[2:0] to 0b10
Step 3.6: Set the duration of the countdown, expressed in number of ticks of the timer's clock. We have set the timer's clock frequency to 1 Hz so we can express the duration of the countdown in seconds.
-> store the duration of the countdown in WUT[15:0]
Step 3.7: start the countdown
-> Set bit WUTE of register RTC_CR to 1
Step 3.8: lock back registers we had unlocked in step 3.1
-> Set the value of register RTC_WPR to 0x00
-> Set bit DBP from the PWR_CR register to 0
I will try to implement that when I have a bit of time and I will report.
2020-08-24 03:33 PM
I implemented this in assembly. Obviously that doesn't work. I debugged in gdb and realized that, despite my attempt, the PWR_CR was not modified (I failed to set the DBP bit, that is, bit 8, to 1). That's probably the reason why all the modification of the RTC related registers also failed. These registers weren't modified either.
Looking for info in the manual about PWR_CR yields the following:
"""
RTC registers access
After reset, the RTC Registers (RTC registers and RTC backup registers) are protected against possible stray write accesses. To enable access to the RTC Registers, proceed as follows:
1. Enable the power interface clock by setting the PWREN bits in the RCC_APB1ENR register.
2. Set the DBP bit in the PWR_CR register (see Section 5.4.1).
3. Select the RTC clock source through RTCSEL[1:0] bits in RCC_CSR register.
4. Enable the RTC clock by programming the RTCEN bit in the RCC_CSR register.
"""
This is on page 100 of the manual.
This seems to be different than what's on page 513 of the same manual:
"""
RTC register write protection
After system reset, the RTC registers are protected against parasitic write access with the DBP bit of the PWR power control register (PWR_CR). The DBP bit must be set to enable RTC registers write access.
After power-on reset, all the RTC registers are write-protected. Writing to the RTC registers is enabled by writing a key into the Write Protection register, RTC_WPR.
The following steps are required to unlock the write protection on all the RTC registers except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR.
1. Write ‘0xCA’ into the RTC_WPR register.
2. Write ‘0x53’ into the RTC_WPR register.
Writing a wrong key reactivates the write protection.
The protection mechanism is not affected by system reset
"""
This was this last procedure that I had followed and this wasn't enough to give me write access to the RTC registers.
When I reset the board, that must be a system reset, I need to unlock the DBP bit of the PWR_CR register, which I tried to do, but I didn't know that there was a prior step to this "setting the PWREN bits in the RCC_APB1ENR register". This is my theory. I'm going to investigate in this direction and will try to implement the unlocking procedure on page 100 before the other unlocking procedure of page 514.
2020-08-31 05:49 AM
I stumbled upon the following in the manual, on page 167:
"""
Bits 17:16 RTCSEL[1:0]: RTC and LCD clock source selection
These bits are set by software to select the clock source for the RTC.
Once the RTC and LCD clock source has been selected it cannot be switched until RTCRST is set or a Power On Reset occurred. The only exception is if the LSE oscillator clock was selected, if the LSE clock stops and it is detected by the CSS, in that case the clock can be switched.
00: No clock
01: LSE oscillator clock used as RTC/LCD clock
10: LSI oscillator clock used as RTC/LCD clock
11: HSE oscillator clock divided by a programmable prescaler (selection through the RTCPRE[1:0] bits in the RCC clock control register (RCC_CR)) used as the RTC/LCD clock
If the LSE or LSI is used as RTC clock source, the RTC continues to work in Stop and Standby low-power modes, and can be used as wake-up source. However, when the HSE clock is used as RTC clock source, the RTC cannot be used in Stop and Standby low-power modes
I wish this last fact had been mentioned in the section about wakeup events: you can't generate a wakeup event when using "ck_spree"! At least not to wake up from a low power mode. Yet, in the section about wakeup events in the manual they use "ck_spree" and there is no mention of the fact that it's actually useless to do that if you're going to make use of low power modes.
So that means I have to rethink almost everything from the beginning and see how I can function without "ck_spree".