cancel
Showing results for 
Search instead for 
Did you mean: 

(STM32F3 Discovery Board) When I set WUTIE bit in RTC_CR register, it sets all other bits in RTC_CR register to zero

SMede.1
Associate II

I am currently working on a Rust implementation of a STM32f3 Discovery Board hal. As mentioned in the documentation, I am doing the following:

0693W000000W8ZhQAK.png

Before setting the WUTE bit, I also set the WUTIE bit. My ultimate goal is the trigger a 1 second periodic interrupt using the RTC. The moment I set the WUTE bit, I see all of the bits that I have just set in the RTC_CR register go low, while the RTC_WUTE bit remaining high. Is this normal? I tried testing out the code to see if the interrupts are active, to no avail.

5 REPLIES 5

At this point I normally would say "post code" but since

> Rust ... HAL

doesn't sound familiar... post instructions (disasm) leading to the described result.

JW

SMede.1
Associate II

Hello @Community member​ ,

I am currently not at home, but I will give you the instructions as soon as I am able! I happen to have screenshots of the registers before and after. For now, I hope this paints a better picture.

BEFORE (I select LSI as clock source):

0693W000000WHlcQAG.png

AFTER ( after setting WUTE, WCKSEL is set back to 0b000 for some reason):

0693W000000WHlrQAG.png

Moreover, when I set WUTIE to allow for the hardware interrupt, it then clears the WUTE bit:

0693W000000WHm6QAG.png

This is the behavior that I was asking about. Is it normal for the signals to be cleared like that?

I'll go ahead and paste the snippet of Rust code, in the event that it aids in understanding.

self.modify(|regs| {
            regs.wutr.write(|w| unsafe { w.wut().bits(0x0001) });
            regs.cr.write(|w| unsafe { w.wcksel().bits(clocksrc) });
            regs.cr.write( |w| w.wute().set_bit() );
            regs.cr.write(|w| w.wutie().set_bit() );
        });

SMede.1
Associate II

Hello @Community member​ ,

I've attached the complete disassembly output (output.txt) describing what is going on leading up to the register changes. Below is the code in Rust for reference:

    fn modify<F>(&mut self, mut closure: F)
    where
        F: FnMut(&mut RTC) -> (), {
        // Disable write protection
        self.regs.wpr.write(|w| unsafe { w.bits(0xCA) });
        self.regs.wpr.write(|w| unsafe { w.bits(0x53) });
        // Enter init mode
        let isr = self.regs.isr.read();
        if isr.initf().bit_is_clear() {
            self.regs.isr.write(|w| w.init().set_bit());
            while self.regs.isr.read().initf().bit_is_clear() {}
        }
        // Invoke closure
        closure(&mut self.regs);
        // Exit init mode
        self.regs.isr.write(|w| w.init().clear_bit());
        // wait for last write to be done
        while !self.regs.isr.read().initf().bit_is_clear() {};
        //Locks write protect
        self.regs.wpr.write(|w| unsafe { w.bits(0xFF) });
    }

The closure on line 14 is kind of like a lambda function. It is executing the code snippet that I posted on the previous post:

self.modify(|regs| {
            regs.wutr.write(|w| unsafe { w.wut().bits(0x0001) });
            regs.cr.write(|w| unsafe { w.wcksel().bits(clocksrc) });
            regs.cr.write( |w| w.wute().set_bit() );
            regs.cr.write(|w| w.wutie().set_bit() );
        });

This is represented by this part of the assembly (taken from output.txt):

~"156\t        // Invoke closure\n"
~"157\t        closure(&mut self.regs);\n"
~"=> 0x08001eca <+376>:\tldr\tr0, [sp, #52]\t; 0x34\n"
~"   0x08001ecc <+378>:\tstr\tr0, [sp, #84]\t; 0x54\n"
~"   0x08001ece <+380>:\tldr\tr1, [sp, #84]\t; 0x54\n"
~"   0x08001ed0 <+382>:\tadd\tr0, sp, #56\t; 0x38\n"
~"   0x08001ed2 <+384>:\tbl\t0x800178a <stm32f3xx_hal::rtc::Rtc::enable_wut::{{closure}}>\n"
~"   0x08001ed6 <+388>:\tb.n\t0x8001ed8 <stm32f3xx_hal::rtc::Rtc::modify+390>\n"
~"   0x08001ed8 <+390>:\tldr\tr0, [sp, #52]\t; 0x34\n"
~"   0x08001eda <+392>:\tstr\tr0, [sp, #284]\t; 0x11c\n"
~"\n"

I have extremely limited experience with reading assembly code. Please let me know if I can provide more useful information!

-Best

Scott

Hello @waclawek.jan (Community Member)​ ,

I've attached the complete disassembly output (output.txt) describing what is going on leading up to the register changes. Below is the code in Rust for reference:

    fn modify<F>(&mut self, mut closure: F)
    where
        F: FnMut(&mut RTC) -> (), {
        // Disable write protection
        self.regs.wpr.write(|w| unsafe { w.bits(0xCA) });
        self.regs.wpr.write(|w| unsafe { w.bits(0x53) });
        // Enter init mode
        let isr = self.regs.isr.read();
        if isr.initf().bit_is_clear() {
            self.regs.isr.write(|w| w.init().set_bit());
            while self.regs.isr.read().initf().bit_is_clear() {}
        }
        // Invoke closure
        closure(&mut self.regs);
        // Exit init mode
        self.regs.isr.write(|w| w.init().clear_bit());
        // wait for last write to be done
        while !self.regs.isr.read().initf().bit_is_clear() {};
        //Locks write protect
        self.regs.wpr.write(|w| unsafe { w.bits(0xFF) });
    }

The closure on line 14 is kind of like a lambda function. It is executing the code snippet that I posted on the previous post:

self.modify(|regs| {
            regs.wutr.write(|w| unsafe { w.wut().bits(0x0001) });
            regs.cr.write(|w| unsafe { w.wcksel().bits(clocksrc) });
            regs.cr.write( |w| w.wute().set_bit() );
            regs.cr.write(|w| w.wutie().set_bit() );
        });

This is represented by this part of the assembly (taken from output.txt):

~"156\t        // Invoke closure\n"
~"157\t        closure(&mut self.regs);\n"
~"=> 0x08001eca <+376>:\tldr\tr0, [sp, #52]\t; 0x34\n"
~"   0x08001ecc <+378>:\tstr\tr0, [sp, #84]\t; 0x54\n"
~"   0x08001ece <+380>:\tldr\tr1, [sp, #84]\t; 0x54\n"
~"   0x08001ed0 <+382>:\tadd\tr0, sp, #56\t; 0x38\n"
~"   0x08001ed2 <+384>:\tbl\t0x800178a <stm32f3xx_hal::rtc::Rtc::enable_wut::{{closure}}>\n"
~"   0x08001ed6 <+388>:\tb.n\t0x8001ed8 <stm32f3xx_hal::rtc::Rtc::modify+390>\n"
~"   0x08001ed8 <+390>:\tldr\tr0, [sp, #52]\t; 0x34\n"
~"   0x08001eda <+392>:\tstr\tr0, [sp, #284]\t; 0x11c\n"
~"\n"

I have extremely limited experience with reading assembly code. Please let me know if I can provide more useful information!

-Best

Scott

  •  

156          // Invoke closure  
157          closure(&mut self.regs);  
=> 0x08001eca <+376>:  ldr  r0, [sp, #52]  ; 0x34  
   0x08001ecc <+378>:  str  r0, [sp, #84]  ; 0x54  
   0x08001ece <+380>:  ldr  r1, [sp, #84]  ; 0x54  
   0x08001ed0 <+382>:  add  r0, sp, #56  ; 0x38  
   0x08001ed2 <+384>:  bl  0x800178a <stm32f3xx_hal::rtc::Rtc::enable_wut::{{closure}}>  
   0x08001ed6 <+388>:  b.n  0x8001ed8 <stm32f3xx_hal::rtc::Rtc::modify+390>  
   0x08001ed8 <+390>:  ldr  r0, [sp, #52]  ; 0x34  
   0x08001eda <+392>:  str  r0, [sp, #284]  ; 0x11c

This does not do much - just pulls some parameters from stack and calls the routine at 0x800178a. That routine presumably does the bulk of the job.

[EDIT] I've just noticed output.txt... okay that would take some time to go through... [/EDIT]

[EDIT2] From what I understand, the code in output.txt does mostly nothing just prepares constants (0x40002824 and 0x4000280C which are RTC_WPR and RTC_ISR, repsectively) onto stack, in several instances; in an incredibly convoluted and inefficient way. Then the call commented above is made which presumably does the "real thing".

Try to single-step the code in disasm view (i.e. instruction-by-instruction) and observe, where and how the RTC registers are written - it's pretty simple to spot when viewed real-time in debugger. It is a STR instruction, where the first parameter is the register which contains the value to be writeen, and the second (in brackets) is the register which contains the target address, sometimes together with a constant offset.

Or, try to describe, what your code is supposed to do, step-by-step, in a common procedural language, e.g. C, or as narrative.

JW