最適な出力のために、Google Chrome(15以降)または Microsoft Edge(79以降)を推奨いたします。
2025-08-08 現在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 - マイコンについて
マイコンについて
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を用いたコードの移植を目的)の資料を参照ください。
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)はオプション非設定時と同様に実行されます。
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);
}
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操作をデバッガ起動直前まで維持すると動作する場合がある。