分享到plurk 分享到twitter 分享到facebook

版本 dd2cbcbe94ad522d404592fae75433448f33e8f3

embedded/RTC

Changes from dd2cbcbe94ad522d404592fae75433448f33e8f3 to d72ef05b7f86aab2c3df906cbb9cd7bda7601af3

Introduction
==============
Summary
----------------- 

基本上RTC(Real-time clock)本身就是一個真正的時鐘,利用原本STM本身所內建的振盪器再利用Prescaler降成1Hz讓RTC使用。

利用硬體達成的binary-coded decimal (BCD) format,可以把下列與時間有關的資訊儲存,而且不需要任何軟體轉換,因為硬體就已經把資料轉成一般的日期格式。
 
- sub-seconds (not programmable) 
 
- seconds
 
- minutes

- hours in 12-hour or 24-hour format

- day of the week (day)

- day of the month (date)

- month

- year

一些可以用的功能  Maskable interrupts/events:

- Alarm A

- Alarm B

- Wakeup interrupt

- Timestamp

- Tamper detection


Block diagram  
--------------------

.. image:: /rtc_block.png


--------------------------------------------------------------------

--------------------------------------------------------------------


Functional description
============================
Clock source 
--------------------

**STM32的 Clock 有分成「SYSCLK」和「RTCCLK」:**

SYSCLK為系統的clock有三種來源:

1. **HSI**  (High-Speed Internal) :16MHz,RC電路

2. **HSE** (Low-Speed External):4-26MHz (一般選用8MHz),石英震盪

3. Main **PLL** clock

RTCCLK為設備的clock有兩種來源:

1. **LSI**  (Low-Speed Internal)  :40kHz,RC電路震盪

2. **LSE** (High-Speed External):32.768kHz,石英震盪

----> RTC 主要是使用 **HSE** , **LSI**  , **LSE** 三種來源

*參閱reference manual p.150*

-----------------------------------------------

**比較 "HSE" , "LSI " , "LSE"三種輸入來源:** 


- HSE  -  較為耗能, 可以處理像是USB或TV訊號的clock,需要和和另一個clock穩定同步。

- LSI  -  是一個低功耗的clock,可以再停機或待機模式下保持運行,用在auto-wakeup(簡稱AWU)與 watchdog看門狗(簡稱IMDG)。

- LSE  -  它是一個低功耗且"精準"的clock,適合用在時間的精確計算。


--------------------------------------------------------------------

--------------------------------------------------------------------




Prescaler 
--------------------

輸入的ck_spre必須要降為1Hz的頻率,因為省電的因素STM設計了兩個Prescaler。

A 7-bit asynchronous prescaler PREDIV_A bits of the RTC_PRER register.

A 15-bit synchronous prescaler PREDIV_S bits of the RTC_PRER register.

*ps. ST在Reference有說明當兩個Prescaler都使用時,建議讓非同步的Prescaler讓他有較大的值,以讓系統更省電*

.. image:: /ck_spre2.png


例如:

LSE: 32.768kHz / (127+1) / (255+1) = 1Hz

LSI: 32kHz / (127+1) /(249+1) =1Hz

-----------------------------------------------------

**設定輸出訊號為 1 Hz 的步驟:**

step1. 選擇 LSE “32768 Hz” 當作 RTC clock 來源。

step2. 設定非同步的 prescaler 去確認值等於“128“。

step3. 設定同步的 prescaler 去確認值等於“256“。

step4. 設定“COE” 為 ‘1’, 能夠輸出 calibration。

step5. CALSEL 被設定為 ‘1’, 可選擇 1 Hz 當作 calibration 的輸出 。

.. image:: /ck_prescaler.PNG


--------------------------------------------------------------------

--------------------------------------------------------------------


RTC Calendar 
--------------------


.. image:: /RTC_calendar.png


**讀取Calendar**


當在讀取Calendar時其實並不是真正直接讀取calendar register,其實是讀shadow register,如果想要直接讀取calendar必須要設BYPSHAD 控制位元為1(在RTC_C Rregister)才能繞過shadow register而直接讀取calender register。

**補充:Shadow Register**

Bit 5 BYPSHAD: Bypass the shadow registers

0:間接在Shadow Register( RTC_SSR, RTC_TR, and RTC_DR)讀取Calendar,資料會延遲兩個RTC Clock更新一次

1:不透過Shadow Register直接讀取Calendar,拿到的資料不會延遲會直接更新

--------------------------------------------------------------------

**Calendar 的設定步驟:**

step1.關閉RTC的防寫功能    --->寫入"0xCA"和"0x53"到RTC_WPR register.

step2. 進入初始模式        --->設RTC_ISR register的INIT bit為1

step3. 等待初始化的確認     --->等待2個clock cycle,讓RTC_ISR register的INITF bit(bit 6)為1

step4. 如果需要調整計數速率  --->寫入RTC_PRER register同步時間的值

step5. 選擇想要的時間與日期  --->設定RTC_TR的秒分時;設定RTC_DR的日週月年

step6. 選用12h或24h       --->設RTC_CR register的FTM bit,等於0表示24制;1表示12制

step7.結束初始模式設定      --->清除RTC_ISR register的INIT bit.

step8. 使RTC寫入保護(防寫)  --->寫入"0xFF"到RTC_WPR register


--------------------------------------------------------------------

--------------------------------------------------------------------



Calibration
-----------------------------

RTC裡面有兩個校正功能,一個是RTC coarse calibration另一個是RTC smooth calibration。

**1、RTC coarse calibration :**

- coarse calibration 被使用在補償石英震盪器的校正。

- 在非同步分頻器(ck_apre)的輸出,藉由增加或減少時間的週期達到校正,最大範圍的校正為63ppm~126ppm。

- 可以使用AFO_CALIB來計算時間偏差,並更新calibration方塊圖的1Hz(ck_apre)輸出。

- 在512Hz時,並不能去檢查校正結果,只能檢查經過calibration方塊圖的1Hz(ck_apre)輸出。

- 完整的校正週期要持續64分鐘。

- 只能在初始化Calendar時候修改,不能在RTC開啟的時候修改。導致不可校正動態的誤差,只能校正固定的誤差,是一個非回授控制系統(opened loop control)。 

- reference clock calibration 和 coarse calibration 不能同時使用。


.. image:: /coarse cal.png

**2、RTC  smooth calibration:**

- smooth calibration 利用每個RTCCLK pulse為單位做出小幅調整,來修正RTC的clock頻率。

- 最大範圍的校正為-487.1ppm~+488.5ppm。 

- smooth calibration 可以補償石英震盪器的偏差,此偏差可能是晶體老化或者溫度所造成。

- 可以使用AFO_CALIB來計算時間偏差,而且可直接檢查512Hz和1Hz的校正輸出。

- 可使用RTC_CALR register裡面的CALP和CALM去增加或減少pulses。 

- smooth calibration可配置8秒、16秒、32秒的校正視窗,沒設定的情況下為32秒的視窗。

- 與coarse calibration不同,可藉由AFO_CALIB得到時鐘的偏差值(clock deviation)。這種方法可以確認修正的結果,是一個閉迴路的控制系統(closed loop control)。

- smooth calibration可以使用在:

      1.AFO_CALIB (512 Hz or 1 Hz)。  2.sub-second alarms。  3.Wakeup timer。

.. image:: /smooth cal.png

**3、RTC reference clock detection:**

- 利用外部時鐘校正,其時鐘源要比LSE的時鐘還精準。

*原文:The reference clock (at 50 Hz or 60 Hz) should have a higher precision than the 32.768 kHz LSE clock.*

---------------------------------------------------

---------------------------------------------------

Low power modes
---------------------------------
--------------------

- RTC 設計為最小的耗能,在休眠模式下,RTC將繼續動作。

- 當clock 的來源是LSE 或 LSI,在停止模式與待機模式下,RTC仍然活躍的動作。

- 在低功率( low power mode)模式下,Alarm, tamper event, time stamp event, and wakeup 依然會被中斷所啟動。

.. image:: /RTC in low power mode.png

---------------------------------------------------

---------------------------------------------------


Interrupt application
==========================

Alarm:
---------------------------

calendar register與alarm作比較,如果相同則將對應的flag拉起來。

.. image:: /embedded/RTC/alarm_pass.png

---------------------------
RTC periodic wakeup unit
----------------------------

Time-stamp function
--------------------------

RTC tamper detection function
---------------------------------


Example of code
========================

initialize RTC
--------------------

.. code-block:: prettyprint
	
    RTC_InitTypeDef RTC_InitStructure;
	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);   /* Enable the PWR clock */
    PWR_BackupAccessCmd(ENABLE);                          /* Allow access to RTC */

    RCC_LSICmd(ENABLE);                                   /* Enable the LSI OSC */
    while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);   /* Wait till LSI is ready */  
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);               /* Select the RTC Clock Source */
	
    RCC_RTCCLKCmd(ENABLE);                                /* Enable the RTC Clock */
    RTC_WaitForSynchro();                                 /* Wait for RTC APB registers synchronisation */

    /* Configure the RTC data register and RTC prescaler */
    RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
    RTC_InitStructure.RTC_SynchPrediv = 0xF9;
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
    RTC_Init(&RTC_InitStructure);

setting time
--------------------

.. code-block:: prettyprint

	/* set 8:29:55 */
	RTC_TimeTypeDef RTC_TimeStruct;
	RTC_TimeStruct.RTC_Hours = 8;
	RTC_TimeStruct.RTC_Minutes = 29;
	RTC_TimeStruct.RTC_Seconds = 55;
	
	RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);


initialize RTC alarm
--------------------

.. code-block:: prettyprint

	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	/* EXTI configuration */
	EXTI_ClearITPendingBit(EXTI_Line17);
	EXTI_InitStructure.EXTI_Line = EXTI_Line17;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);

	/* Enable the RTC Alarm Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);


setting alarm time
--------------------

.. code-block:: prettyprint

	RTC_AlarmTypeDef RTC_AlarmStructure;

	RTC_AlarmCmd(RTC_Alarm_A, DISABLE);   /* disable before setting or cann't write */

	/* set alarm time 8:30:0 everyday */
	RTC_AlarmStructure.RTC_AlarmTime.RTC_H12     = 0x00;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours   = 8;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = 30;
	RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0;
	RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31; // Nonspecific
	RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
	RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay; // Everyday 
	RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
	
	/* Enable Alarm */
	RTC_ITConfig(RTC_IT_ALRA, ENABLE);
	RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
	RTC_ClearFlag(RTC_FLAG_ALRAF);



complete code
--------------------

.. code-block:: c

    git clone git@gitcafe.com:ctc8631/RTC-example.git
    cd RTC-example/
    make flash



Previous
=============

Generate 1Hz
--------------------
http://wiki.csie.ncku.edu.tw/embedded/RTC
RTC基本計算單位為一秒鐘。

由於clock source速度太快,我們需要用prescaler去轉換成一秒鐘。

.. image:: /stm32 RTC prescaler.png

基於省電需求,將prescaler分為兩個區塊,首先經由較省電的Asynchronous prescaler,再透過較耗能量的Synchronous prescaler輸出1Hz。

根據clock source的頻率不同,我們調整不同的prescaler參數。


.. image:: /embedded/RTC/ck_spre_formula.png

LSE: 32.768kHz / (127+1) / (255+1) = 1Hz

LSI: 32kHz / (127+1) /(249+1) =1Hz

Alarm
--------------------
鬧鐘。

calendar register與alarm作比較,如果相同則將對應的flag拉起來。

.. image:: /embedded/RTC/alarm_pass.png




Previous Functionality
-------------------------





Prescaler
----------
Prescaler generates the clock to update the calendar.

To minimize power comsuption the prescaler is split into two prescalers, asynchronous and synchronous. It is recommended to configure the asynchronous prescaler to a high value to minimize consumption.

asynchronous prescaler clocks subsecond of calendar and propagates to synchronous prescaler to update date and time by second.

One can configure them through ``PREDIV_A`` and ``PREDIV_S`` bits in ``RTC_PRER``


Calendar and Alarm
--------------------
A calendar keeps track of the date (day, week, month, year) and time (hours, minutes and seconds) and even subseconds. It manages of numbers of days of mouths automaticly. Daylight saving time adjustment is programmable by software.

Binary repersentation is in binary-coded decimal (BCD) format. 

Data can be read indirectly from shadow registers or directly from counters. The former method delays some clocks but ensures consistency between date and time registers; the later is opposite but this is especially useful after exiting from low power modes, since the shadow registers are not updated during these modes.

Data, time, and subsecond are separately recorded in ``RTC_DR``, ``RTC_TR``, and ``RTC_SSR``. With ``BYPSHAD`` bit set, data can be read directly from counter.

Two programmable alarms (Alarm A, Alarm B) with **interrupt function**. The alarms can be triggered by any **combination** of the calendar fields.

An alarm consists of a register with the same length as the RTC time counter. When the RTC time counter reaches the value programmed in the alarm register, a flag is set to indicate that an alarm event occurred.

In addition to the time to trigger, alarm can be configured to mask some fields and do not compare.


Auto periodic wakeup
------------------------------
A periodic timebase and wakeup unit that can wake up the system from low power modes. When this counter reaches zero, a flag and an interrupt are generated.

It's source clock can be RTC clock or prescaler. Time range can be configured through ``WUCKSEL``


Timestamp
----------
The calendar is saved in timestamp registers when timestamp event is detected on the pin which timestamp alternate function is mapped.


Tamper detection
--------------------
It can be used for edge detection or level detection with filtering according to ``TAMPFLT``. Set to 00 is edge detection, others arg level detection.

When ``TAMPTS`` set to 1, tamper event trigger timestamp event automatically.


Backup registers
--------------------
Program can read or write data from or to these registers, which are not reset by system reset or power-on reset. They are  reset when tamper detection event occurs.


Alternate function outputs
------------------------------
Two outputs are avalible : ``RTC_CALIB`` and ``RTC_ALARM``.

``RTC_CALIB`` output is used to generate a variable-frequency signal. It can use either asynchronous or synchronous prescaler as clock.

besides alarm, ``RTC_ALARM`` can use wakeup timer as source.


Synchronization and Reference clock detection
--------------------------------------------------
RTC can be synchronized to remote clock by adding a 'shift' to counter continuously to delay, or vice versa. 
With reference clock detection, RTC shifts misaligned 1 Hz clock to align it with the nearst referenced edge (found in a given time window).

One can adjust time by configuring shift through ``RTC_SHIFTR``.

When reference clock detection is enabled (``REFCKON``), must not write ``RTC_SHIFTR`` and not enable calibration and set prescalers (``PREDIV_A`` and ``PREDIV_S``) to default.


Digital calibration
--------------------
Calibration can be used to compensate inaccuracy of oscillator by adding or substracting clock cycles in each calibration cycle.

There are two calibration methods : coarse and smooth. They should not be used togather. The cycle of the later is smaller than the former. It makes the later is more flexible to adjust clock. A smooth calibration can be performed on the fly so that it can be changed to handle changed envirenment variables.

coarse calibration is provided for capability reasons. It can only be configured in initialization mode and start when INIT bit is cleared. Also it is recommaned using it for static correction only.


Low power modes
--------------------
The RTC is designed to minimize the power consumption. 

The RTC runs as usual in Sleep mode. 

In Stop mode and Standby mode, the RTC remains active when clock source is LSE or LSI.

Alarm, tamper event, time stamp event, and wakeup cause the device to exit low power mode.

.. image:: /RTC in low power mode.png

wakeup, effectiveness and voltage in three lowpower modes

.. image:: /embedded/RTC/stm32 low power mode summary.png



Previous Configuration  Register write protection
-------------------------------------------------------
After system **reset**, the RTC registers are protected registers are automatically locked to against **possible parasitic write accesses**.

RTC registers need to **disable** backup domain protection to update the current calendar time and date.

    set ``DBP`` bit in ``PWR_CR``

After power-up reset, the RTC registers are also protected and need to write a key into protection register. RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR are except. Write a wrong key will enable protection.

    write ``0xCA`` to ``RTC_WPR``

    write ``0x53`` to ``RTC_WPR``

Initialization mode
--------------------
Modifications of ``RTC_DR``, ``RTC_TR``, and ``RTC_PRER`` must be done in Initialization mode.

    set ``INIT`` bit of ``RTC_ISR`` to enter Initialization mode

    wait until ``RTC_ISR`` / ``INITF`` is set then ready to write

    reset ``INIT`` bit of ``RTC_ISR`` to exit Initialization mode

Counter does not run in Initialization mode.



Reference
================
`RTC application note<http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/DM00025071.pdf>`_

`STM32F405xx/07xx, STM32F415xx/17xx, STM32F42xxx and STM32F43xxx Reference Manual
<http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00031020.pdf>`_