最適な出力のために、Google Chrome(15以降)または Microsoft Edge(79以降)を推奨いたします。
2025-08-08 現在 TWENET リファレンス MWX や TWELITE APPS を支える下層のライブラリ群
TWENETライブラリの情報です。内部開発向けの資料が含まれます。
通常のAct開発 においては、多くの場合、参照する必要はございません。
内部開発向けの情報が含まれており、通常の開発の利用には推奨しない場合があります。 一部開発中の情報も含まれます。 一般開発向けで参照すべき情報一覧 一般開発向けで参照する可能性のある資料を列挙します。
Act (MWX C++ ライブラリ) による開発 Act (MWXライブラリ)の開発では以下を参照してください。
TWENET C (C言語) による開発 TWENET C (C言語) による、半導体メーカ提供の API および TWENET ライブラリを用いた開発です。多くも TWELITE Apps は、TWENET C で記述されています。
その他ライブラリについて 1 - TWENETmcu - マイコンライブラリ マイコンの基本的な動作を支えるライブラリ
マイコンの基本的な動作のためのソースコードが含まれます。
TWENETmcu - マイコンライブラリ
TWENETmcu は TWELITE GOLD 向けの解説です。
マイコンの基本的な動作のためのソースコードが含まれます。多くのコードは JN5189 向け SDK からコピーされたもので、これを TWENET 向けに一部調整しています。また、始動時の関数 main()
, WarmMain()
が含まれ、この中で TWENET を動作させています。
board - ハードウェアの初期化 (クロック・GPIO ピンなど初期化手続き) component - 比較的上位機能を提供する諸ライブラリ群 (SDK_X.Y.Z/components, middleware などから) framework - 比較的上位機能を提供する諸ライブラリ群 (SDK_X.Y.Z/middleware/wireless/framework から) device, startup - JN5189 向けHAL層 drivers - ペリフェラル手続きのための FSL ライブラリ他 libs - ライブラリファイル(libXXX.a) main - main() や デバッグ向けの出力処理を行う _putchar() など printf - printf() ライブラリ (NewLibのものは使わない) uMac - MMAC.h を格納 utilities - assert() やデバッグ PRINTF() など 技術資料 TWENETの実装に関する事項や、アプリケーションプログラム作成上留意すべき事項を記載します。
1.1 - マイコンについて マイコンについて
TWELITE GOLD のマイコンの留意点です。
マイコンについて TWELITE GOLDで使用されるマイコンはARM CortexM4コアでIEEE802.15.4を備えています。TWELITE BLUE/REDではOpenRISCコアを用いており全く違うマイコンで、いくつか留意する必要があります。
※ 特に仕様面で注意を払う内容を記載していますが、お客様が作成するシステムやハードウェア要件によっては、さらに深い情報が必要になる場合があります。詳しくはNXP JN5189データシートを参照してください。
本書の記述について 本書は TWELITE BLUE/RED での利用との相違点を主に記述していますが、JN5189 データシートを一次資料として参照ください。 ピン番号を表現する場合 PIO と表記する場合はマイコン本来での番号、DIO/DOと表記する場合は TWELITE BLUE/RED で使用されるピン名を表現します。文脈によりADC1,ADC2も同様です。 アプリケーションの移植を円滑にするため「AHIサブセット」ライブラリを提供します。このライブラリは、当社が実装する一部のアプリケーションの移植を目的としています。そのため TWELITE BLUE/RED 上の API との振る舞いは、異なる場合があります。 マイコンの相違点 TWELITE BLUE/RED はビッグエンディアンですが TWELITE GOLD はリトルエンディアンです。 ARM CortexM4はクロックは柔軟に構成できるアーキテクチャですが、原則としてマイコンの動作クロックは12MHz/32MHz/48Mhzで、IO(PWMなど)は32Mhzで動作します。TWELITE BLUE/REDは、マイコンの主要クロックは16Mhz/32MhzでIOは16Mhzです。 ピンごとのGPIO割り込みの利用には制限があります。GINT(グループ割り込み)を用い、各ピンが変化したときに割り込みが発生させることができます。AHIサブセットで実装しています。当社製アプリコードの移植を目的としているため、網羅的な実装は行わず、また、一部仕様や振る舞いが異なる場合があります。 GINTでの実装では、割り込みの発生は常に両エッジです。例えば、立ち下がりエッジに設定したいピンがあって初期状態がLOとします。ピンの状態がLO->HI->LOと遷移した場合、LO->HIGH, HIGH->LO両方について割り込みが発生します。 マイコン稼働中はAHIサブセットにより前者は抑制しますが、スリープ起床に用いる場合はソフトウェアによる抑制は行えず、LO->HIGHの遷移が起きたタイミングで起床します。 反対にTWELITE BLUE/REDでは出来なかった両エッジの検出が可能で、AHIサブセットにも反映しています(vAHI_DioInterruptEdge()
, vAHI_DioWakeEdge()
)。 ピンごとの割り込み機能として PINT 機能があります。PINT で使用できるピンの上限数が決まっています。AHIサブセットでは未使用の機能で併用にあたっての特別な手続きはありません。 マイコンの機能 RTCを内蔵しています。TWELITE BLUE/REDは外部オシレータなどを接続しタイマーを高精度化できましたが、TWELITE GOLDでは32Khzオシレータを内蔵しRTC機能を有しています。 浮動小数点演算のための回路は含まれません 。従前どおりソフトウェアライブラリによる計算です。ただし、Cortex-M4には固定小数点演算を用いるDSP機能がありますので、こちらを利用することも選択肢です。 モジュールの相違点 TWELITE RED/BLUEではDIO20ピンに加えSPI専用2ピン・アナログ専用2ピンの合計24ピンありましたが、TWELITE GOLDではディジタル専用ピン16ピン、ディジタルアナログ共用ピン6ピンの22ピンです。このため、TWELITE GOLDでは2ピンが共用となっています。PIO0はDO0(SPICLK)とDIO11と共用です。 PIO14はADC2(Vref)とDIO8は共用です。AHIサブセットでは、DIO8を利用する前にディジタルポートに設定する必要があります。 TWELITE BLUE/REDのDIOピンはリセット時にハイインピーダンス・プルアップとなっていましたが、TWELITE GOLDではピンごとに状態が違います。AHIサブセットでは初期化時に DIO0..19 DO0,1 は入力、プルアップに、ADC1,2 はアナログ入力としています。 取り扱いに注意を要するピン 詳細は JN518x データシートを参照してください。
PIO=5 (ISP_ENTRY) : TWELITE BLUE/RED同様、リセット時にLOW状態になるとファームウェア書き込みなどを行うモードになります。 PIO=4 (ISE_SEL) : ISP_ENTRY 有効時に、その後の振る舞いが変更されます。ファームウェア書き込み時にはHIGHレベルにしないとファームウェア書き込みが実施できません。 PIO=10,11: 主にI2Cの利用を想定しているため、他でGPIOで利用できるピンと異なります。具体的にはプルアップ・ダウンの設定がないなどです。 ペリフェラルについて TWENETmwf(ペリフェラルて手続きで主要機能を整理), TWENETcmpt ライブラリ(AHIを用いたコードの移植を目的)の資料を参照ください。
1.2 - 始動関数 main(), WarmMain() 始動関数 main(), WarmMain()
ファームウェアの始動関数について記述しています。
TWENETmcu のコードは MCUXpresso が持つ機能 Pins, Clocks, Peripherals などには互換性が無く、これらツールによる変更などは出来ません。
始動関数 main(), WarmMain() 本ドキュメントではTWELITE GOLDでのファームウェアの始動関数およびコールバック関数について記述しています。
main(), WarmMain() TWELITE GOLDではファームウェアはmain()
関数から開始します。また、スリープの復帰はWarmMain()
から行われます。これら関数はweak
指定されているためユーザーが独自に定義することも可能です。
__attribute__((weak)) int main(void );
__attribute((weak)) void WarmMain(void );
int main (void ) {
ToCoNet_vInit_Cold_Pre();
ToCoNet_vBoard_Init(FALSE);
ToCoNet_vInit_Cold(0 , 0 );
ToCoNet_vMain(NULL);
}
void WarmMain (void )
{
vAHI_OnWakeup_MW(FALSE);
ToCoNet_vInit_Warm_Pre();
ToCoNet_vBoard_Init(TRUE);
ToCoNet_vInit_Warm(0 );
ToCoNet_vMain(NULL);
}
// source/twenet_main.c
コールドブート(電源投入・リセット)時の呼び出しフロー
main()
ToCoNet_vInit_Cold_Pre() <= メモリ初期化
TWENET C:cbAppColdStart(FALSE), MWX:init_cold()の呼び出し
ToCoNet_vBoard_Init(FALSE)
vAHI_RegEvMgr_MW() <= mwfライブラリの初期化
BOARD_InitBootPins()
BOARD_InitPins() <= この関数で各ピンの初期化
BOARD_BootClockRUN() <= クロックの初期化
vAHI_FRWTStart_MW() <= FRWT(WTIMER)の開始
G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
<= オンチップの温度センサーの取得準備
GPIO_PortInit() <= GPIO の初期化
checkIrqPending() <= 割り込み状態のクリア
AES_Init() <= AES 暗号化の初期化
__enable_irq() <= 割り込み開始
ToCoNet_vInit_Cold() <= TWENET の初期化
TWENET C:cbAppColdStart(TRUE), MWX:setup()の呼び出し
ToCoNet_vMain() <= TWENET メインループ
ウォームブート(RAM保持スリープ復帰)時の呼び出しフロー
WarmMain()
vAHI_OnWakeup_MW(FALSE) <= 復帰直後のペリフェラル処理
ToCoNet_vInit_Warm_Pre() <= TWENET C:cbAppWarmStart(FALSE), MWX:init_warm() の呼び出し
ToCoNet_vBoard_Init(TRUE)
BOARD_BootClockRUN() <= クロックの初期化
vAHI_FRWTSetBootCount_MW() <= FRWT(WTIMER)の起床時カウント保存
G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
<= オンチップの温度センサーの取得準備
GPIO_PortInit() <= GPIO の初期化
vAHI_OnWakeup_MW() <= 起床時の処理
checkIrqPending() <= 割り込み状態のクリア
AES_Init() <= AES 暗号化の初期化
__enable_irq(); <= 割り込み開始
ToCoNet_vInit_Warm() <= TWENET の初期化
TWENET C:cbAppWarmStart(TRUE), MWX:wakeup()の呼び出し
ToCoNet_vMain() <= TWENET メインループ
RAM OFF スリープ起床時の呼び出しフロー
main()
vAHI_OnWakeupRamOff_MW(FALSE) <= ペリフェラル処理(DIO状態の確認)
ToCoNet_vInit_Cold_Pre() <= メモリ初期化
TWENET C:cbAppColdStart(FALSE), MWX:init_cold()の呼び出し
ToCoNet_vBoard_Init(FALSE)
vAHI_RegEvMgr_MW() <= mwfライブラリの初期化
BOARD_BootClockRUN() <= クロックの初期化
vAHI_FRWTStart_MW() <= FRWT(WTIMER)の開始
G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
<= オンチップの温度センサーの取得準備
GPIO_PortInit() <= GPIO の初期化
vAHI_OnWakeupRamOff_MW(TRUE) <= ペリフェラル処理 (GPIO RETENTIONのリリース)
checkIrqPending() <= 割り込み状態のクリア
AES_Init() <= AES 暗号化の初期化
__enable_irq() <= 割り込み開始
ToCoNet_vInit_Cold() <= TWENET の初期化
TWENET C:cbAppColdStart(TRUE), MWX:setup()の呼び出し
ToCoNet_vMain() <= TWENET メインループ
ToCoNet_vBoard_Init(bool_t)
__attribute__((weak)) void ToCoNet_vBoard_Init(bool_t bWarm);
// source/twenet_main.c
この関数では、始動時のハードウェアの初期化を行います。weak指定されているためユーザ独自の初期化手続きを記述できます。詳細はソースコードtwenet_main.c
を参照してください。
これら一連の初期化については MCUXpresso でのプロジェクトウィザードが出力するプロジェクトに対して必要な修正を行っています。関数の構造などについては SDK 資料などを参考にコードを読み下して下さい。
独自のハードウェア初期化を行う場合もこの部分を書き換えることになりますが、動作に対してセンシティブな部分ですので、慎重な修正と十分な検証が求められます。
ToCoNet_vInitCold(uint32)
void ToCoNet_vInit_Cold(uint32 flag, uint32 u32SysHz)
TWENETの初期化手続きを行います。
パラメータ 内容 flag 起動時指定です。通常は0
を指定してください。 u32SysHz SysTickタイマーの周波数を指定します。通常は0
を指定します。 必要に応じて1000の倍数で指定します。
ToCoNet_vInit_Warm()
void ToCoNet_vInit_Warm(uint32 flag)
スリープ復帰時のTWENET初期化手続きを行います。
パラメータ 内容 flag 起動時指定です。通常は0
を指定してください。
ToCoNet_vMain()
void ToCoNet_vMain(PR_TOCONET_MAIN_HOOK fp_hook)
TWENETのメインループです。
checkIrqPending()
static bool_t checkIrqPending ();
uint64_t g_twenet_irq_bm_on_boot;
WEAK bool_t __twenet_irq_handler_pending_on_boot (int32_t );
スリープ中または起床後本関数が呼び出されるまでに発生した割り込み情報を保存及びクリアする関数です。
g_twenet_irq_bm_on_boot
の各ビットは、割り込み源 (IRQ_Type
) に対応します(1uul << IRQ_Type)
。割り込みの種別はJN5189.h
に定義されるtypedef enum IRQn
を参照します。 割り込みのクリアは、NVIC_ClearPendingIRQ()
を呼び出します。 __twenet_irq_handler_pending_on_boot(int32_t IRQ_Type)
関数をユーザが定義した場合、IRQ_Type
の割り込みが有効な場合、本関数が呼び出されます。本関数の戻り値を FALSE
とした場合、NVIC_ClearPendingIRQ(IRQ_Type)
を実行します。TRUE
の場合は何もしません。システムのタイマー周期について SysTickタイマー周期は以下の方法で設定できます。
ToCoNet_vInitCold()
関数で設定する。この設定が優先される。
G_TWENET_SYSTICK_HZ()
をcbAppColdStart(FALSE)
中で設定する。
上記2方法の設定を行わない場合はsToCoNet_AppContext.u16TickHz
の値が採用される。
以下に留意してください。
TWENETの処理周期(sToCoNet_AppContext.u16TickHz
)は最大1000Hz。SysTickの周期はsToCoNet_AppContext.u16TickHz
の整数倍。 標準的な設定はSysTick=1000Hz, sToCoNet_AppContext.u16TickHz
=1000Hz。準標準として SysTick=2000Hz または 4000Hz、sToCoNet_AppContext.u16TickHz
=1000Hz。一部(UART)のバックグラウンド処理をTWENETの周期外で実施し、負荷の分散を図ります。またより速いSysTickタイマー割り込みを用いた処理を行う (参照 AppQAPI_SysTick_Hnd_Reg()
)。 準標準として SysTick=250hz、sToCoNet_AppContext.u16TickHz
=250Hz。無線パケットの1パケットあたりの時間が2-5ms程度(変調したときの伝送時間やパケット間の隙間時間)であるため。省電力やタイマーごとの処理が重い場合の設定です。 準標準での各APIや当社製アプリケーションの動作確認は実施しません。必要な場合は十分な検証を行ってください。 初期化 G_TWENET_B_MAC_ALWAYS_RESET_ON_WAKE()
bool_t G_TWENET_B_MAC_ALWAYS_RESET_ON_WAKE()
// マクロ定義
本変数を 1
に設定することでスリープ起床時に MAC 層を再初期化します。再初期化には余分に処理時間がかかります(約400usec@32MHz)。
本オプションを設定しても、スリープ前の処理(MAC層の状態保存、約100usec@32MHz)はオプション非設定時と同様に実行されます。 1.3 - RAMの割当 RAMの割当
RAMの割当について記述しています。
MCUXpresso の C/C++ Build>MCU Settings の諸機能とは互換性がありません。RAMの割り当てについて変更などを行う場合は、リンカスクリプトのユーザ定義を記述する、または、TWENETmcs/linker/linkscripts
以下のリンカスクリプトを変更します。
RAMの割当 TWWLIET GOLD の SRAM 領域は以下のようになっています。
BASE TOP(末尾+1) SIZE SRAM11 0x0402_C000
0x0403_0000
16KB SRAM10 0x0402_8000
0x0402_C000
16KB SRAM9 0x0402_4000
0x0402_8000
16KB SRAM8 0x0402_0000
0x0402_4000
16KB SRAM7 0x0401_5000
0x0401_6000
4KB SRAM6 0x0401_4000
0x0401_5000
4KB SRAM5 0x0401_2000
0x0401_4000
8KB SRAM4 0x0401_0000
0x0401_2000
8KB SRAM3 0x0400_C000
0x0401_0000
16KB SRAM2 0x0400_8000
0x0400_C000
16KB SRAM1 0x0400_4000
0x0400_8000
16KB SRAM0 0x0400_0000
0x0400_4000
16KB
TWENET ではメモリマップを以下のように定義しています。
BASE TOP サイズ 用途 RET バンク名 アプリケーション利用 0x0400_0000
コンパイル時に決定 ~64KB MMACのリンク時に必要 〇 SRAM0..3 ヒープ 0x0401_5000
(変更可)0x0401_5C00
3KB ヒープ領域 (malloc, new) 〇 SRAM7 未使用 0x0402_0000
0x0402_C000
48KB 未使用領域 SRAM8,9,10 SRAM11 未使用 0x0402_C000
0x0402_F000
12KB 未使用領域 SRAM11 スタック 0x0402_F000
0x0403_0000
4KB スタック領域 SRAM11
(BASE: 開始アドレス, TOP: 終了アドレス+1, RET: スリープ時のRAM保持)
アプリケーション利用領域は、コンパイル時に決まる静的なメモリ範囲です。末尾アドレスは(uint32)&_end_fw_retention
にて参照できます。スリープ時には末尾アドレスをもとに不要なバンクを保持しないように設定してます。 ヒープ領域は、 malloc()
や new
演算子で確保される領域です。一般論として領域補確保・解放を繰り返すと断片化が問題になり、これを意識してアプリケーションの実装を行います。規定ではメモリの割り当てをSRAMのバンク7としています。ただし、バンク7の末尾512バイトはマイコン半導体の仕様で、続く512バイトはTWENETにて予約しています。この領域は App_User_Defs.ld
(build ディレクトリ直下に配置する) にHEAP_START=0x04014000;
HEAP_SIZE = 8192 - BANK7_RESERVE;
のように記述することで調整できます。HEAP_START
はヒープの開始アドレス、HEAP_SIZE
は確保サイズです。代表的な組み合わせを挙げます。0x04014000, 8192-BANK7_RESERVE(7KB, BANK6-7) 0x04012000,16384-BANK7_RESERVE(15KB, BANK5-7) 0x04010000,24576-BANK7_RESERVE(23KB, BANK4-7) 0x0,0 (最大限、つまり_end_fw_rentention
から 0x04016000-BANK7_RESERVE までの領域をHEAPに設定する) 未使用領域は、SRAM8,9,10 の各16KBです。 スタック領域は、SRAM11 の一番最後 (0x0403_0000
)から 4096 バイトを規定として確保しています。この領域はApp_User_Defs.ld
(build ディレクトリ直下に配置する) に STACK_SIZE = 8192;
のように記述すると、サイズを変更することができます。またSTACK_TOP = 0x04024000;
のように、末尾アドレスを指定できます。 build ディレクトリに作成される mapファイルの _vStackTop
__StackLimit
を確認してください。 この領域はスリープ時に保持されません。 スリープ時の保持領域の設定 アプリケーション利用領域やヒープ領域は、TWENETライブラリ内でスリープ時に保持すべきSRAMバンクを適切に設定しています。アプリケーションの設計や実装によっては、保持されないバンクを保持状態にしたい場合もあります。TWENETcmptライブラリ中に定義されるグローバル変数 G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD()
に、追加的に必要なバンクに対応するビットをセットしておきます。
例えばバンク8,9の32KBを保持したい場合は、TWENET CライブラリのToCoNet_vSleep()
や mwx ライブラリのthe_twelite.sleep()
呼び出し前に以下を指定します。
G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() = PM_CFG_SRAM_BANK8_RET | PM_CFG_SRAM_BANK9_RET;
※ 保持するSRAM領域が増えると、その分スリープ電流が増加します。
App_User_Defs.ld 設定例 未指定時は HEAP は 0x0401_5000
から0x0401_5FE0
、STACKは 0x0402_F000
から0x0403_0000
となります。以下に .../build/App_User_Defs.ld
の設定例を記載します。
HEAPを _end_fw_retention
から 0x0401_5FE0
まで最大限確保する。
HEAP_START = 0;
HEAP_SIZE = 0;
HEAP_START = 0x04014000 ;
HEAP_SIZE = 8192 - BANK7_RESERVE;
HEAPを _end_fw_retention
から 0x0401_5000
まで、STACKを0x0401_5000
から0x0401_5FE0
とする。(0x0402_0000
から0x0403_0000
のBANK8..11を未使用領域にする)
HEAP_TOP = 0x04015000;
HEAP_START = 0;
HEAP_SIZE = 0;
STACK_TOP = 0x04015fe0;
STACK_SIZE = 4096-BANK7_RESERVE;
注:HEAP_START
とHEAP_SIZE
がともに0の場合 HEAP_TOP
を設定できます。この場合 HEAP_TOP
は0x0402_0000
以上の領域には設定できません。
HEAP領域に0x0402_0000
から64KB確保しSTACK領域は0x04015fe0
以下の領域に移動する。
HEAP_START = 0x04020000 ;
HEAP_SIZE = 0x10000 ;
STACK_TOP = 0x04015fe0 ;
STACK_SIZE = 4096 - BANK7_RESERVE;
OneTime_Heap.c,h TWENETutils には、メモリ破棄を行わず順番にメモリを確保するための One Time Heap を用意しています。未使用領域の利用を容易にするものです。
#include <OneTimeHeap.h>
OTHEAP_tsContext scOTHeap;
void setup () {
uint32 u32bytes;
void * p;
// 0x0402_0000 から 0x0402_4000 の 16KB 領域を利用する。
OTHEAP_Init(& scOTHeap, 0x04020000 , 0x04024000 , NULL);
Serial << crlf << "--- One Time HEAP ---" ;
Serial << crlf << format("start %08x" , (uint32)OTHEAP_pvGetRegionStart(& scOTHeap));
Serial << crlf << format("top %08x" , (uint32)OTHEAP_pvGetRegionTop(& scOTHeap));
// 100バイト確保する
u32bytes = 100 ;
Serial << crlf;
Serial << crlf << format("head %08x" , (uint32)OTHEAP_pvGetHead(& scOTHeap));
p = OTHEAP_pvAlloc(& scOTHeap, u32bytes, TRUE);
// p=0x0402_0004 (4バイトのヘッダの後が利用可能)
Serial << crlf << format("alloc %dbytes [%08x->%08x)" , u32bytes, (uint32)p, (uint32)p+ u32bytes);
if (p) Serial << crlf << format("next %08x" , * (uint32* )((uint32)p - 4 ));
// ヘッダは次のブロックのアドレス (0x0402_0068)
// 10バイト確保する (4バイト境界に配置されるため実際は12バイト)
u32bytes = 10 ;
Serial << crlf;
Serial << crlf << format("head %08x" , (uint32)OTHEAP_pvGetHead(& scOTHeap));
p = OTHEAP_pvAlloc(& scOTHeap, u32bytes, TRUE);
// p=0x0402_006c
Serial << crlf << format("alloc %dbytes [%08x->%08x)" , u32bytes, (uint32)p, (uint32)p+ u32bytes);
if (p) Serial << crlf << format("next %08x" , * (uint32* )((uint32)p - 4 ));
// ヘッダは次のブロックのアドレス (0x0402_0078)
// 最後に確保されたブロックを開放する。解放されたブロックのアドレス(p=0x0402_006c)
p = OTHEAP_pvFreeLastBlock(& scOTHeap);
}
1.4 - printf について (デバッグ, シリアル出力) printf について (デバッグ, シリアル出力)
printf について (デバッグ, シリアル出力)について記述しています。
printf について (デバッグ, シリアル出力) printfライブラリ TWENETライブラリ内で使用する printf()
処理です。詳細は TWENETmuc/printf を御覧ください。
デバッグ用の PRINTF NXP提供のfslライブラリではPRINTF()
マクロを用いてデバッグ出力を行い、リリース時はコンパイル対象から外すようになっています。TWENETライブラリでも、PRINTF()
を利用できるようにコードを調整していますが、fslライブラリの機能そのままではありません。
PRINTF()
マクロの呼び出し先は上述の printf_()
です。GETCHAR()
マクロなど入力には非対応です。JN518x SDK2.6.3,2.6.4 での NewLib, NewLibNano ではデータ出力の化けや抜けなどが見られ、適切な振る舞いをしません(バッファリングに関する問題と考えられる。RedLib では当該現象がみられないが C/C++ 混在プロジェクトでは使用できない)。このため PRINTF()
マクロを libTWENETmcu/printf 内の printf_()
関数を用いるように変更しています。
SDK_DEBUGCONSOLE 定義 SDK_DEBUGCONSOLE
の値によって振る舞いが変わります。ビルド対象のアプリケーション内の PRINTF()
の振る舞いが変更されます。
値 内容 0 デバッグコンソール(Semihost)へ出力されます(この手続は非常に低速です)。 ※ この出力を有効にするためには libTWENETmcu(Debugビルド)のSDK_DEBUGCONSOLE=0
設定を行いライブラリの再ビルドを行い、アプリケーションコード中で_putchar(-1)
を周期的(16ms程度)に呼び出す必要があります。 (サンプル Samp_bare_MMAC
中に定義された SysTick_Handler()
参照) 1 Debug ビルド時の設定です。PRINTF
はprintf_
関数(libTWENETmcu)を用います。_putchar()
の再定義を行わない場合SERIAL_bTxChar(0, c);
が呼び出されます。TWENETxxxライブラリの Debug 設定もこの値です。 2 Release ビルド時の設定です。PRINTF
はコンパイル対象から外され、またprintf_()
は何も出力しません。printf_()
を用いる場合は_putchar(int)
を再定義してください。TWENETxxxライブラリの Release 設定もこの値です。
libTWENETmcuライブラリ中の _putchar()
は weak リンク指定です。アプリケーションコード中に定義した _putchar()
が優先されます。 TWENETxxx ライブラリ中のPRINTF()
を有効にする場合は、アプリケーション内の SDK_DEBUGCOSOLE
と同じ定義を行い、ライブラリの再ビルドが必要です。 SWO について TWENETmcu/source には SWO 向けの出力コードが含まれます。この機能については正式サポートは行いませんが、コード内の記述等を以下に解説します。
ソース中は -DDEBUG
-DSERIAL_PORT_TYPE=1
の定義を行った部分が SWO 関連処理としている。この定義を行うとPRINTF()
の出力はSWOのITMに出力されるようにコード調整している (main/retarget_itm.c
, main/retarget_putchar.c
)。 SWOのポートは PIO14 としている。 SWOを有効にしてデバッグが開始しないことが多い。ISPピン(PIO5)=LO操作をデバッガ起動直前まで維持すると動作する場合がある。 2 - TWENETmwf - ペリフェラルC++ライブラリ マイコンのペリフェラルを扱うためのライブラリ
マイコンのペリフェラルを扱う手続きを C++ クラスとして、簡素化したものです。
TWENETmwf - ペリフェラルC++ライブラリ マイコンのペリフェラルを扱う手続きを C++ クラスとして、簡素化したものです。
定義済みオブジェクトが用意されており(例mwf::the_i2c0
はI2C0)、このオブジェクト経由で機能にアクセスします。定義済みオブジェクトはstd::unique_ptr<>
によるスマートポインタで、初回の初期化により実体を構築します。
このライブラリでは定義済みオブジェクトは、スリープ前、スリープ復帰時の手続きが含まれ、一括してスリープ前処理、復帰処理を行うことが出来ます。
ペリフェラルオブジェクトについて ペリフェラルの多くは、初期化などの手続きが一体になっています。そのため、クラスオブジェクトとして、その生成から破棄までを管理します。
クラスオブジェクトは、全て std::unique_ptr<>
によるスマートポインタになっています。オブジェクトの生成前は nullptr
になっているため、いかなるアクセスも行えません(おそらくヌルポインタアクセスによりハングアップします)。利用時には nullptr
のチェックを挟むようにしてください。
if (the_adc) { // nullptr チェックをしてから
the_adc-> enable((1UL << 0 ) | (1UL << 1 ));
the_adc-> start();
}
定義済みのペリフェラルクラスオブジェクト オブジェクト名 説明 the_adc
アナログディジタル変換(ADC)を利用する the_gpio
汎用IO(GPIO)割り込みを利用する。(割り込みを利用しない場合はクラスオブジェクトは利用しません) the_i2c0
I2Cバスを利用する。(I2C0のみ) the_ntag
NTAG用のEEPROMを利用する the_pwm[0..9]
PWM0..9を利用する the_rng
乱数生成ライブラリ the_spi1
SPIバスを利用する (SPI1のみ) the_wtimer
ウェイクアップタイマーを利用する the_wwdt
ウォッチドッグタイマーを利用する
ライブラリについて 名前空間について 原則として、以下の名前空間にクラスや関数を定義しています。
2.1 - mwf_common mwf 共通定義
共通定義やペリフェラル用のクラスのための基底クラスを定義する。
mwf_common 共通定義やペリフェラル用のクラスのための基底クラスを定義する。
マクロ BEGIN_CRITICAL, END_CRITICAL (割込み禁止)
#define BEGIN_CRITICAL { uint32_t __TWENET_regPrimask = DisableGlobalIRQ();
#define END_CRITICAL() EnableGlobalIRQ(__TWENET_regPrimask); }
// 例
extern volatile int critical_value;
void some_func () {
...
// 以下はクリティカルセクション
BEGIN_CRITICAL
{
critical_value++ ;
}
END_CRITICAL ();
}
割込み禁止区間を設定するためのマクロです。DisableGlobalIRQ()
, EnableGlobalIRQ()
を呼び出すだけのマクロですが、ローカル変数を定義する必要があるなど、記述が煩雑に見えるため do {…} while() 構文に似せたマクロを定義しています。
上記例では、割り込みハンドラなどで変更しうる値 critical_value
がある場合に、アプリケーション処理内でその値を安全に更新するための手続きです。
※ このマクロは C++ コードのみで使用できます。
定数・列挙体など enum class ID_SYSHAND ペリフェラルクラスオブジェクトを識別するための ID を定義しています。
class sys_ev_handler スリープとスリープ復帰時の手続きを共通化するためのインタフェース定義を行う上位(抽象)クラス。
on_sleep() ペリフェラルのスリープ前の手続きを記述する。
on_wakeup(bool init_2nd) スリープ復帰時に、スリープ前の状態に復帰するためのペリフェラルの手続きを記述する。この関数は2回呼び出されることを想定しています。
init_end
がfalse の場合は、起床後ごく初期の段階で呼び出されます。主に変数の初期化などを行いますが、デバイスなどの再初期化などはここでは行いません。true で呼び出された2回目で。デバイスの再初期化などを行い、スリープ前の状態に復元します。
TWENETでは vAHI_OnWakeup_MW()
の呼び出し中に処理されます。以下のような呼び出し順になります。詳細は TWENETmcu の twenet_main.c
を参照してください。
WarmMain()
関数の呼び出し (スリープ復帰時に最初に呼び出される関数)vAHI_OnWakeup_MW(FALSE)
ここで mwf ライブラリオブジェクトの on_wakeup(false)
が呼び出される ToCoNet_vInit_Warm_Pre()
cbAppWarmStart(FALSE)
(mwxでは init_warm()
)ToCoNet_vBoard_Init()
無線マイコンのハードウェアの初期化(クロックなど) vAHI_OnWakeup_MW(TRUE)
ここで mwf ライブラリオブジェクトの on_wakeup(true)
が呼び出される ToCoNet_vInit_Warm()
cbAppWarmStart(TRUE)
(mwx では setup()
)TWENET初期化 TWENETアプリケーションループ class sys_global_resource_handler I2C, PWMなど同一機能が複数単位定義される場合に、初期化と破棄の手続きを管理する上位クラス。
これら複数利用可能なペリフェラルでは一度だけ初期化の際に行う手続きと、全て利用終了してから破棄する手続きが存在する場合に利用する。(左記のペリフェラルであっても、実装状況に応じて本クラスを利用したりしない場合がある)
初期化と破棄の手続きは、オブジェクトが生成・破棄されるたびに更新される参照カウンタ(コンストラクタより渡す)により行う。
※ sys_ev_handler は抽象クラスだが、本クラスは CRTP を用いている。
init() 参照カウンタが1
になったとき(=初期化が必要な場合)に T::global_init()
を呼び出す。
※ このメンバ関数はペリフェラルクラスのコンストラクタから明示的に呼び出すこと。
deinit() 参照カウンタが0
になったとき T::global_deinit()
を呼び出す。
※ このメンバ関数はペリフェラルクラスのデストラクタから明示的に呼び出すこと。
class sys_ev_manager ペリフェラルクラスオブジェクトを一括管理するためのコレクションクラス。ただし、オブジェクトの所有はせず、sys_ev_handler
クラスポインタを格納する固定配列にID_SYSHAND
列挙体が示すIDをインデックスとして格納する。
主目的はon_sleep()
, on_wake()
の手続きを一括で行うためである。
どのペリフェラルクラスオブジェクトが生成されるかはユーザプログラム次第であるため、すべてのクラスオブジェクトに対して if(the_pwm1) the_pwm1->on_sleep();
といった呼び出しは余分なコードをリンクすることにもなり非効率である。sys_ev_handler
型の抽象オブジェクトとして格納し、virtual
メソッドを呼び出している。
global_init_sysevmgr() the_sys_ev_manager
インスタンスを生成する。
global_deinit_sysevmgr() the_sys_ev_manager
インスタンスを破棄する。
reg_obj() ペリフェラルクラスオブジェクトを登録する。
unreg_obj() ペリフェラルクラスオブジェクトを登録から除外する。
on_wakeup(bool init_2nd) 登録オブジェクトに全てに対し、on_wake()
を実行する。
void on_sleep() 登録オブジェクトに全てに対し、on_sleep()
を実行する。
ペリフェラルクラスの定義例
class timer_n_pwm :
public mwf:: sys_ev_handler // 基底クラス
, public mwf:: sys_global_resource_handler< timer_n_pwm> // 基底クラス(必要な場合のみ)
{
using global_hdr = mwf:: sys_global_resource_handler< timer_n_pwm> ;
// 長いので省略形を定義しておく
static uint32_t _global_init_ct;
// sys_global_resource_handlerの参照カウンタ
public :
static void global_init_pwm(uint8_t u8_pwm_id, ...) { ... }
static void global_deinit_pwm_manager (uint8_t u8_pwm_id) { ... }
// the_pwm? の実体を生成・破棄するための手続き。
public :
// コンストラクタ
timer_n_pwm(/* コンストラクタ引数 */ )
: mwf:: sys_ev_handler(/*ID*/ ,static_cast < sys_ev_handler*> (this ))
, mwf:: sys_global_resource_handler< timer_n_pwm> (_global_init_ct)
{
global_hdr:: init(); // sys_global_resource_handler<>の生成手続き
}
// デストラクタ (抽象クラスを継承しているため virtual 定義する)
virtual ~ timer_n_pwm()
{
global_hdr:: deinit(); // sys_global_resource_handler<>の破棄手続き
}
// sys_ev_handlerクラスの実装
virtual void on_sleep () { ... } // スリープ前に呼び出す
virtual void on_wakeup () { ... } // スリープ復帰後に呼び出す
// sys_global_resource_handler<>の実装。staticメンバ関数。
static void global_init (); // 一番最初の初期化手続き
static void global_deinit (); // 一番最後の破棄手続き
};
...
uint32_t mwf:: periph:: timer_n_pwm:: _global_init_ct; // 参照カウンタの実体
上記は PWM (mwf_periph_pwm.hpp
) ペリフェラルクラスの定義抜粋です。他の殆どのクラスではsys_global_resource_handler<>
を利用していません。
2.2 - mwf_periph_common - ペリフェラル共通 mwf_periph_common - ペリフェラル共通
ペリフェラル共通定義やピン操作の定義。
mwf_periph_common - ペリフェラル共通 include
#include "mwf_periph_common.hpp"
GPIO操作関数 struct pin 内に定義する static 関数(インライン関数)を呼び出します。
static void set_pin_as_input(uint8_t pin, uint32_t param = 0 )
pin
を入力状態に設定します。
set_pin_as_output()
static void set_pin_as_output(uint8_t pin, uint32_t param = PORTOUT_INITSTATE_HIGH)
pin
を出力状態に設定します。
param
はPORTOUT_INITSTATE_HIGH
を指定すると、本関数の呼び出し時にHIGH側に設定されます。set_output()
void set_output(uint8_t pin, uint8_t value)
pin
の出力状態を変更します。value
をPORT_HIGH
(1)にするとHIGH、PORT_LOW
(0)にするとLOWにします。
static uint8_t get_input(uint8_t pin)
入力状態にあるpin
の状態を読み出します。戻り値はHIGHの場合はPORT_HIGH
(1)、LOWの場合はPORT_LOW
(0)です。
static uint32_t get_input_bm (uint32_t u32mask = 0x3FFFFF )
// 例
uint32_t bm = get_input_bm((1ul << 0 ) | (1ul << 3 ));
if (bm & (1ul << 3 )) { ... } // PIO3 が HIGH の場合
else { ... } // PIO3 が LOW の場合
全ピンの入力状態をビットマップで読み出します。
PIOn の値は (1UL « n ) のビットに対応します。 入力状態にないピンの値は未定義です。 例ではピンのビットマップ(u32mask
)を指定し、入力ピンの状態をまとめて取得します。ビットマップは、例えば PIO0 と PIO3 の値が必要な場合は (1ul << 0) | (1ul << 3)
と指定します。
戻り値も同様に入力状態のビットマップです。HIGHレベルが1
、LOWレベルが0
で表現します。例えば PIO3 が HIGH の場合は LSB から数えて4番目のビットが 1 になります。
set_output_bm()
static void set_output_bm (uint32_t u32mask, uint8_t value)
// 例
set_output_bm((1ul << 0 ) | (1ul << 3 ), 0 ); // PIO0, 3 を LOW レベルに設定する
u32mask
で指定したビットマップに対応するピンについて出力状態を変更する。
PIOn の値は (1UL « n ) のビットに対応します。 value
をPORT_HIGH
(1)にするとHIGH、PORT_LOW
(0)にするとLOWにします。例ではピンのビットマップ(u32mask
)を指定し、出力の状態をまとめて設定します。ビットマップは、例えば PIO0 と PIO3 を設定する場合は (1ul << 0) | (1ul << 3)
と指定します。また出力状態value
は1
がHIGHレベル、0
がLOWレベルです。
PIN操作関数 struct pin 内に定義する static 関数(インライン関数)を呼び出します。
static void __conf_digital()
static void __conf_digital(uint8_t pin, uint8_t func)
指定したピンpin
のPIOレジスタに対してIOCON_PIO_FUNC(func)
を設定します。
IOCON-> PIO[0 ][pin] =
( 0
| IOCON_PIO_FUNC(func) // SETFUNC (e.g. PWM is 0x04)
| IOCON_PIO_MODE(0x00u ) // 0x00:pullup
| IOCON_PIO_DIGIMODE(0x01u )
| IOCON_PIO_INPFILT_OFF
);
static void conf_default()
static void conf_default(uint8_t pin)
ピンをデフォルト定義に戻します。TWENETmcu ライブラリ中の board/pin_mux.c で設定した値にします。
static void __conf_gpio_input(uint8_t pin)
内部的に使用します。ピンpin
を GPIO の入力とします。
※ ユーザプログラムでは set_pin_as_input()
を使用します。
static void __conf_gpio_output()
static void __conf_gpio_output(uint8_t pin, bool b_init_high = true)
内部的に使用します。ピンpin
をGPIOの出力とします。b_init_high
をtrue にすると規定出力がHIGH(Vcc)レベル、false ならLOW(GND)レベルです。
※ ユーザプログラムでは set_pin_as_output()
を使用します。
static void set_pullup()
static void set_pullup(uint8_t pin, uint8_t mode)
指定したピンpin
のPIOレジスタに対してIOCON_PIO_MODE(mode)
を設定します。プルアップの制御のビットです。
static void conf_pwmout()
static void conf_pwmout(uint8_t pin, bool b_enable)
__conf_digital()
を用い、指定したピンpin
のPIOレジスタに対してIOCON_PIO_FUNC(0x04)
を設定します。通常はPWM出力に設定されます。
static void conf_adc_input(uint8_t pin)
PIO14..19に対してADCに設定するため以下の指定を行います。
IOCON-> PIO[0 ][pin] =
( 0
| IOCON_PIO_FUNC(0x00u ) // FUNC_ALT0
| IOCON_PIO_MODE(0x00u ) // 0x00:pullup
| IOCON_PIO_DIGIMODE(0x00u ) // ANALOGUE
| IOCON_PIO_INPFILT_OFF
);
static void conf_sclN _pioM ()
static void conf_scl0_pio10 () {
__conf_digital(10 , 0x05 );
}
static void conf_sda0_pio11 () {
__conf_digital(11 , 0x05 );
}
static void conf_scl0_pio15 () {
__conf_digital(15 , 0x05 );
}
static void conf_sda0_pio16 () {
__conf_digital(11 , 0x05 );
}
static void conf_scl1_pio06 () {
__conf_digital(06 , 0x05 );
}
static void conf_sda1_pio07 () {
__conf_digital(07 , 0x05 );
}
static void conf_scl1_pio12 () {
__conf_digital(12 , 0x05 );
}
static void conf_sda1_pio13 () {
__conf_digital(13 , 0x05 );
}
ピンをI2Cで利用するための設定関数です。
static void conf_uart1(uint8_t tx, uint8_t rx)
static void conf_uart1(uint8_t tx, uint8_t rx)
UART1のTXDピンをtx
に、RXDピンをrx
に指定します。
本関数では、TXD または RDX の一方のみを設定することはできません。 その他 struct ts_retention_context
struct ts_retention_context {
uint32_t u32_bm_io;
uint32_t u32_bm_set;
void save ();
void restore ();
};
static ts_retention_context s_retention_context;
static void retention_on_sleep()
static void retention_on_wake()
内部的に利用します。GPIO出力状態のスリープ時の保持に関する処理と必要なデータを管理します。
static bool __b_check_swdbg_port(uint8_t pin)
static bool __b_check_swdbg_port(uint8_t pin)
内部的に利用します。pin
がデバッグ時に、デバッガで使用されるかどうかを判定します。
スリープ時のふるまい GPIO の出力状態を set_pin_as_output()
による手続きを行ったピンについて、スリープ時にも出力状態が維持されます。ただし retention_on_sleep()
並びに retention_on_wake()
が適切に呼び出される必要があります。TWENETでは、TWENETmcu,TWENETcmptライブラリ内で処理されるスリープ前処理、スリープ復帰処理でこれらが呼び出されています。 2.3 - mwf_periph_adc - ADC mwf_periph_adc - ADC
アナログディジタル変換(ADC)を利用するための手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_adc - ADC アナログディジタル変換(ADC)を利用するための手続きをまとめたペリフェラルオブジェクトです。
コード例 以下の例では mwf::
名前空間を明示的に指定しています。省略する場合は using namespape mwf;
を記述してください。
#include "mwf_periph_adc.hpp"
// the_adc クラスオブジェクトの生成
mwf:: the_adc-> global_init_adc_manager();
// ADCの入力ピンを指定
mwf:: pin:: conf_adc_input(14 );
mwf:: pin:: conf_adc_input(15 );
// 初期化
mwf:: the_adc-> init();
// チャネルの指定
mwf:: the_adc-> enable(
(1ul << mwf:: adc:: CH_0)
| (1ul << mwf:: adc:: CH_1)
| (1ul << mwf:: adc:: CH_VCC));
// ADC 開始
mwf:: the_adc-> start(); // ワンショット
while (! mwf:: the_adc-> available()) {} // ポーリングで終了待ちを行う
// 値の取得
int16_t v_ch0 = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_0);
int16_t v_ch1 = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_1);
int16_t v_vcc = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_VCC);
// チャネルの指定
mwf:: the_adc-> enable(
(1ul << mwf:: adc:: CH_0)
| (1ul << mwf:: adc:: CH_1)
| (1ul << mwf:: adc:: CH_VCC));
// ADC 開始
mwf:: the_adc-> start(true); // 連続
// アプリケーションループ内で。
void loop () {
if (mwf:: the_adc-> available()) {
// 値の取得(周期的に実行する)
int16_t v_ch0 = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_0);
int16_t v_ch1 = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_1);
int16_t v_vcc = mwf:: the_adc-> get_value_mv(mwf:: adc:: CH_VCC);
...
}
}
int32_t i32temp;
int16_t i16volt;
// 内部センサーの電源ON、安定化待ち処理、ADCの計測処理 (1回のみ)までを実行。
mwf:: the_adc-> temp_capture(i32temp, i16volt, 0 );
// i32temp は温度℃の128倍値。i16volt はミリボルト
Serial << format("%dC %dmV" , i32temp >> 7 , i16volt);
class mwf::periph::adc the_adc クラスオブジェクトの主要定義を記載します。
定数定義
static const uint8_t CH_MAX = 7 ;
static const uint8_t CH_0 = 0 ; // ADC0
static const uint8_t CH_1 = 1 ; // ADC1
static const uint8_t CH_2 = 2 ; // ADC2
static const uint8_t CH_3 = 3 ; // ADC3
static const uint8_t CH_4 = 4 ; // ADC4
static const uint8_t CH_5 = 5 ; // ADC5
static const uint8_t CH_VCC = 6 ; // VCC
static const uint8_t CH_TEMP = 7 ; // 内部温度センサー (通常のADとは取得方法が違います)
ADCチャネルについての設定定義です。
struct config
struct config {
uint8_t prescale;
};
設定を行うための構造体。init()
のパラメータとして渡す。
prescale
: **《現バージョンでは DEFAULT_PRESCALE=6
のみに対応》**ADCの変換時間を決めるためのプリスケール値。fslライブラリで定義されるadc_config_t::clockDividerNumber
に (1ul << .prescale)
を設定し::ADC_Init()
を呼び出します。global_init_adc_manager() global_deinit_adc_manager()
static void global_init_adc_manager ();
static void global_deinit_adc_manager ();
クラスオブジェクトthe_adc
の生成と破棄を行う。
set_pin_as_adc()
static void set_pin_as_adc(uint8_t pin)
指定したピン番号pin
をADC入力にする。
init() deinit()
void init (bool b_wait_init = true);
void deinit ();
ADCを初期化します。
b_wait_init
をFALSEに設定すると、ADCの安定化の待ち時間 (300ms) を省略します。待ち時間の扱いについてはis_periph_enabled()
を参照してください。
内部温度センサー取得用に ADC を初期化または再初期化するには init_for_temp_volt()
を呼び出します。すでに init()
により初期化済みの場合は temp_capture()
を
is_periph_enabled()
bool is_periph_enabled()
void force_periph_enabled()
uint32_t get_init_freerun_tick()
ADCが初期化され必要な待ち時間を経過すると true
を戻します。
the_wtimer
で提供するFRWT(Free Running Wake Timer)が動作している場合は、is_periph_enabled()
が適切な時期までfalse
を戻します。init()
が呼び出されたときのカウント値を得るには get_init_freerun_tick()
を呼び出します。FRWTが動作していない場合は初回のis_periph_enabled()
の呼び出し時におよそ300usecの待ち時間が発生します。この待ち処理を行わないようにするためには init()
呼び出し直後にforce_periph_enabled()
を呼び出しておきます。この処理は内部状態を強制的に待ち時間が経過したものとして取り扱います。 enable()
void enable (uint32_t chmask);
ADCを動作可能な状態にします。chmask
は変換対象のチャネルのビットマスクで、ADC0 と ADC1 と VCC が対象の場合は (1ul << CH_0) | (1ul << CH_1) | (1ul << CH_VCC)
と指定します。
start() stop()
void start (bool b_cont = false);
void stop ();
enable()
実行後に start()
を実行することで、ADCを開始します。b_cont == true
とした場合は、連続変換を行います。すでにstart()
が呼び出されADCが実行中のときには、呼び出してはいけません。
連続変換時に変換を停止するには stop()
を呼び出します。
変換が終了した時点で the_adc->available()
の読み出しが true になります。
available()
変換終了後に true を戻します。true を読み出した後は再びfalse を戻します。
is_started()
start()
によりADCが実行中である場合true を戻します。
get_value()
uint16_t get_value (uint8_t ch);
ch
で指定するチャネルのAD変換値(12bit)を取得する。AD変換終了後に呼び出す。
get_value_mv()
int16_t get_value_mv (uint8_t ch);
ch
で指定するチャネルのAD変換値をmvで取得する。AD変換終了後に呼び出す。
global_init_device() global_deinit_device()
static void global_init_device ();
static void global_deinit_device ();
ハードウェアの初期化と利用終了の手続きを行う。
※ コンストラクタ、デストラクタなどから内部的に呼び出され、ユーザアプリケーションから明示的に呼び出す必要はありません。
register_callback()
typedef void (* PFN_ADC_CALLBACK)(uint32_t , uint32_t );
void register_callback(PFN_ADC_CALLBACK pfn)
割り込みハンドラ内からのコールバック関数の指定。
コールバック関数の第一パラメータは kADC_ConvSeqAInterruptFlag
, 第二パラメータは変換が行われたチャネルのビットマスクが渡されます。
温度センサー temp_capture()
bool temp_capture(
int32_t & temp128th,
int16_t & volt_mv,
uint8_t times_adc_scaler = 0 ,
bool b_power_on_temp_sensor = true)
オンチップ温度センサーの値を取得する。副次的に電源電圧も計測する。
temp128th
には、温度の計測結果を格納する変数を指定する。値は摂氏の128倍値になる。整数部は temp128th >> 7
、小数点1桁部分は (10 * temp128th) >> 7
で計算できる。volt_mv
には、電圧の計測結果を格納する変数を指定する。値はミリボルト[mV]。times_adc_scaler
には、ADCの繰り返し回数に対応するスケーラ値を指定する。0..3まで指定でき、0の場合は1回、1は2回、2は4回、3は8回のAD変換を行ったのち、値を平均化処理する。戻り値は成功時にtrue,失敗時にfalseを戻す。 暗黙に以下の処理を行います。
温度センサーがONになっていない場合は、センサーをONに設定し必要な待ち処理を行います。(temp_power_on()
参照) 実行後は温度センサーをOFFにします。 ADCの初期化(init()
)が行われていない場合は失敗します。 ADCの初期化後、デバイスが利用可能になっていない場合は、待ち処理を行います (is_periph_enabled()
参照)。 temp_get_capt_tick()
uint32_t temp_get_capt_tick()
最後に温度を取得したときの FRWT のカウンタ値を返す。
temp_power_on(), temp_power_off()
void temp_power_on()
void temp_power_off()
明示的に温度センサーのON/OFFを行う。
FRWT が有効な場合に限り、カウント値をもとに待ち時間が完了しているかを判定するため、事前にON処理を行っておくことで待ち時間を短縮できる。
temp_computation()
int32_t temp_computation(
uint16_t adcout_vbat_lsb_sum8,
uint16_t tsens_adcout_T_sum8,
uint8_t nb_samples_actual = 1 )
内部的に利用します。ADC計測値から温度を計算します。
get_ctrl0_adc_reg_context()
class ctrl0_adc_reg ;
ctrl0_adc_reg get_ctrl0_adc_reg_context (uint8_t mode, uint8_t tsamp)
//例
if (auto rc = get_ctrl0_adc_reg_context(
0x0
, 0x14
)) {
; // このスコープ内は (0x0, 0x14) の設定が有効。スコープを出ると元の値に戻す。
}
内部的に利用します。一時的に ADCの設定パラメータを変更します。
class mwf::periph::adc (sys_ev_handler) on_sleep() ADCの停止処理を行います。
on_wakeup() スリープ前に ADC が初期化されていた場合は、初期化手続き(init()
)を行います。enable()
, start()
は改めて実行する必要があります。
その他 連続モードでの動作について 変換周期はハードウェアによって決まっています。現バージョンではプリスケーラの値は固定です。
AHI, mwx での利用 AHI や mwx ライブラリの内部では mwf::the_adc
を利用していますので、直接 mwf::the_adc
を利用する場合は注意が必要です。
AHIライブラリを利用しかつ mwf::the_adc
を利用する場合は、ADCに関連する一切の手続きを呼び出さないようにしてください (vAHI_ApConfigure()
, vAHI_AdcEnable()
, vAHI_AdcStartSample()
など。App_Tweline 付属の adc.c
) mwx ライブラリを利用しかつ mwf::the_adc
を利用する場合は、Analogue
クラスオブジェクトに対して操作を行わないようにしてください(Analogue.setup()
など)。 2.4 - mwf_periph_gint - GINT(GPIO) mwf_periph_gint - GINT(GPIO)
汎用IOの入出力の設定、また GINT を用いたIO割り込みを実装しています。
mwf_periph_gint - GINT(GPIO) 汎用IOの入出力の設定、また GINT を用いたIO割り込みを実装しています。
TWENETでは、初期化、割り込み処理はTWENETライブラリ(TWENETcmpt)内で処理されます。ユーザプログラム内で本関数を呼び出すことは通常ありません。
include
#include "mwf_periph_gint.hpp"
class mwf::periph::gint the_gint
クラスオブジェクトの定義です。ピンを割り込み動作させる場合(スリープ割り込みも含む)、the_gint
クラスオブジェクトの生成が必要です。実装の詳細は後述の「GINTを用いたDIO割り込み実装」を参照してください。
global_init_gint_manager() global_deinit_gint_manager()
static void global_init_gint_manager ();
static void global_deinit_gint_manager ();
クラスオブジェクトthe_gint
の生成と破棄を行う。
init_int() deinit_int()
void init_int (tpf_gpio_int_handler pf_callback, void * p_data = nullptr );
void deinit_int ();
GPIO 割り込みの初期化を行う。割り込みハンドラ(pf_callback
と割り込みハンドラに伝達されるパラメータ(p_data
)を指定します。
GPIO 割り込みを停止するには deinit_int()
を呼びます。
pf_callback
は、以下のように定義されます。
using tpf_gpio_int_handler = void (* )(uint32_t bm_now, uint32_t bm_changed, void * p_data);
bm_now
は、現時点でのピン状態に対応するビットマップ。bm_changed
は、変更のあったピンに対応するビットマップ。p_data
は、init_int()
で指定したp_data
です。set_int_pins_bm()
void set_int_pins_bm (uint32_t u32mask_rising_edge, uint32_t u32mask_falling_edge);
割り込み対象のピンを指定します。
1番目のパラメータu32mask_rising_edge
は立ち上がりエッジの検出対象ピンのビットマップ、2番目のパラメータu32mask_falling_edge
は立ち下がりエッジの検出対象ピンのビットマップです。
立ち上がり、立ち下がり両方のエッジを設定することも可能です。
gint_poll()
割り込み時の処理と同じ処理を行う。
1msシステムタイマーなどから一定周期で呼び出すことで、後述の「GINTを用いたDIO割り込み実装」で解説する制限(割り込みハンドラ中で読み出した状態からポート状態が変化してそのままその変化が処理されない場合)を緩和できる場合があります。多くの場合はこの処理は必要ありません。
set|unset|get_opt_stop_int_when_changed()
void set_opt_stop_int_when_changed ();
void unset_opt_stop_int_when_changed ();
bool get_opt_stop_int_when_changed ();
メカボタンのチャタリングなどの影響を緩和するために、状態変化検出後に当該ピンの割り込み動作を停止します。
具体的には、ピンの状態が変化し割り込みが発生し、かつ、その割り込みハンドラ中で変化があったと判定されたピン*について、割り込みピンから一時的に除外します。
*割り込み要因のピンはGINTの割り込み機構では知ることが出来ないため、割り込みハンドラが実行された直後にピンの状態を読み出し、直前の状態で比較することで変化を検出しています。
このオプションを設定した場合、ピンの変化が検出されたあとピンの状態の安定を待ってからreactivate_in_pins()
を呼び出します。
reavtivate_int_pins()
void reavtivate_int_pins ();
割り込みを一時停止したピンの割り込みを再開する。set_opt_stop_int_when_changed()
のオプション設定参照。
get_gint_context()
gint_context& get_gint_context();
内部構造体にアクセスします。設定済みの立ち上がり立ち下がりピンのビットマップ(.bm_rise
.bm_fall
)や、スリープ起床時の起床要因のピン(.bm_wake
)を得るために使用します。
_gint_update()
std:: tuple< uint32_t , uint32_t > _gint_update(
uint32_t u32mask_rising_edge = 0x80000000
, uint32_t u32mask_falling_edge = 0x80000000 );
(内部的に呼び出される関数でユーザプログラムからは使用しません)
1.割り込みピンの設定を行う。
2.ピンの状態変化を判定、更新する(u32mask_rising_edge
, u32mask_falling_edge
が0x80000000
の場合)。状態変化があれば init_int()
で登録したコールバック関数を呼び出す。
gint_handler()
static void gint_handler ();
(内部的に呼び出される関数でユーザプログラムからは使用しません)
GINTの割り込みハンドラ。
_gint_get_changed_by_specified_edge()
uint32_t _gint_get_changed_by_specified_edge(uint32_t bm_cur, uint32_t bm_changed)
(内部的に呼び出される関数でユーザプログラムからは使用しません)
変化したピンのから、立ち上がり・立ち下がりの指定条件に合致するピンを抽出します。計算には、現在のビットマップ状態(bu_cur
)と変化したピン(bm_changed
)を用います。
class mwf::periph::gpio (sys_ev_handler) on_sleep() GINTが稼働中なら割り込みの停止を行います。
TWENETでは vAHI_DioOnSleep_MW()
で、本ライブラリを経由(set_int_pins_bm()
)して設定した割り込み設定ピンをスリープ起床用として設定しています。なお、スリープ起床では立ち上がりまたは立下りのエッジの指定はできません。
on_wakeup() GPIO割り込み起床した場合は、起床要因に対応するピン情報 (PMC->WAKEIOSOUCE
) を保存します。
また、スリープ前に割り込みピンの指定があった場合は、改めて GINT による割り込みが動作するように再初期化します。
GINTを用いたDIO割り込み実装 PINT機能は利用数が最大4ポートまでの制限があるため、GINT(Group INT)の機能を用い類似の機能を実装してます。PINTのように特定のピンに注目した割り込み検出機構ではないため制限事項が存在します。TWENET ライブラリ中では PINT を用いていませんので、GINTによる実装の制限に問題がある場合は、PINT による実装も検討してください。
制限事項 ノイズや短いパルスといった状態変化後に短時間で再び状態が変化する信号の場合、期待しないふるまいになる場合があります(取りこぼしなど)。
状態変化後、一定の間同じ状態が維持されることを想定します。GINTの制約上、ごく短いパルスの場合GINT割り込みは検出できますが、変化したピンを得ることは出来ません。詳細は後述の「実装」を御覧ください。 変化(エッジ)から約10usecの間状態が維持されれば、GINT のエッジ再設定が行えるため原理的には動作が期待できますが、安全を見て割り込みハンドラ1回の処理時間に相当する約30~50usecの間同じ状態が維持することを目安としてください。 GND状態で立ち下がりエッジを検出する、またその反対に VCC 状態で立ち上がりエッジを検出する場合は、原理上、取りこぼしが発生しやすくなります。 チャタリング・ノイズが含まれるものについては、初回割り込み発生時点で割り込み対象から外すオプション(vAHI_DioInterruptDisablePinsIntWhenChanged_MW(TRUE);
またはmwf::the_gpio->set_opt_stop_int_when_changed();
)を利用し、割り込み発生時点から一定時間待ってから、vAHI_DioInterruptReavtivate_MW();
または mwf::the_gpio->reavtivate_int_pins();
を呼び出してください。 多くの場合必要ありませんがthe_gpio->gint_poll()
を1ms単位のシステムティックなど一定周期で呼び出すことで、割り込みのオーバーヘッドが増えるものの、取りこぼしの影響を緩和できる場合があります。 ※ 記載の数値は CPU が 32Mhz 動作した場合を前提としてます。
※ 半導体の機能をそのまま利用したい場合は、当ライブラリの初期化を行わず、GINT や PINT を直接利用してください。
実装 GINTは本来、複数のピンをグループとして扱い、全体として変化があった場合に割り込みを発生させるもので、個別のピンの状態を意識した機能ではありません。
以下のように実装しています。
現在のピンの状態を読み出し、Hなら立ち下がり、Lなら立ち上がりエッジとして、GINTでの検出エッジの設定して、割り込みを有効にする。 GINT割り込み発生(いずれかのピンに変化し、割り込みハンドラが呼び出される)各ピンの状態を読み出し、変化のあったピンを検出する GINTの検出エッジ設定を、読み出したピンの状態に合わせて再設定する 変化のあったピンに対してアプリケーションに通知(コールバック)する ※ 割り込みハンドラは、直後にもう一度呼び出されます。
動作例 ※ 記載中の数値などは、開発中のライブラリコード、検出対象ピンは2つ、マイコンは CPUは32MHzで駆動した場合です。
同時に2つのピンが L レベルになった時 割り込み発生から 1.5usec で割り込みハンドラが呼び出されます。割り込みの前段階の処理(ピンの読み出しと検出エッジの再設定)は、6.6usec後までかかります。その後、アプリケーション通知(割り込み時のコールバック)を行います(割り込み発生から 22usecまで)。
さらにもう一度割り込みが発生します(GINTのハードウェアの振る舞いと考えられます)。2回目の割り込みでは、多くの場合状態の変化は検出されないため値の確認のみですが、例外的な取りこぼしを抑制する場合があります。
横軸 (10usec/DIV) ピンク:割り込みハンドラの先頭から、GINTの検出エッジ再設定まで (1V/div) シアン・イエロー:入力信号 (2V/div) 割り込みハンドラ中に他のピンが変化した場合1 この例では、割り込みハンドラの前半処理中に他のピン(シアン)が変化したため、最初のハンドラ中で矛盾なく処理できた例です。上述の同時変化と同じ振る舞いになります。最初の割り込みでイエローとシアン両方の変化がアプリケーションに伝達されます。
横軸 (10usec/DIV) ピンク:割り込みハンドラの先頭から、GINTの検出エッジ再設定まで (2V/div) ブルー:割り込みハンドラの開始から終了まで (2V/div) シアン・イエロー:入力信号 (5V/div) 割り込みハンドラ中に他のピンが変化した場合2 この例では、割り込みハンドラ中で他のピン(シアン)が変化していますが、検出エッジ再設定後の変化であるため、直後に割り込みが発生しています。2回目のハンドラ終了後に、更にもう一度ハンドラが実行されます。最初の割り込みでイエローの変化がアプリケーションに伝達され、2回目の割りr込みでシアンの変化が伝達されます。
横軸 (10usec/DIV) ピンク:割り込みハンドラの先頭から、GINTの検出エッジ再設定まで (2V/div) ブルー:割り込みハンドラの開始から終了まで (2V/div) シアン・イエロー:入力信号 (5V/div) 2.5 - mwf_periph_i2c - I2C mwf_periph_i2c - I2C
I2Cバスを用いるための手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_i2c - I2C I2Cバスを用いるための手続きをまとめたペリフェラルオブジェクトです。
コード例 以下の例では mwf::
名前空間を明示的に指定しています。省略する場合は using namespape mwf;
を記述してください。
#include "mwf_periph_i2c.hpp"
// create instance of the_i2c0.
if (! mwf:: the_i2c0) {
mwf:: i2c:: global_init_i2c0_manager();
}
// I2C device init
mwf:: the_i2c0-> init();
// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60 , 0x9C };
if (! mwf:: the_i2c0-> write_blocking(0x70 , cmd1)) return false;
// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000 * 30 ); // wait some for sensor data conversion.
// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6 ];
mwf:: the_i2c0-> read_blocking(0x70 , data);
// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60 , 0x9C };
if (! mwf:: the_i2c0-> write_blocking(0x70 , cmd1)) return false;
// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000 * 30 ); // wait some for sensor data conversion.
// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6 ];
mwf:: the_i2c0-> read_blocking(0x70 , data);
この例では、センサーの取得開始コマンドを送付し、センサー動作時間待ち(センサーが必要とする時間)を経てから、データ取得を行なっています。
// write 2bytes (e.g. kick sensor capturing)
const uint8_t cmd1[] = { 0x60 , 0x9C };
if (! mwf:: the_i2c0-> write(0x70 , cmd1)) return false;
while (! mwf:: the_i2c0-> available()); // waiting for completion of write operation.
// wait (e.g. wait sensor data conversion.)
CLOCK_uDelay(1000 * 30 ); // wait some for sensor data conversion.
// read 6 bytes (e.g. read the sensor data.)
uint8_t data[6 ];
mwf:: the_i2c0-> read(0x70 , data);
while (! mwf:: the_i2c0-> available()); // waiting for completion of read operation.
ブロッキングAPIと同じwrite/readですが、ノンブロッキングAPIでは write()
/read()
関数はデータ送信完了を待たず速やかに終了します。十分な時間を待つか the_i2c0->available()
がtrueになるのを待ってから続く操作を行う必要があります(上記の例では、write/read直後にポーリング待ちを行っているので、ブロッキングAPIの利用と違いがありません)。
class mwf::periph::i2c I2Cを利用するための手続きを記述しています。
※ 現状の実装では I2C0 を利用する the_i2c0
クラスオブジェクトのみが利用できます。
E_PIN_CONF
enum class E_PIN_CONF : uint8_t {
NODEF = 0 , // 未指定
PRIMARY = 1 , // 主割り当て (PIO10/11)
ALT = 2 // 副割り当て (PIO15/16)
};
// enum class と int 型の代入、比較等をするための型。
using wE_PIN_CONF = mwf:: enum_wapper< E_PIN_CONF> ;
ピン割り当てを指定するための列挙体。
global_init_i2c0_manager(), global_deinit_i2c0_manager()
static void global_init_i2c0_manager (wE_PIN_CONF pin_conf = E_PIN_CONF:: PRIMARY);
static void global_deinit_i2c0_manager ();
the_i2c0
クラスオブジェクトの生成と破棄を行います。
生成時にピン配置をpin_conf
にE_PIN_CONF::PRIMARY 値:0
(SCL=PIO10,SDA=PIO11)またはE_PIN_CONF::ALT 値:1
(SCL=PIO15,SDA=PIO16)を指定します。ピンの初期化は init()
呼出時に行われる。
(eE_PIN_CONF
はenum class E_PIN_CONF
のラッパクラスで、int
型との代入比較のための定義を設けています)
init(), deinit()
void init (uint32_t clock_freq = 0 , wE_PIN_CONF pin_conf = E_PIN_CONF:: NODEF);
void deinit ();
I2Cバスの初期化と利用終了手続きを行う。初期化時にはclock_freq
をパラメータとして与え、0
の場合は規定クロック100kHzが選択され、それ以外はclock_freq
[Hz]を周波数として指定する。
pin_conf
を指定しない場合(E_PIN_CONF::NODEF 値:0
)は、global_init_i2c0_manager()
で指定したピンを用います。pin_conf
を指定した場合、そのピン設定を用いて初期化します。以降、本パラメータの省略時は最後に指定したピンを用います。
write_blocking(), write()
bool write_blocking (uint8_t addr, const uint8_t * buf, unsigned size);
template < unsigned N> bool write_blocking(uint8_t addr, const uint8_t (& buf)[N]);
bool write (uint8_t addr, const uint8_t * buf, unsigned size);
template < unsigned N> bool write(uint8_t addr, const uint8_t (& buf)[N]);
I2Cバスへデータを書き込む。
write_blocking()
は書き込み完了まで待ち処理を行うブロッキング処理、write()
は書き出し完了を待たずに関数を終了するノンブロッキング処理です。書き出しが完了すると .available()
が true になります。
addr
はI2Cバスのアドレス(7bit)、buf
は書き出すデータ、size
は書き出すデータバイト数を指定します。buf
がサイズN
の固定配列の場合はNバイト書き出します。
read_blocking(), read()
bool read_blocking (uint8_t addr, uint8_t * buf, unsigned size);
template < unsigned N> bool read_blocking(uint8_t addr, uint8_t (& buf)[N]);
bool read (uint8_t addr, uint8_t * buf, unsigned size);
template < unsigned N> bool read(uint8_t addr, uint8_t (& buf)[N]);
I2Cバスからデータを読み込む。
read_blocking()
は読み出し完了まで待ち処理を行うブロッキング処理、write()
は読み出し完了を待たずに関数を終了するノンブロッキング処理です。読み出しが完了すると .available()
が true になります。
addr
はI2Cバスのアドレス(7bit)、buf
はデータ格納バッファ、size
は読み出すデータバイト数を指定します。buf
がサイズN
の固定配列の場合はNバイト読み出します。
_transfer()
bool _transfer (OPT op, uint8_t addr, uint8_t * buf, unsigned size);
ノンブロッキング読み書きを行う処理関数。op
は読み出しか書込みの指定、addr
はI2Cバスのアドレス、buf
は読み書きのためのバッファ、size
は読み書きバイト数です。
_transfer_blocking(), _start_blockin(), _stop_blocking()
bool _transfer_blocking (OPT op, uint8_t * buf, unsigned size, bool sendStop = false)
bool _start_blocking(OPT op, uint8_t addr);
bool _stop_blocking ();
mwxライブラリ向けに調整したブロッキング読み書きの手続き。_start_blocking()
、_transfer_blocking()を必要な回数、
_stop_blocking()の順で呼び出す。サイトの転送で
sendStop`をtrue に設定することで適切にSTOP信号を発光できる。
available()
ノンブロッキングAPI利用時に、転送終了を判定する。転送終了するとtrue を戻す。
is_success()
ノンブロッキングAPI利用時に、直前の転送が成功したかどうかを返す。true なら転送が成功したことを示す。
class mwf::periph::i2c (sys_ev_handler) on_sleep() スリープ前の手続きとして I2C デバイスの利用終了手続きを行う。
on_wakeup() スリープ時に初期化(init()
呼出)済みの場合は、再度 init()
の呼び出しを行い初期化する。
2.6 - mwf_periph_ntag - NTAG mwf_periph_ntag - NTAG
チップ内蔵の近距離無線通信(NTAG)コントローラ(NT3H2211)のEEPROMを読み書きするための手続きです。
このページでは、EEPROMの手続きのみ記述しています。
NTAG 通信の扱いについては、後日追記する予定です。
mwf_periph_ntag - NTAG チップ内蔵の近距離無線通信(NTAG)コントローラ(NT3H2211)のEEPROMを読み書きするための手続きです。コントローラはI2C接続されていますがmwf::periph::i2c
は用いません。
本手続きにより読み書きできるのは 1KB の領域(NT3H2211 の I2C block address 64-127)です。
コード例
#include "mwf_periph_ntag.hpp"
void func () {
// create the_ntag class object.
if (! mwf:: the_ntag) {
mwf:: ntag:: global_init_ntag_manager();
}
// initialize
mwf:: the_ntag-> init();
// write 128bytes
uint8_t xfer1[128 ];
for (unsigned i = 0 ; i < 128 ; i++ ) xfer1[i] = i;
mwf:: the_ntag-> write_user_area(0x00 , xfer1);
// read 128bytes
uint8_t xfer2[128 ];
mwf:: the_ntag-> read_user_area(0x00 , xfer2);
}
class mwf::periph::ntag global_init_ntag_manager(), global_deinit_ntag_manager()
static void global_init_ntag_manager ();
static void global_deinit_ntag_manager ();
the_ntag
クラスオブジェクトの生成と破棄を行います。
init(), deinit()
void init ();
void deinit ();
デバイスアクセスのための初期化と利用終了手続きを行います。初期化init()
には300usecの待ち処理が含まれます。
write_user_area()
bool write_user_area (uint16_t addr, const uint8_t * p, uint16_t len);
template < unsigned N> bool write_user_area(uint8_t addr, const uint8_t (& buf)[N]);
EEPROMのユーザエリアにバイト列を書き込みます。
addr
は開始アドレスで0..1023を指定します。p
またはbuf
は書込みデータのバッファです。len
またはN
はデータバイト数です。
read_user_area()
bool read_user_area (uint16_t addr, uint8_t * p, uint16_t len);
template < unsigned N> bool read_user_area(uint8_t addr, const uint8_t (& buf)[N]);
EEPROMのユーザエリアからバイト列を読み出します。
addr
は開始アドレスで0..1023を指定します。p
またはbuf
は読み出し先のデータのバッファです。len
またはN
はデータバイト数です。
class mwf::periph::ntag (sys_ev_handler) on_sleep() スリープ前に利用終了の手続きを行います。
on_wakeup() スリープ時に初期化済みの場合は、再度初期化します。再初期化が不要な場合は deinit()
してからスリープしてください。
2.7 - mwf_periph_pwm - PWM, Timer mwf_periph_pwm - PWM, Timer
PWM,タイマーを用いるための手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_pwm - PWM, Timer PWM,タイマーを用いるための手続きをまとめたペリフェラルオブジェクトです。
クラスオブジェクトthe_pwm[]
を用いて操作します。クラスオブジェクトは配列として定義されていますがPWM0(the_pwm[0]
)からPWM9(the_pwm[9]
)まで利用できます。
PWM10は本ライブラリでは対応しません。
コード例 以下の例では mwf::
名前空間を明示的に指定しています。省略する場合は using namespape mwf;
を記述してください。
TWENETcmpt (AHI 互換関数) を利用する場合は、
#include "mwf_periph_pwm.hpp"
// in some func.
void func () {
// create instance of PMW0.
if (! the_pwm[0 ]) { // The class object of PMW0 is the_pwm[0].
timer_n_pwm:: global_init_pwm_manager(
0 , // PWM0
timer_n_pwm:: PIN:: ALT,
// The timer_n_pwm::PIN::PRIMARY will assign smaller PIO number PIO0 from PWM0,
// or conversely, timer_n_pwm::PIN::::ALT assigns PIO12.
true // set true to enable PWM output.
);
}
// set `x' as an alias of the_pwm[0].
auto & x = the_pwm[0 ];
// Init the device
//x->init(); // not necessary, the constructor will call init() implicitly.
// if needs INT, set true. (default: false)
x-> set_int_enabled(true);
// set prescale
x-> set_prescale(6 ); // 0:32MHz 1:16Mhz 2:8Mhz ...
// set polarity: if false, set HIGH while active state. (default: false)
x-> set_invert(false);
// set cycle
// note: 500Hz Duty 10% (Hi 0.2ms, Low 1.8ms)
x-> set_cycle(
100 // conut for an active state (HIGH)
, 999 // count for a period (+1)
);
// start PWM out
x-> restart();
}
// INT handler (call set_int_enabled() before restart())
// note: if TWENETcmpt library is not linked, the IRQ handlers for PWM1..9 shall be defined.
extern "C" void PWM0_IRQHandler(void ) {
... // some procedures.
PWM_ClearStatusFlags(PWM, kPWM_Pwm0);
}
class mwf::periph::timer_n_pwm global_init_pwm_manager()
static void global_init_pwm_manager (
uint8_t u8_pwm_id
, uint8_t u8_pin_number
, bool b_output_enabled = true
);
static void global_init_pwm_manager (
uint8_t u8_pwm_id
, PIN e_pin
, bool b_output_enabled = true
);
クラスオブジェクトthe_pwm[]
を構築します。構築時にPWM番号と対応するピンを指定します。
PWM番号は(u8_pwm_id
)として指定すします。各PWMは利用可能なピンが2ピンあり(PWM5はPIO16のみ)、本APIではu8_pin_number
として直接ピン番号を指定するか、指定可能なピンのうち若い番号(timer_n_pwm::PIN::PRIMARY
)または別のピン番号(timer_n_pwm::PIN::ALT
)を指定します。
矛盾する番号を指定した場合の動作は未定義です。
global_deinit_pwm_manager()
static void global_deinit_pwm_manager (uint8_t u8_pwm_id);
構築済みのthe_pwm[]
クラスオブジェクトを破棄します。
set_pwm_output()
void set_pwm_output (bool_t b_enable);
bool get_pwm_output ();
ピンの出力状態を変更します。b_enable
がtrue の場合は出力を有効にする指定でハードウェアのピンも設定変更されます。false の場合はデフォルトのピン(conf::pin::conf_defautl()
)に設定します。
PWM出力中に呼び出すことが出来ます。 global_init_pwm_manager()
のパラメータで出力設定している場合、改めて呼ぶ必要はありません。set_int_enabled()
void set_int_enabled (bool_t b_enable);
bool get_int_enabled ();
割り込みの有効・無効を設定します。b_enable
がtrue の場合は割り込みが有効、false の場合は無効になります。
PWM出力中に呼び出すことが出来ます。 後述の「割り込みハンドラ」を参照してください。 set_prescale(), set_divisor()
void set_prescale (uint8_t u8_prescale);
void set_divisor (uint16_t u16_div);
PWM制御のプリスケールを設定します。これによりPWM制御周波数が決まります。
PWM出力中に呼び出すことが出来ます。 set_prescale(u8_prescale)
を指定した場合、制御周波数は0
:32Mhz, 1
:16Mhz, 2
:8Mhz, …, 9
: 62500Hz, 10
: 31250Hz, 11
以降は未定義(デバッグ時assert
)です。set_divisor(u16_div)
を指定した場合, 制御周波数は (32Mhz / u16_div) です。値域は 1..1024 の範囲で、それ以外の値を指定した場合の振る舞いは未定義です。PWM周期とDUTY比はset_cycle()
のパラメータで決まります。例えば set_prescale(2)
と指定した場合は制御周波数は fb=8Mhz です。この設定でset_cycle(2, 10)
を指定すると PWM 周期は fbx10=800Khz で、パルス幅が 2x1/fb=1/8000000=250nsec になります。 set_cycle()
void set_cycle (uint16_t ct_comp, uint16_t ct_period);
uint16_t get_period_val (); // get total period count
uint16_t get_comp_val (); // get active region count
PWM1周期とその中でのアクティブ区間を決めるカウント値を指定します。アクティブ区間の間ピンの値が変化し、その終わりに割り込みが発生します。
ct_comp
までの値がアクティブ、ct_period
が1周期のカウント数です。例えばct_comp
を100
、ct_period
を1000
とした場合、PWM周期はPWM制御周波数で1000カウント分、set_invert(false)
の条件で100カウント分がHIGH、残りの900カウントがLOWになる振る舞いをします。
PWM出力中に呼び出すことが出来ます。 ct_comp
は0
からct_period-1
までが有効です。アクティブが(ct_period-1/ct_period)
の比率までが上限で100%に設定することが出来ません。set_duty()
では100%の設定を考慮しています。1周期分のカウント値ct_period
について、ハードウェアレジスタには ct_period - 1
として設定しています。本関数にはハードウェアレジスタ値を指定しないよう注意してください。 set_duty()
void set_duty (uint16_t u16duty, uint16_t u16duty_max = 1000 );
PWMのDUTY比を設定します。
事前に set_cycle()
を用いて、PWMの1周期のカウント数を指定しておきます。左記の手続きを省略した場合 u16duty_max
がPWM周期のカウント数として設定されます。 1周期に対してu16_duty/u16duty_max
の割合をアクティブ区間とします。例えば set_duty(100)
と指定した場合はアクティブ区間は1周期に対して10%です。 u16duty
にu16duty_max
と同じ値を指定した場合は、全区間がアクティブとなりデフォルトの反転しない波形出力set_invert(false)
の場合HIGHレベルに設定します(ハードウェアの制約からアクティブ区間を全区間に設定できないため、内部的には波形出力レジスタを反転して、アクティブ区間を0に設定しています)。このためset_duty()
で100%設定した後にset_cycle()
を呼び出すと波形が反転します。混用しないように注意してください。 set_invert()
void set_invert (bool_t b_invert);
bool get_invert ();
出力波形を反転します。false (デフォルト)設定時はアクティブ区間がHIGHレベル、true ではLOWレベルです。
start(), stop()
void start ();
void restart ();
void stop ();
PWM出力の開始、設定&開始(再開)、停止処理を行います。
停止処理 stop()
時のピンの状態は、set_invert(false)
(デフォルト)の場合 LOW レベル、set_invert(false)
の場合HIGHレベルです。 class mwf::periph::timer_n_pwm (sys_ev_handler) sys_ev_handler
はスリープ前後の手続きです。
on_sleep() PWMの実行状態を保存した上で、スリープ時のピン状態をデフォルト設定に戻す。
on_wakeup() スリープ前の状態した状態を復元する。
class mwf::periph::timer_n_pwm (sys_global_resource_handler) sys_global_resouce_handler<T>
(T
はtimer_n_pwm
クラス)は、複数のPWMクラスオブジェクトに対して、1度だけ必要な初期化処理、終了手続きを行うための手続きです。内部的に暗黙に利用されます。
コンストラクタやon_wakeup()
でsys_global_resource_handler<T>::init()
を呼び出します。最初に作成されたインスタンスの場合は T::global_init()
を呼び出します。 デストラクタやon_sleep()
でsys_global_resource_handler<T>::deinit()
を呼び出します。最後に破棄されるインスタンスの場合は T::global_deinit()
を呼び出します。 T::global_init() ::PWM_Init()
を呼び出し、PWMを初期化します。
T::global_deinit() ::PWM_DeInit()
を呼び出し、PWMの利用終了手続きを行います。
割り込み set_int_enabled(true)
を設定すると、アクティブ区間の終了で割り込みが発生します。割り込みハンドラはシステムで用意されたもので PWMn_IRWHandler()
(nはPWMチャネル)です。
割り込み発生 割り込み発生
V V
Vcc +----+ +----+
| | | | t
GND----+ +-------------+ +-------- ->
<----> アクティブ区間
<------------------> PWM 1周期
割り込みハンドラを明示的に定義します。TWENETcmpt ライブラリをリンクするかどうかで要定義のハンドラ関数が変わります。
TWENETcmpt をリンク => 使用する PWM チャネルのみ定義する TWENETcmpt をリンクしない => PWM0 から PWM9 チャネルまでの割り込みハンドラを割り込みを使用していなくても明示的に 定義する 割り込みハンドラ TWENET を利用する場合は、割り込み関数(cbToCoNet_u8HwInt()
)、イベント(cbToCoNet_vHwEvent()
)に変換されます。
独自の割り込みハンドラを定義する場合は PWNn_IRQHandler()
を別途定義します。以下の例は PWM1 の定義例です。独自に定義する場合 TWENET の割り込み・イベントは発生しません。
// note: in c file, `extern "C"' should be remoded.
extern "C" void PWM1_IRQHandler(void ) {
PWM_ClearStatusFlags(PWM, kPWM_Pwm1);
}
2.8 - mwf_periph_rng - TRNG mwf_periph_rng - TRNG
チップ内蔵の乱数生成ハードウェアを利用するため手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_rng - TRNG チップ内蔵の乱数生成ハードウェアを利用するため手続きをまとめたペリフェラルオブジェクトthe_rng
を実装しています。
TWENET では、暗黙に利用しますので、ユーザプログラム上での初期化の手続きは不要です。
コード例
if (! mwf:: the_rng) {
mwf:: rng:: global_init_rng_manager();
mwf:: the_rng-> init();
}
uint32_t val = mwf:: the_rng-> random();
class mwf::periph::rng global_init_rng_manager(), global_deinit_rng_manager()
static void global_init_rng_manager ();
static void global_deinit_rng_manager ();
the_rng
クラスオブジェクトの生成と破棄を行います。クラスオブジェクト生成時に自動的に初期化され、ランダム値の取得が可能になります。
random()
乱数値を戻します。
class mwf::periph::rng (sys_ev_handler) on_sleep() TRNGの停止処理を行います。
on_wakeup() TRNGの始動処理を行います。
2.9 - mwf_periph_spi - SPI mwf_periph_spi - SPI
SPIバスを利用するためのクラスオブジェクトです。
mwf_periph_spi - SPI SPIバスを利用するためのクラスオブジェクトthe_spi1
を実装しています。
SPI0 の対応コードは含まれません。 一部 non blocking (非ブロック) を想定した定義が含まれますが、現バージョンでは blocking (ブロック) の API のみ利用可能です。 コード例
#include "mwf_periph_spi.hpp"
void func_spi_init () {
if (! mwf:: the_spi1) {
mwf:: spi:: global_init_spi1_manager();
Serial << crlf << "the_spi1 constructed." ;
}
mwf:: spi:: config conf{};
conf.baud = 4000000UL ; // 4MHz
conf.bits = 8 ; // 8bit
conf.dir = mwf:: spi:: E_SPI_DIR:: MSB_FIRST;
conf.mode = mwf:: spi:: E_SPI_MODE:: MODE_3_INV_RISE;
conf.pin_ssel[0 ] = mwf:: spi:: E_PIN_SSEL:: SSEL0_PIO3;
conf.pin_ssel[1 ] = mwf:: spi:: E_PIN_SSEL:: SSEL1_PIO16;
mwf:: the_spi1-> init(conf);
}
void func_spi_transfer () {
uint8_t tx[16 ] = { 0xa5 , 0x5a , 0x11 , 0x88 }; // data to transmit
uint8_t rx[16 ]; // receive buffer
mwf:: the_spi1-> ssel_select(0 );
mwf:: the_spi1-> transfer_blocking(tx, rx, 4 ); // four bytes transfer
CLOCK_uDelay(5 ); // wait 5us
mwf:: the_spi1-> transfer_blocking(tx, rx, 4 ); // four bytes transfer
mwf:: the_spi1-> ssel_deselect();
}
class mwf::periph::spi struct config mwf::periph::spi::config
構造体は以下のように定義されています。
struct config {
// evaluated only in init()
E_PIN_MAIN pin_conf; // master pin configuration (so far not used)
E_PIN_SSEL pin_ssel[3 ]; // SSEL0..2 (assignment settings for slave select pins.
// At least pin_ssel[0] shall be configured.
// evaluated in conf(), reconf()
uint32_t baud; // SPI frequency (default 50Mhz)
E_SPI_DIR dir; // transfer LSB first
E_SPI_MODE mode; // SPI mode (clock polarity and detect edge)
uint8_t bits; // bit width (0:default=8, ...)
uint8_t ssel; // 0..3 or 0x80..0x80 (if MSB is set, assert/deassert SSEL automatically)
};
構造体に値を設定してinit()
を呼び出します。init()
中で構造体の設定値は内部的にコピーされますので、呼び出し後は構造体領域を破棄しても構いません。
構造体の各メンバーの解説です。
信号名 解説 pin_conf
使用するピン割り当て(主・副)の指定を行います。E_PIN_CONF::NODEF
(=0)を選択した場合は global_init_spi1_manager()
の指定を利用します。 pin_ssel[3]
SELECTピンを指定します。配列の0番目はSPI SELECTの0番目(SSEL0)のピン、1番目はSSEL1、2番目はSSEL2を指定します。SSEL0は必ず指定し SSEL1,2 は E_PIN_SSEL::SSEL_VOID=0
にしておきます。ピンを2種類利用する場合は SSEL0, SSEL1 を指定し、3種類の場合は全てに値を格納します。 ※ソフトウェア制御のピン(E_PIN_SSEL::SSEL0_PIO3
など )を指定した場合は、すべてのセレクトピンはソフトウェアによる制御を行います。ソフトウエア制御ではピンはHIGHレベルで常時出力設定となり、セレクト時に対象ピンが LOW レベルに変化します。なお、TWENETcmpt (AHIライブラリ互換) ではソフトウェア制御を用いています。 ※ハードウェア制御の場合 SELECT ピンの制御は fsl_spi.c のSPI_MasterTransferNonBlocking()
の動作に倣います。 baud
SPIのクロック周波数を指定します。32Mhz まで設定可能ですがセンサーデバイスなどは 1Mhz 前後がよく使われます。 (動作は、fsl_spi.h の spi_master_config_t::bandRate_Bps
, fsl_spi.c のSPI_MasterSetBaud()
に倣います) mode
SPISELはinit()
で指定します。 bits
転送単位です。通常は8を指定します。1..16まで設定できます。9ビット以上の場合、データ転送時に指定するバイト配列は2バイト単位で読み出されるため、データ数の二倍必要で、1バイト目が LSB から 8ビット分2バイト目が 残りのビットを表現します。 (動作は、fsl_spi.hのSPI_MasterTransferBlocking()
に倣います) ssel
SPIのSELECTです。0..2 を指定します。
enum class E_PIN_CONF
enum class E_PIN_CONF : uint8_t {
NODEF = 0 , // 未指定
PRIMARY = 1 , // 主割り当て (PIO10/11)
ALT = 2 // 副割り当て (PIO15/16)
};
// enum class と int 型の代入、比較等をするための型。
using wE_PIN_CONF = mwf:: enum_wapper< E_PIN_CONF> ;
ピン割り当てを指定するための列挙体です。
enum class E_PIN_SSEL
enum class E_PIN_SSEL : uint8_t {
SSEL_VOID = 0 , // 未定義
SSEL_PRIMARY, // 主設定ピン
SSEL_ALT, // 副設定ピン
SSEL_SOFT = 0x10 ,
SSEL0_PIO3, // SSEL0 をソフトウェア制御し PIO3 を使用する
SSEL1_PIO16, // SSEL1 をソフトウェア制御し PIO16 を使用する
SSEL2_PIO17, // SSEL2 をソフトウェア制御し PIO17 を使用する
SSEL1_PIO4, // SSEL1 をソフトウェア制御し PIO4 を使用する
SSEL2_PIO13, // SSEL2 をソフトウェア制御し PIO13 を使用する
};
この列挙体はSPI SELECTピンの配置を決めます。spi::confg::pin_ssel[3]
に対応する値か保存されます。
enum class E_SPI_DIR
enum class E_SPI_DIR {
MSB_FIRST = 0 ,
LSB_FIRST
};
ビットの並び順を指定します。通常は MSB_FIRST
です。
enum class E_SPI_MODE
enum class E_SPI_MODE {
MODE_0_RISE = 0 ,
MODE_1_FALL = 1 ,
MODE_2_INV_FALL = 2 ,
MODE_3_INV_RISE = 3 ,
};
SPI転送モードの指定です。クロックの判定エッジと、その時の H/L の値を 0 とするか 1 とするかを決めます。接続デバイスのデータシートに従い設定します。
global_init_spi1_manager(), global_deinit_spi1_manager()
static void global_init_spi1_manager (E_PIN_MAIN pin_conf = E_PIN_MAIN:: PRIMARY);
static void global_deinit_spi1_manager ();
SPI1のバスを利用するためのクラスオブジェクトの生成と破棄を行います。クラスオブジェクト生成時にpin_conf
により利用するためのピンの組み合わせを選択します。ピン設定の指定は E_PIN_MAIN::PRIMARY 値:0
及びE_PIN_MAIN::ALT 値:1
を指定できます。
init()
void init ();
void init (spi:: config& cnf);
void init (spi:: config&& cnf);
SPIバスを初期化します。パラメータcnf
を与えることでいくつかの設定を行います。パラメータを省略した場合は、以前の設定を用いて最初期化します。
セレクトピンをユーザプログラムでソフトウェア制御する場合であっても、必ず1つは指定してください。指定されたピンはGPIOの出力として設定されます。unset_ssel_auto()
を呼び出しておけば、当該ピンに対するライブラリによる制御は行われなくなります。 reconf()
ペリフェラルのパラメータを再反映します。内部設定にアクセスするには spi::config& get_conf()
を用います。この手続でピンの設定 (pin_ssel[]
)は反映されません。
set_data_width()
void set_data_width (uint8_t bits);
転送データ幅を変更します。reconf()
より軽い手続きです。
set|unset|get_ssel_auto()
void set_ssel_auto ();
void unset_ssel_auto ();
bool get_ssel_auto ();
セレクトピンの自動制御フラグの設定、解除、取得。
ソフトウェア制御を利用する場合のみ有効。 transfer_blocking()
呼び出し時に自動的にSELECTピンがLOWに制御され、終了時にSELECTピンがHIGHに設定される。ssel_select()
void ssel_select (uint8_t select);
セレクトピンの指定を行います。select
は 0, 1, 2 の値をとり、各々 SSEL0..2 に対応します。
ハードウェア制御、ソフトウェア制御で自動制御フラグ(set_ssel_auto()
)設定時は、ピンの制御は転送API呼び出し時に行われる。 ソフトウェア制御の場合は、自動制御フラグの有無に関係なく ssel_select()
呼び出し直後に、SELECTピンがLOWに設定される。 ハードウェア制御の場合は、reconf()
を呼び出し再初期化します。この処理は処理時間のコストが大きいため、頻繁にデバイスを切り替えて転送を行う場合は、ソフトウエア制御を使用してください。 ssel_deselect()
セレクトピンの解除を行います。
ソフトウェア制御の場合は、セレクトピンをすべて HIGH レベルに戻します。 ハードウェア制御の場合は、なにもしません。 ssel_select()
でのピンの指定は変更しません。その他
bool has_init (); // init() 実行済みであれば true を返す
spi:: config& get_conf(); // 内部保存の設定情報にアクセスする
ピンの割り当て E_PIN_CONF::PRIMARYの場合 信号名 PIO番号 解説 SCK 0 クロック信号 MOSI 2 SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 MISO 5 SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。
セレクトピン pin_ssel E_PIN_SSEL PIO 備考 SSEL0
pin_ssel[0]
SSEL_PRIMARY
3 SSEL_ALT
16 SSEL0_PIO3
3 ソフトウェア制御 SSEL0_PIO16
16 ソフトウェア制御 SSEL1
pin_ssel[1]
SSEL_PRIMARY
4 SSEL_ALT
14 SSEL1_PIO4
4 ソフトウェア制御 SSEL1_PIO14
14 ソフトウェア制御 SSEL1_PIO16
16 ソフトウェア制御(SSEL0_PIO16
の指定は不可) SSEL_VOID
セレクトは SSEL0
のみとする SSEL2
pin_ssel[2]
SSEL_PRIMARY
13 SSEL2_PIO13
13 ソフトウェア制御 SSEL2_PIO17
17 ソフトウェア制御 SSEL_VOID
セレクトは SSEL0
SSEL1
の2つとする
セレクトは SSEL0
から順に SSEL1
SSEL2
まで最大3種類設定できます。 pin_ssel[]
のいずれかの指定がソフトウェア制御の場合、セレクトピンは全てライブラリ中でソフトウェア制御を行います。E_PIN_CONF::ALTの場合 信号名 PIO番号 解説 SCK 15 クロック信号 MOSI 17 SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 MISO 18 SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。
セレクトピン pin_ssel E_PIN_SSEL PIO 備考 SSEL0
pin_ssel[0]
SSEL_PRIMARY
16 SSEL_ALT
3 SSEL0_PIO3
3 ソフトウェア制御 SSEL0_PIO16
16 ソフトウェア制御 SSEL1
pin_ssel[1]
SSEL_PRIMARY
14 SSEL0の指定必須 SSEL_ALT
4 SSEL1_PIO4
4 ソフトウェア制御 SSEL1_PIO14
14 ソフトウェア制御 SSEL_VOID
セレクトは SSEL0
のみとする SSEL2
pin_ssel[2]
SSEL_PRIMARY
13 SSEL_ALT
5 PRGピンでもあるので注意が必要。 SSEL2_PIO5
5 ソフトウェア制御。PRGピンでもあるので注意が必要。 SSEL2_PIO13
13 ソフトウェア制御 SSEL_VOID
セレクトは SSEL0
SSEL1
の2つとする
セレクトは SSEL0
から順に SSEL1
SSEL2
まで最大3種類設定できます。 pin_ssel[]
のいずれかの指定がソフトウェア制御の場合、セレクトピンは全てライブラリ中でソフトウェア制御を行います。class mwf::periph::spi (sys_ev_handler) on_sleep() スリープ前の手続きとして、SPIを未使用状態に戻す。
init()
により初期化済みであればこれを保存しておく。
on_wakeup() スリープ前に初期化状態であれば、SPI バスを利用できるように最初期化します。
2.10 - mwf_periph_wtimer - WTIMER, FRWT mwf_periph_wtimer - WTIMER, FRWT
ウェイクアップタイマーを利用するため手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_wtimer - WWDT, FRWT ウェイクアップタイマーを利用するため手続きをまとめたペリフェラルオブジェクトthe_wtimer
を実装しています。
TWENETでは暗黙に使用されますので、ユーザプログラムでの初期化は不要です。
ウェイクアップタイマーはモジュール内に内蔵する 32768Hz の水晶振動子に基づき減算カウントします。例えば32768からタイマーを開始した場合、1秒後にカウンタは0にり割り込みが発生します。通常はスリープ起床に用います。起床後もカウンター値は減算を継続するため、起床後にカウント値を読み出すことで、起床後からの経過時間を計算できます。
ウェイクアップタイマーは、2系統あり系統0は40bit(当ライブラリでは32bitカウンタとして利用)、系統1は28bitのカウンタを用います。
またウェイクアップタイマーを利用した FTWT (Free Running Wake Timer) の手続きが含まれます。スリープ時も低消費電流で動作できる特徴をいかし、2系統あるウェイクアップタイマーのうちの一つを常に動作させることで、実時間に対応するカウンタとして利用します。TWENETでは、特定の設定を行うことでFRWTが機能し、FRWTが動作している場合は ADC の初期化待ちなどを効率的に行えます。
TWENETでは系統0をFRWTとして利用し、系統1を通常の起床用タイマーとして利用します。
コード例
#include "mwf_periph_wtimer.hpp"
class mwf::periph::wtimer global_init_wtimer_manager(), global_deinit_wtimer_manager()
static void global_init_wtimer_manager ();
static void global_deinit_wtimer_manager ();
the_wtimer
クラスオブジェクトの生成と破棄を行います。
init(), deinit()
void init ();
void deinit ();
ウェイクアップタイマーを初期化または終了します。
初期化時のパラメータu32ms
はタイムアウトをミリ秒(ms)で指定します。0
または省略したときは4000msとなります。 start(), stop()
void start(uint8_t dev, uint32_t u32ct)
void stop(uint8_t dev)
ウェイクアップタイマーを開始または停止します。
dev
には、使用するウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。u32ct
には、開始時のカウント値を指定します。FRWT が動作しているウェイクアップタイマーを指定した場合は、なにもしません。 read()
uint32_t read(uint8_t dev)
ウェイクアップタイマーのカウント値を読み出します。
dev
には、使用するウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。FRWT が動作しているウェイクアップタイマーの値は読み出せません。 is_running()
bool is_running(uint8_t dev)
ウェイクアップタイマーが動作中かを判定します。
dev
には、使用するウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。FRWT が動作しているウェイクアップタイマーを指定した場合は、false を戻します。 set_interrupt()
void set_interrupt(uint8_t dev, bool b_enabled)
ウェイクアップタイマーが割り込みを発生させるかどうかを指定します。
dev
には、使用するウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。b_enabled
をtrue に設定すると割り込みを発生させます。この指定がないと、スリープ起床時にも割り込みが発生しません。なお、いちどtrue を指定したウェイクアップタイマーに対してfalse を指定しても、割り込みを無効にすることはできません。FRWT が動作しているウェイクアップタイマーを指定した場合は、なにもしません。 get_fired_status_on_wakeup()
uint8_t get_fired_status_on_wakeup()
スリープ起床後に呼び出し、その起床要因がウェイクアップタイマーであった場合は、デバイスに対応するビット (WTIMER0_DEVICE_MASK
またはWTIMER1_DEVICE_MASK
)が設定される。
class mwf::periph::wtimer (sys_ev_handler) on_sleep() 特別な処理はありません。
on_wakeup() 起床要因を確認し内部に情報を保存し、割り込み状態をクリアします。また、タイマーは停止しません。
FRWT関連 freerun_start(), freerun_stop()
void freerun_start(uint8_t dev)
void freerun_stop()
FRWTの開始と終了を行います。カウント値は開始時を0として、32768Hzで加算される値です。
dev
には、ウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。freerun_is_running()
bool freerun_is_running()
FRWT が動作している場合に true を返す。
freerun_is_device()
bool freerun_is_device(uint8_t dev)
FRWT が動作しているデバイスなら true を返します。
dev
には、ウェイクアップタイマーのデバイス番号(WTIMER0_DEVICE
またはWTIMER1_DEVICE
)を指定します。freerun_ct_get()
uint32_t freerun_ct_get()
FRWTのカウント値を返します。FRWTのカウント値は、ウェイクアップタイマーの値そのものではなく、0から加算される値に変換されます(大まかには正負反転した値)。
カウント値計算関数 FRWTカウント値をミリ秒に変換したり、2つのカウント値の差を計算する関数です。
freerun_ct_convert_msec()
uint32_t freerun_ct_convert_msec(uint32_t ct, uint32_t * dec_part = nullptr )
FRWTのカウント値ct
をミリ秒に変換します。dec_part
を指定した場合は、1/10 の桁の値を 0..9 で設定します。
freerun_ct_diff()
int32_t freerun_ct_diff(uint32_t val_past, uint32_t val_now)
カウント値同士を差を計算します。基本的にはval_now - val_past
の値ですが、カウンタが最大値から0に戻った場合を考慮して計算します。カウンタの最大値の半分までの時間差が計算可能で、val_past
の方が古い場合は、正の値を戻します。
freerun_ct_diff_msec()
int32_t freerun_ct_diff_msec(int32 vdiff)
freerun_ct_diff()
で得られるカウンタ差分vdiff
をミリ秒に変換します。
freerun_ct_diff_usec()
int32_t freerun_ct_diff_usec(int32 vdiff)
int32_t freerun_ct_diff_usec(uint32_t val_past, uint32_t val_now)
freerun_ct_diff()
で得られるカウンタ差分値vdiff
またはval_past
,val_now
により計算されるカウンタ差分をマイクロ秒に変換します。
計算上int32_t 型の計算による桁溢れが発生します(およそ2000秒を超えるような場合)。 2.11 - mwf_periph_wwdt - WWDT mwf_periph_wwdt - WWDT
ウォッチドッグタイマーを利用するため手続きをまとめたペリフェラルオブジェクトです。
mwf_periph_wwdt - WWDT ウォッチドッグタイマーを利用するため手続きをまとめたペリフェラルオブジェクトthe_wwdt
を実装しています。
TWENETでは暗黙に使用されますので、ユーザプログラムでの初期化は不要です。
コード例
void setup_func () {
mwf:: gobal_init_wwdt_manager();
the_wwdt.init(); // timeout in 4000ms approx.
}
// in some function called periodically (e.g. invoked by SysTick Timer.)
void do_every_tick () {
the_wwdt.refresh();
}
class mwf::periph::wwdt global_init_wwdt_manager(), global_deinit_wwdt_manager()
static void global_init_wwdt_manager ();
static void global_deinit_wwdt_manager ();
the_wwdt
クラスオブジェクトの生成と破棄を行います。
init(), deinit()
void init (uint32_t u32ms = 0 );
void deinit ();
ウォッチドッグタイマーを初期化・停止(※1)します。
初期化時のパラメータu32ms
はタイムアウトをミリ秒(ms)で指定します。0
または省略したときは4000msとなります。 ※1 ハードウェアの制約上、一度実行したウォッチドッグタイマーは停止しません。deinit()
はライブラリ手続きとして用意しています。(タイマーの再始動時などに deinit()
を実行してから init()
を再度呼び出す) set_timeout()
void set_timeout (uint32_t u32ms);
ウォッチドッグタイマーのタイムアウトまでの時間を変更します。u32ms
にはタイムアウト時間をミリ秒(ms)で指定します。
u32ms
の妥当性の検証はしません。init()
では0
を規定値としていましたが、本関数で0
を与えた場合の振る舞いは未定です。refresh()
ウォッチドッグタイマーのタイムアウトまでに必ず呼び出すリフレッシュ関数です。
class mwf::periph::wwdt (sys_ev_handler) on_sleep() WWDTの停止処理を行います。
on_wakeup() WWDTの始動処理を行います。
スリープ前に稼働状態の場合は、WWDTを再度稼働させます。 2.12 - class tick_counter - Stop Watch class tick_counter - Stop Watch
msec, usec 領域のごく短い処理時間を計測するために用います。マイコンのハードウェアのカウント機能を用いています。
class tick_counter - Stop Watch msec, usec 領域のごく短い処理時間を計測するために用います。マイコンのハードウェアのカウント機能を用いています。
本ライブラリコードについては、十分な確認の上、実験的な利用にとどめておくことを推奨します。最小30usec程度の単位での計測でよい場合は、ウェイクアップタイマーのカウント値が簡便です。
例:
#include <mwf_stop_watch.hpp>
void some_func () {
...
// 計測開始1
mwf:: periph:: tick_counter sw;
sw.lap(); // 計測開始1(直前の sw 構築時にも lap() は呼ばれるが、より厳密に処理の直前に lap() を呼び出す
... // 計測したい処理
sw.lap(); // 計測終了1
// 値の表示(計測開始1~計測終了1)
PRINTF("%dusec" , sw.get_us());
// 次の処理
sw.lap(); // 計測開始2
... // 計測したい処理
sw.lap(); // 計測終了2
// 値の表示(計測開始2~計測終了2)
PRINTF("%dusec" , sw.get_us());
}
_start_counter(), _stop_counter()
static void _start_counter ();
static void _stop_counter ();
CoreDebug機能を用い、カウントタイマーの開始と停止を行います。
tick_counter() コストラクタです。他に構築されたオブジェクトがなければカウンターを開始し、また、lap() を呼び出し計測を開始します。
~tick_couter() デストラクタです。すべてのクラスオブジェクトが破棄された時点でカウンターを停止します。
lap() 直前のカウント値を退避し、呼び出された時点でのカウント値を保存します。
経過時間は get_us()
により得ます。
2.13 - mwf-utils - utils mwf-utils - utils
その他ユーティリティ。
mwf_utils その他ユーティリティ。
prepare_object()
template < class T >
static inline std:: unique_ptr< T>& prepare_object(std:: unique_ptr< T>& spobj, bool b_construct_if_null = true) {
if (! spobj && b_construct_if_null) {
spobj.reset(new T());
}
return spobj;
}
スマートポインタstd::unique_ptr<>
のオブジェクトを参照します。オブジェクトが構築されていない場合は new T()
により構築します。
get_value_if()
// 関数などから値を得て、その値を用いて処理をすすめる場合
int v = some_func();
if (v != - 1 ) {
// v の値を用いてなにか処理をする
printf("%d" , v);
}
// 以下のように書き換える
if (auto x = get_value_if:: ne(some_func(), - 1 )) {
printf("%d" , x.value());
}
上記の例のように、関数の戻り値をある条件の場合に利用するときの記述を、if 節中の変数宣言を用いて記述するためのユーティリティクラスです。
上記の例では get_value_if::ne()
を用い、1つ目のパラメータは戻り値をもった関数呼び出し、2つ目のパラメータは比較する値を指定します。この場合 some_func()
の戻り値が -1
でない場合に if 節の中が評価されます。1つ目のパラメータと2つ目のパラメータの型は同じでなければなりません。
判定式により eq
, ne
, lt
, le
, gt
, ge
が利用できます。
get_value_if::xx()
(T は型)判定式 eq(T lhs, const T rhs)
(lhs == rhs)
値が同じであれば true ne (T lhs, const T rhs)
(lhs != rhs)
値が違っていれば true lt (T lhs, const T rhs)
(lhs < rhs)
値の比較、より小さい値なら true le (T lhs, const T rhs)
(lhs <= rhs)
値の比較、以下なら true gt (T lhs, const T rhs)
(lhs > rhs)
値の比較、より大きい値なら true ge (T lhs, const T rhs)
(lhs >= rhs)
値の比較、以上なら true
※ T
は型を示します (template 構文の型パラメータ)
3 - TWENETutils - TWENET ユーティリティ 一般的なアルゴリズムやペリフェラルの手続きを内包するライブラリ
このライブラリは一般的なアルゴリズムやペリフェラルの手続きなどが含まれます。
TWENETutils - TWENET ユーティリティ このライブラリは一般的なアルゴリズムやペリフェラルの手続きなどが含まれます。libTWENETutils.a に相当します。
3.1 - utils.h 始動関数 main(), WarmMain()
utils.h をインクルードすることで利用できるマクロ・関数を紹介します。
utils.h utils.h をインクルードすることで利用できるマクロ・関数を紹介します。
S_OCTET(x) 1バイトをメモリを書き込む。
uint8 * q = & sTx.au8Data[0 ];
S_OCTET(0x12 );
S_BE_WORD(0x1234 );
S_BE_DWORD(0x12345678 );
uint8 *q
をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。代入演算子の評価後 q++ が実行される。
S_BE_WORD(x) 2バイトをメモリを書き込む。
uint8 * q = & sTx.au8Data[0 ];
S_OCTET(0x12 );
S_BE_WORD(0x1234 );
S_BE_DWORD(0x12345678 );
uint8 *q をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。代入演算子の評価後 q+=2 が実行される。
BE はビッグエンディアン、LE はリトルエンディアン。
S_BE_DWORD(x) 4バイトをメモリを書き込む。
uint8 * q = & sTx.au8Data[0 ];
S_OCTET(0x12 );
S_BE_WORD(0x1234 );
S_BE_DWORD(0x12345678 );
uint8 *q
をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。代入演算子の評価後 q+=4 が実行される。
BE はビッグエンディアン、LE はリトルエンディアン。
G_OCTET() 1バイトメモリを読み込み uint8 型の変数に値を格納する。
uint8 * p = & sRx.au8Data[0 ];
uint8 u8data1 = OCTET();
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();
uint8 *p
をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。=
演算子の評価後 p++
が実行される。
G_BE_WORD() 2バイトメモリを読み込み uint16 型の変数に値を格納する。
uint8 * p = & sRx.au8Data[0 ];
uint8 u8data1 = OCTET();
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();
uint8 *p
をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。=
演算子の評価後 p+=2
が実行される。
BE はビッグエンディアン、LE はリトルエンディアン。
G_BE_DWORD() 1バイトメモリを読み込み uint8 型の変数に値を格納する。
uint8 * p = & sRx.au8Data[0 ];
uint8 u8data1 = OCTET();
uint16 u16data2 = G_BE_WORD();
uint32 u32data3 = G_BE_DWORD();
uint8 *p
をローカル変数として宣言しておき、データを読み込みたい領域のポインタとしておく。=
演算子の評価後 p+=4
が実行される。
BE はビッグエンディアン、LE はリトルエンディアン。
ENCODE_VOLT(x) 2000~3600 の値を 8bit 値に変換します。
1.95~2.80V は 5mV 刻み 2.81~3.65V は 10mV 刻み
// utils.h の定義
#define ENCODE_VOLT(m) \
(m < 1950 ? 0 : \
(m > 3650 ? 255 : \
(m <= 2802 ? ((m-1950+2)/5) : ((m-2800-5)/10+171)) ))
...
uint16 u16Volt = 2860 ;
uint8 u8Volt_enc = ENCODE_VOLT(u16Volt);
uint16 u16Volt_dec = DECODE_VOLT(u8Volt_Enc);
2000~2800 の値は 5 刻み、2800~は10 刻みで 8bit 値に割り当てます。
DECODE_VOLT(x) ENCODE_VOLT() により得られた8bit値を元の値に戻します。
1.95~2.80V は 5mV 刻み 2.81~3.65V は 10mV 刻み
// utils.h の定義
#define DECODE_VOLT(i) \
(i <= 170 ? (1950+i*5) : (2800+(i-170)*10) )
...
uint16 u16Volt = 2860 ;
uint8 u8Volt_enc = ENCODE_VOLT(u16Volt);
uint16 u16Volt_dec = DECODE_VOLT(u8Volt_Enc);
2000~2800 の値は 5 刻み、2800~は10 刻みで 8bit 値に割り当てます。
ポートcを入力に設定する
#define vPortAsInput(c) vAHI_DioSetDirection(1UL << (c), 0)
vPortAsOutput(c) ポートcを出力に設定する
#define vPortAsOutput(c) vAHI_DioSetDirection(0, 1UL << (c))
vPortSetHi(c) ポートcをHi状態にする
#define vPortSetHi(c) vAHI_DioSetOutput(1UL << (c), 0)
vPortSetLo(c) ポートcをLo状態にする
#define vPortSetLo(c) vAHI_DioSetOutput(0, 1UL << (c))
vPortSet_TrueAsLo(c, s) ポート c を s が TRUE なら Lo, FALSE なら Hi に設定する
#define vPortSet_TrueAsLo(c, s) vAHI_DioSetOutput((s) ? \
0 : 1UL << (c), s ? 1UL << (c) : 0)
bPortRead(c) ポート c を読み出す。Loレベルなら TRUE が返る
#define bPortRead(c) ((u32AHI_DioReadInput() & \
(1UL<<(c))) ? FALSE : TRUE)
u32PortReadBitmap() ポート c を読み出す。Loレベルなら TRUE が返る。
#define u32PortReadBitmap() (u32AHI_DioReadInput())
ビットマップの1がHi,0がLoとなります。
bPortCheckBitmap(bitmap, c) 読みだしたビットマップのポート c に対応するビットがLoレベルならTRUEを返す。
#define bPortCheckBitmap(bitmap, c) \
(bitmap & (1UL<<(c))) ? FALSE : TRUE)
vPortDisablePullup(c) ポート c のプルアップを停止する。
#define vPortDisablePullup(c) vAHI_DioSetPullup(0x0, 1UL << (c))
_C switch でスコープを定義したい場合 _C { … } と記述している。
// for example
switch (c) {
case 1 :
_C {
uint8 u8work;
; // work
} break ;
default :
}
LB 改行コード (CRLF) 文字列です。
2バイトの文字列リテラルですので、vPutChar () では利用できません。
vWait()関数 ループによる時間待ちを行います。
void vWait (uint32 c) {
static volatile uint32 u32ct = 0 ;
while (c-- > 0 )
u32ct++ ;
}
処理内容はソースコードの通りです。
vAnalogueConfig(), vAnalogueDisable() ADC機能の初期化と停止を行う手続きをまとめています。既存コードの互換性を目的としています。
void vAnalogueConfig (void ) {
#if defined(JN516x)
if (! bAHI_APRegulatorEnabled()) {
vAHI_ApConfigure(E_AHI_AP_REGULATOR_ENABLE,
E_AHI_AP_INT_DISABLE,
E_AHI_AP_SAMPLE_4,
E_AHI_AP_CLOCKDIV_1MHZ,
E_AHI_AP_INTREF);
while (! bAHI_APRegulatorEnabled())
;
}
#elif defined(CPU_JN518X)
#endif
void vAnalogueDisable(void ) {
#if defined(JN516x)
vAHI_ApConfigure(E_AHI_AP_REGULATOR_DISABLE,
E_AHI_AP_INT_DISABLE,
E_AHI_AP_SAMPLE_4,
E_AHI_AP_CLOCKDIV_1MHZ,
E_AHI_AP_INTREF);
#elif defined(CPU_JN518X)
#endif
}
その他マクロ定義
// 64bit mac address
#define MAC_EXT_ADDR_TO_64BIT(ext) ((uint64)(ext.u32L) | (((uint64)(ext.u32H)) << 32))
// TIME COMPARE
#define u32TimeDiff(ref, now) (now - ref < 0x7FFFFFFF ? now - ref : )
// IO settings
#define vPortSetHi(c) vAHI_DioSetOutput(1UL << (c), 0)
#define vPortSetLo(c) vAHI_DioSetOutput(0, 1UL << (c))
#define vPortSet_TrueAsLo(c, s) vAHI_DioSetOutput((s) ? 0 : 1UL << (c), s ? 1UL << (c) : 0)
#define vPortAsInput(c) vAHI_DioSetDirection(1UL << (c), 0)
#define vPortAsOutput(c) vAHI_DioSetDirection(0, 1UL << (c))
#define bPortRead(c) ((u32AHI_DioReadInput() & (1UL<<(c))) ? FALSE : TRUE) // Lo as True
#define u32PortReadBitmap() (u32AHI_DioReadInput())
#define bPortCheckBitmap(bitmap, c) ((bitmap & (1UL<<(c))) ? FALSE : TRUE)
#define vPortDisablePullup(c) vAHI_DioSetPullup(0x0, 1UL << (c))
#if defined(JN516x) || defined(CPU_JN518X)
#define PORT_KIT_SW1 2
#define PORT_KIT_SW2 3
#define PORT_KIT_SW3 10
#define PORT_KIT_SW4 9
#define PORT_KIT_LED1 17
#define PORT_KIT_LED2 13
#define PORT_KIT_LED3 12
#define PORT_KIT_LED4 11
#endif
#define PORT_KIT_SW1_MASK (1UL << PORT_KIT_SW1)
#define PORT_KIT_SW2_MASK (1UL << PORT_KIT_SW2)
#define PORT_KIT_SW3_MASK (1UL << PORT_KIT_SW3)
#define PORT_KIT_SW4_MASK (1UL << PORT_KIT_SW4)
#define PORT_KIT_SW_ALL2_MASK (PORT_KIT_SW1_MASK | PORT_KIT_SW2_MASK)
#define PORT_KIT_SW_ALL4_MASK (PORT_KIT_SW1_MASK | PORT_KIT_SW2_MASK | PORT_KIT_SW3_MASK | PORT_KIT_SW4_MASK)
#define PORT_KIT_LED1_MASK (1UL << PORT_KIT_LED1)
#define PORT_KIT_LED2_MASK (1UL << PORT_KIT_LED2)
#define PORT_KIT_LED3_MASK (1UL << PORT_KIT_LED3)
#define PORT_KIT_LED4_MASK (1UL << PORT_KIT_LED4)
#define PORT_KIT_LED_ALL2_MASK (PORT_KIT_LED1_MASK | PORT_KIT_LED2_MASK)
#define PORT_KIT_LED_ALL4_MASK (PORT_KIT_LED1_MASK | PORT_KIT_LED2_MASK | PORT_KIT_LED3_MASK | PORT_KIT_LED4_MASK)
// UART related
#define WAIT_UART_OUTPUT(P) SERIAL_vFlush(P)
// IO clock (on JN514x, IO runs at 16Mhz regardless of CPU clock.
#if defined(JN516x)
#define u32IO_FREQ_HZ 16000000UL
#elif defined(CPU_JN518X)
//#define u32IO_FREQ_HZ 32000000UL
#define u32IO_FREQ_HZ 16000000UL
#endif
void vAnalogueConfig (void );
void vAnalogueDisable (void );
void vWait (uint32 c);
3.2 - Timerライブラリ Timerライブラリ
Timer
ライブラリを紹介します。
Timerライブラリ tsTimerContext
Timer
ライブラリで用いる設定用の構造体。
型 名前 解説 uint8
u8Device
タイマーデバイスを指定する (E_AHI_DEVICE_TIMER0
.. 4)。 uint16
u16Hz
タイマー周波数を Hz で指定する。 uint8
u8PreScale
16Mhz クロックに対するプリスケールを設定する。 bool_t
bPWMOut
TRUE
なら PWM 出力を行う。bool_t
bDisableInt
TRUE
なら割り込みを禁止する。
vTimerConfig()
解説 Timer
の初期化を行う。
引数 型 名前 詳細 tsTimerContext
psTC
タイマー設定の構造体。
戻り値 なし
サンプル
tsTimerContext sTimerApp; // global or static allocation
// set 64ticks/sec
memset (& sTimerApp, 0 , sizeof (tsTimerContext));
sTimerApp.u8Device = E_AHI_DEVICE_TIMER0;
sTimerApp.u16Hz = 64 ;
sTimerApp.u8PreScale = 4 ; // 15625ct@2^4
vTimerStart()
解説 Timer
を開始する。
本関数は、既に開始済みのTimer
についても呼び出し可能です。Duty 比の変更を行う場合などに利用します。
引数 型 名前 詳細 tsTimerContext
psTC
タイマー設定の構造体。
戻り値 なし
サンプル
// initialize and start
vTimerConfig (& sTimerApp); // initialize
vTimerStart (& sTimerApp); // start
// change duty
sTimerPWM.u16Duty = 256 ; // set new duty ratio
vTimerStart (& sTimerPWM); // just start again to change duty
vTimerStop()
解説 Timer
の動作を停止する。
引数 型 名前 詳細 tsTimerContext
psTC
タイマー設定の構造体。
戻り値 なし。
サンプル
// just stop the timer
vTimerStop (& sTimerApp);
...
// restart
vTimerStart (& sTimerApp);
...
// now, disable timer completely
vTimerStop (& sTimerApp);
vTimerDisable (& sTimerApp);
vTimerDisable()
Timer
を破棄する。
引数 型 名前 詳細 tsTimerContext
psTC
タイマー設定の構造体。
戻り値 なし
サンプル
// just stop the timer
vTimerStop (& sTimerApp);
...
// restart
vTimerStart (& sTimerApp);
...
// now, disable timer completely
vTimerStop (& sTimerApp);
vTimerDisable (& sTimerApp);
3.3 - fprintf ライブラリ fprintf ライブラリ
fprintf
の簡易的な実装です。
fprintf ライブラリ fprintf
の簡易的な実装です。
本ライブラリは、ソースコードの互換性のために用意しています。新規実装には TWENETmcu/printf
の利用を推奨します
参考 tsFILE vfPrintf()
vPutChar()
で指定する出力先を定義した構造体。
メンバー 型 名前 詳細 uint8
u8Device
シリアルポート (E_AHI_UART_0
または E_AHI_UART_1
を指定する) bool_t (*) (uint8 u8Device, uint8 u8Char)
bPutChar
出力用の関数ポインタ。SERIAL
ライブラリ用には SERIAL_bTxChar()
が準備されているので、これを指定する。
{% hint style=“info” %}
SERIAL_bTxChar()
は、u8Char
として渡されたバイトを SERIAL
ライブラリ内の FIFO キューに投入します。
独自に出力関数を準備することで、UART 以外への文字列の出力にも利用できます。
{% endhint %}
サンプルコード
#include "serial.h"
#include "fprintf.h"
tsFILE sSerStream;
tsSerialPortSetup sSerPort;
void vSerialInit (uint32 u32Baud, tsUartOpt * pUartOpt) {
// initialize sSerPort
...
SERIAL_vInit (& sSerPort);
// for vfPrintf()
sSerStream.bPutChar = SERIAL_bTxChar;
sSerStream.u8Device = E_AHI_UART_0;
}
void vSerOut () {
vfPrintf (& sSerStream, "HELLO!" );
}
以下は、キャラクタ LCD の出力コードとして利用した一例です。
#include "serial.h"
#include "fprintf.h"
tsFILE sLcdStream;
// handle LCD display
PUBLIC bool_t LCD_bTxChar (uint8 u8Device, uint8 u8Data) {
int i;
switch (u8Data) {
case '\n' :
...
}
void vInitHardware () {
/* Initialise the LCD */
vLcdReset (3 , 0 );
/* register for vfPrintf() */
sLcdStream.bPutChar = LCD_bTxChar;
sLcdStream.u8Device = 0xFF ;
}
void vSomeOutput () {
vfPrintf (& sLcdStream, "Hello World! \n " );
}
vfPrintf() 解説 tsFILE
構造体の示す出力先(UART)に printf
書式にて出力する。
引数 型 名前 詳細 tsFILE*
psStream
出力先 const char *
pcFormat
出力書式 … 可変引数
対応する書式 s
文字列 d
整数(32bitまで) u
符号なし整数(32bitまで) x
16進数。a-f
は小文字。 X
16進数。A-F
は大文字。 b
bit列
戻り値 なし。
サンプル
void cbToCoNet_vMain (void ) {
while (! SERIAL_bRxQueueEmpty (sSerPort.u8SerialPort)) {
int16 i16Char;
i16Char = SERIAL_i16RxChar (sSerPort.u8SerialPort);
vfPrintf (& sSerStream, " \n\r ## [%c] --> " , i16Char);
SERIAL_vFlush (sSerStream.u8Device);
...
}
}
vPutChar() 解説 tsFILE
構造体の示す出力先(UART)に1バイト出力する。
引数 型 名前 詳細 tsFILE*
psStream
出力先 uint8
u8Char
出力バイト
戻り値 なし
サンプル
#define IS_ASC(c) ((c) >= 0x20 && (c) <= 0x7e)
void cbToCoNet_vRxEvent (tsRxDataApp * pRx) {
uint8 u8i;
vfPrintf (& sSerStream, LB"RX(len=%d):[" , pRx-> u8Len);
for (i = 0 ; i < pRx-> u8Len; i++ ) {
uint8 c = pRx-> auData[i];
vPutChar (& sSerStream, IS_ASC (c) ? c : '.' );
}
}
4 - TWENETcmpt - AHI互換レイヤー BLUE / RED シリーズと互換性のある API を提供する GOLD シリーズ向けの互換レイヤー
TWENETライブラリ TWENETcmpt の解説。TWELITE BLUE/RED で利用されていた AHI 関数の一部を TWELITE GOLD で利用できるようにするものです。
TWENETcmpt - AHI互換レイヤー AHIライブラリの互換性を目的としたライブラリです。
TweApps のビルド、動作を目的としており包括的な互換性を達成することは目的としてません。 実装には TWENETmwfライブラリ(fslライブラリにより実装されたC++ライブラリ)を用いています。 以下には、互換レイヤーの諸定義について留意事項を記述しています。
4.1 - AHI互換関数 TWENETライブラリ、AHI互換レイヤーの解説
AHI互換関数全般の話題及び特定のペリフェラル等に属さないAHI関数の解説です。
AHI互換関数 AHI 関数群の一部について、ソースコードの互換を目的として実装しています。
本ライブラリの実装は、 fsl ドライバの手続きをまとめた TWENETmwf ライブラリを用いて実装されています。 この実装は完全な互換性を保つことを目的とはしていません。 独自拡張を行った関数は関数名に _MW
を付記しています。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 TWELITE GOLD 特有の話題や FSL ライブラリ、またマイコンコアなどの振る舞いについては、NXP社のJN5189半導体マニュアル及び TWENETmcu ライブラリの実装を参照してください。 以下には AHI 互換関数について記載しています。SPI, I2C などは別ファイルに記載しているものもあります。
一般関数 u32AHI_Init()
本来AHIライブラリの初期化を行いますが、本ライブラリでは一部の変数の初期化のみを実施します。
bAHI_SetClockRate(), u8AHI_GetSystemClkRate()
bool_t bAHI_SetClockRate (uint8 u8clk_code);
uint8 u8AHI_GetSystemClkRate ();
CPUのクロック速度を設定または設定値の取得を行います。
設定されるクロックは以下のようになります。TWELITE BLUE/REDの設定とは大きく異なるため注意が必要です。
u8clk_code
TWELITE BLUE/RED TWELITE GOLD 0
4Mhz 12Mhz 1
8Mhz 12Mhz 2
16Mhz 32Mhz 3
32Mhz 48Mhz 4..
設定有り 無視される
kFROM1M_to_MAIN_CLK
といったクロックも fsl ライブラリ内では設定可能ですが、動作に大きな難があるため設定できないようにしています。デバッガを利用するような場合は、クロック変更に支障が出る場合があります。 規定値は 2、32Mhz (TWELITE GOLD) です。(参考:TWELITE BLUE/REDでは 16MHz) bAHI_Set32KhzClockMode()
bool_t bAHI_Set32KhzClockMode (uint8 u8mode);
なにもしません。
vAHI_CpuDoze()
static inline void vAHI_CpuDoze () { __WFI(); }
割り込み待ち低電力待機 DOZE 状態に入ります。TWELITE-GOLD では WFI (割り込み待ち) を発効します。
vAHI_SwReset()
static inline void vAHI_SwReset () { NVIC_SystemReset(); }
リセットを行います。
電源関係 u16AHI_PowerStatus()
uint16 u16AHI_PowerStatus ();
本関数では、以下のビットマップを報告します。
ビット 解説 bit0 スリープからの復帰時に 1 bit1 RAMが保持されていた場合に 1
POR 時は 0
、通常のRAM保持スリープからの復帰は 3
になります。
static inline void vAHI_BrownOutConfigure (
uint8 const u8VboSelect,
bool_t const bVboRstEn,
bool_t const bVboEn,
bool_t const bVboIntEnFalling,
bool_t const bVboIntEnRising) { ; } // DUMMY FUNC
コンパイルエラー回避のための定義です。この関数は何もしません。
スリープについて
void ToCoNet_vSleep(uint8 u8Device, uint32 u32Periodms, bool_t bPeriodic, bool_t bRamOff)
スリープは TWENET C ライブラリでは ToCoNet_vSleep()
関数を用います。
※ mwxライブラリでは the_twelite.sleep()
を用います。
bRamOff
はTRUEを指定した場合、全てのRAMセグメントを保持しない形でスリープを行います。なお、この場合もJN518x FSL ライブラリ定義のPM_POWER_DOWN
を用いPM_DEEP_DOWN
は使用しません。スリープの失敗について(TWELITE GOLD) TWELITE GOLD では、スリープ遷移の半導体ライブラリ中の手続き(POWER_EnterPowerMode()
)が稀に失敗し、スリープが行われません。そのため以下の対処を行っています。
半導体ライブラリの手続き失敗時は関数呼び出しからそのまま抜けてしまうが、100usec 相当(DelayLoopN(100)
)のループ待ちを行った後、再度スリープの手続きを実行します。 上記を3回 試行して失敗した場合は ToCoNet_vSleep()
は無限ループを呼び出し、通常はウォッチドッグタイマーによるリセットが発生します。当社では、2回または3回の再試行は確認されていませんが、念のため3回までとしています。 上記スリープ手続きが行われた場合、スリープ復帰後 extern uint8 g_twenet_power_down_fails;
の値が0
以外であれば、上記の再試行が行われていたことを示します。但し、ウォッチドッグタイマーによるリセット時はこの変数は初期化されます。 内部処理用 u32AppApiInit()
uint32
u32AppApiInit (PR_GET_BUFFER prMlmeGetBuffer,
PR_POST_CALLBACK prMlmeCallback,
void * pvMlmeParam,
PR_GET_BUFFER prMcpsGetBuffer,
PR_POST_CALLBACK prMcpsCallback,
void * pvMcpsParam);
AppQAPIの初期化処理を行います。
vAHI_RegEvMgr_MW()
TWENETmwfライブラリでのクラスオブジェクトを管理するための管理オブジェクト(mwf::the_sys_ev_manager
)を構築します。
vAHI_OnWakeup_MW(), vAHI_OnWakeupRamOff_MW()
void vAHI_OnWakeup_MW (bool_t b_init_2nd);
void vAHI_OnWakeupRamOff_MW (bool_t b_init_2nd);
起床時に実施する手続きです。TWENETmcuのtwenet_main.cの処理を参照してください。
TWENETmwf ライブラリ内のクラスオブジェクトの起床時処理mwf::the_sys_ev_manager->on_wakeup()
を行います。 vAHI_DioOnWakeup_MW()
を呼び出します。起床要因のピンを保存します。b_init_2nd
がFALSEの場合は始動初期の段階の呼び出しで、TRUEの場合はある程度の初期化が終わった時点(cbAppWarmStart(TRUE)
呼び出し前)での呼び出しになります。vAHI_OnWakeupRamOff_MW()
はRAM非保持スリープ復帰時に呼び出されます。
b_init_2nd
がFALSEの場合は始動初期の段階の呼び出しで、TRUEの場合はある程度の初期化が終わった時点(cbAppWarmStart(TRUE)
呼び出し後 )での呼び出しになります。vAHI_OnSleep_MW()
スリープ前に実施する手続きです。
TWENETmwf ライブラリ内のクラスオブジェクトのスリープ前処理mwf::the_sys_ev_manager->on_sleep()
を行います。 vAHI_DioOnSleep_MW()
を呼び出します。DIO起床ピンの設定をします。vAHI_DMAEnable_MW(), vAHI_DMADisable_MW()
void vAHI_DMAEnable_MW ();
void vAHI_DMADisable_MW ();
DMA機能の有効化と無効化を行います。
vAHI_DMADisable_MW()
は何も実行しません。
4.2 - ADC関連のAHI関数と解説 TWENETライブラリ、ADC関連のAHI関数と解説
TWENETライブラリ、ADC関連のAHI関数と解説です。
ADC AHI の ADC(アナログディジタル変換) 関連の一部について、ソースコードの互換を目的として実装しています。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 概要 ADCのハードウェア仕様はモデルによって違いがあります。
TWELITE BLUE TWELITE RED TWELITE GOLD ビット数 10bit 10bit 12bit フルスケール 2470mV 2470mV 3600mV チャネル数 (API未サポート) 4 4 (2) 4 (2)
本ライブラリでは ADC0..3 までの4チャネルと Vcc を利用するための処理を記述しています。ただし、変換時間や変換データの互換性まではライブラリでは実施せず、アプリケーションソースで調整する前提です。
なお6ピンまでの変換や、複数チャネルをまとめた ADC、AHIライブラリでは対応せずmwf::the_adc
を直接利用するようにしてください。
関連:オンチップ温度センサー
ピン PIO 備考 ADC0 15 ADC1 14 DIO8と共用 ADC2 16 ADC3 17
AHIcmpt_ADC.cpp 本ライブラリ内では、TWELITE BLUE/RED の AHI ライブラリとの違いについて記述します。APIの仕様については、AHIライブラリマニュアルも参照ください。
void vAHI_ApConfigure (
bool_t bAPRegulator,
bool_t bIntEnable,
uint8 u8SampleSelect,
uint8 u8ClockDivRatio,
bool_t bRefSelect);
ADCの初期化(mwf::the_adc
オブジェクトの構築と the_adc->init()
初期化)を行います。
bAPRegulator
をTRUEに指定するとADCを有効化します。FALSEにした場合はADCを無効化します。bIntEnable
をTRUEに指定するとADC割り込みが有効になります。u8SampleSelect
とbRefSelect
は無視されます。u8ClockDivRatio
も現時点では設定が反映されません。bAHI_APRegulatorEnabled()
を用いたアナログ回路の安定化待ち処理は必要です。bAHI_APRegulatorEnabled()
bool_t bAHI_APRegulatorEnabled(void )
ウェイクタイマを用いたFRWTを動作していない場合は(Cライブラリでは標準)、固定時間の待ち処理を行います(300usec)。この場合vAHI_ApConfigure()
呼び出し直後に本関数を呼び出すことを推奨します。相応の時間経過後であっても固定時間の待ち処理を行います。
FRWTを有効化している場合は、タイマカウント値に基づき、必要な待ち処理を行います。相応の時間経過後は、本関数内の待ち処理は行いません。
vAHI_APRegisterCallback()
void vAHI_APRegisterCallback (PR_HWINT_APPCALLBACK prApCallback);
割り込みハンドラを登録します。ADC完了時に呼び出されます。
vAHI_AdcEnable()
void void vAHI_AdcEnable (
bool_t bContinuous,
bool_t bInputRange,
uint8 u8Source);
ADCの変換設定を行います。
bContinuous
を選択すると連続変換しますが、内部的な割り込みが変換都度発生するため、パフォーマンス面で注意が必要です。bInputRange
を指定しても、そういったハードウェア機能がないため反映されません。この呼出時にu8Source
に対応したピンがADC用として設定されます。 vAHI_ApConfigure()
実行後にbAHI_APRegulatorEnabled()
を未実行で待ち処理が実行されなかった場合は、本呼び出しにて待ち処理を行います。vAHI_AdcDisable()
void vAHI_AdcDisable (void );
ADCを停止します。
vAHI_AdcStartSample()
void vAHI_AdcStartSample (void );
ADCの変換開始を行います。
原則として初期化時は入力状態ですが、厳密には TWENETmcu ライブラリの pinmux.c BOARD_InitPins()
の初期化状態が規定値になります。 bAHI_AdcPoll()
bool_t bAHI_AdcPoll (void );
ADC完了待ちを行うポーリング待ち処理while(bAHI_AdcPoll());
に使用します。
ADC完了の割り込み後、本呼び出しは1度だけ FALSE を返します。 u16AHI_AdcRead(), i16AHI_AdcRead_mv()
uint16 u16AHI_AdcRead (void );
int16 i16AHI_AdcRead_mv (void ); // 非AHI独自関数
実行したADC値を読み出します。
u16AHI_AdcRead()
は ADC 値を 12bit (0..4095) で返します。エラー時は 0xffff
を戻します。i16AHI_AdcRead_mv()
は AHI ライブラリにはない独自関数で、ADC値を mV で返します。エラー時は -32768
を戻します。s_adc_int_handler()
static void s_adc_int_handler (uint32_t a1, uint32_t a2);
AHIcmpt_ADC.cpp
で定義された静的関数で、ADC完了時に呼び出される割り込みハンドラとして、TWENETの AppQApi に割り込みを伝達します。
vAHI_APRegisterCallback()
にてコールバック関数が指定されいている場合は、呼び出されません。実験的な実装 複数チャネル一括処理
// TWELITE GOLD 専用
// FSLドライバ機能を用いて複数チャネルのADC取得を一括で行う。
// ADC実行(パラメータはvAHI_AdcEnable()と同様)
void vAHI_AdcEnableSeq (
bool_t bContinuous,
bool_t bInputRange,
uint32 u32MaskSource);
// ADC値の読出し
uint16 u16AHI_AdcReadSeq (
uint8 u8Source
);
// ADC値の読出し (mV値にて)
int16 i16AHI_AdcReadSeq_mv (
uint8 u8Source
);
sensor_driver, adc.c, adc.h sensor_driver
は既存のTWEAppsアプリケーションなどで利用される処理関数群で、センサー処理の抽象化するためのメカニズムを提供しています。adc.c
,.h
は、sensor_driver
でチップ内ADCを動作させるために、一連のコマンド発行、待ち、データ取得といった順序処理を記述したものです。なお TWENETmwx/sensors/legacy
以下には ADC 以外のいくつかのセンサー向けの実装が含まれます。
TWELITE BLUE/REDのプロジェクトをTWELITE GOLDに移行する場合は、App_Twelite/Common
に格納された調整済みのファイルを利用下さい。但し、プロジェクトごとに内容が違う場合があるため、修正等が必要になる場合があります。
ソース名 内容 adc.c
adc処理部分 (ADC値の変換部分は TWELITE GOLD の値域に合わせている) adc.h
定義部 sensor_driver.c
センサー処理抽象化部分 sensor_driver.h
定義部
コード例 以下のコード中のコメントを参照してください。
#include "sensor_driver.h"
#include "adc.h"
tsObjData_ADC sObjADC; // ADC管理構造体(データ部)
tsSnsObj sADC; // ADC管理構造体(制御部)
int16 a1,a2,ab; // 結果格納用
...
// ADC 初期化
vSnsObj_Init(& sADC);
vADC_Init(& sObjADC, & sADC, TRUE);
vADC_WaitInit(); // ハード初期化待ちを行う
...
// ADC計測したいポートの指定(以下では電源電圧とADC1,2)
sObjADC.u8SourceMask = TEH_ADC_SRC_VOLT
| TEH_ADC_SRC_ADC_1 | TEH_ADC_SRC_ADC_2;
// ADC開始
vSnsObj_Process(& sADC, E_ORDER_KICK); // 開始の号令
// ADCの1チャネル処理が終わるのを待って(=E_AHI_DEVICE_ANALOGUE割り込み)
// vSnsObj_Process() を順次呼び出す。
void cbToCoNet_vHwEvent (uint32 u32DeviceId, uint32 u32ItemBitmap) {
switch (u32DeviceId) {
case E_AHI_DEVICE_ANALOGUE:
// ADC完了割り込み
vSnsObj_Process(& sADC, E_ORDER_KICK);
if (bSnsObj_isComplete(& sADC)) {
// 全チャネルの処理が終わった。
// 値は以下に格納される
a1= sObjADC.ai16Result[TEH_ADC_IDX_ADC_1]; // ADC1[mV]
a2= sObjADC.ai16Result[TEH_ADC_IDX_ADC_2]; // ADC2[mV]
ab= sObjADC.ai16Result[TEH_ADC_IDX_VOLT]; // 電源電圧[mV]
// ADC開始前の初期状態に戻す
vSnsObj_Process(& sADC, E_ORDER_KICK);
// 連続して実行する場合はもう一度E_ORDER_KICK
vSnsObj_Process(& sADC, E_ORDER_KICK);
}
break ;
default :
break ;
}
}
関数 vSnsObj_Init()
void vSnsObj_Init(tsSnsObj * pSnsObj)
センサー管理構造体を初期化します。vADC_Init()
の直前に呼び出します。
vADC_Init()
void vADC_Init(tsObjData_ADC * pData, tsSnsObj * pSnsObj, bool_t bInitAPR)
ADCの初期化を行います。tsObjData構造体(結果格納用)とtsSnsObj構造体(ADC管理)はあらかじめ用意しておきます。
bInitAPRはTRUEの場合、ADCハードウェアの初期化を行います。ハードウェアの初期化には若干の時間が必要ですので、必ずvADC_WaitInit()を実行して初期化を待ちます。 vSnsObj_Process()
void vSnsObj_Process(tsSnsObj * pObj, teEvent eEv)
ADC処理の進捗させる。具体的には、ADCの1ポート分の変換完了するたびに本処理を呼び出す。
本処理中で、ADC値の取得と mV値への演算処理が行われ、tsSnsObj
構造体中に値が格納される。
本処理は、tsSnsObj
構造体で管理される状態遷移に対するイベント処理になる。本処理直後にbSnsObj_isComplete()
を呼び出し処理が完了したかを確認する。再び初期状態に戻すには、改めてE_ORDER_KICK
を引数として本処理を実行する(つまりADCを再度実行するには完了後にE_ORDER_KICK
を2回実行することになる)。
tsObjData_ADC
構造体この構造体には、指定する ADC チャネル、結果として得られる電圧値が含まれます。
u8SourceMask
:ADC対象のポートを指定するビットマップ。指定したポートがADC対象となる。- TEH_ADC_SRC_VOLT : 電源電圧- TEH_ADC_SRC_ADC_1-4
: ADC1,2,3,4u8InputRangeMask
:ADC対象のポートのレンジ(0-Vrefまたは0-2Vref)を指定する。指定したポートは0-Vrefとなる。未指定の場合 0-2Vref となる。ai16Result[]
:ADC値を保存する構造体。結果はmV値として格納される。- TEH_ADC_IDX_VOLT : 電源電圧- TEH_ADC_IDX_ADC_1-4
: ADC1,2,3,44.3 - DIO (GPIO)関連のAHI関数と解説 TWENETライブラリ、DIO (GPIO)関連のAHI関数と解説
TWENETライブラリ、DIO (GPIO)関連のAHI関数と解説です。
DIO (GPIO) AHI の DIO (GPIO) 関連の一部について、ソースコードの互換を目的として実装しています。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 本解説で PIO と DIO という2つの用語が出てきます。PIO: TWELITE GOLD の使用半導体で定義されているピン番号で、FSLライブラリなどでは全てこのピン番号を用いる。 DIO: TWELITE BLUE/RED での AHI API でも使用するピン番号です。当ライブラリでは TWELITE BLUE/RED のソースコードの互換性を保つために DIO から PIO の変換、またはその反対を行っています。 概要 ピンの割当については TWELITE BLUE/RED とは違うアーキテクチャになっています。ここでは TWELITE BLUE/RED で使用したピンを DIO0..19/DO0..1/ADC0…3、TWELITE GOLD の半導体でのピン名を PIO0..21 と記載します。ピンの詳細は、各モジュール利用の半導体データシートを参照ください。
モジュール上のピンの対応が1:1にならない部分がある。PIO0 は DIO11 と DO0 で共用。 PIO14 は DIO8 と ADC1 で共用。 DIO割り込みについて、以下の相違点がある。DIO0..19まで独立した割り込みが可能であったが、そういった機能は存在しないため GINT (グループ割り込み) 機能を用いて、類似の動作を実現している。(他に独立した割り込みが可能な PINT という機能があるが4ポートまでの利用なので、本ライブラリでは使用していない) ハードウェアの割り込み検出は両エッジのみであるため、いずれかのエッジで内部割込みが発生する。稼働中(スリープしていない)の場合は、割り込み発生後のピンの状態で AHI の割り込みハンドラを呼び出すか決めているため、両エッジであることは表面的に見えません。 スリープ起床でのエッジは指定できません。 ピンの割当 DIO DIO PIO 備考 DIO0 0 16 DIO1 1 17 DIO2 2 18 DIO3 3 19 DIO4 4 7 DIO5 5 6 DIO6 6 8 DIO7 7 9 DIO8 8 14 ADC1と共用 DIO9 9 12 DIO10 10 4 DIO11 11 0 DO0と共用 DIO12 12 13 DIO13 13 1 DIO14 14 10 DIO15 15 11 DIO16 16 20 DIO17 17 21 DIO18 18 2 DIO19 19 3 DO0 (PROG) 0 DIO11と共用 DO1 5 ADC2 14 DIO8と共用 ADC1 15
AHIcmpt_Dio.cpp - 定義・定数 定義
#define BOARD_GPIO_PORT_MAX_PIN_COUNT 22 // ピン数
#define BOARD_GPIO_PIN_TABLE_SIZE 24 // ピン数22を4の倍数で切り上げたもの
g_twenet_ioport_remap_by_PIOn[]
const uint8 g_twenet_ioport_remap_by_PIOn[BOARD_GPIO_PIN_TABLE_SIZE];
(ライブラリ内部使用)PIO番号をDIO番号に変換するテーブル。
0x80: SPIMISO ピン 0x90: ADC1ピン (アナログ専用) 0xFF: 未使用・未定義 g_twenet_ioport_remap_by_AHIn[]
const uint8 g_twenet_ioport_remap_by_AHIn[BOARD_GPIO_PIN_TABLE_SIZE];
(ライブラリ内部使用)AHI番号からPIO番号を参照するテーブル。
AHIcmpt_Dio.cpp - 定義 変数
uint32 G_TWENET_IOPORT_OUTPUT_BM () = 0 ; // 出力ポート一覧のDIOビットマップ
uint32 G_TWENET_IOPORT_INT_ENABLED_BM () = 0 ; // 割り込み有効ポート一覧のDIOビットマップ
uint32 G_TWENET_IOPORT_INT_RISING_BM () = 0 ; // 立ち上がり割り込み有効のDIOビットマップ
uint32 G_TWENET_IOPORT_INT_FALLING_BM () = 0 ; // 立ち下がり割り込み有効のDIOビットマップ
volatile uint32 G_TWENET_IOPORT_INT_STATUS () = 0 ; // DIO割り込み起床した場合の、起床ピンを記録したDIOビットマップ
uint32 G_TWENET_IOPORT_WAKE_STATUS () = 0 ; // 起床時のIO割り込み要因を保存したDIOビットマップ
DIOビットマップはビットnがDIOnに対応します (例: DIO0, 3 なら (1UL << 0) | (1UL << 3)
) check_pio(), get_pio(), get_dio()
static inline bool check_pio (uint8 u8pio);
static inline uint8 get_pio (const uint8 u8dio);
static inline uint8 get_dio (const uint8 u8pio);
check_pio()
: 指定された PIO が有効な番号か、また、他のペリフェラルで使用済みかどうかを判定するインライン関数。get_pio()
: 指定された DIO 番号に対応する PIO 番号を返します。無効な割当である場合は 0xff
を返します。get_dio()
: 指定された PIO 番号に対応する DIO 番号を返します。無効な割当である場合は 0xff
を返します。s_gpio_int_handler()
static void s_gpio_int_handler (uint32 bm_pio, uint32 bm_pio_changed, void * p_data);
DIO割り込み発生時に内部的に呼び出される割り込み処理関数。
ピンの変化がある場合は __twenet_vAppQApiPostHwIntT()
を用いて、AppQAPI 経由で割り込み情報を伝達します。 AHIcmpt_Dio.cpp - AHI関数定義 vAHI_DioSetDirection()
void vAHI_DioSetDirection (
uint32 u32Inputs,
uint32 u32Outputs);
ポートの入出力を設定します。
原則として初期化時は入力状態ですが、厳密には TWENETmcu ライブラリの pinmux.c BOARD_InitPins()
の初期化状態が規定値になります。 vAHI_DioSetOutput()
void vAHI_DioSetOutput ( // u32On:HIGH, u32Off::LOW
uint32 u32On,
uint32 u32Off);
ポートの出力状態を変更します。u32On
はHIGHレベルに変更するDIOビットマップ、u32off
はLOWレベルに変更するDIOビットマップです。
複数のピンを指定した場合はピンの変化は同時では有りません。内部実装として、ループ内で1ピンずつ設定されるためです。 vAHI_DioSetPullup()
void vAHI_DioSetPullup (
uint32 u32On,
uint32 u32Off);
プルアップ状態を設定します。
原則としてプルアップ有りの設定ですが、厳密には TWENETmcu ライブラリの pinmux.c BOARD_InitPins()
の初期化状態が規定値になります。
uint32 u32AHI_DioReadInput (void );
すべてのポートの状態を一度に取得します。
戻り値が全ポートの状態を示すビットマップで1
になっているビットがHIGHレベル、0
がLOWレベルです。 存在しないDIO番号やペリフェラルなどで使用中のポートの値は未定義です。 vAHI_DioWakeEnable()
void vAHI_DioWakeEnable (
uint32 u32Enable,
uint32 u32Disable);
DIO割り込みを開始します。u32Enable
には割り込み処理を追加するDIOビットマップ、u32Disable
には割り込み処理を除外するDIOビットマップを指定します。加えて割り込みを有効にしたピンに対して vAHI_DioWakeEdge()
により割り込みエッジを指定する必要があります。
入力設定ピンでないピン(出力ピンや他のペリフェラル機能が割り当てられているピン)を指定した時の振る舞いは未定です。 vAHI_DioWakeEdge()
void vAHI_DioWakeEdge (
uint32 u32Rising,
uint32 u32Falling);
割り込みピンの設定を行います。この呼び出しでは、指定したピンに対して立ち上がり立ち下がり設定を一度に行います。追加や削除は出来ないことに注意してください。
本関数名には Wake が含まれますが、稼働中の割り込みの処理と、スリープ復帰の処理の両方を設定します。
動作原理上 u32Rising
とu32Falling
に同一ピンを指定した場合は、双方のエッジで割り込みが発生します。(ただし、AHIでの有効な設定ではないため、動作検証外とします) 割り込み動作中はvAHI_DioWakeEnable()
が内部的に呼び出され再設定されます。 入力設定ピンでないピン(出力ピンや他のペリフェラル機能が割り当てられているピン)を指定した時の振る舞いは未定です。 スリープ復帰時の割り込みエッジは、両エッジになります。 u32AHI_DioWakeStatus()
uint32 u32AHI_DioWakeStatus (void );
DIO割り込み起床時の起床要因となったピンのビットマップを返します。
内部的には、呼び出し時の__twenet_ioport_int_status
の値を返します。呼び出し後は0
にセットされます。 bAHI_DoEnableOutputs()
static inline bool_t bAHI_DoEnableOutputs (bool_t bEnableDO) {
return bAHI_DoEnableOutputsEx_MW(bEnableDO, bEnableDO);
}
DO0,DO1ピンを出力設定にします。
DO0/DO1 双方ともに出力設定にします。 片側だけを設定したい場合は bAHI_DoEnableOutputsEx_MW()
を呼び出します。DO1 (PIO5) は、始動時にプログラムモードへの遷移判定(ISP_ENT)をするピンに割り当てられているため、ハードウェア設計上留意が必要なピンです。特別な理由がなければ、別のピンを利用することを推奨します。 DO0(PIO0) は DIO11 にも割り当てられているため、両方利用している場合はコードの調整(片側の制御を除外する)が必要です。 vAHI_DoSetDataOut()
void vAHI_DoSetDataOut (
uint8 u8On,
uint8 u8Off);
DO0(PIO0),DO1(PIO1)に対して出力設定を行います。
DO0がbit0 (0x1)、DO1がbit1 (0x2) のビットマップで指定します。 u8On
にビットを設定すると HIGH レベル、u8off
に指定すると LOW レベルになります。vAHI_DoSetPullup()
void vAHI_DoSetPullup (
uint8 u8On,
uint8 u8Off);
なにもしません。
AHIcmpt_Dio.cpp - AHI拡張API 末尾に _MW
がつく関数は、AHI ライブラリには存在しない独自拡張です。
bAHI_DoEnableOutputsEx_MW()
bool_t bAHI_DoEnableOutputsEx_MW (
bool_t bEnableDO0, bool_t bEnableDO1);
DO0, DO1 を出力用に設定する。bAHI_DoEnableOutputs()
が2ポート双方を設定するために追加した関数。
vAHI_DioInterruptDisablePinsIntWhenChanged_MW(), vAHI_DioInterruptReavtivate_MW()
void vAHI_DioInterruptDisablePinsIntWhenChanged_MW (bool_t bSet);
void vAHI_DioInterruptReavtivate_MW ();
割り込み判定されたピンの割り込みを一時的に停止する。
bSet
をTRUEとして呼び出すと、DIO割り込みが発生した時点で、その割り込み対象ピンの割り込みは一時的に停止します。チャタリングが多いメカボタンなどの入力の場合この設定を有効にして、割り込み発生から一定時間経過後に vAHI_DioInterruptReavtivate_MW()
を呼び出し割り込みを再開します。
vAHI_DioOnSleep_MW()
void vAHI_DioOnSleep_MW ();
内部的な処理関数でユーザは呼び出しを行いません。スリープ前の DIO 割り込み関係の処理を行います。具体的には DIO 起床ピンの設定を行います。
vAHI_DioOnWakeup_MW()
void vAHI_DioOnWakeup_MW (bool_t b_init_2nd);
内部的な処理関数でユーザは呼び出しを行いません。起床時の DIO 割り込み関係の処理を行います。起床要因となったピンを保存します。
b_init_2nd
がfalse
の呼び出しは、WarmMain()
処理のごく初期の段階で呼び出され、起床要因の特定などの処理が行われます。つづいてcbAppWarmStart(TRUE)
の呼び出しの直前にtrue
での呼び出しを行います。
vAHI_DioRetentionRelease_MW()
void vAHI_DioRetentionRelease_MW ();
スリープ復帰後の DIO 出力状態保持を解除する。本関数は RAM OFF スリープ復帰時かつcbAppColdStart()
内で使用します。
JN518Xでは、DIO出力状態を保持するためのレジスタ設定 (SYSCON->RETENTIONCTRL
) を行ってからスリープします。出力設定を行ったDIOピンはレジスタ設定時の出力状態を維持し、スリープ復帰後もレジスタ設定を変更しない限り出力状態が保持されます。本関数を呼び出すことで出力保持が解除されます。
スリープ前の状態と同じ設定にするには本関数呼び出し前 にvAHI_DioSetDirection()
やvAHI_DioSetOutput()
を行い、明示的に出力設定を行っておきます。DIOの内部レジスタはスリープ時にクリアされるためです。
cbAppColdStart()
呼び出し後は、TWENETmcuライブラリ内の処理として、本関数と同じ処理を実行します。不用意なポートのHI/LO遷移を避けたい場合は、cbAppColdStart()
内でポートの出力設定を行うようにしてください。
その他 本ライブラリを利用しない場合の留意事項 本ライブラリ中の関数は呼び出さないようにしてください。呼び出しを行わない場合であっても、本ライブラリは TWENETmcu, TWENETlib ライブラリと依存性があります。
依存関係を解消するためには以下を参考にしてください。
スリープ手続きを行う際の割り込みピンに関する部分vAHI_DioOnSleep_MW()
, vAHI_DioOnWakeup_MW()
を調整する必要があります。この2つの関数は TWENETcmpt 内の vAHI_OnSleep_MW()
, vAHI_OnWakeup_MW()
から呼び出されます。 vAHI_OnSleep_MW()
関数は、ソース非開示のTWENETlibライブラリに依存しています。vAHI_DioOnSleep_MW()
で__twenet_ioport_int_status
に割り込み起床判定を行う PIO ビットマップを指定します。ToCoNet_vSleep()
内で反映され、適切にスリープ実行されます。vAHI_OnWakeup_MW()
, vAHI_DioOnWakeup_MW()
は、TWENETmcuライブラリソース中で呼び出されます。必要に応じて処理を変更してください。 4.4 - Timer (PWM)関連のAHI関数と解説 TWENETライブラリ、Timer (PWM)関連のAHI関数と解説
TWENETライブラリ、Timer (PWM)関連のAHI関数と解説です。
Timer (PWM) AHI の Timer 関連の API の一部について、ソースコード互換を取る目的で実装しています。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 AHI APIについて vAHI_TimerFineGrainDIOControl()
void vAHI_TimerFineGrainDIOControl(uint8 u8BitMask)
出力ピンを無効化するビットマスクを指定します。TIMER_0 … TIMER_4 に対応するビットのみ有効です。
vAHI_TimerEnable()
実行前に本関数を呼び出します。vAHI_TimerEnable()
のパラメータで出力を有効化していても、ピンを無効化設定されている場合は、出力無効化として取り扱います。vAHI_TimerAssignPIOPin_MW()
void vAHI_TimerAssignPIOPin_MW(
uint8 u8_timer_id,
uint8 u8_pin_id)
TWELITE GOLD専用です。
指定したタイマーデバイス(u8_timer_id
)で使用するピンをPIO番号で指定します。
PIO番号には特定のPWMチャネルが紐づいています。またPWMが使用できないPIO番号もあります。指定方法によっては、重複したPWMチャネルを利用するといった矛盾した設定になる場合があります。PIO番号とPWMチャネルの割り当てについては、ピン配置表などを参照してください。
u8_timer_id
は、対象のタイマーデバイス (E_AHI_DEVICE_TIMER0-4
)を指定します。vAHI_TimerFineGrainDIOControl()
の設定も有効ですが、出力の有無はvAHI_TImerEnable()
のbOutputEnable
で出力の制御を行います。出力を行わずタイマー割り込みのみを利用する場合でも、利用するPWMチャネルに対応したピン番号を指定します。 本ライブラリの独自関数です。
vAHI_TimerEnable()
void vAHI_TimerEnable(
uint8 u8_timer_id,
uint8 u8Prescale,
bool_t bIntRiseEnable,
bool_t bIntPeriodEnable,
bool_t bOutputEnable)
タイマーを有効化します。
bIntRiseEnable==TRUE
の場合はbIntPeriodEnable==TRUE
として取り扱います。bOutputEnable==TRUE
の設定が行われてもvAHI_TimerFineGrainDIOControl()
でピンが無効化されている場合はFALSE
として取り扱います。すでに有効化したタイマーIDに対して、再度本関数を呼び出した場合の動作は不定です。 ハードウェア資源に矛盾がある場合 TWELITE BLUE/RED とのハードウェアの差異から、すべてのタイマーデバイスを同じように利用できるわけではありません。詳しくは後述のピン割当を参照してください。
PWM出力が有効になっている場合は、ソフトウェアでのPWM出力エミュレーションを行います。 PWM出力が無効になっている場合は、目的がタイマー割り込みと限定されるため、空いているPWM3またはPWM5をピン出力無しで利用します。 上記割当を行ったかどうかを調べるAPIや手続きは用意していません。 vAHI_TimerDisable()
void vAHI_TimerDisable(uint8 u8_timer_id)
タイマーを無効化します。
出力ポートは入力(プルアップは設定変更しない)に戻します。
void vAHI_TimerConfigure(
uint8 u8_timer_id,
bool_t bInvertPwmOutput,
bool_t bGateDisable)
タイマーの設定を変更します。
bInvertPwmOutput
の設定を行います。bGateDisable
は無視されます。vAHI_TimerStartRepeat()
void vAHI_TimerStartRepeat(
uint8 u8_timer_id,
uint16 u16Hi,
uint16 u16Lo)
タイマーを開始します。
この関数はタイマー動作中にも呼び出すことができ、PWMのDUTY設定を変更する目的で使用できます。 vAHI_TimerStop()
void vAHI_TimerStop(uint8 u8_timer_id)
タイマーを停止します。
vAHI_TimerSetLocation()
void vAHI_TimerSetLocation(
uint8 u8Timer,
bool_t bLocation,
bool_t bLocationOverridePWM3andPWM2)
ピンの割当変更を行います。
vAHI_TimerEnable()
実行前に本関数を呼び出します。vAHI_TimerXRegisterCallback
PUBLIC void vAHI_Timer0RegisterCallback (
PR_HWINT_APPCALLBACK prTimer0Callback);
PUBLIC void vAHI_Timer1RegisterCallback (
PR_HWINT_APPCALLBACK prTimer1Callback);
PUBLIC void vAHI_Timer2RegisterCallback (
PR_HWINT_APPCALLBACK prTimer2Callback);
PUBLIC void vAHI_Timer3RegisterCallback (
PR_HWINT_APPCALLBACK prTimer3Callback);
PUBLIC void vAHI_Timer4RegisterCallback (
PR_HWINT_APPCALLBACK prTimer4Callback);
割り込みハンドラの登録関数は実装されていません。AppQAPIにより割り込みハンドラが呼び出されます。
独自に割り込みハンドラの定義を行う場合は、以下のWEAK
定義のハンドラ関数を実装します。実装についてはAHIcmpt_TImers.cpp
の実装を参考にしてください。少なくともPWM_ClearStatusFlags(PWM, kPWM_PwmX);
を呼び出しておく必要があります。
WEAK void PWM0_DriverIRQHandler (void ); // MONO WIRELESS, DEFINED AS WEAK FUNCTION.
WEAK void PWM1_DriverIRQHandler (void );
WEAK void PWM2_DriverIRQHandler (void );
WEAK void PWM3_DriverIRQHandler (void );
WEAK void PWM4_DriverIRQHandler (void );
WEAK void PWM5_DriverIRQHandler (void );
WEAK void PWM6_DriverIRQHandler (void );
WEAK void PWM7_DriverIRQHandler (void );
WEAK void PWM8_DriverIRQHandler (void );
WEAK void PWM9_DriverIRQHandler (void );
上記以外の関数
void vAHI_TimerClockSelect (
uint8 u8Timer,
bool_t bExternalClock,
bool_t bInvertClock);
void vAHI_TimerStartSingleShot (
uint8 u8Timer,
uint16 u16Hi,
uint16 u16Lo);
関数定義なし、または、何もしないダミー関数です。
出力ピンについて 出力ピンは vAHI_TimerEnabled()
呼び出し時に PWM 用途として初期化されます。 出力ピンはvAHI_TimerDisable()
呼び出し時に、入力ポート (プルアップ設定は設定を変えない) として最初期化します。 割り込みについて 周期途中の出力変化点での割り込みには対応しません。周期ごとの割り込みのみに対応します。
割り込みハンドラ 割り込みハンドラは、TWENET 標準の cbToCoNet_u8HwInt()
, cbToCoNet_vHwEvent()
のみに対応します。別途ハンドラを登録することはできません。
個別のハンドラを定義したい場合はPWMx_IRQHandler()
関数を別途定義します。この場合、定義されたハンドラから TWENET へのイベント通知は行いません。
ピン割当 ピン割当は TIMER_ID 毎に個別に設定できますが、TWELITE BLACK ではハードウェアの違いから、割当が困難な場合があります。
標準 AHI TIMER ID 0 1 2 3 4 SMD PIN## 12 16 13 15 19 AHI DIO## 10 11 12 13 17 PIO## 4 0 13 1 21 PWM channel 4 0 2 1 9
標準で DO1,2 を利用した場合 AHI TIMER ID 0 1 2 3 4 SMD PIN## 12 16 1 2 19 AHI DIO## 10 11 DO0 DO1 17 PIO## 4 0 0 5 21 PWM channel 4 0 0 N/A 9
TIMER_1, TIMER_2 の割当が衝突します。 TIMER_3 の出力ピンにはハードウェアタイマーの機能がありません。 副割当 AHI TIMER ID 0 1 2 3 4 SMD PIN## 6 7 8 9 10 AHI DIO## 4 5 6 7 8 PIO## 7 6 8 9 14 PWM channel 7 6 8 9 1
副割当で DO1,2 を利用した場合 AHI TIMER ID 0 1 2 3 4 SMD PIN## 6 7 1 9 10 AHI DIO## 4 5 DO0 DO1 8 PIO## 7 6 0 5 14 PWM channel 7 6 0 N/A 1
TIMER_3 の出力ピンにはハードウェアタイマーの機能がありません。 その他 ピン割り当てに矛盾が出たときの振る舞い PWM出力設定をしている場合で矛盾が出たピン(そもそもPWM機能がないものなど)は、ソフトウェアでのエミュレーションになります。ソフトウェアでのエミュレーションはシステムタイマー(SysTick)の割り込み処理下で16クロックを1周期として出力を制御します。1Khz で動作する場合は 1000/16 = 約62Hz の PWM 周期です。 PWM出力設定をしない場合で矛盾が出たピン(PWM デバイス番号の衝突)は、空いている PWM3 または PWM5 を割り当てます。ピン出力なしの場合でもPWM割り込みは動作します。 本ライブラリのPWM機能を利用しない場合 AHI のタイマー関連の API (?AHI_Timer???
) を呼び出さないようにしてください。当該APIを呼び出すことで、AHI互換のための処理オブジェクトを生成します。この状態でfsl_pwm.h
に定義されるAPIを呼び出した場合の振る舞いは未定義です。 PWM0_IRQHandler()
… PWM9_IRQHandler()
を別途定義してください。これらはweak
リンク指定されているので、アプリケーションで定義したweak
指定のないものが優先してリンクされます。スリープ復帰時の振る舞い RAM保持スリープ時は、スリープ直前の PWM 出力状態の状態を復元します。RAM非保持の場合は、通常のDIO初期化を実施します。 関連AHI API
void vAHI_TimerFineGrainDIOControl (
uint8 u8BitMask);
PUBLIC void vAHI_TimerConfigure (
uint8 u8Timer,
bool_t bInvertPwmOutput,
bool_t bGateDisable);
PUBLIC void vAHI_TimerEnable (
uint8 u8Timer,
uint8 u8Prescale,
bool_t bIntRiseEnable,
bool_t bIntPeriodEnable,
bool_t bOutputEnable);
PUBLIC void vAHI_TimerDisable (
uint8 u8Timer);
PUBLIC void vAHI_TimerClockSelect (
uint8 u8Timer,
bool_t bExternalClock,
bool_t bInvertClock);
PUBLIC void vAHI_TimerStartRepeat (
uint8 u8Timer,
uint16 u16Hi,
uint16 u16Lo);
PUBLIC void vAHI_TimerStop (
uint8 u8_timer_id);
PUBLIC void vAHI_TimerSetLocation (
uint8 u8Timer,
bool_t bLocation,
bool_t bLocationOverridePWM3andPWM2);
※ マクロで関数名が再定義されているものもあります。
※ utils.h のタイマーライブラリも上記 APIを利用します。
ハンドラー定義例 最小限の手続きを含めた定義です。
void PWM0_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm0); }
void PWM1_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm1); }
void PWM2_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm2); }
void PWM3_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm3); }
void PWM4_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm4); }
void PWM5_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm5); }
void PWM6_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm6); }
void PWM7_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm7); }
void PWM8_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm8); }
void PWM9_IRQHandler (void ) { PWM_ClearStatusFlags(PWM, kPWM_Pwm9); }
この関数定義を行うとTWENETへの割り込み・イベント伝達は行われません。 本ライブラリの実装について AHIcmpt_Timer.cpp
には主要な実装コードが含まれます。
上記コードは_periph_pwm.hpp
, _periph_pwm.cpp
を引用しています。これらはプラットフォームドライバ(driver/fs_???
)を用いた手続きをまとめたクラスライブラリです。
4.5 - SMBUS(I2C)関連の手続きを定義したSMBus.c,hの解説 TWENETライブラリ、SMBUS(I2C)関連の手続きを定義したSMBus.c,hの解説
TWENETライブラリ、SMBUS(I2C)関連の手続きを定義したSMBus.c,hの解説です。
SMBUS(I2C) TWENETを用いたサンプルコードやアプリコードの多くは、I2Cバスの利用は、AHIライブラリ内の低レベル手続きは直接用いず、読み書き手続きを簡素化したSMBus.c
, .h
定義関数群を用いています。
以下に、利用する関数名を列挙します。
void vSMBusInit (void );
void vSMBusInit_setClk (uint32 u32Clk);
void vSMBusDeInit ();
void vSMBusDeInit (void );
bool_t bSMBusWrite (uint8 u8Address, uint8 u8Command,
uint8 u8Length, uint8* pu8Data);
bool_t bSMBusSequentialRead (uint8 u8Address, uint8 u8Length,
uint8* pu8Data);
SMBus.c SMBus.h I2C の代表的な手続きをまとめた関数群でTWENETmwx/source/sensors/legacy
にソースコードを格納しています。
※TWENETmwx ライブラリをリンクしない場合(Cプロジェクト)は、このソースコードをコピーして利用します。
vSMBusInit()
I2Cバスを初期化します。使用するピンはDIO14(CLK),15(DATA)で、クロック周波数は100Kbpsです。
vSMBusInit_setClk(uint32)
void vSMBusInit_setClk (uint32 u32Clk);
vSMBusInit()
の替わりに本関数を用いることで、u32clk
に対応するクロックにてI2Cバスを初期化します。
u32clk>=7
かつu32clk>=255
の場合⇒クロック周波数320000ul/(u32clk+1)
を指定して初期化します。例えば31
を指定すると、100KHz、7
を指定すると400kHzとなります。u32clk >= 12500
かつu32clk <= 400000
⇒u32clk
を指定して初期化します。それ以外⇒未定義 ※ 実際の周波数は、ハードウェアのクロックディバイザに対応し近傍の周波数が選択されます。具体的な計算方法についてはソースコードを参照 (TWELITE GOLDの場合は NXP の FSL ライブラリの仕様を参照ください。
// TWELITE GOLDの実装
PUBLIC void TWENET_smbus_vSMBusInit_setClk (uint32_t u32clk)
{
...
if (u32clk >= 7 && u32clk <= 255 ) { // given by divisor
u32clk = 3200000ul / (u32clk + 1 );
}
if (u32clk < 12500ul || u32clk > 400000ul ) {
u32clk = 100000ul ;
}
// initialize the I2C
//...以下、呼び出し先関数の実装
_conf.baudRate_bps = u32clk;
I2C_MasterGetDefaultConfig(& _conf); // FSLライブラリ関数
}
// TWELITE BLUE/RED の実装
void vSMBusInit_setClk (uint32 u32Clk)
{
/* convert clock to clock devisor */
if (u32Clk > 255 ) {
u32Clk = (3200000UL / u32Clk) - 1 ;
}
if (u32Clk < 7 || u32Clk > 255 ) u32Clk = 31 ; // set 100kHz
/* run bus at specified value */
vAHI_SiMasterConfigure(TRUE, FALSE, u32Clk);
// 16/[(PreScaler + 1) x 5]MHz
// --> 31:100KHz, 7:400KHz, 47:66Khz
}
vSMBusDeInit()
I2Cバスの利用を停止します。
TWELITE BLUE/RED はvAHI_SiMasterDisable()
を呼び出します。 TWELITE GOLDはI2Cバスの利用の停止と、DIO14,15ピンを TWENET ライブラリ初期化時の設定 (入力ポート、プルアップ) に戻します。 bSMBusWrite()
bool_t bSMBusWrite(
uint8 u8Address,
uint8 u8Command,
uint8 u8Length,
uint8* pu8Data)
I2Cバスへの書き込みを行います。
u8Address
⇒I2Cバスのデバイスアドレスを指定します。u8Command
⇒書き込み時のコマンド(最初の転送バイト)を指定します。u8Length
⇒続くバイト数。0
の場合はコマンドのみの転送です。1以上を指定した場合はpu8Data
の定義が必須です。pu8Data
⇒転送するバイト列を格納したメモリ領域へのポインタを指定します。転送が成功した場合は TRUE
を戻し、失敗した場合は FALSE
を戻します。
bSMBusSequentialRead()
bool_t bSMBusSequentialRead(
uint8 u8Address,
uint8 u8Length,
uint8* pu8Data)
I2Cバスの読み込みを行います。
u8Address
⇒I2Cバスのデバイスアドレスを指定します。u8Length
⇒読み出すバイト数(1以上)を指定します。pu8Data
⇒読み出すバイト列を格納するメモリ領域へのポインタを指定します。転送が成功した場合は TRUE
を戻し、失敗した場合は FALSE
を戻します。
その他 スリープ時の取り扱い TWELITE BLUE/REDは、スリープ復帰時にハードウェアの再初期化を行う必要があります。vSMBusDeInit()
を呼び出さない場合のピンの状態は未定義(またはJN516x のペリフェラル仕様書に基づく)ですが、再度vSMBusInit()
vSMBusInit_setClk()
の呼び出しを行うことで初期化することができます。 TWELITE GOLDは、以下の振る舞いをします。RAM ON(通常)スリープ時:スリープ手続きを行った時点で、I2Cバスが初期化されていた場合は、スリープ復帰時に再初期化を行います。I2Cバスが使用されていない場合は、通常の汎用IOのスリープ復帰時の手続きとなります。 RAM OFF(ディープ)スリープ時:スリープ復帰時にTWENETによるピンの初期化(入力ピン、プルアップ)行います。 TWELITE GOLD の実装 AHIライブラリ互換関数は用意せず SMBus.c
,h
に対応する関数を実装しています。
// TWENETcmptライブラリ内での実装
PUBLIC void TWENET_smbus_vSMBusInit (void );
PUBLIC void TWENET_smbus_vSMBusDeInit (void );
PUBLIC void TWENET_smbus_vSMBusInit_setClk (uint32 u32clk);
PUBLIC bool_t TWENET_smbus_bSMBusWrite (uint8 u8Address,
uint8 u8Command, uint8 u8Length, uint8* pu8Data);
PUBLIC bool_t TWENET_smbus_bSMBusSequentialRead (uint8 u8Address,
uint8 u8Length, uint8* pu8Data);
// SMBus.hで inline 定義により上記関数群を呼び出す
static inline void vSMBusInit (void ) {
TWENET_smbus_vSMBusInit();
}
static inline void vSMBusInit_setClk (uint32 u32Clk) {
TWENET_smbus_vSMBusInit_setClk(u32Clk);
}
static inline void vSMBusDeInit () {
TWENET_smbus_vSMBusDeInit();
}
static inline void vSMBusDeInit (void ) {
TWENET_smbus_vSMBusInit();
}
static inline bool_t bSMBusWrite (uint8 u8Address, uint8 u8Command,
uint8 u8Length, uint8* pu8Data) {
return TWENET_smbus_bSMBusWrite(u8Address, u8Command, u8Length, pu8Data);
}
static inline bool_t bSMBusSequentialRead (uint8 u8Address, uint8 u8Length,
uint8* pu8Data) {
return TWENET_smbus_bSMBusSequentialRead(u8Address, u8Length, pu8Data);
}
4.6 - SPI関連のAHI関数と解説 TWENETライブラリ、SPI関連のAHI関数と解説
TWENETライブラリ、SPI関連のAHI関数と解説です。
SPI SPI関連のAHI互換関数の実装です。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 SPIの対応については、以下のピンを利用します。
信号名 ピン名(PIO番号) 解説 SCK SPLCLK=DIO11(PIO0) クロック信号このピンはSPICLK, DIO11共用になっています MOSI DIO18(PIO2) SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 MISO SPIMISO(PIO5) SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。 SEL0 DIO19(PIO3) SEL1 DIO0(PIO16) SEL2 DIO1(PIO17)
副割り当てのピン (vAHI_SpiSetLocation_MW(FALSE)
により設定)を用いた場合は、以下となります。
信号名 ピン名(PIO番号) 解説 SCK ADC1(PIO15) クロック信号 MOSI DIO1(PIO17) SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 MISO DIO2(PIO18) SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。 SEL0 DIO0(PIO16) SEL1 DIO8=ADC2(PIO14) このピンはDIO8, ADC2共用になっています SEL2 DIO12(PIO13)
SPIはハードウェアの機能を用い動作するため、ピンの振る舞い(特に転送していないときの HIGH/LOW の状態など)には一部違いが出ます。
実装は、ブロッキング転送を用いています。コードの互換性を維持するため、転送APIの直後にポーリング待ちコードを含めるようにしてください(bAHI_SpiPollBusy()
, vAHI_SpiWaitBusy()
)。
void vAHI_SpiConfigure (
uint8 u8SlaveEnable,
bool_t bLsbFirst,
bool_t bPolarity,
bool_t bPhase,
uint8 u8ClockDivider,
bool_t bInterruptEnable,
bool_t bAutoSlaveSelect);
SPIの初期化を行います。
bInterruptEnable
には対応してません。パラメータは無視されます。vAHI_SpiDisable()
void vAHI_SpiDisable (void );
SPIの利用停止をします。
vAHI_SpiSelect()
void vAHI_SpiSelect(
uint8 u8SlaveMask)
SPIのSELECTピンを選択します。
vAHI_SpiConfigure()
のbAutoSlaveSelect
がTRUE設定の場合は、制御対象のピンを指定します。この呼出時点ではピンの制御は行いません。vAHI_SpiConfigure()
のbAutoSlaveSelect
がFALSE設定の場合は、SELECTピンの制御(対象品のみをLOW,それ以外はHIGH) します。vAHI_SpiStop()
PUBLIC void vAHI_SpiStop (void );
SELECTピンを解除します。vAHI_SpiSelect(0)
と同じ処理です。
vAHI_SpiStartTransfer()
void vAHI_SpiStartTransfer (
uint8 u8CharLen,
uint32 u32Out);
void vAHI_SpiStartTransfer32(uint32 u32Out)
void vAHI_SpiStartTransfer16(uint16 u16Out)
void vAHI_SpiStartTransfer8(uint8 u8Out)
SPI転送を実行します。
この処理はブロッキングで実行されます。 8の倍数ビット数でない場合は、転送が2~3回に分割されます。 32bit指定時は、エンディアンの違いによるメモリ上のバイト配置にかかわらず、数値の上位のバイトから下位のバイトの順に送信されます。結果として、BLUEとGOLDでは転送波形が同じになります。 AHI_SpiReadTransfer
static inline uint32 u32AHI_SpiReadTransfer32 (void );
static inline uint16 u16AHI_SpiReadTransfer16 (void );
static inline uint8 u8AHI_SpiReadTransfer8 (void );
転送完了後に呼び出し、読み出した値を返す。
bAHI_SpiPollBusy()
bool_t bAHI_SpiPollBusy (void );
inline void vAHI_SpiWaitBusy (void ) { while (bAHI_SpiPollBusy()); }
常に FALSE を返します。転送APIがブロッキング転送を行うためです。
bAHI_SpiTransferBlocking_MW()
bool_t bAHI_SpiTransferBlocking_MW (
uint8 * au8tx,
uint8 * au8rx,
uint8 u8len);
バイト単位の転送を行います。au8tx
が送信データの配列、au8rx
が受信データの配列、u8len
が転送バイト数です。
配列の先頭から順に転送されるため、LSBから順に転送する場合は、バイト順も LSB 側のバイトを先に格納しておく必要があります。受信データも同様です。 vAHI_SpiWaitBusy()
void vAHI_SpiWaitBusy (void );
速やかに return します。
vAHI_SpiSetLocation_MW()
void vAHI_SpiSetLocation_MW (bool_t bLocation);
使用するピンの組み合わせを変更します。既定のピンを用いる場合は本関数の呼び出しは不要ですが、副割り当てピンを用いる場合はvAHI_SpiConfigure()
関数呼び出し前に本関数を呼び出します。
bLocation == FALSE
(デフォルト)→既定のピン割り当てを用います。bLocation == TRUE
→副割り当てピンを用います。その他 転送の分割 vAHI_SpiStartTransfer()
では8bitの整数倍(8,16,24,32bit)以外の転送を行う場合は、内部的に転送を2分割して行います。そのため、1回目と2回目の転送の間、波形は一定時間保持されることになります。
スリープ復帰時の振る舞い RAM保持スリープ直前にSPIバスが初期化済みである場合は、復帰時に初期化状態を復元します。RAM非保持スリープの場合は、通常の始動時のDIO初期化が行われます。
BLUE/REDとのコード互換性を高めたい場合はスリープ前に vAHI_SpiDisable()
を明示的に呼び出すようにしてください。
4.7 - Random(乱数)関連のAHI関数と解説 TWENETライブラリ、Random(乱数)関連のAHI関数と解説
TWENETライブラリ、Random(乱数)関連のAHI関数と解説です。
Random(乱数) 乱数生成関連のAHI 互換関数の実装。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 vAHI_Start|StopRandomNumberGenerator()
void vAHI_StartRandomNumberGenerator (bool_t const bMode, bool_t const bIntEn);
void vAHI_StopRandomNumberGenerator (void );
乱数生成を開始・停止します。
u16AHI_ReadRandomNumber()
uint16 u16AHI_ReadRandomNumber (void );
16bitの乱数値を読み出します。
乱数生成が開始されていない場合は57005
を戻します。 u32AHI_ReadRandomNumber_MW()
uint32 u32AHI_ReadRandomNumber_MW (void );
(TWELITE GOLD 専用関数)32bitの乱数値を読み出します。
乱数生成が開始されていない場合は3735928559
を返します。 vAHI_ReinitRandomNumberGenerator_MW()
void vAHI_ReinitRandomNumberGenerator_MW ();
(TWELITE GOLD 専用関数)乱数生成デバイスの再初期化を行います。
4.8 - UART関連のAHI関数と解説 TWENETライブラリ、UART関連のAHI関数と解説
TWENETライブラリ、UART関連のAHI関数と解説です。
UART UARTの利用は TWENETutils にある serial.c
,.h
および uart.c
,.h
を用います。ここでは、TWELITE GOLD で特有の振る舞いをするAHI互換関数について解説します。
UART1を用いる場合は、vAHI_UartSetLocation()
または vAHI_UartSetLocationByPio_MW()
を呼び出し、事前に割り当てポートを指定する必要があります。 UART0 は使用にあたりUART1のような特別な手続きは必要ありません。 vAHI_UartSetLocation()
void vAHI_UartSetLocation (uint8_t u8port, bool_t bSel);
UART のポート割り当てを指定します。
UART0 の割り当てには影響しません。規定のポート(DIO6,7)から変更できません。 UART1 の割り当ては以下の2種類が可能です。 UART1を利用する場合は必ず本館数を呼び出す必要があります。 UART1 の他の割り当てを行うには vAHI_UartSetLocationEx_MW()
を用いてください。 bSel
TX RX FALSE DIO14(PIO10) DIO15(PIO11) TRUE DIO11(PIO0)*1 DIO13(PIO1)
*1 規定のSPICLKピンと重複します。
vAHI_UartSetLocationByPio_MW()
void vAHI_UartSetLocationByPio_MW(uint8_t u8port, uint8 u8TxPort, uint8 u8RxPort)
UART のポート割り当てを行います。u8port
はE_AHI_UART_1
を指定します。TXポートとRXポートのPIO番号 を、u8TxPort
とu8RxPort
で指定します。
設定可能なPIO番号(DIO番号)
TX : 0(DO0,DIO11) 6(DIO5) 10(DIO14) 20(DIO16) RX : 7(DIO4) 1(DIO13) 11(DIO15) 19(DIO13) vAHI_UartDisable()
void vAHI_UartDisable(uint8_t u8port)
u8port
で指定するUARTポートを利用停止します。ピンの状態は起動直後の初期化状態(TWENETmcu/board/pin_mux.c
での定義)に戻ります。
4.9 - WatchDog(WDT)関連のAHI関数と解説 TWENETライブラリ、WatchDog(WDT)関連のAHI関数と解説
TWENETライブラリ、WatchDog(WDT)関連のAHI関数と解説です。
WatchDog(WDT) vAHI_WatchdogStart()
void vAHI_WatchdogStart (uint8 u8Prescale);
ウォッチドッグタイマーを利用開始します。
タイムアウト時間はおおよその値を設定している。具体的にはタイムアウトはu8Prescale == 0
の場合8
ms, それ以外は((1UL<<(u8Prescale-1)) + 1) * 8
msとしてthe_wwdt->init()
を呼び出している。 値域外の値 u8Presacale > 12
を指定した場合は、u8Prescale = 10
(約4秒) とする。 -DDEBUG
でコンパイルするデバッグ時はこの処理は実行されず、WDTは停止したままとします。vAHI_WatchdogStop()
void vAHI_WatchdogStop ();
TWELITE GOLD では、いったん稼働したウォッチドッグの停止を行うことが出来ません 。本関数は、ウォッチドッグタイマーのタイムアウトを変更する際に以下のように呼び出します。
...
vAHI_WatchdogStop(); // 一旦停止API(実際は停止しない)を呼び出す
vAHI_WatchdogStart(12 ); // 約16秒に再設定する
vAHI_WatchdogRestart()
void vAHI_WatchdogRestart ();
ウォッチドッグタイマーのタイムアウトまでに呼び出します。
-DDEBUG
でコンパイルするデバッグ時はこの処理は実行されません。4.10 - WakeTimer(ウェイクタイマー)関連のAHI関数と解説 TWENETライブラリ、WakeTimer(ウェイクタイマー)関連のAHI関数と解説
WakeTimer(ウェイクタイマー) vAHI_WakeTimer
関連の互換関数の実装です。
この実装は完全な互換性を保つことを目的とはしていません。 本書記述時点で判明している留意点などを記載します。 内部の実装は予告なく変更される場合があります。 解説中のパラメータについても、留意が必要な部分のみ記述しています。省略部分は、原典の AHI ライブラリマニュアルを参照ください。 ウェイクタイマーは2系統あり、スリープ中問わずカウンタが動作します。カウンタは減算式で値が0になったときに割り込みが発生します。またウェイクタイマーは、動作し続ける特性から起動時からの経過時間を計る時計として利用することもできます。時計として利用するための手続きをまとめた FRWT(FreeRunning WTimer)関数軍も用意しています。
タイマーはE_AHI_WAKE_TIMER_0
の場合41ビット、E_AHI_WAKE_TIMER_1
の場合28ビットです。後者は BLUE/RED(JN516x) と仕様が違いますので注意してください(カウンタ値として時間差分を計算する場合は、最大値が 0x0FFFFFFF
である点に注意してください。例えばct1
からct2
の間の経過カウントを計算する場合は (((ct2 << 4) - (ct1 << 4)) >> 4)
のように計算します) 本ライブラリでは 32ビットを超えるタイマー値を扱う関数は用意していません。 mwxライブラリやいくつかのアプリケーションでは、タイマーの1系統(E_AHI_WAKE_TIMER_0
を動作しつづけて時間計測をするための処理(Free Running WTimer:FRWT
API)を行います。 vAHI_WakeTimerEnable()
void vAHI_WakeTimerEnable(uint8 u8Timer,
bool_t bIntEnable)
タイマーを初期化する。
vAHI_WakeTimerStart()
void vAHI_WakeTimerStart(uint8 u8Timer, uint32 u32Count)
タイマーを開始する。u32count
はカウンター値を指定する。TWELITE GOLD の場合、1秒後に割り込みを発生させたい場合は 32768
(32KHz 水晶振動子の周波数) を指定する。
vAHI_WakeTimerStop()
void vAHI_WakeTimerStop(uint8 u8Timer)
タイマーを停止する。
u32AHI_WakeTimerCalibrate()
uint32 u32AHI_WakeTimerCalibrate (void );
ウェイクタイマーのキャリブレーション値 10000
を返します。
本来は精度の低いRCタイマーで 10000 に対して±30%程度の値になりますが、TWELITE GOLDでは32KHz水晶によるタイマー回路が含まれるため、この水準でのキャリブレーションは不要です。無条件で 10000
を返します。 u32AHI_WakeTimerRead()
uint32 u32AHI_WakeTimerRead(uint8 dev)
カウンタ値を返します。起床割り込みはカウンタが0になったときに発生します。その後もカウンタは減算を続けます(0の次はカウンタの最大値)。
u8AHI_WakeTimerStatus()
uint8 u8AHI_WakeTimerStatus(void )
タイマーの稼働状況のビットマップを返す。E_AHI_WAKE_TIMER_0
の場合 E_AHI_WAKE_TIMER_MASK_0
(1)
、E_AHI_WAKE_TIMER_1
の場合E_AHI_WAKE_TIMER_MASK_1
(2)
が設定されます。
u8AHI_WakeTimerFiredStatus()
uint8 u8AHI_WakeTimerFiredStatus()
起床直後に使用し、起床要因が WTIMER の場合、0 以外の値が戻ります。
E_AHI_WAKE_TIMER_0
の場合、E_AHI_WAKE_TIMER_MASK_0
(1)
が戻ります。E_AHI_WAKE_TIMER_1
の場合、E_AHI_WAKE_TIMER_MASK_1
(2)
が戻ります。Free Running WTimer (FRWT) WAKE TIMER を1系統(原則E_AHI_WAKE_TIMER_0
)用い、実行し続けることによりリアルタイムカウンタとして用います。スリープ状態を問わず時間を計測することができます。
グローバル変数 G_TWENET_FREE_RUNNING_WTIMER_ENABLED()
uint8_t G_TWENET_FREE_RUNNING_WTIMER_ENABLED() // MACRO
この辺数は cbAppColdStart(FALSE)
呼び出しで設定します。0x80
を指定することで E_AHI_WAKE_TIMER_0
をFRWTとして動作させます。WAKE TIMER のカウンタは時間の経過とともに減算されますが、FRWTは加算します。
mwxライブラリでは、自動的にE_AHI_WAKE_TIMER_0
によるFRWTが設定されます。 g_twenet_free_running_wtimer_boot_tick
uint32_t g_twenet_free_running_wtimer_boot_tick
スリープ復帰直後(RAM保持)のカウント値を保存します。TWENETライブラリ中からvAHI_FRWTSetBootCount_MW()
が呼び出されることにより設定されます。
vAHI_FRWTStart_MW()
void vAHI_FRWTStart_MW(uint8_t u8Timer)
本関数はTWENETライブラリ中で用いるため、原則としてユーザプログラムでは使用しません 。グローバル変数G_TWENET_FREE_RUNNING_WTIMER_ENABLED()
の設定によりFRWTを起動させます。
u32AHI_FRWTGetCurrentCount_MW()
uint32 u32AHI_FRWTGetCurrentCount_MW()
FRWTのカウント値(32000カウント/秒) を返す。
u32AHI_FRWTGetCurrentCount_msec_MW()
uint32 u32AHI_FRWTGetCurrentCount_msec_MW(uint32* dec_part)
現在のFRWTをミリ秒で返す。
dec_part
はNULL
またはuint32
変数へのポインタを指定します。指定された場合は 1/10 ミリ秒の値 (0..9) を返します。u32AHI_FRWTConvertCount_msec_MW()
static inline uint32 u32AHI_FRWTConvertCount_msec_MW (uint32 ct, uint32* dec_part) {
// note: see wtimer::freerun_ct_convert_msec()
uint64_t v = 1000ull * ct;
if (dec_part) * dec_part = (10 * (v & 32767 )) >> 15 ;
return (uint32)(v >> 15 );
}
FRWTのカウント値をミリ秒に変換します。dec_part
は指定された場合は 1/10 ミリ秒の値(0..9)を返します。
i32AHI_FRWTCompareCount_MW()
int32 i32AHI_FRWTCompareCount_MW(uint32 val_past, uint32 val_now)
FRWTのカウント値の比較を行います。val_now
がより最近の値、val_past
がより過去の値を指定し、この場合は正の値のカウント値を戻します。
i32AHI_FRWTCompareCount_msec_MW()
int32 i32AHI_FRWTCompareCount_msec_MW(uint32 val_past, uint32 val_now)
FRWTのカウント値の比較を行います。val_now
がより最近の値、val_past
がより過去の値を指定し、この場合は正の値のミリ秒を戻します。
vAHI_FRWTSetBootCount_MW()
void vAHI_FRWTSetBootCount_MW()
本関数はTWENETライブラリ中で用いるため、原則としてユーザプログラムでは使用しません 。
スリープ起床時(RAM保持、ウォームブート)に、FRWTカウント値を保存するために用います。
uint32 u32AHI_FRWTGetBootCount_MW()
uint32 u32AHI_FRWTGetBootCount_MW()
スリープ起床時(RAM保持、ウォームブート)に、FRWTカウント値を返します。
u32AHI_FRWTGetBootCount_msec_MW()
uint32 u32AHI_FRWTGetBootCount_msec_MW()
スリープ起床時(RAM保持、ウォームブート)に、FRWTカウント値をミリ秒に変換して返します。
4.11 - Onchip temp sensor (温度センサー)関連のAHI関数と解説 TWENETライブラリ、Onchip temp sensor (温度センサー)関連のAHI関数と解説
Onchip temp sensor (温度センサー) TWELITE GOLDでは、内部チップ中に温度センサーが実装されています。このセンサー値は、無線MAC層の初期化のパラメータとして用いられます。
MAC層の初期化時の温度センサーの取り扱い 温度センサーの値が取得できない場合は20℃として初期化します。 スリープ復帰時にG_TWENET_CHIPSENSOR_ADC_INTERVAL_MS()
ミリ秒以上経過している場合は、スリープ起床時(RAM保持)に再度温度計測を行い、センサー値をもとにMACの再初期化を行う。 グローバル変数
uint8 G_TWENET_CHIPSENSOR_AUTO_ON_BOOT()
// 変数アクセス用のマクロ
温度センサーの取得を自動で行うための設定用変数。cbAppColdStart(FALSE)
中で設定する。
設定値 内容 備考 0 温度センサーの取得を自動で行わない。 MAC層の温度補正は固定値 (20℃で行う) 1 温度センサーの取得を自動で行う。
uint8_t G_TWENET_CHIPSENSOR_ADC_TIMES_SCALER()
// 変数アクセス用のマクロ
温度センサーのADC回数に対応するスケーラー値を指定します。
int32 G_TWENET_CHIPSENSOR_TEMP128TH()
// 変数アクセス用のマクロ
TWENETライブラリ内で計測されたチップセンサーの温度(℃ の128倍値)が格納される。
int16 g_twenet_chipsensor_volt_on_boot;
TWENETライブラリ内で計測された電圧値[mV]。温度センサー計測時に同時に計測された値が格納される。
uint32 G_TWENET_CHIPSENSOR_ADC_INTERVAL_MS()
= (10*60*1000ul)
// 変数アクセス用のマクロ
この変数で指定された期間内は温度センサーの取得を省略する。cbAppColdStart(FALSE)
中で設定する。
uint8 g_twemet_chipsensor_capture_this_time;
ブート時に温度測定を行うか否かを判定した内部フラグ。
bAHI_AdcTemp_Measure_MW()
bool_t bAHI_AdcTemp_Measure_MW(
int32 * i32temp_128th,
int16 * i16volt_mv,
uint8 adc_times_scaler,
bool_t bTurnOnSensor)
温度センサーの計測を行います。
i32temp_128th
は温度計測結果を返すint32
がたの変数へのポインタ。i16volt_mv
は同時に計測される電源電圧[mV]値。adc_times_scaler
は温度センサーのADC回数に対応するスケーラー値を指定します。設定値は G_TWENET_CHIPSENSOR_ADC_TIMES_SCALER()
の解説を参照してください。bTurnOnSensor
はTRUE
を設定すると、関数呼び出し内で温度センサーの電源を投入し必要な待ち処理を行います。FALSE
を指定した場合は、事前にvAHI_AdcTemp_TurnOn_MW()
を行い必要な待ち時間を経過している必要があります。vAHI_AdcTemp_TurnOn_MW()
void vAHI_AdcTemp_TurnOn_MW()
温度センサーの電源を投入する。この呼び出し後 100μ秒 の待ち時間が必要です。
uint32 u32AHI_AdcTemp_GetCaptTick_MW()
uint32 u32AHI_AdcTemp_GetCaptTick_MW()
最後に温度センサー値を取得した FRWT 時刻を32KHzカウント値で返す。
uint32 u32AHI_AdcTemp_GetCaptTick_msec_MW()
uint32 u32AHI_AdcTemp_GetCaptTick_msec_MW()
最後に温度センサー値を取得した FRWT 時刻をミリ秒で返す。
u32AHI_AdcTemp_ElapsedFromCapt_msec_MW(), u32AHI_AdcTemp_TickrefFromCapt_msec_MW()
uint32 u32AHI_AdcTemp_ElapsedFromCapt_msec_MW()
uint32 u32AHI_AdcTemp_TickrefFromCapt_msec_MW(uint32 tick_ref)
最後に温度計測してからの経過時間をミリ秒で返す。
5 - TWENETeastl - EASTLライブラリ 静的メモリ確保による C++ の STL の実装
EASTLライブラリについての補足解説を行います。
TWENETeastl - EASTLライブラリ EASTL は Electronic Arts 社が整備した標準テンプレートライブラリ(コンテナ・アルゴリズム)で、C++ の STL (Standard Template Library) に倣い実装されていますが、制約の多いゲーム機の開発で整備されてきた経緯があり、メモリの取り扱いに制約が大きい環境を意識したコンテナやアルゴリズムが用意されています。
本ライブラリは EASTL を TWENET 内で利用できるようにしています。
以下に特徴的な要素を記載します。
メモリ固定確保のコンテナ (fixed_
) : 動的確保を行わず、固定長の要素数を持つコンテナの宣言が可能です。グローバル宣言すれば、コンパイル時に固定的にメモリ領域が確保され、ローカル宣言すればスタックエリアに確保されそのスコープ内で利用できます。 Intrusive コンテナ:通常のコンテナは任意のデータ構造を格納できますが、Intrusiveコンテナはデータ構造に対して専用の基底クラスを継承することで、コンテナ内のリンク構造などを維持するためのリンク情報などを保持します。コンテナ内の各要素はそのコンテナ専用になりますが、リストやマップ構造では非常にメモリ利用効率の良くなります。(参考: Intrusive and non-intrusive containers ) 2007年の記事EASTL (open-std.org) に開発動機などが記されています。(関連記事:EASTL から垣間見るゲームソフトウェア開発現場の現状 その 1 , その 2 )
EASTL ライブラリ添付資料 doc 以下の html ファイルを参照して下さい。
配布時に最上位ディレクトリに格納されている README.md, CONTRIBUTING.md は doc/ に移動しています。
TWENETでの利用 以下に留意してください。
当社ではライブラリの動作については包括的な検証は行っておりません。お客様での動作検証をお願いいたします。また EASTL の利用方法についてのお問い合わせについても当社では対応できません。配布元の開設資料・ライブラリソースコードなどの情報を参照してください。
EASTL3.07 (2018/1/31) のバージョンを利用します。(C++11でコンパイルできる一番最後のバージョン)以下のライブラリは組み込んでいません。test/packages/EAAssert
, source/assert.cpp
test/packages/EATest
test/packages/EAThread
, source/thread_support.cpp
テストコード test/source
の動作移植はしていません。 sprintf 関連ではEA::StdC::Vsnprintf(char8_t*, ...)
のみを printf.h ライブラリ中の vsnprintf_()
を呼び出すことで解決しています。組み込み・コンパイル方法 EASTL はアクト Act の記述の際に利用できます。
TWELITE 向けの開発環境で必要なインクルードパスの追加、ライブラリの追加は行います。作成するコード中でライブラリヘッダのインクルードを行ってください。
#include <TWELITE>
#include <EASTL/fixed_string.h>
using namespace eastl;
using tstr128 = fixed_string< char , 127 + 1 , false> ;
void setup () {
tstr128 s1;
s1 = "Hello World" ;
Serial << s1.c_str();
}
void loop () {
;
}
組み込み方法(詳細) EASTL/source 内のコードをコンパイルして、ライブラリアーカイブとしておく (libEASTL.a
)。リンク時にはこのライブラリの参照が必須です。 コンパイル時に以下のインクルードパスを追加しておく。 $(PATH_EASTL)
を EASTL ディレクトリとした場合、インクルードパスは以下となります。
-I$( PATH_EASTL) /include
-I$( PATH_EASTL) /test/packages/EAAssert/include
-I$( PATH_EASTL) /test/packages/EABase/include/Common
-I$( PATH_EASTL) /test/packages/EAMain/include
-I$( PATH_EASTL) /test/packages/EAStdC/include
-I$( PATH_EASTL) /test/packages/EATest/include
-I$( PATH_EASTL) /test/packages/EAThread/include
コーディングについて std::
と eastl::
について標準ライブラリ (std::
) と EASTL(eastl::
)では同じ名前で同じ機能を持つものが定義されています。これらは混在できる場合もありますが、使用するとエラーになる場合もあります。つまりEASTLで使用するものは、通常はEASTL内の定義を用います(例:std::unique_ptr
に eastl::fixed_string
を格納しようとするとコンパイラエラーになる)。
グローバルオブジェクトの初期化1 (配置new) TWENET の開発では、コンパイラの制約により、グローバル宣言のオブジェクトのコンストラクタが実行されません。グローバル宣言宣言したオブジェクトのメモリ領域がゼロクリアされるだけです。そのまま、コードを実行すると大抵の場合 null pointer access によりハングアップします。
このオブジェクトを初期化するためには*placement new (配置new)*を用います。
#include <TWELITE>
#include <EASTL/fixed_string.h>
using namespace eastl;
using tstr128 = fixed_string< char , 127 + 1 , false> ;
tstr128 g_str1; // constructor is NOT called! needs to be initialized before use.
void setup () {
(void ) new ((void * )& g_str1) tstr128("Hello World" );
Serial << g_str1.c_str();
}
placement new のコードは少し乱雑に見えるため、補助関数mwx::pnew()
を用意しています。先ほどの例を以下のように書き換えることができます。
(void ) new ((void * )& g_str1) tstr128("Hello World" );
// ↓
mwx:: pnew(g_str1, "Hello World" );
※ 2番目の引数以降は可変数で、コンストラクタにそのまま渡されます。
グローバルオブジェクトの初期化2 (unique_ptr) グローバルオブジェクトの初期化方法として unique_ptr
(std::unique_ptrの解説 )を用いる方法もあります。unique_ptr
は std::
にも eastl::
にもありますが、EASTLのクラスではeastl::
のものを使用します。
以下のように初期化のタイミングで .reset()
を呼び出します。
#include <TWELITE>
#include <EASTL/unique_ptr.h>
#include <EASTL/fixed_string.h>
using namespace eastl;
using tstr128 = fixed_string< char , 127 + 1 , false> ;
eastl:: unique_ptr< tstr128> uq_str1;
void setup () {
uq_str1.reset(new tstr128("Hello World" ));
if (uq_str1) { // true: object is stored.
Serial << uq_str1-> c_str();
}
}
intrusive コンテナについて 以下の例は intrusive_list
の要素定義例です。メンバーは int mX
のみです。
struct IntNode : public eastl:: intrusive_list_node {
int mX;
IntNode(int x = 0 ) : mX(x) { }
// no need to call super class's constructor eastl::intrusive_list_node()
};
inline bool operator < (const IntNode& a, const IntNode& b) { return a.mX < b.mX; }
inline bool operator > (const IntNode& a, const IntNode& b) { return a.mX > b.mX; }
intrusive_list
の要素は、必ず intrusive_list_node
を基底クラスに持っている必要があります。基底クラス内にはリストを維持するためのリンクポインタが含まれます。ここではさらに sort
などで使用する比較演算子の定義も行います。
using tiList = intrusive_list< IntNode> ;
void setup () {
IntNode nodeA(5 );
IntNode nodeB(1 );
IntNode nodeC(9 );
IntNode nodeD(2 );
IntNode nodeE(4 );
tiList l; // intrusive_list body
l.push_front(nodeA); // forming list strucure
// by updating link info in intrusive_list_node.
l.push_front(nodeB);
l.push_front(nodeC);
l.push_front(nodeD);
l.push_front(nodeE);
l.sort(); // sort, using < operator
l.sort(eastl:: greater< tilist:: value_type> ()); // sort, using > operator
}
参考資料 本サンプルについて EASTLのライセンス記述は以下です。
Modified BSD License (3-Clause BSD license) see the file LICENSE in the project root.
/*
Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
サンプルコードは MWSLA-1J/E を適用します。
6 - TWENETstgs - twesettingsライブラリ インタラクティブモードによる設定を支えるライブラリ
TWENETstgs - twesettingsライブラリの解説を行います。
TWENETstgs - twesettingsライブラリ このライブラリは主にインタラクティブモードにより設定処理を行うための諸関数が含まれます。
※ これらの関数はエンドユーザ向けの API としては公開していません。
6.1 - printfライブラリ printfライブラリ
printf相当関数の解説。
printf 相当関数
参照する printf ライブラリは TWENETmcu/printf に格納されています。
本 TWENETstgs ではオープンソースによるprintfライブラリを利用した
fprintf
, vfprintf
, sprintf
相当関数を定義しています。
int TWE_fprintf (TWE_tsFILE * fp, const char * format, ...);
int TWE_vfprintf (TWE_tsFILE * fp, const char * format, va_list va);
#define TWE_snprintf(out,siz,fmt,...) snprintf_(out,siz,fmt,__VA_ARGS__)
参照するソースコードの記述
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
6.2 - TWESTG_CMD_u32CmdOp() コマンド解説 TWESTG_CMD_u32CmdOp() コマンド解説(内部開発者向け)
TWESTG_CMD_u32CmdOp() のコマンドについて解説します。
TWESTG_CMD_u32CmdOp() コマンド解説(内部開発者向け)
TWESTG_CMD_u32CmdOp()
関数によるコマンド実行は、TWENETstgs ライブラリを利用し実装されたアプリケーション(ファームウェア)との共通的な手続きを提供するものですが、この情報はライブラリ内部の実装に関するもので、通常のユーザが使用することは想定していません。
概要 twesettings_cmd.[ch]
の TWESTG_CMD_u32CmdOp()
関数は、0xdb
コマンドの実行処理を行うことを想定している。この関数は、モジュールの諸情報の取得、設定情報の取得、設定情報の反映、リセットなどの処理が含まれる。多くの処理は設定関連の補助関数 TWEINTRCT_cbu32GenericHandler()
を呼び出すようになっている。
データ型 TWE_APIRET
は、0x80000000
のビットの有で成功、なしで失敗。残りの31ビットをパラメータとする。TWE_tsBuffer
はバッファへのポインタ、系列長、バッファ最大長を格納した構造体。TWESTG_tsFinal
は、設定関連の管理構造体。TWESTG_CMD_u32CmdOp()
TWE_APIRET TWESTG_CMD_u32CmdOp(uint8 u8Op, TWE_tsBuffer *pBufIn, TWE_tsBuffer *pBufOut, TWESTG_tsFinal *psFinal)
処理内容u8Op
に対応した処理を行う。処理によって入力データpBufIn
、出力データpBufOut
を用いる。最後のパラメータは設定管理構造体は psFinal
を指定する。
パラメータ 型 処理 u8Op
uint8
処理内容を指定する。 pBufIn
TWE_tsBuffer *
入力系列。 pBufOut
TWE_tsBuffer *
出力データの格納領域を指定する。処理によっては NULL
指定でも構わない。処理の失敗時の状態は原則未定義である。 psFinal
TWESTG_tsFinal *
設定情報管理構造体を指定する。
u8Opの概要は以下である。
E_TWESTG_CMD_OP_ACK = 0xF0 ACK処理
E_TWESTG_CMD_OP_QUERY_MODULE_INFO = 0xF1 SIDなどの取得
E_TWESTG_CMD_OP_APPLY_SETTINGS = 0xF2 設定の反映(セーブはしない)
E_TWESTG_CMD_OP_QUERY_SETTINGS = 0xF3 設定の読出
E_TWESTG_CMD_OP_MODULE_CONTROL = 0xF8 設定関連の諸処理
E_TWESTG_CMD_OP_REVERT = 0xFD 設定を元に戻す
E_TWESTG_CMD_OP_SAVE = 0xFE 設定の保存
E_TWESTG_CMD_OP_DO_MDDULE_RESET = 0xFF, モジュールリセット
戻り値は成功・失敗を戻す。処理によってはパラメータが設定されることがある。
戻り値 VALUE 状況 TWE_APIRET_SUCCESS
b0..b7 → u8Op、他は処理次第 成功時 TWE_APIRET_FAIL
b0..b7 → u8Op、他は処理次第 失敗時
処理 E_TWESTG_CMD_OP_ACK (F0) ACK応答を行う。入力した系列をそのまま出力する。
例
(なし) -> 01 : 入力なしの場合は 01 が戻る
112233 -> 112233 : 112233の場合は、出力にそのまま戻る。
E_TWESTG_CMD_OP_QUERY_MODULE_INFO (F1) モジュールの諸情報を取得する。
入力列 データ型 値 内容 [0]
OCTET 0x01 モジュールのSIDを得る。 そのほか 未定義 以降のデータは未定義
出力列 ([0] == 0x01) データ型 値 内容 [0..3]
BE_DWORD モジュールのSID。
E_TWESTG_CMD_OP_APPLY_SETTINGS(F2) 設定情報を変更する。
設定情報はセーブ&リセットされるまでは反映されません。 未反映の状態でのアプリケーションのふるまいは未定義です。 未定義の状態でインタラクティブモードに遷移すると変更したデータは破棄されます。 設定済みのデータと同じ内容に変更しようとしたときも、この処理は成功として戻り値を返します。ただしセーブ(E_TWESTG_CMD_OP_SAVE
)を実行しても、実際のセーブは行われません。 この処理は出力 (pBufOut
) には書き込みません。 入力列 データ型 値 内容 [0]
OCTET 0x01 IDに指定する設定を変更する。 [1]
OCTET 0x00以外 設定ID [2..]
データ型依存
設定データ 設定ID 内容 入力データ 備考 0x01 アプリケーションID BE_DWORD (uint32_t) 0x02 論理ID (8bit) OCTET (uint8_t) 0x03 チャネル OCTET (uint8_t) 0x04 チャネル(複数指定) BE_WORD(uint16_t) b0: ch11, b1: ch12, …, b15: ch16 BE_DWORD(uint32_t) 1UL « ch のビット和 (11, 13なら 1UL « 11 | 1UL « 13) ※ STGSTD では無効化されている。 0x05 無線出力と再送 OCTET (uint8_t) 上位4ビットが再送回数、下位4ビットは出力設定 (0..3, 3が最高出力) 0x06, 0x08, 0x09, 0x0A オプション(32bit) BE_DWORD (uint32_t) 0x07 UART 設定 BE_WORD (int16_t) 内部形式の設定データをそのまま入力する。 BE_DWORD ボーレートを指定する(9600 … 250000)。他の通信条件は 8N1 を指定する。 BE_DWORD OCTET OCTET OCTET 全パラメータを指定する。 - ボーレート(DWORD) - ビット数 (7 or 8) - パリティ (‘N’ or ‘E’ or ‘O’) - ストップビット (1 or 2)
例
01011234BEEF アプリケーションID(0x01)に0x1234BEEF を設定する。
010212 チャネル(0x02)に0x12(18)を設定する。
E_TWESTG_CMD_OP_QUERY_SETTINGS(F3) 設定情報を取得する。
入力列 データ型 値 内容 [0]
OCTET 0x01 (QTYP)IDに指定する設定を取得する。 [1]
OCTET 0x00以外 設定ID
QTYP==1 の出力 備考 [0]
OCTET データタイプ (uint8_t: 1, int8_t: 2, uint16_t: 3, int16_t: 4, uint32_t: 5, int32_t:6, uint8_t[]: 0x80 (下位5bitはデータ長) [...]
データタイプ依存 (整数型 WORD, DWORD は BigEndian並び)
設定ID 内容 入力データ 備考 0x01 アプリケーションID BE_DWORD (uint32_t) 0x02 論理ID (8bit) OCTET (uint8_t) 0x03 チャネル OCTET (uint8_t) 0x04 チャネル(複数指定) BE_WORD(uint16_t) b0: ch11, b1: ch12, …, b15: ch16 0x05 無線出力と再送 OCTET (uint8_t) 上位4ビットが再送回数、下位4ビットは出力設定 (0..3, 3が最高出力) 0x06, 0x08, 0x09, 0x0A オプション(32bit) BE_DWORD (uint32_t) 0x07 UART 設定 BE_WORD (int16_t) 内部形式の設定データ b15: 1 なら 7bit, 0 なら 8bit b14: 1 なら STOPBIT=2, 0 なら 1 b12,13: 0->NONE, 1->ODD, 2->EVEN b0..b11->ボーレートの1/100
例
0101 -> 051234BEEF -> アプリケーションID(uint32_t 0x1234beef)
0102 -> 010D -> チャネル(uint8_t 13)
E_TWESTG_CMD_OP_REVERT (0xFD) このコマンドを実行直後に E_TWESTG_CMD_OP_SAVE
を発効することで、設定情報を初期値に戻す。
TWEINTRCT_cbu32GenericHandler(psIntr, E_TWEINRCT_OP_REVERT, TRUE, 0, NULL)
を呼び出す。第3引数の TRUE
指定により、セーブされた設定情報はロードしない。アプリケーションの TWEINTRCT_cbu32GenericHandler()
が正しく実装されていること。入力データ、出力データは無し。
E_TWESTG_CMD_OP_SAVE (0xFE) 設定情報を変更した場合に、不揮発性メモリに保存する。
上書き、既に設定済みと同じ値に変更しようとした場合は、セーブは行わない。関数の戻り値としてTWE_APIRET_SUCCESS_W_VALUE(0x100 | E_TWESTG_CMD_OP_SAVE)
を返す。 セーブを行った場合は、速やかにリセットを行う(設定変更したままの動作は未定義)。 入力データ、出力データは無し。
E_TWESTG_CMD_OP_DO_MDDULE_RESET (0xFF) モジュールをリセットする。
入力データ、出力データは無し。