Skip to content
This repository has been archived by the owner on Jun 5, 2019. It is now read-only.

STM32F4 RTC support #359

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ Listings/

*.axfdump
/crypto/lib
Firmware License (Crypto).rtf
License (Crypto).rtf
PKCryptoWelcome.rtf
REDIST_CRYPTO.TXT
ReleaseNotesCrypto.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "..\stm32f2xx.h"
#endif

#include "..\..\..\..\..\pal\time\Time_driver.h"

#ifndef FLASH
#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE)
#endif
Expand Down Expand Up @@ -276,8 +278,9 @@ void __section("SectionForBootstrapOperations") STM32F4_BootstrapCode()
// remove Flash remap to Boot area to avoid problems with Monitor_Execute
SYSCFG->MEMRMP = 1; // map System memory to Boot area

#ifdef STM32F4_Enable_RTC
STM32F4_RTC_Initialize(); // enable RTC
#ifdef STM32F4_RTC_ENABLE
Time_Uninitialize();
Time_Initialize();
#endif

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
BOOL RTC_Initialize ( );
INT64 RTC_GetTime ( );
void RTC_SetTime ( INT64 time );
#ifndef STM32F4_RTC_ENABLE
INT32 RTC_GetOffset ( );
void RTC_SetOffset ( INT32 offset );

#endif
//--//

#endif // _DRIVERS_RTC_DECL_H_
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,149 @@
#include "..\stm32f2xx.h"
#endif

#define RCC_LSE_TIMEOUT_VALUE ((uint32_t)6000) // 6000 ms
#define LSI_TIMEOUT_VALUE ((uint32_t)100) // 100 ms

BOOL RTC_Initialize()
{
#ifndef STM32F4_RTC_ENABLE

PWR->CR |= PWR_CR_DBP; // enable RTC access
RCC->BDCR |= RCC_BDCR_RTCSEL_0 | RCC_BDCR_LSEON | RCC_BDCR_RTCEN; // RTC & LSE on

#else

UINT64 ticksStart;
uint32_t tmpreg1 = 0;

// enable power clock
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// also on sleep mode
RCC->APB1LPENR |= RCC_APB1LPENR_PWRLPEN;

// enable access to the backup domain allowing access to RTC
PWR->CR |= PWR_CR_DBP;

#if defined(STM32F4_RTC_LSE)
// enable LSE

if((RCC->BDCR & RCC_BDCR_RTCSEL) != RCC_BDCR_RTCSEL_LSE)
{
// Store the content of BDCR register before the reset of Backup Domain
// and clear RTC clock source
tmpreg1 = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
// RTC Clock selection can be changed only if the Backup Domain is reset
RCC->BDCR |= RCC_BDCR_BDRST;
RCC->BDCR &= ~RCC_BDCR_BDRST;
// Restore the Content of BDCR register
RCC->BDCR = tmpreg1;
}

// Set LSEON bit
RCC->BDCR = RCC_BDCR_LSEON;

// Get Start Tick
ticksStart = HAL_Time_CurrentTicks();

// wait for external low-speed oscillator valid
while(!(RCC->BDCR & RCC_BDCR_LSERDY))
{
if((HAL_Time_CurrentTicks()-ticksStart) > CPU_MillisecondsToTicks((UINT32)RCC_LSE_TIMEOUT_VALUE))
{
// external low-speed oscillator is not working or not fitted
return FALSE;
}
}

// Select the RTC Clock Source
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;

#elif defined(STM32F4_RTC_LSE_BYPASS)
// enable LSE and bypass oscillator

// Set LSEBYP and LSEON bits
RCC->BDCR = RCC_BDCR_LSEBYP | RCC_BDCR_LSEON;

// Get Start Tick
ticksStart = HAL_Time_CurrentTicks();

// wait for external low-speed oscillator valid
while(!(RCC->BDCR & RCC_BDCR_LSERDY))
{
if((HAL_Time_CurrentTicks()-ticksStart) > CPU_MillisecondsToTicks((UINT32)RCC_LSE_TIMEOUT_VALUE))
{
// external low-speed oscillator is not working or not fitted
return FALSE;
}
}

// Select the RTC Clock Source
RCC->BDCR |= RCC_BDCR_RTCSEL_LSE;

#elif defined(STM32F4_RTC_LSI)
// enable LSI

// enable internal low-power oscillator
RCC->CSR |= (uint32_t)RCC_CSR_LSION

// Get Start Tick
ticksStart = HAL_Time_CurrentTicks();

// Wait till LSI is ready
while(!(RCC->CSR & RCC_CSR_LSIRDY))
{
if((HAL_Time_CurrentTicks()-ticksStart) > CPU_MillisecondsToTicks((UINT32)LSI_TIMEOUT_VALUE))
{
// external low-speed oscillator is not working
return FALSE;
}
}

// Select the RTC Clock Source
RCC->BDCR |= RCC_BDCR_RTCSEL_LSI;

#else
// sanity check for RTC enabled but no selection of clock source
#error RTC is enabled in configuration but there is no RTC clock source selected
#endif

// Enable the RTC Clock
RCC->BDCR |= RCC_BDCR_RTCEN;

// Disable the write protection for RTC registers
RTC->WPR = 0xCA;
RTC->WPR = 0x53;

// Check if the Initialization mode is set
if (!(RTC->ISR & RTC_ISR_INITF))
{
// Set the Initialization mode
RTC->ISR |= (uint32_t)RTC_ISR_INIT;

// Wait till RTC is in INIT state and if Time out is reached exit
// according to the STM32 manual it's OK to wait without a timeout as it takes from 1 to 2 RTCCLK clock cycles to enter Initialization mode
while(!(RTC->ISR & RTC_ISR_INITF));
}

// can be read from the shadow registers only if APB clock is at least 7 times the frequency of the RTC
// to avoid adding another check on this, RTC will always be read directly from registers
RTC->CR |= RTC_CR_BYPSHAD;

// Configure the RTC PRER
RTC->PRER = (uint32_t)0xFF;
RTC->PRER |= ((uint32_t)0x7F << 16);

// Exit Initialization mode
RTC->ISR &= ~RTC_ISR_INIT;

// Enable the write protection for RTC registers
RTC->WPR = 0xFF;

// disable access to the backup domain
PWR->CR &= ~PWR_CR_DBP;

#endif

return TRUE;
}

Expand All @@ -42,12 +179,18 @@ UINT32 RTC_BinToBcd(UINT32 bin)

INT64 RTC_GetTime()
{
if (!(RTC->ISR & RTC_ISR_INITS)) { // RTC not set up
if (!(RTC->ISR & RTC_ISR_INITS))
{
// RTC not set up
return 0;
}


#ifndef STM32F4_RTC_ENABLE

while (!(RTC->ISR & RTC_ISR_RSF)); // wait for shadow register ready

#endif

UINT32 ss = ~RTC->SSR & 255; // sub seconds [s/256]
UINT32 tr = RTC->TR; // time
UINT32 dr = RTC->DR; // date
Expand All @@ -65,6 +208,8 @@ INT64 RTC_GetTime()

void RTC_SetTime( INT64 time )
{
#ifndef STM32F4_RTC_ENABLE

RTC->WPR = 0xCA; // disable write protection
RTC->WPR = 0x53;
RTC->ISR = 0xFFFFFFFF; // enter Init mode
Expand Down Expand Up @@ -97,8 +242,53 @@ void RTC_SetTime( INT64 time )

RTC->ISR = 0xFFFFFFFF & ~RTC_ISR_INIT; // exit Init mode
RTC->WPR = 0xFF; // enable write protection

#else

// enable access to the backup domain allowing access to RTC
PWR->CR |= PWR_CR_DBP;

RTC->WPR = 0xCA; // disable write protection
RTC->WPR = 0x53;

// Set the Initialization mode
RTC->ISR |= (uint32_t)RTC_ISR_INIT;

SYSTEMTIME sysTime;
Time_ToSystemTime(time, &sysTime);
UINT32 tr = RTC_BinToBcd(sysTime.wSecond)
| RTC_BinToBcd(sysTime.wMinute) << 8
| RTC_BinToBcd(sysTime.wHour) << 16;
UINT32 dr = RTC_BinToBcd(sysTime.wDay)
| RTC_BinToBcd(sysTime.wMonth) << 8
| (sysTime.wDayOfWeek ? sysTime.wDayOfWeek : 7) << 13
| RTC_BinToBcd(sysTime.wYear % 100) << 16;

// Wait till RTC is in INIT state and if Time out is reached exit
// according to the STM32 manual it's OK to wait without a timeout as it takes from 1 to 2 RTCCLK clock cycles to enter Initialization mode
while(!(RTC->ISR & RTC_ISR_INITF));

// 24h format
RTC->CR &= ~(RTC_CR_FMT);
// set time register
RTC->TR = tr;
// set date register
RTC->DR = dr;

// Exit Initialization mode
RTC->ISR &= ~RTC_ISR_INIT;

// Enable the write protection for RTC registers
RTC->WPR = 0xFF;

// disable access to the backup domain
PWR->CR &= ~PWR_CR_DBP;

#endif
}

#ifndef STM32F4_RTC_ENABLE

INT32 RTC_GetOffset()
{
return RTC->BKP0R;
Expand All @@ -111,3 +301,5 @@ void RTC_SetOffset(INT32 offset)
RTC->BKP0R = offset;
RTC->WPR = 0xFF; // enable write protection
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,32 @@ HRESULT Time_Initialize()
RTC_Initialize();
HRESULT res = g_TimeDriver.Initialize();
INT64 time = RTC_GetTime();

#ifndef STM32F4_RTC_ENABLE

if (time != 0) {
g_TimeDriver.SetUtcTime(time, FALSE);
INT32 offset = RTC_GetOffset();
g_TimeDriver.SetTimeZoneOffset(offset);
}

#else

if (time >= 0x10000000)
{
// RCT value seems to be valid
// set time driver value with time from RCT
g_TimeDriver.SetUtcTime(time, FALSE);
}
else
{
// invalid time from RCT probably because it hasn't been initialized yet
// set RTC with time driver value
RTC_SetTime(g_TimeDriver.GetUtcTime());
}

#endif

return res;
}

Expand All @@ -41,7 +62,9 @@ INT64 Time_SetUtcTime( INT64 UtcTime, bool calibrate )
INT32 Time_SetTimeZoneOffset(INT32 offset)
{
// offset in minutes
#ifndef STM32F4_RTC_ENABLE
RTC_SetOffset(offset);
#endif
return g_TimeDriver.SetTimeZoneOffset(offset);
}

Expand All @@ -55,12 +78,21 @@ HRESULT Time_Uninitialize()

INT64 Time_GetUtcTime()
{
#ifndef STM32F4_RTC_ENABLE
return g_TimeDriver.GetUtcTime();
#else
return RTC_GetTime();
#endif
}

INT64 Time_GetLocalTime()
{
#ifndef STM32F4_RTC_ENABLE
return g_TimeDriver.GetLocalTime();
#else
// GetTimeZoneOffset() returns the offset in minutes so we need to convert it back to TIMEUNIT_TO_MINUTES
return RTC_GetTime() + (g_TimeDriver.GetTimeZoneOffset() * 600000000);
#endif
}

INT32 Time_GetTimeZoneOffset()
Expand Down Expand Up @@ -137,6 +169,3 @@ LPCSTR Time_CurrentDateTimeToString()
{
return g_TimeDriver.DateTimeToString(Time_GetLocalTime());
}



12 changes: 10 additions & 2 deletions Solutions/MCBSTM32F400/TinyBooter/TinyBooter.proj
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,16 @@
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\palevent\stubs\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<DriverLibs Include="Time_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\Time\dotNetMF.proj" />
<DriverLibs Include="Time_pal.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'false'"/>
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\Time\dotNetMF.proj" Condition="'$(USE_RTC)' == 'false'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="Time_pal_rtc.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'true'"/>
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_RTC\Time_Pal_Rtc\dotNetMF.proj" Condition="'$(USE_RTC)' == 'true'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="STM32F4_RTC.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'true'" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_RTC\dotNetMF.proj" Condition="'$(USE_RTC)' == 'true'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="TimeService_pal_stubs.$(LIB_EXT)" />
Expand Down
13 changes: 11 additions & 2 deletions Solutions/MCBSTM32F400/TinyCLR/TinyCLR.proj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<CompressImageDatSym>TinyClr_Dat_Start</CompressImageDatSym>
<CompressImageCfgSym>g_ConfigurationSector</CompressImageCfgSym>
<USE_SSL Condition="'$(FLAVOR)'=='Release'">true</USE_SSL>
<USE_RTC>false</USE_RTC>
</PropertyGroup>
<ItemGroup>
<CompressImageSymdef Include="$(BIN_DIR)\$(AssemblyName).symdefs" />
Expand Down Expand Up @@ -247,8 +248,16 @@
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\palevent\dotNetMF.proj" />
</ItemGroup>
<ItemGroup>
<DriverLibs Include="Time_pal.$(LIB_EXT)" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\Time\dotNetMF.proj" />
<DriverLibs Include="Time_pal.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'false'"/>
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Pal\Time\dotNetMF.proj" Condition="'$(USE_RTC)' == 'false'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="Time_pal_rtc.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'true'"/>
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_RTC\Time_Pal_Rtc\dotNetMF.proj" Condition="'$(USE_RTC)' == 'true'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="STM32F4_RTC.$(LIB_EXT)" Condition="'$(USE_RTC)' == 'true'" />
<RequiredProjects Include="$(SPOCLIENT)\DeviceCode\Targets\Native\STM32F4\DeviceCode\STM32F4_RTC\dotNetMF.proj" Condition="'$(USE_RTC)' == 'true'"/>
</ItemGroup>
<ItemGroup>
<DriverLibs Include="FS_Config_stubs.$(LIB_EXT)" />
Expand Down
Loading