0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Simulink/Embedded Coder のビルドプロセスをカスタマイズする (#6)

Posted at

はじめに...

第6回は、生成したコードを make してバイナリファイルを作成し、それを対象ハードウェアボードへ書き込んで、L チカを試みます。第5回で作成したモデル blink を引き続き使用します。


生成コードのビルド

前回、モデル コンフィギュレーション パラメータ設定において、[コード生成] ペイン ⇨ [ビルドプロセス] カテゴリの [コード生成のみ] パラメータにチェックを付けて、コードを生成するに止めましたが、実は既にこの段階でビルドを行える状況にありました。
これを確認します。

MATLAB コマンドウィンドウ
cd('z:\qiita\model');
open_system('blink');
set_param('blink','GenCodeOnly','off');
save_system('blink');

rmdir('blink_mytarget_ert','s');
rmdir('slprj','s');

slbuild('blink')

[コード生成のみ] パラメータのチェックを外してモデルを保存し、model フォルダ下のビルドフォルダ 「blink_mytarget_ert」と「slprj」を削除したのちにビルドします。

次は表示されたビルドメッセージの例です。

MATLAB コマンドウィンドウ
...
### Creating blink.hex 
c:/ArduinoIDE/arduino-1.8.19/hardware/tools/avr/bin/avr-objcopy -O ihex -R .eeprom blink.elf blink.hex 
### Created blink.hex ###
 
### Project size 
   text	   data	    bss	    dec	    hex	filename 
   1050	      4	     15	   1069	    42d	blink.elf 
 
### Created blink.hex successfully (or it was already up to date) 
### ビルド プロセスが正常に完了: blink
...

バイナリファイル blink.hex は、ビルドフォルダ blink_mytarget_ert 下に作られます。

mytarget_after_make.m

after_make フックポイントで呼び出す、バイナリファイル書き込み処理を記述した関数 m ファイルです。ファイル名は任意で、Target フォルダ (mytarget¥mytarget) へ置きます。

まずは mytarget_after_make() の全体構成です。

mytarget_ after_make.m
function mytarget_after_make(modelName)
    {ボードパラメータ設定}
    {書き込み確認}
    {対象ハードウェア探索}
    {書き込み実行}
    {ボードをリセット}
end

function comport = searchTargetBoard()
...
end

function resetArduino(comport,baudrate)
...
end

ボードパラメータ設定

mytarget_ after_make() :: ボードパラメータ設定
mcu      = 'atmega328p';
baudrate = 115200;
protocol = 'arduino';
modelName = char(modelName);

対象ハードウェアのボードパラメータを設定します。これらの値は Arduino IDE で用意されている boards.txt ファイルからの転記です。
1.8.19 の場合、boards.txt ファイルのパスは arduino-1.8.19\hardware\arduino\avr\boards.txt です。
modelName は、ファイル下方で角括弧の文字連結を行うため、文字ベクトルへ変換しています。

書き込み確認

mytarget_ after_make() :: 書き込み確認
if ~ strcmp(get_param(modelName,'DownloadToArduino'),'on')
    fprintf('DownloadToArduino が OFF です。\n');
    return;
end

get_param() でコンフィギュレーションパラメータ設定 [Download To Arduino] の値を取得し、チェックが付いていなければ、メッセージを表示して処理を終えます。

画像6-1.png

対象ハードウェア探索

mytarget_ after_make() :: 対象ハードウェア探索
comport = searchTargetBoard();
if isempty(comport)
    warning('RTW:mytarget:noBoardSpecification', ...
         ['Arduino Uno が見つかりません。' newline, ...
        '##### 書き込みを中止します。']);
    return;
end

fprintf('\n次の Arduino Uno が見つかりました。\n');
fprintf("COMポート: %s\n", comport);

[Download To Arduino] にチェックが付いていれば、searchComPort() で対象ハードウェアを探します。searchComPort() は後述します。
対象ハードウェアが見つかれば、COMポート番号を表す「COM4」のような文字列が、そうでなければ空文字が comport に入ります。
comport が空文字の場合、メッセージを出力して処理を中止します。

書き込み実行

書き込み実行 (1)
hexDir = RTW.GetBuildDir(bdroot).BuildDirectory;
hexFile = strrep(fullfile(hexDir, [modelName '.hex']),'\','/');

バイナリファイル (blink.hex) のパスを設定します。

書き込み実行 (2)
avrPath = 'c:\ArduinoIDE\arduino-1.8.19\hardware\tools\avr';
avrdude = fullfile(avrPath,'bin','avrdude.exe');
avrdudeConf = strrep(fullfile(avrPath,'etc','avrdude.conf'),'\','/');

avrdude ユーティリティと、avrdude.conf ファイルのパスを設定します。

書き込み実行 (3)
cmd = sprintf( ...
    '%s -C%s -v -p%s -c%s -P%s -b%u -D -Uflash:w:%s:i', ...
    avrdude, avrdudeConf, mcu, protocol, comport, baudrate, hexFile);

fprintf("\n%s\n", cmd);
status = system(cmd,'-echo');

if (status ~= 0)
    error('RTW:mytarget:downloadFailed', '書き込みに失敗しました。シリアル接続を確認してください。');
end

コマンドプロンプトへ渡すコマンド文字列を作成します。
MATLAB コマンドウィンドウで avrdude の出力メッセージを表示するよう「-echo」オプションを付けて実行します。

ボードをリセット

mytarget_after_make.m :: ボードをリセット
resetArduino(comport,baudrate);

対象ハードウェアをリセットします。resetArduino() は後述します。

searchTargetBoard()

まずは処理の全体です。

mytarget_after_make.m
function comport = searchTargetBoard()
    board = 'uno';
    if ispc
        cmd = 'chcp 437&pnputil /enum-devices /connected /class Ports';
        [~,str] = system(cmd);
        
        patt = 'Device Description: *Arduino ([0-9A-Za-z ]+?) \(COM(\d+)\)';
        deviceInfo = regexpi(str,patt,'tokens');
        comport = '';
        for ii = 1:numel(deviceInfo)
            if strcmpi(deviceInfo{ii}{1,1},board)
                comport = deviceInfo{ii}{1,2};
                break;
            end
        end
    end
end

COM ポート情報の取得
cmd = 'chcp 437&pnputil /enum-devices /connected /class Ports';
[~,str] = system(cmd);

USB 接続済み COM ポートの情報を PnPUtil コマンドで取得します。
/enum-devices」は Windows 10 バージョン 1607以降で利用できるオプションです。
str には次のような値が入ります。

Instance ID:                USB\VID_2341&PID_0043\...
Device Description:         Arduino Uno (COM5)
Class Name:                 Ports
Class GUID:                 {4d36e978-... }
Manufacturer Name:          Arduino LLC (www.arduino.cc)
Status:                     Started
Driver Name:                oem92.inf

Instance ID:                USB\VID_2A03&PID_0042\...
Device Description:         Arduino Mega 2560 (COM4)
Class Name:                 Ports
Class GUID:                 {4d36e978-... }
Manufacturer Name:          Arduino Srl (www.arduino.org)
Status:                     Started
Driver Name:                oem225.inf

(※) str はコマンドウィンドウ上でこのように表示されますが、実体は1行 n 列の文字ベクトルです。次に述べる deviceInfo が cell 「行」配列となるのはこのためです。

ボード名とポート番号のペアを作る
patt = 'Device Description: *Arduino ([0-9A-Za-z ]+?) \((COM\d+)\)';
deviceInfo = regexpi(str,patt,'tokens');

「Device Description:」に続く「Arduino」を除いたボード名とポート番号をペアにして deviceInfo へセットします。

deviceInfo は cell 配列で、上の例では次となります。

MATLAB コマンドウィンドウ
>> deviceInfo
deviceInfo =
  1×2 の cell 配列
    {1×2 cell}    {1×2 cell}
>> deviceInfo{1}
ans =
  1×2 の cell 配列
    {'Uno'}    {'COM5'}
>> deviceInfo{2}
ans =
  1×2 の cell 配列
    {'Mega 2560'}    {'COM4'}

ボード名と一致するポート番号を取得
comport = '';
for ii = 1:numel(deviceInfo)
    if strcmpi(deviceInfo{ii}{1,1},board)
        comport = deviceInfo{ii}{1,2};
        break;
    end
end

ボード名が「uno」と一致する COM ポート番号を comport へ設定します。

resetArduino()

mytarget_after_make.m
function resetArduino(port, baudrate)
    s = serialport(port,baudrate);
    pause(0.25);
    delete(s);
    clear s;
end

ソフトウェアリセットです。詳細は「Arduino UNO Rev3 with Long Pins」の「Automatic (Software) Reset」をご覧ください。

mytarget_make_rtw_hook.m

作成した mytarget_after_make() を、after_make フックポイントで呼び出すように mytarget_make_rtw_hook.mを編集します。

mytarget_make_rtw_hook.m
function mytarget_make_rtw_hook( ... )
    ...
    switch hookMethod
    ...
    case 'after_tlc'
        mytarget_after_make(modelName);
    case 'exit'
    ...
    end  % case
end  % function
...

L チカ

対象ハードウェア (Arduino Uno Rev3) をPCとつなぎ、モデル コンフィギュレーションパラメータ設定の以下を確認して、ビルドします。

  • [コード生成] ペイン
    [ビルドプロセス] カテゴリの [コード生成のみ]:チェックなし
     
  • [コード生成] ⇨ [My Target HW options] ペイン
    [Download to board]:チェックあり

次はこちらで表示された、after_make フック処理ビルドメッセージの抜粋です。
MATLAB コマンドウィンドウ
次の Arduino Uno が見つかりました。
COMポート: COM5

"c:\ArduinoIDE\arduino-1.8.19\hardware\tools\avr\bin\avrdude.exe" -Cc:/ArduinoIDE/arduino-1.8.19/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM5 -b115200 -D -Uflash:w:Z:/qiita/model/blink_mytarget_ert/blink.hex:i
 
avrdude.exe: Version 6.3-20190619
...
Writing | ################################################## | 100% 0.21s 
avrdude.exe: 1054 bytes of flash written 
avrdude.exe: verifying flash memory against Z:/qiita/model/blink_mytarget_ert/blink.hex: 
avrdude.exe: load data flash data from input file Z:/qiita/model/blink_mytarget_ert/blink.hex: 
avrdude.exe: input file Z:/qiita/model/blink_mytarget_ert/blink.hex contains 1054 bytes 
avrdude.exe: reading on-chip flash data: 
Reading | ################################################## | 100% 0.15s 
 avrdude.exe: verifying ... 
avrdude.exe: 1054 bytes of flash verified 
avrdude.exe done.  Thank you.

書き込みに成功すれば、このようなメッセージが表示されて、LED が点滅します。

本 blink モデルでは、Repeating Sequence Stair ブロックパラメータの [サンプル時間] を「-1」としているため、モデル コンフィギュレーションパラメータ [ソルバー] ペイン [固定ステップ サイズ (基本サンプル時間)] で指定した値が点滅時間になります。

終わりに...

以上で本連載を終了します。最後までお読みくださり、ありがとうございました。
対象ハードウェアを固定したり、ボード固有のパラメータをファイル内に直書きしたりして、保守性や柔軟性を欠いたものではありますが、ひとます、カスタムラピッドプロトタイピング環境の完成です。

いつものように登場したファイル (今回登場したファイルは薄黄色) とその格納先フォルダを示して、連載の締めくくりとします。

画像6-2.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?