あなたの天然記念物
ホーム更新雑談Perl鉄ゲタランドナーコースガイド自転車Linuxリンク経歴連絡先

仕様と違うRTC_OSCF (2012.09.30)

RTCの自動リセットをやりたい

バックアップ電池がない、または、一旦外すとRTCの設定がご破算のままリセットされません。 これはシステムをリセットしてもRTCがバックアップ電池で稼働していてリセットが不要なケースがあるからです。 まあRTCを使う場合、大抵はバックアップ電池で稼働させるから便利ですよね。 ご破算だけどリセットされないRTCの現在時刻を液晶に表示させたりすると単にデタラメな時刻表示というだけではなく 時刻の進み方がとんでもない状態になります。 それは、RTCの内部レジスタもご破算になっていて、通常の時刻の進め方でなくなるためです。 もっとも派手な動作は1秒毎に1時間以上進む事態になったことがあります(苦笑)。 そこでRTCがご破算になったかどうかを判定して、ご破算のときは2012年1月1日0時0分0秒から1秒ずつ進むようにリセットをかけることにしました。 そのためにレジスタRTC_OSCFが用意されています。

RTC_OSCFの仕様

ユーザマニュアルUM10360.pdfの説明を読むと、OSCの発振が失敗したときに1になるか、RTCに最初に電源が入ったときに1になります。 右端にリセット時に1になる(Reset value=1)と書いてあるのは間違いです。 RTC_OSCFの仕様

リセットでRTC_OSCFが1?

早速、RTC_OSCFを利用してみました。 システム起動時にRTC_OSCFが1であればRTCのリセット動作を行うようにプログラムを組みました。 が、RTCをバックアップ電池から稼働させているのに、USB電源をオフ→オンにすると RTC_OSCFが1になってしまいRTCをリセットしています。 その様子を動画に収めました。

原因追及開始

仕様と異なる動作がメーカー販売のボードで起きてしまいました。 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版)の実機情報

  1. 改造済
     LPCXpresso(LPC1768版)にはVBAT周りの周辺回路に問題があり
     LPC-LINK→VBAT端子間のダイオードD7(BAT60A)を外す対策を施してあります。
     詳細はをご覧ください。
  2. LPCXpressoのシルク印刷(今もシルク印刷?)
     LPCXpresso LPC1768 REV A (C)2010 www.nxp.com/lpcxpresso
  3. LPC1768の刻印
     NXP
     LPC1768FBD100
     SNO311.1     02
     ZSD1013
  4. VBATバックアップ電源
     CR2032(コイン型リチウム電池)
     タカチの専用電池ホルダを介しLPCXpressoのピンヘッダJ6-1(GND)、J6-3(VB)にハンダ付け
     電圧:3.228V(テスタ三和CD800aで測定)
  5. VDDオフ→オンの方法
     LPC-LINK(LPCXpressoの左半分)にPCのUSBケーブル接続
     内蔵電源回路で3.3Vに変換後、右半分のターゲット部分へ供給
  6. VBATバックアップ電圧の挙動
     アナログオシロスコープKENWOOD CS-4025で観測。
     VDDオフ→オンの間にヒゲ、凹みなどの変動がないことを確認済。

USBからの電源供給を疑う→ハズレ

他の電源供給と挙動を比較します。 J6-2(VIN)にアルカリ乾電池3本(4.7V)を供給して起動させました。 VIN→LPC-LINK→内蔵電源回路→3.3V→VDDというルートです。 結果はUSBと同様、LED2点灯(RTC_OSCFビットが1)でした。 USBからの電源供給に問題ありません。

バックアップ電池~VBAT間のダイオードD8を疑う→ハズレ

D8(BAT60A)がない状態と比較します。 D8はUSB電源供給時の逆流防止用なのでD7取り外しと共に不要です。 D8を取り外して代わりに抵抗のリード線で短絡、バックアップ電池とVBATを直結しました。 結果はD8使用時と同様、LED2点灯(RTC_OSCFビットが1)でした。 D8使用に問題ありません。

LPCXpresso(1768版)を疑う→当たり!

無改造の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の挙動がややこしいので動画にまとめました。

LPCXpresso(1768版)に残る可能性

エラッタを見てもRTC_OSCFについて書いてないから3、4、5は除外。 たぶん1ですね(笑)。 大穴で2(ぐぬぬ)。
  1. 私がLPCXpresso(1768版)を壊した。
  2. Embedded ArtistsがLPCXpresso(1768版)のエラッタを見つけて1769版で修正した。
  3. NXPがLPCXpresso(1768版)のエラッタを見つけて1769版で修正した。
  4. NXPがLPC1768にエラッタを見つけてLPC1769リリース時に修正した。
  5. NXPがLPC1769にエラッタを見つけてLPC1769リビジョンAリリース時に修正した。
なお、今後調査できるのは、2について1768版と1769版の回路図を比較する程度です。

プログラム

/*
===============================================================================
 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 ;
}

今回の鉄ゲタは…

このページ自体が鉄ゲタですよホントにもう(ぐすん)。