stm32duino / STM32LowPower

Arduino Low Power library for STM32
183 stars 52 forks source link

Adding support for wakeup from TwoWire #72

Open mkals opened 2 years ago

mkals commented 2 years ago

Are there any plans for implementing the enableWakeupFrom(TwoWire ...) function? This would be very useful to have!

mkals commented 2 years ago

If it is not too hard I could take a look at implementing it myself, but I am assuming there may be a reason for it to have been left out of the library so far.

fpistm commented 2 years ago

I @mkals Main reason is the time. I don't know if it can be added easily across all series. If you want you can try to implement it and proposed a PR.

mkals commented 2 years ago

Ok, thanks for your quick reply! I have been looking into this for a few hours now, but I am struggling. The core needs to wake in time for the address specified in the I2C packet to be parsed, but I am not sure how to can be ensured with the delays to wake from the sleep modes. Any suggestions as to where I should start looking for implementing this? There are no options related to I2C wake from sleep in the STM32CubeMX tool for example..

fpistm commented 2 years ago

Well, in that case I try to find an example project in the STM32CubeFw. IIWR you work with L010RB. There is no project but for L011K4 it exists: https://github.com/STMicroelectronics/STM32CubeL0/tree/master/Projects/NUCLEO-L011K4/Examples/I2C/I2C_WakeUpFromStop

From Reference manual

image

mkals commented 2 years ago

Thanks a lot @fpistm! I'll see what I can figure out.

mkals commented 2 years ago

By setting the I2C1->CR1 |= I2C_CR1_WUPEN; bit, the STM32L0 wakes on I2C from LowPower.sleep(), but it does not seem to wake on LowPower.deepSleep() or HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);.

I make sure I use HSI by calling __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI); before going to sleep. I'm using the STM32L051C8, which supports I2C wakeup from stop on I2C1 according to the datasheet.

Screenshot 2022-06-16 at 10 50 19
mkals commented 2 years ago

I have also tried setting other bits in the I2C_CR1 register manually, but it does not make a difference.

        SET_BIT(I2C1->CR1, I2C_CR1_PE); 
        SET_BIT(I2C1->CR1, I2C_CR1_WUPEN); 
        SET_BIT(I2C1->CR1, I2C_CR1_STOPIE); 
        SET_BIT(I2C1->CR1, I2C_CR1_RXIE); 
        SET_BIT(I2C1->CR1, I2C_CR1_ADDRIE); 
        SET_BIT(I2C1->CR1, I2C_CR1_NACKIE);
        CLEAR_BIT(I2C1->CR1, I2C_CR1_NOSTRETCH);
fpistm commented 2 years ago

Hard to tell. We should try to mimic this: https://github.com/STMicroelectronics/STM32CubeL0/blob/master/Projects/NUCLEO-L011K4/Examples/I2C/I2C_WakeUpFromStop/Src/main.c#L199-L217

Best thing would be to properly add those mechanism to Wire.

asukiaaa commented 1 year ago

Thank you for the infomation.

I'm using stm32l432kc and tried but not succeded in handleing i2c with low poer. Could you give me some advice?

=== What I tried ===

I called HAL_I2CEx_EnableWakeUp function (with the following code) after i2c_custom_init ( https://github.com/stm32duino/Arduino_Core_STM32/blob/565f3ecc1c2c12f9577cf648c292a5ddc5b7eb6b/libraries/Wire/src/utility/twi.c#L782-L785 ) which is called in Wire.begin().

        // manualy add
        if (HAL_I2CEx_EnableWakeUp(handle)) {
          // SERIAL_DEBUG.println("error on enabling wakeup");
          Error_Handler();
        }

I called LowPower.enableWakeupFrom(&Serial, []() {}); to enable stop 0 or 1 because i2c1 of stm32l4 cannot wakeup from stop 2.