余白 Copyright © 2018-2024 てきーらサンドム


■■■ SAMマイコンの道標(開発ツール) ■■■


●ツール総合

デバッガ(PICkit5, PICkit4, Snap)対応状況 2024/3/15 更新
・v6.20 細かな機能改良のようです。
v6.15 PICit3, ICD3などの旧ツールがソフトウエアの更新無しで対応できるようになりました。 
v6.10のリリース・ノートが改版されました(2023/7/12)。PICit3, ICD3, オンボードデバッガの接続不具合があり、この場合ソフトウエアの更新が必要になるようです。
v6.10からデバイス対応表にICD5, PICkit5の対応が掲載されています。 
・v6.05からWindows11に対応しているようです。
・v5.45から無線モジュール(?)のSAMRxxにも対応しています。v5.45〜v5.50でSAMHAの対応品種が順次拡大されています。
・v5.40から64bitOS専用になりました(ただし5.40はProgramFiles(x86)にインストール, 6.00はProgramFilesにインストール)。32bitOSで最新のデバイスを使用するには、新しいバージョンのpackフォルダの下にあるDFPファイルをv5.30またはv5.35にコピーすれば良いようです(動作未確認) 旧版はこちらからダウンロードできます
・v5.35以降はMCUはほぼ全品種対応していますが、MPU(SAMA5Dxx)はv5.35で正式だったのがv5.40で未リリースになったりとまだ安定してないようです。

 (2019/4月ごろ)SAMC21で使用したところ、PICkit4はホストPCがWin10(64bit)でもWin7(32bit)でも安定に動作していますが、SnapはWin7(32bit)環境ではデバイスを認識しないことがあったり、Running後しばらくして通信障害が起きることがありました。Win7(32bit)環境はUSB2.0 Hub経由なのでそちらの影響かもしれませんだったようです。Win7(32bit)ノートPC直結で試したところ障害は出ませんでした(2019/5/6追記)。PICkit4とSnapは使用しているマイコン自体が違うので挙動が異なっても不思議はありませんが、やはり新しく作られたSnapの方はまだこなれてないという気がします。
 (2019/7/16追記、7/22更新, →2020/5/20 XIDE5.35では以下の現象は出ていません)MPLAB Snapは壊れやすいかも: デバッグ開始早々の5月に1台お釈迦、そして本日2台目がお釈迦になりました。現象としてはどちらもプログラム書き込み後にベリファイエラーになるというものです。実際には書込み出来ているような感じです(動いているので)。単なるプログラマとしてなら使えるかもしれません。でもデバッグはできません。1台目の時はCPUクロックを数kHzまで落として反応がなくなった後だったので、それが原因だと思ってました。本日デバッグ後に「RUN」アイコンで書き込みした後にその現象が出て、そう言えば1台目の時もCPUクロックを元に戻すプログラムを「RUN」で書いたような気がしてきました。とりあえずPICkit4では「RUN」で正常に書けています。いくら安くてもこれ以上はSnapを買う気がしませんので、しばらくはPICkit4でしのごうと思います。思ってましたが、何とPICkit4でも同じ現象が発生しました。こんどは「RUN」を使って無く、デバッグでのみ発生です。どうやらX IDE(v5.15)の問題でしょうかね。
 祈る気持ちで先日不具合が出たSnapを接続したところ正常に動作しました。先日はX IDEの再起動までは試しましたがパソコン再起動とか試してなかったので、その影響かもしれません。あるいは一旦PICkit4を接続して再度Snapに戻した(プロパティ設定を変更した)のが影響しているかもしれません。

下表は、XIDEリリース・ノートのDevice Support.htm(v6.00以降は含まれてないのでWebのDevice_Support.pdf参照)からの抜粋です。PICkit5はv6.10以降対応。バリエーション品種(Device Variant)によっては未サポートの場合があります。
品種 v5.15
(2019/2/21)
[4.60GB]
v5.20
(2019/5/14)
v5.25
(2019/8/2) 
v5.30
(2019/10/29)
[6.43GB]
v5.35
(2020/2/28)
 
v5.40
(2020/4/14)
[9.22GB]
v5.45
(2020/10/15)
[未]
v5.50
(2020/5/13)
[未]
v6.00
(2021/12/22)
[8.39GB]
v6.05
(2022/10/28)
[未]
v6.10
(2023/5/16)
旧ツール非推奨
v6.15
(2023/8/9)
[未]
v6.20
(2024/1/30)
[未]
SAMC20 (32〜64pin) β対応 β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAMC20 (100pin) β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAMC21 (32〜100pin) β対応(注) β対応(注) β対応(注) 正式対応(注) 正式対応(注) 正式対応(AUも対応) 正式対応(AUも対応) 対応
SAMD09/D10/D11 - - β対応 正式対応 正式対応 正式対応 正式対応 対応
SAMD20 (32〜64pin) β対応(注) β対応(注) β対応(注) 正式対応(注) 正式対応(注) 正式対応(注) 正式対応(注) 対応(A,BU,Uを除く)
SAMD21 (32〜64pin) β対応(注) β対応(注) β対応(注) 正式対応(注) 正式対応(注) 正式対応(注)(DU,AUは対応) 正式対応(注)(DU,AUは対応) 対応(A,Lは一部対応)
SAMD51 (48〜128pin) β対応 β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAME51 (64,100pin) β対応 β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAME53 (64,100pin) β対応 β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAME54 (100,128pin) β対応 β対応 β対応 正式対応 正式対応 正式対応 正式対応 対応
SAML10(24, 32pin) - - 正式対応 正式対応 正式対応 正式対応 正式対応 対応
SAML11 正式対応 正式対応 正式対応 正式対応 対応
SAML21(B variant) 正式対応(Bのみ) 正式対応(Bのみ) 正式対応(Bのみ) 正式対応(Bのみ) 対応(Bのみ)
SAML22(48〜100pin) 正式対応 正式対応 正式対応 正式対応 対応
SAME70/S70/V7x 正式対応(V7xはBのみ) 正式対応(V7xはBのみ) 正式対応 正式対応 対応 対応(V7xはBのみ)
SAMHA 一部正式対応 一部正式対応(追加あり) 対応(RB,WBを除く)
SAMR2x/R3x 非対応 正式対応(一部β) 正式対応 対応(R2x除く) 対応(R2x含む)
SAMA5D A5D26のみ正式対応 非対応 非対応 21〜28まで対応 21〜29まで対応(PICkit4のP除く)
注:パッケージやバリエーション品種(Device Variant)によっては未サポートの場合があります。詳細はXIDEリリース・ノートのDevice Support.htm(v6.00以降は含まれてないのでWebのDevice_Support.pdf)を参照してください。
*:インストールサイズは、8bit, 16bitを含む全品種をインストールした場合。インストール時に「8bit,16bit,32bit,その他」の単位で必要サイズが表示され選択できる(v5.40)。
 
デバッガ(PICkit4, Snap)とSAMマイコンの接続 2019/12/21 更新
 PICkit4ユーザガイドAppendix Bに記載があります(注:日本語版クイックスタートガイドは古いA版の訳なのでリセット端子位置が違っています→更新済み 2019/7/18に改版でてました)。
 SWO端子はトレース出力で、D5x,E5x以上の品種にありますが、デバッガとの接続は必須ではありません。
 PICkit4, SnapともにSAMC21と接続できました。
 
PICkit4 ピン番号 CORTEX SWD用(SAMマイコン用)
1 RESETn端子
2 VDD
3 GND
4 SWO (D5x, E5x以上の品種。端子名はパッケージ依存)
5 SWCLK (PA30端子)
6 無接続
7 無接続
8 SWDIO (PA31端子)

 
コンフィグレーション 2020/8/10 更新
 XIDEでは、コンフィグレーション・ビット(SAMではNVM User Row)をソースに記述する必要があります。
 (1)メニューのProduction > Set Configration Bits を選ぶと右下にConfigration Bits画面が出ます。
  PICであればこのままパラメータ選択できるのですが、「ARMの場合はデバイスリードが必要」と表示されてパラメータ選択できませんでした。
  どうやらSAMの場合、この機能ではコンフィグレーション・ビットを生成できないようです。SAMC2xの場合は書き換え禁止ビットがあるので分かりますが、SAMD2xには禁止ビットがなさそうなのに生成できません。
 (2)コンフィグレーション・ビットを記述しなくても書き込みやデバッグには支障ないようです(赤字の警告メッセージはでますが)。
  Harmony(v3)を使うと initialization.c の中にコンフィグレーション・ビットの記述が生成されます。これをHarmonyを使わない自分のプログラムにコピーして使ってみたところ警告は消えました。
  SAMD21はこの方法で試していますが、書き換え禁止ビットのあるSAMC21は怖くて試していません。

  (以前RH850ボードでチップ消去したらデバイスがオシャカになったというトラウマが・・・。しちゃいけないならできないようにしてくれれば良いのにi_i)
 
X IDE備忘録 2021/2/1 更新
(1)エディタ
@漢字コメントの注意:
 海外製エディタの常として、//漢字コメントを使うと次の行までコメントアウトされることがあります(行末の漢字コード2バイト目が¥になる場合)。//漢字コメントを使う場合は最後に半角(.とか)を入れるようにします。
A漢字コード設定: Properties(プロジェクト名を右クリック)→General(カテゴリツリーの一番上)→Encodeing(下の方)で、漢字コードを選択します。私は過去のソース互換性からシフトJISを選択しています。
  この方法ではプロジェクトやX IDEを閉じると、文字コードがプロジェクト作成時の設定に戻ってしまいます。プロジェクト作成後に変更する場合は、一旦プロジェクトを閉じて、
  nbprojectフォルダのproject.xmlをエディタで開き、<sourceEncoding>のうしろにある文字コード名を変更します。Shift_JISに変更すればシフトJISになります。試していませんが、UTF-8, UTF-16なども可能と思います。

Bタブ設定: Tools→Options→Editor→Formattingで、LanguageをAllにして設定します。「Expand Tabs to Space」にチェックが入っているとタブが空白に変換されます。(これに気付かず空白で作成してしまったソースをタブに戻すのに「ソフトサポート」のページに掲載のSPtoTabを使えます)
Cデバイス名不認識(v5.30?): XC32はデバイス名(__SAMC21J18__など)を認識するにもかかわらずエディタが認識しないためxc.hをナビゲート機能で追いかけることができません。Properties→xc32-gcc→Preprocessing(プルダウン)→Preprocessor macroでデバイス名を定義すれば追いかけられます。もっとも私はたどるのが面倒になったのでcomponentの下のファイルを1つのファイルにまとめて別エディタで参照しています。
D#undef認識不足(v5.30?): 2階層以下の#includeファイルにある#undefが認識されないことが度々あり(常にではない)、xc.hをインクルードするとintやcharなどの基本的な型名でエラー表示が出てしまいます。鬱陶しい場合は、そのファイル自身または1階層下のインクルード・ファイルで、#undef char, #undef short, #undef int, #undef long, #undef signed, #undef unsignedを記載します。
Eおせっかい(v5.15?): エディタでレジスタ構造体名を指定すると、勝手にソース先頭に#include"当該レジスタ名を含むコンポーネントヘッダ名" を挿入する場合があります(xc.hを間接的にインクルードしている場合)。これによって「__IO」等が未定義になりコンパイルエラーが出ます。とにかく勝手に追加されたものは削除するしかありません(v5.15特有の挙動かも)。

(2)XC32
@プリプロセッサ出力、アセンブルリストを見たい場合:
 プロジェクト名を右クリックしてProperties画面を表示し、XC32 (Global Option)の"Don't delete intermidiate files"にチェックすれば、プロジェクトフォルダのbuildのずっと下の方にオブジェクト(.o)とともにプリプロセッサ出力(.i)が残ります。
A最小スタックサイズおよびヒープサイズ: プロパティ→xc32-ldのGeneral設定項目で指定できます。最小スタックサイズは_min_stack_sizeというシンボル名でソースから参照可能です。スタックボトムを示す_stackも参照可能です。余ったRAMはスタックに割り当てられるため、実際に確保されるスタックサイズは_min_stack_sizeの値より大きな値となります(PIC32でサポートされていた実際のセクションの先頭位置を返す関数はSAMには無いようです)。ヒープサイズは_min_heap_sizeで参照可能なはずです(未確認)。_minという語が付いていますが、ヒープは指定通りのサイズが確保されています(ビルド後の.mapで確認しました)。

(3)デバッグ
@すぐRunさせるか一旦停止するかの選択:
 Tools→Options→Embedded→Generic Settingsの「Debug startup」で選択できます。リセット・アイコンを押したときは「Debug Reset」で停止する位置のみ選択可能(mainかリセット直後か)です。ウオッチドッグ・リセットの場合は、選択項目が見当たらず、リセット直後で停止します。
A漢字コード設定: Tools→Options→Embedded→Generic Settingsの「Default Charset」で選択できます。
 

 


●コンパイラ

XC32(コンパイラ)対応状況 2024/7/17 更新
 参考にSAMC21-can5テストプログラムのビルド結果を参考に示します(漢字フォント除くサイズ)。v3.00で増加となったROM/RAMサイズはv4.0ではv2.4よりも小さくなりました。
SAMC21-can5_test(R3.x) SAMC21-can5_test(R4.04)
Ver ROM (対2.4比) RAM (対2.4比) Ver ROM (対4.0比) RAM (対4.0比)
2.40 35,563     6,182     4.00 40,637 6,053
2.50 35,619 (+0.2%) 6,182 (±0%) 4.10 40,063 (-0.28%) 6,053 (±0%)
3.00 36,728 (+3.3%) 6,285 (+1.7%) 4.35 40,165 (-0.23%) 6,053 (±0%)
4.00 34,985 (-1.6%) 5,797 (-7.8%)

v4.35でオプションのデフォルト変更が予告されています。-fcommon → -fno-common(Project Properties → xc32-gcc → Option categories: Optimization → Use common tentative definitions: Disable)。
v4.30でスマートIO対応が向上しているようです。デフォルトではスマートIOが適用となるため、適用したくない場合は -mno-smart-io オプションを付ける必要があります。
・v4.20でバイナリファイルをhex表記のCソースに変換する機能がリリースされました(主に画像データ取込み用)。v4.21はバグフィックス版です。
・v4.10で旧stdinの_mon_getc()が復活しました。 SAMx7xシリーズのレガシーバージョンがサポート対象外となりB品のみとなりました。(詳細未確認)。
・v4.00からCライブラリが新しくなったようです。C言語非標準の関数/マクロは削除されたようです(詳細未確認)。
・v3.01はLAN9255(Cortex-M4F内蔵品)に関する変更のようなので、下表への記載は省略します。
・v3.00からGCC v8.3.1, Binutils v2.32ベースになったため、バックワード・コンパチビリティに影響が出るらしいです。
・v2.41はLinux版不具合解消のようで、Windows版は影響なさそうです。
v2.40から64bit OS専用になりました。また旧形式のヘッダが削除されています。 旧版はこちらからダウンロードできます
・v2.10では文字列リテラル中に漢字を含むとエラーになったと記憶していますが、v2.15以降は大丈夫のようです。実際にv2.40でfprintfによる漢字を含む文字列リテラルの表示を確認しました。

下表はXC32のリリース・ノートから抜粋した情報です。β対応か正式リリースかはXIDEのリリース・ノートを参照してください。
品種 v2.10
(2018/1/9)
 
v2.15
(2018/12/11)
[5.20GB]
v2.20
(2019/6/6)
 
v2.30
(2019/8/27)
[7.54GB]
v2.40(2020/2/19),
v2.41(2020/4/24)
[v2.40: 7.12GB]
v2.50
(2020/8/29)
[6.08GB]
v3.00
(2021/4/26)
[3.85GB]
v4.00
(2021/11/4)
[3.26GB]
v4.10
(2022/4/29)
[3.93GB]
v4.20
(2022/9/26)
v4.21
(2022/12/5)
[未]
v4.30
(2023/5/17)
[未]
v4.35
(2023/8/28)
[4.61GB]
v4.40
(2024/3/28)
v4.45
(2024/6/13)
[未]
SAMA5D2x無印 - - 対応 対応 対応 対応 対応 対応 対応 対応(29も追加)
SAMA5D2x(CD,CLD) - - - - - 対応 対応 対応 対応 対応
SAMC20/C21 - 対応 対応 対応  対応  対応 対応 対応 対応 対応
SAMD09/D10/D11 - - - 対応 対応 対応 対応 対応 対応 対応
SAMD20/D21/D51 - 対応 対応 対応  対応  対応(D20E16BU追加) 対応 対応 対応 対応
SAMDA1 - - - 対応 対応 対応 対応 対応 対応 対応
SAME51(48pin除く)/E53/E54 - 対応 対応 対応  対応  対応 対応 対応 対応 対応
SAME51G(48pin) - - - - 対応 対応 対応 対応 対応 対応
SAME70 対応 対応 対応 対応  対応  対応 対応 対応 B品に限定 B品に限定
SAMG5x/Lxx - - 対応 対応 対応 対応 対応 対応 対応 対応
SAMHA1 - - - - - 対応 対応 対応 対応 対応
SAMS70/V70/V71 対応 対応 対応 対応  対応  対応 対応 対応 B品に限定 B品に限定
SAMR R35のみ対応 30/34/35対応 ←(21も追加)
参考: v2.10から正式対応になった品種としてSAMS70,SAME70の一部品種、v2.20から正式対応になった品種としてSAMA5Dがあります。
 
SFR名(レジスタ名)によるアクセス 2019/12/21 更新
 XCコンパイラでは、以下のようにxc.hをインクルードすればレジスタ名でのアクセスが可能になります。
 #include <xc.h>
 ただし、v2.15でデフォルトでインクルードされるxc.hは、Harmony用(?)のレジスタ名になります(xc32¥v2.15¥pic32c¥include_mccの下のxc.h)。
 さらに、v2.30ではXC32ではなくXIDEの下のxc.hがインクルードされます (XIDEv5.30の場合 C:¥.......¥MPLABX\v5.xx¥packs¥Microchip¥......¥xc32¥include¥xc.h)。
 これらのxc.hを使うとマニュアルに準じたビット名でのアクセス(例えば レジスタ名.ビット名 = 値; という書き方)ができません。
 マニュアルに準じたビット名構造体でアクセスしたい場合は、xc32¥v2.15¥pic32c¥includeの下のxc.hがインクルードされるように変更すれば良いです。
   (v2.15での方法)#include <../include/xc.h> と記述します。つまりinclude_mccフォルダから一つ上に上がってからincludeフォルダの下に降ります。
   (v2.30での方法)#include <../../pic32c/include/xc.h> と記述します。これによりXIDEの下から探すのをあきらめてXC32の下から探してくれます。
 SAMC2xなどはこの方法でよかったのですが、新しくサポートされたSAML1xなどのデバイスはビット構造体定義がなくなってしまいました。まぁビットアクセス命令を持たないCPUで左辺にビット名を書くのは処理効率が悪くなる(あるいはそれを効率よく32bitアクセス命令に置き換えるコンパイラの負担が増える)ので廃止してしまったのでしょうね(というか元々推奨されてたわけではないのですが)。
 今後の品種拡張やメンテナンスを考えると新しいxc.hに変更せざるを得ませんが、そのままコーディングすると名前が非常に煩雑になる(例: GCLK->GENCTRL[0] が GCLK_REGS->GCLK_GENCTRL[0] になる)のでかなり抵抗感が強いです。
 そこでマクロを使ってデータシート上のレジスタ名、ビット名だけでコーディングできないか考えてみました。しかし、配列添え時の有無、下位構造体の有無、インスタンス番号の有無などで多種のマクロが必要になってしまい、これもスマートでは無いなという感じで迷走しています。しかもオブジェクトが0.4%増加してしまいました。(結論保留)

(2019/12/21追記)XIDEエディタとの相性悪し!(コンパイルは通るがエディタに不具合表示が出る!)
(1)デバイス名(__SAMC21J18A__など)をマクロ定義する必要があります。コンパイラオプション(プロパティ→xc32-gcc→プリプロセッサ定義(オプションカテゴリ3番目の一番上)で定義しておけばよいです。これを定義しないとエディタのナビゲート機能でxc.hの先を追いかけようとしてもxc.hの中でエラー条件に陥って追いかけられなくなります。さらに#ifの条件としてSFR定義名を参照してもエディタ上では定義されてない扱いとなり、本来通常表示される部分が灰色表示になって悩むことになります。
(2)コア定義のあるフォルダをインクルードパスに追加する必要があります。コンパイラオプションでC:/Program Files (x86)/Microchip/MPLABX/v5.30/packs/arm/CMSIS/5.4.0/CMSIS/Core/Includeを追加しました。これを定義しないとナビゲート機能でコア定義にたどり着けません。また、#include <xc.h>にエラーを示す下線表示が出て鬱陶しいです。
(3)char, intなどの基本型を#undefする必要があります。しないとエディタ上に「予期しない文字がある」というフラグが立ってしまいます。xc.hを追いかけていくと例えばintに+2を定義している部分がありました(...../sys/_intsup.hの中)。もしかしたら何かの定義名をエディタが認識して無いためにその変な定義が有効扱いになっているのでしょう。コンパイルは通りますが、赤線で表示されると非常に鬱陶しいので、#include <xc.h>の後ろに#undef char, #undef short, #undef int, #undef long, #undef signed, #undef unsignedの6行を追加しました。

(2019/7/16追記)勝手に#includeが追加されてコンパイルエラーになる!本日エディタが本当にタコだと思い知らされました。xc.hを別のインクルードファイルから間接的に読込んでいるソースで、レジスタ名による代入文を書いたところ、エディタ上ではレジスタ名が青色で表示されて正常に認識されているように見えましたが、「__IO」が未定義というコンパイルエラーがでました。xc.hの中で__IOを定義しているヘッダを読み込んでからレジスタ定義を読み込んでいるので、絶対そんなことは起きないはずなのに・・・と途方に暮れてしまいました。ところがソースの最初の方を見るといつの間にかレジスタ定義をインクルードしている行が先頭に追加されていました。間接的にxc.hをインクルードしている行より前に追加されていたので、当然__IOを定義しているヘッダがインクルードされる前なので、エラーになるのは当然です。間接的にインクルードしているxc.hを認識できないことも問題ですが、他の定義が先に必要なレジスタ定義をソース先頭に自動で追加するなんて、「何てタコなんだ!」と絶叫してしまいました。(v5.15です。v5.20は試してないです)
 
INTFLAGレジスタのbit構造体がリード・オンリ属性 2019/5/6 追加
 タイマやシリアル通信など、各種周辺回路のINTFLAGのbit構造体がヘッダ(xc.hの下の階層のtc.h, sercom.hなど)上ではリード・オンリ属性で定義してあります(記述的には__I属性付き変数)。
 そのため割込みフラグをクリアしようとしてbit構造体で書き込みを行うと、コンパイル(ビルド)時に「リード・オンリ領域に書き込みを行っている」というワーニングが出ます。
 なぜリード・オンリ属性になっているかというと、リード・モディファイ・ライトを防ぐためです。bit構造体でアクセスするとコンパイル・コードとしては、INTFLAGを読んで該当位置のみ書き換えて書き込みを行うのですが、同時に他のINTラグが立っていた場合はそちらもクリアしてしまいます。
 そもそもINTFLAGというレジスタ名がよくありません。INTFLAGを完全にリード・オンリ属性にして、クリアするレジスタ名は他のxxxCLRというレジスタ同様にINTFLAGCLRという名称にすれば間違いが減らせるはずです。
 まぁ、とにかく割込みフラグをクリアする場合はbit構造体ではなく、.regを使うようにします。ただし使用する割込み要因が1つしかなければ、__Iを__IOに書き換えて対処することもできます(単純に__Iを消すとvolatile属性も消えるのでよろしくありません)。

 
スタートアップ 2019/6/30 追加
 自動的に組み込まれるスタートアップのソースは下記です(ATSAMC21J18Aの場合)。
   C:¥Program Files¥Microchip¥xc32¥v2.15¥pic32c¥lib¥proc¥ATSAMC21J18A¥startup_atsamc21j18a.c
 見ればわかると思いますが、ユーザ固有処理を追加したい場合は、プロジェクト内の任意のソースファイルの中で、下記関数の実体を記述するだけでよいです(宣言不要)。
   void _on_reset(void);   リセット後のスタックポインタ設定直後に呼び出し。(C言語で記述する場合は変数初期化やライブラリ初期化が行われてないことに注意)
   void _on_bootstrap(void); C言語の変数領域初期化、ライブラリ初期化後に呼び出し。(main()より前に呼び出し)

 
標準入出力ライブラリ 2019/8/14 更新
 stdio.hで定義されている標準入出力を使おうと四苦八苦しています。

 (1)printf(), puts(), putchar(), putc(char, stdout), を使うには
   void _mon_putc (char c); の実体を記述します。
  試しにUARTへ出力するプログラムを書いてみて、問題なく動いているようです。→問題発覚(後述の2019.7.10追記参照)

 (2)getchar()を使うには
   int _mon_getc (int canblock); の実体を記述します。
  ただし、_mon_getc()から−1(EOF)を返しても、getcharの戻り値が0になってしまいます。XC32 v2.15特有のバグかもしれません。
  このせいか、gets()を使うとCPUがハングアップしてしまいます(スタートアップの未定義割り込みのところで永久ループ)。

 どうにも解決できそうにないので、プロジェクトフォルダー内に自分用のstdio.hを記述して、getchar,putchar,gets,puts等の関数を自分で作りました。
 printfを自分で作るのは面倒なので、とりあえずsprintf()とputs()の組み合わせで記述していましたが、やはりヤボったいのでvsprintf()を使ってprintf()をエミュレートする関数を作ってみました。
結果、問題なく動作したのですが、stdio関連のライブラリ・オブジェクトのサイズが32Kバイトに膨れました。
元々sprintf()を使った段階で、ROM17Kバイト、RAM1Kバイトの増加でしたが、ROMがさらに15Kバイト増加しています。

 今のところROMに余裕がありますが、なんかもったいない気がします。
 そこでとりあえず、出力側は(1)の方法で対処し、入力側のみ自分で作るという方法にしています。以下プロジェクトフォルダー内に作成したstdio.hとsrdio.cの例です。
 (a)stdio.h
    include <../include/stdio.h> //ご本尊のstdio.h読込み
    #undef getchar
    #define getchar UART_getc//自作関数
 (b)stdio.c
   include "UART.h" //自作関数ヘッダ
   include <stdio.h> //上記(a)読込み
   void _mon_putc (char c) { UART_putc(c); return; }
   char* gets(char* s) { return UART_gets(s); }
   #undef getc
   int getc(FILE *fp) { return UART_getc(); }
   int _mon_getc (int canblock) { return '\n'; }//使用しないがワーニングが出るので記述

 (2019.7.10追記) 残念なことにXC32 v2.15のstdioライブラリにバグがありました。1秒ごとに*を表示するプログラムを作ったところ、最初の*は問題なく表示されましたが、その次から2秒ごとに**と表示されてしまいました。書き方としてprintf("*")でもputc('*', stdout)でも変わりません。UART_putc('*')と書くと正常に1個づつ表示されます。つまり_mon_putc()が正常に呼び出されてないということですね。printf("*-+")のように表示文字が2文字以上の場合は正常に毎秒出力されました。
 ライブラリを解析するのは面倒なので、結局はvsprintfを使ってprintfをエミュレートする方法にしました。ついでにvsscanfを使ってscanfもエミュレートしてみました。その結果、組み込まれるライブラリ・サイズが50Kバイト以上という凶悪なオブジェクトになってしまいました。でもC言語準拠の書き方ができて説明が楽なのでテスト用に配布するには良いかなという感じです。そのうち公開しようと思ってます(そのうちって・・・^^;)。

 (2019.7.14追記) XC32(v2.15)で四苦八苦が続いています。fputsはマクロレベルではなくコンパイラレベルでfwriteに置き換えられてしまいます(別ソースから呼ぶ場合)。fwriteを自分で定義しない限り、XC32添付のfwriteが引き当てられてしまうので問題が起きます。とりあえずfputsをマクロでSTDIO_fputsにリネームして置き換えが起きないようにしました。printf("ABCD\n")もコンパイラレベルでputsに置き換えてしまいますが、putsは私家版も定義済みなので問題にはなりません。不思議なことに改行無しのfprint("ABCD")はfputsへの置き換えをせずにprintfがそのまま呼ばれます。 (2019.8.14追記) 同様にprintf("ABCD\n")もコンパイラレベルでfwriteに置き換えてしまいました。マクロ置き換えでは対処できないので私家版のfwriteを定義しました。
 (2019.7.16追記) スタック消費量を実測したところmain()や割込み込みで、printf使用時が912バイト、scanf使用時が1256バイトでした。printf,scanfを使わないときは256バイト以下です(スタック破壊の危険があるため測定下限を256バイトにしています)。printfは実引数が1個でも4個でもスタックサイズへの影響はありませんでした。printf,scanfともに自家製で、実際には256バイトのバッファをスタックに確保してXC32ライブラリのvsprintfやvsscanfを呼び出していますので、そのあたりで大きくなっています。
 
CPU制御関数 2019/12/21 更新
 XC32はnop, halt, ei(割込許可), di(割込禁止)と言ったCPU制御命令を必要に応じてbuiltin関数で定義しています。今年6月にようやく発行されたSAM用のコンパイラマニュアルで、nop, ei, diの3つは見つかりました。
  __builtin_nop()   nop
  __enable_irq()   ei
  __disable_irq()   di
 私の場合は、RL78からの移植のしやすさのため、ルネサスCC-RLコンパイラの関数名に合わせて再定義しています。
   #define __EI()  __enable_irq()  // asm("CPSIE i")と同じ
   #define __DI()  __disable_irq()  // asm("CPSID i")と同じ
   #define __halt() asm("WFI")
   #define __nop() _nop() //実体は__builtin_nop()
 
USBドライバをHarmonyから移植 2020/8/10 追加
 XC32のStandalone Projectで作成したSAMD21用プロジェクトに、Harmony 3 Projectで生成したUSBドライバを移植してみました。時間をかけて調べれば本当に必要な移植部分はそんなに多くないと思いますが、今回は手間をかけずに、将来の更新も容易にするために不要部分も含めて丸コピーする方式にしました。USBのCDC(コミュニケーション・デバイス・クラス)でホストと通信するためのドライバをHarmonyで生成した後、以下の手順で移植しました。
(1)ソースのコピー
  Standalone Projectは、プロジェクトフォルダ(xxx.X)の下にソースを置きます。私の場合は直下ではなく、SRCというフォルダを作ってソースを格納しています。
  Harmony3 Projectは、なぜかプロジェクトフォルダの上にfirmwareというフォルダが作成され、プロジェクトフォルダと並んでsrcというフォルダが作成され、ここにソースが格納されます。
  このsrcの下のconfigの下のdefaultフォルダを丸ごと自分のSRCフォルダの下にコピーします。このままの名前でも支障はないのですが、自分としてはdefault→USBにリネームしています。ドライバ更新のことを考えるとdefaultのままが手間が少ないのですが、気分的に落ち着かないので(^^;
  ちなみにドライバ更新の場合は、新たに生成したdefaultフォルダの内容を全部SRC/USBフォルダに上書きコピーしてクリーンビルドすれば良いはずです(ドライバ更新でファイル構成が変更にならなければ)。
(2)プロパティにインクルードディレクトリ追加
 プロパティ>x32-gcc>Processing and messages>Include directoriesに、上記ディレクトリ名SRC/USB (リネームしないならSRC/default)を追加します。
(3)ソースの追加
 下記7つをプロジェクトのソースとして追加します。私の場合は、source Filesの下にUSBという論理フォルダを作成して、その下に登録しました(Source Filesを右クリックしてNew Logical Folderを選択し、さらにリネーム)。
 SRC\USB\driver\usb\usbfsv1\src\drv_usbfsv1.c
 SRC\USB\driver\usb\usbfsv1\src\drv_usbfsv1_device.c
 SRC\USB\system\int\src\sys_int.c
 SRC\USB\usb\src\usb_device.c
 SRC\USB\usb\src\usb_device_cdc.c
 SRC\USB\usb\src\usb_device_cdc_acm.c
 SRC\USB\usb_device_init_data.c
(4)デバイス定義の追加
 新たにdevice.hというファイルが必要で、その中に少なくとも#include <xc.h>が含まれている必要があります。
 これは偶然というか想定外の干渉というか、私のプロジェクトには元からそう言うファイルがあるので、私の場合は新たに作る手間はありませんでした。
 ただし下記2つの定義を追加しました。
  #define DEVICE_DESC_BANK_NUMBER USB_DEVICE_DESC_BANK_NUMBER
 これはSRC\USB\driver\usb\usbfsv1\src\drv_usbfsv1_local.hでしか使われてない定義です。ドライバのソースは修正しない方針としたのでdevice.hに追加しました。
  #define DRV_USBFSV1_USB_Handler USB_Handler
 これはUSBの割込み関数名の書き換え用です。Standalone Projectの場合、XC32によって自動で組み込まれるスタートアップ関数の中において、USBの割込み関数名がUSB_Handlerと定義されています。一方USBドライバのソース(drv_usbfsv1.c)では割込み関数名がDRV_USBFSV1_USB_Handlerとなっています。ドライバのソースは修正しない方針なので#defineでリネームすることにしました(スタートアップを手動組み込みにすれば変更できますがリネームの方が簡単なので)。ちなみにHarmonyでは割込みベクタをinterrupts.cに記述しており、組み込むドライバに応じて関数名を自動的に修正しているようです。
 細かく言うと後述のapp.cでは、
  #define CACHE_ALIGN
 も修飾子として参照していますが、見ての通り実体がないので省略しています(SAMEとか上位のマイコンでも不要かは未確認)。
(5)空のapp.hを追加
 Harmonyでドライバを生成した時にアプリケーション依存のapp.h, app.cというファイルも生成されます(Harmonyプロジェクトのsrc直下)。これらはアプリケーション依存で書き換える内容であり、ドライバが直接必要としているわけではないようですが、#include "app.h"が記述されているファイルがあって、それを複数から参照しているため、app.hファイルが存在することは必須になります。アプリケーション依存部をappという名前で作るなら問題ありませんが、私の場合はtask_usbという名前で作るので、インクルードエラー対策として空のapp.hを作成してSRC/USBの下に置いています(某ワンドライブだと本当に空だとコピーしてくれないので、ダミーファイルというコメントだけのファイルにしてます)。app.hの置き場所がSRC/USBの下だとドライバ更新の時に削除されないように上書きコピーが必要になりますが、個人的にSRC直下には起きたくないのでSRC/USBの下としました。
(6)アプリケーション依存部の作成
 Harmonyで生成されるアプリケーション依存部(app.h, app.c)はほとんど中身がないので、応用サンプルからコピーして修正する方が手っ取り早いでしょう。CDCであれば、Harmony3ディレクトリのusb\apps\device\cdc_com_port_single\firmware\srcの下にあるapp.h, app.cが参考になります。さらに私の場合、各所に散らばっているUSB関連の設定(クロック設定、バスクロック設定、ポート設定、初期設定など)をtask_usb.cに1本化するためにSRC\USB\peripheralの下にある各種ペリフェラル設定やUSB直下のinitialization.c, tasks.cからUSB関連部分を抜き出しています。
 ちなみに私はリングバッファを使った私家版stdio.cでprintfやfgetsなどの標準入出力関数を使えるようにしているため、アプリケーション依存部はUSBドライバのバッファとリングバッファ間のデータ受け渡しとして記述しています。USBドライバのバッファサイズはサンプルソースでは512バイトでしたが、256バイトに減らしています(現状のリングバッファ・サイズ256バイト固定のため)。
 

 


●ソフト開発フレームワーク (Harmony v3)

隠れポートを表示させる方法 2021/1/27 追加
 HarmonyでTCP/IP STACKを組み込んだところ、サンプルプロジェクトでは表示されていたSYS_CONSOLEポートが表示されませんでした(Project Graph上で見て)。
 一番下の階層のTCPIP COREにはSYS_CONSOLEポートが表示されているのですが、その上のBASIC CONFIGRATIONにも、トップ階層のTCP/IP STACKにも表示がありませんでした。
 英文のマニュアルには書いてあるのかもしれませんが、読む気力が無いので色々いじってみた結果、以下の操作で表示させることが出来ました。
  (1)Project Graph上でTCP/IP STACKをダブルクリックして下の階層を開き、BASIC CONFIGRATIONをクリックして選択状態にする。
  (2)Project Graphに表示されている操作アイコンのうち、上矢印の左隣アイコン(Configure Group Nodes)をクリックする。
  (3)隠れポートのSYS_CONSOLEがリストに表示されるので、Visibleにチェックを入れると図にポートが表示される。
  (4)上矢印アイコンを押すかView(階層選択)でrootを選択して上の階層に戻る。
  (5)TCP/IP STACKを選択してConfigure Group Nodesアイコンを押すと隠れポートのSYS_CONSOLEがリストに表示されるので、Visibleにチェックを入れると図にポートが表示される。
 なお、表示されたポートを結線してしまうとリストに表示されなくなります。表示を消すには結線をはずしてからリストを表示し、Visibleのチェックを外します。