仕様と違うRTC_OSCF
投稿:2012-09-30、更新:2018-01-19
バックアップ電池がない、または、一旦外すとRTCの設定がご破算のままリセットされません。
これはシステムをリセットしてもRTCがバックアップ電池で稼働していてリセットが不要なケースがあるからです。
まあRTCを使う場合、大抵はバックアップ電池で稼働させるから便利ですよね。
ご破算だけどリセットされないRTCの現在時刻を液晶に表示させたりすると単にデタラメな時刻表示というだけではなく
時刻の進み方がとんでもない状態になります。
それは、RTCの内部レジスタもご破算になっていて、通常の時刻の進め方でなくなるためです。
もっとも派手な動作は1秒毎に1時間以上進む事態になったことがあります(苦笑)。
そこでRTCがご破算になったかどうかを判定して、ご破算のときは2012年1月1日0時0分0秒から1秒ずつ進むようにリセットをかけることにしました。
そのためにレジスタRTC_OSCFが用意されています。
ユーザマニュアルUM10360.pdfの説明を読むと、OSCの発振が失敗したときに1になるか、RTCに最初に電源が入ったときに1になります。
右端にリセット時に1になる(Reset value=1)と書いてあるのは間違いです。
早速、RTC_OSCFを利用してみました。
システム起動時にRTC_OSCFが1であればRTCのリセット動作を行うようにプログラムを組みました。
が、RTCをバックアップ電池から稼働させているのに、USB電源をオフ→オンにすると
RTC_OSCFが1になってしまいRTCをリセットしています。
その様子を動画に収めました。
2018-01-19
【この動画を削除しました】
仕様と異なる動作がメーカー販売のボードで起きてしまいました。
NXPセミコンダクターズジャパン ツイッター公式アカウントの方にご協力頂いて原因を追求していくことにしました。ありがとうございます。
以下の内容はRTC_OSCFビットが1になる話 - Tabtterとほぼ同じです。
このプログラムはLPCXpresso(LPC1768版)でRTC_OSCFビットの状態をLED2で表示します。
LPC17xxシリーズ用ユーザーマニュアルUM10360.pdfによるとVBATをバッテリーバックアップ中にVDDオフ→オンで
RTC_AUXのRTC_OSCFビットが0のままのハズです。
でも実機では1になっていますので再現プログラムを作りました。
このコードは新規プロジェクト、LPC1768、Cプロジェクトのmain.cです。
ヘッダファイルなしで内容を把握できるようペリフェラルのアドレスをべた打ちしてあります。
ユーザーマニュアル記載のアドレスと見比べながら確認してください。
ビットが0のときのテストをelse節だけ実行してLED2消灯を確認済み。
このソースで電源を入れると百発百中でLED2が点灯したままになります。
つまりRTC_OSCFビットが1になっています。
- 改造済
LPCXpresso(LPC1768版)にはVBAT周りの周辺回路に問題があり
LPC-LINK→VBAT端子間のダイオードD7(BAT60A)を外す対策を施してあります。
詳細はをご覧ください。 - LPCXpressoのシルク印刷(今もシルク印刷?)
LPCXpresso LPC1768 REV A (C)2010 www.nxp.com/lpcxpresso - LPC1768の刻印
NXP
LPC1768FBD100
SNO311.1 02
ZSD1013 - VBATバックアップ電源
CR2032(コイン型リチウム電池)
タカチの専用電池ホルダを介しLPCXpressoのピンヘッダJ6-1(GND)、J6-3(VB)にハンダ付け
電圧:3.228V(テスタ三和CD800aで測定) - VDDオフ→オンの方法
LPC-LINK(LPCXpressoの左半分)にPCのUSBケーブル接続
内蔵電源回路で3.3Vに変換後、右半分のターゲット部分へ供給 - VBATバックアップ電圧の挙動
アナログオシロスコープKENWOOD CS-4025で観測。
VDDオフ→オンの間にヒゲ、凹みなどの変動がないことを確認済。
他の電源供給と挙動を比較します。
J6-2(VIN)にアルカリ乾電池3本(4.7V)を供給して起動させました。
VIN→LPC-LINK→内蔵電源回路→3.3V→VDDというルートです。
結果はUSBと同様、LED2点灯(RTC_OSCFビットが1)でした。
USBからの電源供給に問題ありません。
D8(BAT60A)がない状態と比較します。
D8はUSB電源供給時の逆流防止用なのでD7取り外しと共に不要です。
D8を取り外して代わりに抵抗のリード線で短絡、バックアップ電池とVBATを直結しました。
結果はD8使用時と同様、LED2点灯(RTC_OSCFビットが1)でした。
D8使用に問題ありません。
無改造の1769リビジョンA版と比較します。以下「9版」と省略します。
1769版にバックアップ電源(CR2032)を接続。
LPC-LINKにUSBケーブルを差し込み、LED2が2回フラッシュ(パッパッ)を繰り返す。
1769版は下ろし立ての新品ですから、製品出荷時のプログラムが動作しました。
続いて再現プログラムをデバッガでの書き込み→実行でLED2点灯、
バックアップ電源の接続時にRTC_OSCFビットが1になり仕様通りです。
このときRTC_OSCFビットが1ですので、1を書き込んで0クリアしています。
デバッガを終了させ、実機は無限ループを継続しています。
LPC-LINKからUSBケーブルを抜き、VDDをオフ、
再度USBケーブルを差し込むと、LED2が消灯します。
VDDがオフ→オンでもRTC_OSCFビットが0のままとなりました。
1769版は仕様通りに動作しています。
これで1768版に問題があることが判明しました。
RTC_OSCFの挙動がややこしいので動画にまとめました。
2018-01-19
【この動画を削除しました】
エラッタを見てもRTC_OSCFについて書いてないから3、4、5は除外。
たぶん1ですね(笑)。
大穴で2(ぐぬぬ)。
- 私がLPCXpresso(1768版)を壊した。
- Embedded ArtistsがLPCXpresso(1768版)のエラッタを見つけて1769版で修正した。
- NXPがLPCXpresso(1768版)のエラッタを見つけて1769版で修正した。
- NXPがLPC1768にエラッタを見つけてLPC1769リリース時に修正した。
- NXPがLPC1769にエラッタを見つけてLPC1769リビジョンAリリース時に修正した。
/* =============================================================================== Name : main.c Author : Version : Copyright : Copyright (C) Description : main definition =============================================================================== */ #ifdef __USE_CMSIS #include "LPC17xx.h" #endif #include <cr_section_macros.h> #include <NXP/crp.h> // Variable to store CRP value in. Will be placed automatically // by the linker when "Enable Code Read Protect" selected. // See crp.h header for more information __CRP const unsigned int CRP_WORD = CRP_NO_CRP ; // TODO: insert other include files here // TODO: insert other definitions and declarations here #define uint32_t unsigned long int main(void) { // TODO: insert code here uint32_t *pRTC_AUX = (uint32_t *)0x4002405C; uint32_t RTC_AUX = *pRTC_AUX; // RTC_OSCFビットを見る if (0x00000010 & RTC_AUX) { //LED2を点灯させたまま //RTC_OSCFビットに1を書き込んでクリア *pRTC_AUX = 0x00000010; } else { //LED2を消灯します。 //ポート0ピン22をGPIO uint32_t *pPINSEL1 = (uint32_t *)0x4002C004; *pPINSEL1 = 0b00 << 12; //プルアップ uint32_t *pPINMODE1 = (uint32_t *)0x4002C044; *pPINMODE1 = 0b00 << 12; //ノーマルモード(オープンドレインなし) uint32_t *pPINMODE_OD0 = (uint32_t *)0x4002C068; *pPINMODE_OD0 = 0b0 << 22; //出力に切替 uint32_t *pFIO0DIR = (uint32_t *)0x2009C000; *pFIO0DIR = 0b1 << 22; //Lを出力して消灯 uint32_t *pFIO0CLR = (uint32_t *)0x2009C01C; *pFIO0CLR = 0b1 << 22; } // Enter an infinite loop, just incrementing a counter volatile static int i = 0 ; while(1) { i++ ; } return 0 ; }
このページ自体が鉄ゲタですよホントにもう(ぐすん)。