鳥の巣箱

ネトゲしたり、機械いじったり、ソフト書いたり、山篭ったり、ギャンブルしたりする人

HAL Driverが使えるSTM32系開発環境を作る

オヒサシブリデス


ARM Coreは昨今の組込技術には無くてはならない存在になってますね。
きがついたら
hbol.jp

Softbankが買収してたりと、最近になってARMという存在を知らなかった人にも名前くらいは浸透したのではないでしょうか。


さて、もちろん私もこの業界にいる限り避けては通れない存在です。
ARM Core CPUを販売しているメーカーのひとつにSTMicroがあります。STM32シリーズは価格が安く機能が充実しているものが多いので重宝されます。
今回はこのSTM32系の開発環境を構築していく手順をまとめます。


今回使用したものは、STMicro社のNucleo-F030R8ボードです。
評価ボードなので、ICEもついてて非常に使いやすいです。
秋月で1500円くらいで売ってます。
搭載されてるCPUはSTM32030R8T6で、STM32F0xシリーズに分類されます。


この記事では上記のボード、CPUを前提に進めますがそれ以外のものでも基本大丈夫なはずです。
少々手を加える必要はありますが。


STMicroが提供しているライブラリは現時点で2種類

Standard Peripheral Driver(通称SPD)
Hardware Abstraction Layer(通称HAL)
があります。
SPDの方が最初に提供されていたライブラリなのですが、後にHALが登場。
なのでネットなどを調べてもSPDを用いたものと、HALを用いたものでは出てくる量が全然違います。特に日本語(
しかし、STMicroは今後HALを推し進めていくようです。
さらには、一部評価ボードなどではもうSPDで操作できない部分もあるようで完全に切り捨てるようですね(
SPDとHALは互換性もないので、楽してSPDを使うと今後使えなくなった時にキッツイので。。。
なのでHALを使うことを目標に環境を立ち上げます。


色々と試行錯誤の末デバッグ環境までこぎつけた感じなので、もしかしたらいらない工程が含まれてるかもしれません。
とりあえず、現時点での私の環境をそのまま再現する手順を書きました。
これいらなかったとかアレばコメントなどください。

続きを読む

特定サイズのダミーファイルを生成するコマンド

とある事情により、HDDの空き容量を調整するためにダミーファイルを大量に生成する必要がでてきたので
ついでに紹介。

Windows XP以降のコマンドプロンプトには、fsutil.exeというツールが用意されており
これを使うことでとても簡単にしかもサクサクとダミーファイルを生成することができる。

使い方はこんな感じ

fsutil file createnew filename xxx

filenameはそのまま生成されるファイル名を、xxxにはファイルサイズを指定します。
当然2進接頭辞で指定しないと正確なサイズにはなりません。

1kB : 1024
1MB : 1048576
1GB : 1073741824

といった具合。
ディスクのフォーマットによって作成できる1つあたりのサイズは当然決まってきますので、その範囲を超えないように。

一つのファイルをつくるならこれで簡単にできますが、例えば「1GBのダミーを100個」とかいう場合、いちいちコマンドを叩くのは大変なのでバッチファイルを作ってしまいます。

for /L %%n (1,1,100) do fsutil file createnew %%n 1073741824

と、たった1行のバッチファイルを作成するだけですぐ作れます。
この例だとファイル名1~100で1つあたり1GBのダミーファイルを生成してくれます。
生成される場所はバッチファイルがあるディレクトリです。


なお、これで生成にかかる時間は数秒程度です。
全然時間は食いませんね。


ディスク容量をあらかじめ確保する必要がある場合や、負荷テスト、その他いろいろな試験などなど使う場面は多々あるかも?

HDD容量の取得とLARGE_INTEGERの扱い

HDD容量を取得する場合は、Windows APIにあるGetDiskFreeSpace関数を使うと各変数に色々値をぴったんこしてくれるわけですが

僕、最初普通にこの「GetDiskFreeSpace関数」の方を使ってたんですね。

そしたら正しい値が返ってこないというわけで。

https://msdn.microsoft.com/ja-jp/library/cc429305.aspx

MSDNを読んでみたら、そりゃそうだって感じなんですが
それぞれのポインタ変数はDWORD型で定義されてるんで、32bitしかデータ長がないわけで。

ページ下の方にも書いてありましたけど、2GB以上の容量を持つ場合正確な値を返さないともありますね。

そりゃ無理だわ。


ってことで、上位版(?)の「GetDiskFreeSpaceEx関数」の方を使ってみました。

https://msdn.microsoft.com/ja-jp/library/cc429308.aspx

Exってついてるあたり凄みを感じちゃう!!!ってのはとりあえず置いといて。


この関数はそれぞれPULARGE_INTEGER(ポインタ型でなければULARGE_INTEGER)で定義されてるので、64bitまで扱えます。

ここで引っかかってしまったのが、ULARGE_INTEGERの扱い方。

こいつ、構造体だったんですな(

プロトタイプ宣言だと

typedef union _LARGE_INTEGER {
    struct {
        DWORD LowPart;
        LONG HighPart;
    };
    struct {
        DWORD LowPart;
        LONG HighPart;
    } u;
    LONGLONG QuadPart;
} LARGE_INTEGER;

typedef LARGE_INTEGER *PLARGE_INTEGER;


typedef union _ULARGE_INTEGER {
    struct {
        DWORD LowPart;
        DWORD HighPart;
    };
    struct {
        DWORD LowPart;
        DWORD HighPart;
    } u;
    ULONGLONG QuadPart;
} ULARGE_INTEGER;

typedef ULARGE_INTEGER *PULARGE_INTEGER;

となってます。
これを見ると分かる通り、上位32bitと下位32bit(それぞれDWORD型)のメンバで構成されてるようで
LowPartが下位32bit、HighPartが上位32bitになります。
2つまとめたのがQuadPartで、これがLONGLONG型。

つまるところ、LARGE_INTEGER64bit分をまとめて数値代入したりなんだりするには、QuadPartを使わなきゃいけないぜ!ってこと。

それをふまえて。。。

Function TForm1.HDDFreeSpace:ULARGE_INTEGER;
var
  lpRootPathName : PWideChar;
  FreeByteAvailable, TotalNumberOfByte : Int64;
  TotalNumberOfFreeByte : ULARGE_INTEGER;
  Root : string;
begin
  //  string型をPWideChar型に変換
  Root := 'C:\';
  GetMem(lpRootPathName,length(root)+1);
  StrPCopy(lpRootPathName,root);
  FreeMem(lpRootPathName);

  GetDiskFreeSpaceEX(lpRootPathName, FreeByteAvailable, TotalNumberOfByte, @TotalNumberOfFreeByte);
  Result := TotalNumberOfFreeByte;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.Add(HDDFreeSpace.QuadPart.ToString);
end;

あ、System.SysUtilsをuses句に追加は必要。
このソースだと、Cドライブのみなんで数行追加するなりなんなりで汎用性は高めてください←

普段から「あ、こんな関数あるんだーこれ使えばよくねー?」みたいな軽いノリでざっくり組むから変なところに引っかかる(

ちゃんと読まなきゃダメな(

Delphiで処理速度を計測する

今作ってるプログラムで、ちょっとレスポンスが悪いプロシージャがあったので
プロシージャ内部のどの処理が時間を食ってるのか調べることにした。

何パターンかやり方があるけど、とりあえず簡単なのを。

timeGetTime関数

uses MMSystem;

procedure TimeCheck;
var
  time : DWORD;
begin
  time := timeGetTime;
  
  {
    測定したい処理
  }
  
  time := timeGetTime - time;
end;

使い方としてはざっくりこんな感じ。
timeGetTime関数とは、Windowsのシステム時刻をミリ秒単位で取得する関数。
戻り値はDWORDで返ってきます。
上記のソースは、測定したい処理の直前の時刻を取得しておき、処理終了後の時刻を再度取得してその差分を計算するという単純なもの。

uses句にMMSystemを追加すれば使えます。
精度としては1msec程度の分解能。WindowsNTに限っていうとマシンによっては5msec以上になることもあるそうな。

DWORD型ということで戻り値は、0~2^32[msec]の間を循環します。
2^32[msec]は49.71日に相当するので、これ以上の時間は測定できません。

50日近く終わらない処理なんて測定することはしないでしょう(

変数timeに最終的な結果が代入されているので、なんかしらの形でこれを出力してやれば結果を見れます。
デバッグ画面から追っていってもいいんじゃないかと。

上記リンク、MSDNを見てもらえれば分かる通り今回はDelphi向けの書き方をしてますが、当然C#C++でも使えます。
文法をそれに合わせるだけ。

基本的には1msec程度の分解能でも十分使えるんだけども、これ以上に細かいところを見たいとなると別の手法になってきます。

QueryPerformanceCounter関数とQueryPerformanceFrequency関数を使うことになるのですが、今回は使わなかったのでまたいずれ。

Sublime Text 2のインストール後に3をインストールした場合に、既定のプログラムとして登録できない問題

最初、Sublime Text 2を導入してたんですがいろいろと使いたいパッケージがあったため後からSublime Text 3をインストールしました。

当然2の方はアンインストールしたわけなんですが、txtファイル等よく開く拡張子を関連付けしようとしたところ
どうも設定上2の方を選んだことにされるようで、アンインストールしているので当然開こうとするとエラーを吐きます。

なんでやろかなーと思ってたら
forum.sublimetext.com

フォーラムに解決策でてましたね。

レジストリから書き換えが必要らしいです。
レジストリエディタを開いて

\HKEY_CLASSES_ROOT\Applications\sublime_text.exe\shell\open\command

の階層下にあるレジストリを編集。

僕の場合

"C:\Program Files\Sublime Text 2\sublime_text.exe""%1"

となってたのを、2→3に書き換えただけです。

これで関連付けができるようになります。