セクションの複数ページをまとめています。 印刷またはPDF形式で保存...

もとのページに戻る

2025-08-08 現在

TWENETmcu - マイコンライブラリ

マイコンの基本的な動作を支えるライブラリ
マイコンの基本的な動作のためのソースコードが含まれます。

TWENETmcu - マイコンライブラリ

マイコンの基本的な動作のためのソースコードが含まれます。多くのコードは 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()
ファームウェアの始動関数について記述しています。

始動関数 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を指定してください。
u32SysHzSysTickタイマーの周波数を指定します。通常は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の割当について記述しています。

RAMの割当

TWWLIET GOLD の SRAM 領域は以下のようになっています。

BASETOP(末尾+1)SIZE
SRAM110x0402_C0000x0403_000016KB
SRAM100x0402_80000x0402_C00016KB
SRAM90x0402_40000x0402_800016KB
SRAM80x0402_00000x0402_400016KB
SRAM70x0401_50000x0401_60004KB
SRAM60x0401_40000x0401_50004KB
SRAM50x0401_20000x0401_40008KB
SRAM40x0401_00000x0401_20008KB
SRAM30x0400_C0000x0401_000016KB
SRAM20x0400_80000x0400_C00016KB
SRAM10x0400_40000x0400_800016KB
SRAM00x0400_00000x0400_400016KB

TWENET ではメモリマップを以下のように定義しています。

BASETOPサイズ用途RETバンク名
アプリケーション利用0x0400_0000コンパイル時に決定~64KBMMACのリンク時に必要SRAM0..3
ヒープ0x0401_5000
(変更可)
0x0401_5C003KBヒープ領域 (malloc, new)SRAM7
未使用0x0402_00000x0402_C00048KB未使用領域SRAM8,9,10
SRAM11
未使用0x0402_C0000x0402_F00012KB未使用領域SRAM11
スタック0x0402_F0000x0403_00004KBスタック領域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;
  • RAM6,7にHEAPを確保する (約8KB)。
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_STARTHEAP_SIZEがともに0の場合 HEAP_TOP を設定できます。この場合 HEAP_TOP0x0402_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() 参照)
1Debug ビルド時の設定です。PRINTFprintf_関数(libTWENETmcu)を用います。_putchar() の再定義を行わない場合SERIAL_bTxChar(0, c); が呼び出されます。TWENETxxxライブラリの Debug 設定もこの値です。
2Release ビルド時の設定です。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操作をデバッガ起動直前まで維持すると動作する場合がある。