Indy10 Could not load SSL library 対応(Raspberry Pi)(備忘録)

Raspberry Pi Lazarusでindy10を使用して、SMTPでgmail送信をしようとした所、「Could not Load SSL Library」のエラーとなりました。
Indy10 Could not load SSL library 対応(Raspberry Pi)

indyのバージョンは indy-10.2.0.3 です。

原因は、OpenSSLのライブラリーバージョンが「システム > Indy10」とバージョンサポート範囲外でした。
システム側の利用出来るバージョンは 1.0.0 で Inyd10が対応しているバージョンは 0.9.9~0.9.6 でした。

■対策
Indy10側で対象バージョンを無理やり、 1.0.0 もLoadLibray()の対象としました。
バージョン違いによる弊害は「幸運を期待する」です。

※なお、この対策をしても、Lazarusのデバッグモードでは「例外クラス'Extemal:SIGILL'」が発生します。実行ファイルを直接実行させると例外は発生しませんでした。よって、この件は将来の叡智に任せる事にしました。(使えればいいじゃん!)



環境


ハード:Raspberry Pi 3 Model B V1.2
pi@rp3a:~ $ uname -a
Linux rp3a 4.9.24-v7+ #993 SMP Wed Apr 26 18:01:23 BST 2017 armv7l GNU/Linux
pi@rp3a:~ $ 

pi@rp3a:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 8.0 (jessie)
Release: 8.0
Codename: jessie
pi@rp3a:~ $ 

pi@rp3a:~ $ openssl version
OpenSSL 1.0.1t  3 May 2016
pi@rp3a:~ $ 

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

Indy10 : indy-10.2.0.3.tar.gz



テストプログラム



メイン
unit u_app;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, IdSMTP, IdSSLOpenSSL, FileUtil, Forms, Controls, Graphics,
  Dialogs, StdCtrls,
  IdMessage;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    IdSMTP1: TIdSMTP;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  idmessage: tidmessage;
begin
  memo1.Lines.add('send start.');

  idmessage := tidmessage.Create(nil);
  idmessage.attachmentencoding := 'MIME';
  idmessage.charset := 'UTF-8';
  idmessage.ContentTransferEncoding := 'BASE64';
  idmessage.contenttype := 'text/plain; charset=UTF-8';  //←ここがポイント

  idmessage.from.address := 'ffffff@gmail.com';
  idmessage.recipients.emailaddresses := 'rrrrrr@gmail.com';

  idmessage.subject := 'test ' + formatdatetime('yyyy/mm/dd hh:mm:ss', now);
  idmessage.body.Text := 'test body.' + #$0d#$0a + '日本語' + #$0d#$0a +
    formatdatetime('yyyy/mm/dd hh:mm:ss', now);

  idsmtp1.connect();
  try
    idsmtp1.send(idmessage);
  finally
    idsmtp1.disconnect;
    idmessage.Free;
  end;

  memo1.Lines.add('send end.');
end;

end.


TIdSMTPとTIdSSLIOHandlerSocketOpenSSL
  object IdSMTP1: TIdSMTP
    IOHandler = IdSSLIOHandlerSocketOpenSSL1
    Host = 'smtp.gmail.com'
    Password = 'xxxxx'
    Port = 465
    SASLMechanisms = <>
    UseTLS = utUseImplicitTLS
    Username = 'xxxxxx@gmail.com'
    Left = 96
    Top = 40
  end

  object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
    Destination = 'smtp.gmail.com:465'
    Host = 'smtp.gmail.com'
    MaxLineAction = maException
    Port = 465
    DefaultPort = 0
    SSLOptions.Method = sslvSSLv23
    SSLOptions.Mode = sslmUnassigned
    SSLOptions.VerifyMode = []
    SSLOptions.VerifyDepth = 0
    Left = 120
    Top = 104
  end




経過


エラー発生時の経過を辿って行くと、下記の青枠の LoadLibrary() で複数のバージョンのロードを試みていますが、全て失敗しています。
Indy10 Could not load SSL library 対応(Raspberry Pi)

上記の赤枠の ALibVersions[] をみてみると、

Indy10 Could not load SSL library 対応(Raspberry Pi)

0.9.9~0.9.6 となっていました。
※先頭の「.」があるのとないのがありますが、これでよいのか不明です。

ldconfig -v で調べてみると

pi@rp3a:~ $ ldconfig -v

/usr/lib/arm-linux-gnueabihf:

   libssl.so.1.0.0 -> libssl.so.1.0.0

   libcrypto.so.1.0.0 -> libcrypto.so.1.0.0



.1.0.0 となっているので、

下記のように、 .1.0.0 を追加しました。

Indy10 Could not load SSL library 対応(Raspberry Pi)


これで、 gmai 送信できましたが、冒頭の記述のようにLazarusのデバッグモードでは「例外クラス'Extemal:SIGILL'」が発生します。
実行ファイルを直接実行させると例外は発生しませんでした。



例外クラス'Extemal:SIGILL'を追う


これを追っていくと、

こんな箇所に遭遇しました。
Indy10 Could not load SSL library 対応(Raspberry Pi)

{}のネスト不良がありました。
修正方法がわからないので、(* *)でコメント化し、万一この関数を呼ばれた時の為に、 raise を入れて置きました。
ただし、これを行っても結果はなんら変わりませんでした。

Indy10 Could not load SSL library 対応(Raspberry Pi)

※しかし、このような状態でコンパイルが通ったのかは判りません。これも「将来の叡智に任せる」ですね。



感想


色々探っているなかで、if xxx then begin xxx; exit; end; で exit; を通過しているにもかかわらず、exitしないで次の文に制御が移ります。
「コンパイラオプション」で「最適化なし」にすると、この現象は無くなりました。

色々、難問が残っていますがとりあえずこのまま使ってみます。



スポンサーサイト

Lazarus ソースエディタで入力ダブリ(Raspberry Pi)(備忘録)

Raspberry Pi 3上のLazarusにおいて、ソースエディタで半角英文字を入力すると、
1文字入力で2文字表示される。
ただし、この現象は「オブジェクトインスペクター」や「Leafpad」では発生しない。

暫定対策は 「Raspberry Pi設定」のローカライゼーションを「en(Englich)」にして、この現象を逃げる。

ダブリが発生する時


Lazarus ソースエディタで入力ダブリ(Raspberry Pi)



正常に入力できる時


Lazarus ソースエディタで入力ダブリ(Raspberry Pi)
※Lazarusの「IDEオプション」→「環境」→「一般」→「言語」は「日本語[ja]」に設定しても正しく動作する。



環境


ハード:Raspberry Pi 3 Model B V1.2
pi@rp3a:~ $ uname -a
Linux rp3a 4.9.24-v7+ #993 SMP Wed Apr 26 18:01:23 BST 2017 armv7l GNU/Linux
pi@rp3a:~ $ 

pi@rp3a:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 8.0 (jessie)
Release: 8.0
Codename: jessie
pi@rp3a:~ $ 

pi@rp3a:~ $ openssl version
OpenSSL 1.0.1t  3 May 2016
pi@rp3a:~ $ 

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)(備忘録)

Raspberry Pi 3(Raspbian)に indy-10.2.0.3 をインストールした時のメモです。

■不具合との遭遇
(1)indy10をLazarusに組み込む為に、コンパイルをするとエラーとなります。
(2)indyとは無関係に、ソースエディタで半角文字を一文字入力すと二文字表示されます。(電動タイプライター風にいうとダブリます)
(3)indy10が対応しているSSLのバージョが古い為にSMTP利用時にSSLが使用できない不具合があります。(ライブラリーロードエラー)

(1)の対策は本記事で対策しています。
(2)の対策は、Lazarusのソースを修正する必要があると思われますが、困難なので暫定的に環境で対応しました。(別記事)
(3)の対策は、幸運を期待した対策をしました。(別記事予定)


要点版


indy10のダウンロードはコチラから
indy-10.2.0.3.tar.gz をダウンロードする。

■解凍後フォルダ名変更
「fpc」フォルダ → 「indy_fpc」
「lazarus」フォルダ → 「indy_lazarus」

■フォルダをコピー(windows上で作業の場合)
「indy_fpc」 → 「/usr/local/fpc/source/packages」に
「indy_lazarus」 → 「/usr/local/share/lazarus/components」に

■パーミッション変更
0777に変更する。
「/usr/local/share/lazarus」
「/usr/local/fpc」

■パッケージ lpk ファイル指定
メニュー「パッケージ」 → 「パッケージファイルを開く」
/usr/local/share/lazarus/components/indy_lazarus/indylaz.lpk

■パッケージOptions指定
「コンパイラオプション→パス」 → 「Other unit files(-Fu)」欄の横の「...」をクリックする。
「/usr/local/fpc/source/packages/indy_fpc」を指定

■パッケージコンパイル
「パッケージダイアログ」の「コンパイル」クリック

■バグ修正
idMessageの831行目の if Encoding = meMIME then でErrorとなるので、
これを if self.Encoding = meMIME then と修正する。

■再度コンパイル

■パッケージのインストール
「パッケージ」ダイアログの「Use」→「インストール」をクリックしてインストール。



画像付版


環境


ハード:Raspberry Pi 3 Model B V1.2
pi@rp3a:~ $ uname -a
Linux rp3a 4.9.24-v7+ #993 SMP Wed Apr 26 18:01:23 BST 2017 armv7l GNU/Linux
pi@rp3a:~ $ 

pi@rp3a:~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 8.0 (jessie)
Release: 8.0
Codename: jessie
pi@rp3a:~ $ 

pi@rp3a:~ $ openssl version
OpenSSL 1.0.1t  3 May 2016
pi@rp3a:~ $ 

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)



準備


■indy10 ダウンロード

indy10のダウンロードはコチラから
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
indy-10.2.0.3.tar.gz をダウンロードする。

■indy10 解凍

windows上で解凍しました。
7-Zipでindy-10.2.0.3.tar.gzを解凍後、解凍されたindy-10.2.0.3.tarを更に解凍。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
解凍されたファイル

■フォルダ名変更(任意)

解凍されたファイルの2つのフォルダの名前を下記のように変更する。
(indyである事と用途が分かるように)(他とダブらなければ任意の名前でよい)

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

■解凍したファルダをRaspberry Piに転送
windows上で作業しているので、解凍した内2つのフォルダをlazarusに転送する。
転送はWinSCPでしました。ログインはrootで。

(1)indy_lazarusファルダ

下記のようにcomponentsフォルダに転送する。
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
転送結果

componentsのフォルダの位置は環境により変わるので注意。
components中の他のフォルダに「.lpk」が存在する事で確認しました。

(2)indy_fpcフォルダ

下記のようにpackagesフォルダに転送する。
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
転送結果



作業性向上の為に


Lazarusのインストール等はrootで行いましたが、indyインストールの作業やアプリの作成はpiでするので、
色々面倒な事を避ける為 lazarus と fcp のフォルダのパーミッションは何でも可にして置きました。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

下記のエラーは「スキップ」で対応。
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

/usr/local/fpcも同様に処置します。



パッケージのインストール



■Lazarusを起動し、 メニュー→パッケージ→パッケージファイルを開く をクリック。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

■indylaz.lpkを開く

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

パッケージダイアログが開いたところ
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

■Option指定

上記画面の「Options」をクリックする。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

「コンパイラオプション」ダイアログで「コンパイラオプション→パス」を選択し、
「Other unit files(-Fu)」欄の横の「...」をクリックする。

表示された「パスエディタ」ダイアログの「検索パス」グループの検索用フォルダマークボタンをクリックして、
先程、コピーした「indy_fpc」を指定する。
その後、「追加」ボタンをクリックして、一覧に追加する。
Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
追加後の画面

「OK」をクリックして戻る。

■パッケージをコンパイル

「コンパイル」ボタンをクリックしてコンパイルする。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

■バグ修正

idMessageの831行目の if Encoding = meMIME then でErrorとなるので、
これを if self.Encoding = meMIME then と修正する。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

赤枠が修正対象行。 水色枠は原因行でwithによる限定子省略の戻し忘れが原因と思われる。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)
修正後

■再度コンパイル

「コンパイル」ボタンをクリックしてコンパイルする。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

コンパイル成功

■パッケージのインストール

「パッケージ」ダイアログの「Use」→「インストール」をクリックしてインストール。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

Lazarus再構築の許可を与える。
「はい」ボタンをクリックする。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

パッケージのインストールが完了し、Lazarusが再起動される。

Raspberry Pi 3(Raspbian)に indy10 をインストール(Raspberry Pi)

indy登録完了。


Lazarus と FreePascalのインストール(Raspberry Pi)(備忘録)

雨降りセンサーや郵便投函センサーのサーバーとして現在PCはEZGO(手のひらサイズPC)とIP Powerを組み合わせているのですが、
これをRaspberry Pi 3に置き換えてみようと挑戦中です。

この記事は、開発言語としてWindowsとRaspbianの両方で使えるFree Pascal(FPC)を試す事にしてLazarusのインストールを試みた時の備忘録です。
古いバージョンなら比較的簡単にインストールできましたが、出来るだけ新しいバージョンを狙うとなかなか苦労します。

前提


■OS
Raspberry Pi 3のOSはRaspbianで、

RASPBIAN JESSIE WITH PIXEL
Image with PIXEL desktop based on Debian Jessie
Version:April 2017
Release date:2017-04-10
Kernel version:4.4

ここからダウンロードしました。

■開発言語とライブラリー
Free Pascal and Lazarus と indy10を使用する。



LazaFree Pascal and Lazarusのインストール


こちらについては、下記のサイトで非常にわかりやすく書かれています。(感謝)

Tweaking4All.com - How to install Lazarus Pascal on Raspberry Pi 2 (Raspbian)

■ただし、記事は2015年に書かれたものなので、最新のFree Pascal(FPC)をコンパイルする為に必要なFPCのバージョンが古く、コンパイルできませんでした。
この為、Step4に書かれている fpc-2.6.4.arm-linux.tar を fpc-3.0.2.arm-linux-eabihf-raspberry.tar に置き換えて実施しました。

fpc-3.0.2.arm-linux-eabihf-raspberry.tarはこちらからダウンロードしました。

■もう一迷った箇所は、
Step4で、fpc-3.0.2をインストールする時に、問い合わせがあります。
ideとかドキュメントなどインストールするかなどです。
これは、全て「n」で応答しました。....この記事を記述時点ではこの選択の影響は不明です。

■重要なポイント
「Increase the swap file size (required)」で書かれている、スワップファイルの拡張はRaspberry Pi 3でも必須です。
これをしないと、地獄を見ます。私のように。
※ 設定値は記事の通り、 CONF_SWAPSIZE=500 で成功しました。


参考にした記事が非常によく書かれていて、これ以上メモって置くことはありません。改めて感謝感謝です。


Raspberry Piと秋月I2C接続LCD(gnublin-api)(C++)(備忘録)

Raspberry Pi B Rev2 (china) に秋月の「I2C接続小型キャラクタLCDモジュール 8x2行」を繋いで、表示させてみる。

Raspberry Pi(Raspbian)の設定


raspi-configのAdvanced Optionsで設定。

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

RaspRaspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

Raspberry Piと秋月I2C接続LCD

再起動して完了。

C++用 I2C API(gnublin-api)入手


I2C用APIライブラリーを下記より入手。

参考:https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=43725

ダウンロード:https://github.com/embeddedprojects/gnublin-api

gnublin.cppとgnublin.hをダウンロードする。


LCD制御


■資料
I2Cを使用してLCDを制御する方法は、秋月のI2C接続小型キャラクタLCDモジュール 8x2行の頁に参考資料のリンクがあるので、そちらから入手する。


テスト


■ソース
#define BOARD RASPBERRY_PI
#include "gnublin.h"
#include <time.h>
#include <sys/time.h>
#include <unistd.h>

#define POWERONWAITTIME 50000000
#define EXECWAITTIME       30000
#define FOLLWAITTIME   200000000
#define CLEARWAITTIME    2000000

void nano_sleep(unsigned Anano_sec){
struct timespec req;
req.tv_sec = Anano_sec/1000000000;
req.tv_nsec = Anano_sec%1000000000 ;
nanosleep(&req, NULL);
}

int main() {
gnublin_i2c i2c;
unsigned char buffer[100];

i2c.setAddress(0x3e); // set the address of the slave you want to read/write

// init begin
nano_sleep(POWERONWAITTIME);
//Function SET IS=0
buffer[0] = 0x00;
buffer[1] = 0x38;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Function SET IS=1
buffer[0] = 0x00;
buffer[1] = 0x39;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Internal OSC frequency
buffer[0] = 0x00;
buffer[1] = 0x14;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Contrast set
buffer[0] = 0x00;
buffer[1] = 0x70;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Pwoer/ICON/Contrast control
buffer[0] = 0x00;
buffer[1] = 0x56;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//follower control
buffer[0] = 0x00;
buffer[1] = 0x6c;
i2c.send(buffer, 2);
nano_sleep(FOLLWAITTIME);

//nano_sleep(EXECWAITTIME);
//Function set
buffer[0] = 0x00;
buffer[1] = 0x38;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Display ON/OFF control
buffer[0] = 0x00;
buffer[1] = 0x0c;
i2c.send(buffer, 2);
nano_sleep(EXECWAITTIME);

//Clear Display
buffer[0] = 0x00;
buffer[1] = 0x01;
i2c.send(buffer, 2);
nano_sleep(CLEARWAITTIME);

//DDRAM Address set
buffer[0] = 0x00;
buffer[1] = 0x80;
i2c.send(buffer, 2);

// init end


//disp char
buffer[0] = 0x40;
buffer[1] = 'A';
i2c.send(buffer, 2);

buffer[0] = 0x40;
buffer[1] = 'B';
i2c.send(buffer, 2);

}



■結果
LCD左上から「AB」と続けて表示した。

以下はロジックアナライザの画面
Raspberry Piと秋月I2C接続LCD


問題点


Raspberry Pi電源投入後、第一回目の実行では文字が表示されない。
二回目移行は問題なく動作する。

原因は下図の様に、「00」「56」に続いて送られる「00」「6C」が送出されていない。(時により、6Cのみ送出されない時もある)
Raspberry Piと秋月I2C接続LCD

現在、真の原因は不明。

環境


root@raspberrypi:/# uname -a
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux

os-release(ファイル内容)
PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)"
NAME="Raspbian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"


Eclipse IDE for C/C++ Developers

Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


<?xml version="1.0"?>
<Toolchain xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ToolchainName>Raspberry PI</ToolchainName>
  <ToolchainType>Linux</ToolchainType>
  <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
  <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
  <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
  <BinaryDirectory>bin</BinaryDirectory>
  <Prefix>arm-linux-gnueabihf-</Prefix>
  <Make>make.exe</Make>
  <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&amp;target=arm-linux-gnueabihf&amp;filter={0}</BSPIndexUrlFormat>
  <IsCygwinBased>false</IsCygwinBased>
  <GCCVersion>4.9.2</GCCVersion>
  <GDBVersion>7.10</GDBVersion>
  <Revision>1</Revision>
  <RelativeSysrootPath>arm-linux-gnueabihfsysroot</RelativeSysrootPath>
</Toolchain>


※2016/03 実施

Raspberry Pi C++ GPIO読み取り方式比較(メモリマップ式)(備忘録)

Raspberry Pi GPIO入力ポートの読み取り三方式の動作時間比較。

テストの概要


1.GPIO入出力はメモリマップ方式で行う
2.入力ポートの読み取りはレジスタ一括方式(二種類)とビットフィールド方式の比較を行う。

■読み込み方式
(1)レジスタ一括方式(都度bitマスク生成方式)
  (0x1 << (22%31)) & (sel->levn[22/31]))
(2)レジスタ一括方式(事前bitマスク生成方式)
  levn_mask & (sel->levn[22/31])
(3)ビットフィールド方式
  sel->lev22


■測定方法
1.GPIO27ポートを出力ポートとしてon/offし、それをオシロスコープで観測する。
2.GPIO27ポートをon → 「入力ポートの読み込み」 → 出力ポートoff。
3.項番2の方法で、「入力ポート読み込みなし」及び「■読み込み方式」三種を連続して実行し、
4.オシロスコープで観測する。

■参考資料
 「BROACOM BCM2835 ARM Peripherals


結果



Raspberry Pi C++ GPIO読み取り方式比較(メモリマップ式)(備忘録)
./testreg07 100000000 1 1000 で実行

■パルス順に
1.入力読み込みなし
2.レジスタ一括方式(都度bitマスク生成方式)
3.レジスタ一括方式(事前bitマスク生成方式)
4.ビットフィールド方式

入力ポートの読み込み速度が最も早いのは
 1.「レジスタ一括方式(事前bitマスク生成方式)」
 2.「ビットフィールド方式」
 3.「.レジスタ一括方式(都度bitマスク生成方式)」


テスト用プログラム ソース



■main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include "nrpgpio01.h"

static volatile GPREGISTERS *sel;

int main(int argc, char *argv[], char *envp[]) {

    int n;
    int x;
    int i1;
    unsigned levn_mask;
    struct timespec req;
    req.tv_sec = 0;
    req.tv_nsec = 0;

    long loop = 1;
    long pulse_width = 1;

    if (argc == 4) {
        loop = atoi(argv[1]);
        pulse_width = atoi(argv[2]);
        req.tv_sec  = 0;
        req.tv_nsec = atoi(argv[3]); // (ns)
    }

    sel = get_gpio_map();
    if ((int)sel == -1) {
        return 1;
    }

    GPFSELOUTPUT(sel,27);     //sel->fsel27 = GPIOOUTPUT;
    GPFSELINPUT(sel,22);    //sel->fsel22 = 0x0;

    printf("sel:%08x\n",(unsigned)sel);

    levn_mask = 0x1 << (22%31);
    printf("levn_mask:%08x\n",levn_mask);

    GPCLRN(sel,27);
    for (i1 = 0;i1 < loop;i1++){

        //基本パルス幅
        for (n = 0;n < pulse_width;n++){
            GPSETN(sel,27);
        }
        for (n = 0;n < pulse_width;n++){
            GPCLRN(sel,27);
        }

        //GPLEVN (0x1 << (22%31)) & (sel->levn[22/31])) 方式のパルス幅
        for (n = 0;n < pulse_width;n++){
            GPSETN(sel,27);
        }
        x = GPLEVN(sel,22);
//        printf("GPLEVN   :%08x\n",x);
        for (n = 0;n < pulse_width;n++){
            GPCLRN(sel,27);
        }

        //levn_mask & (sel->levn[22/31])) 方式のパルス幅  (都度シフトの回避)
        for (n = 0;n < pulse_width;n++){
            GPSETN(sel,27);
        }
        x = levn_mask & (sel->levn[22/31]);
//        printf("levn_mask :%08x\n",x);
        for (n = 0;n < pulse_width;n++){
            GPCLRN(sel,27);
        }


        //GPLEVNbm sel->lev22 方式のパルス幅
        for (n = 0;n < pulse_width;n++){
            GPSETN(sel,27);
        }
        x = GPLEVNbm(sel,22);
//        printf("GPLEVNbm  :%08x\n",x);
        for (n = 0;n < pulse_width;n++){
            GPCLRN(sel,27);
        }

         nanosleep(&req, NULL);
    }

    printf("end.\n");

    return 0;
}


■nrpgpio01.h
typedef struct gpregisters GPREGISTERS;  //例 static volatile GPREGISTERS *sel;
typedef unsigned GPIODIRECTION;

//GPIO registers 定数
#define GPIOINPUT 0x0
#define GPIOOUTPUT 0x1

//    gpio register アドレス情報
#define GPIO_BASE    (0x20000000 + 0x200000)
#define BLOCK_SIZE  4096

//旧バージョン 新たに使用しない事
#define FSEL(asel,no) asel->fsel##no




//GPIO registers 設定用

#define GPFSELINPUT(asel,no) asel->fsel##no = GPIOINPUT        //GPFSELn INPUTモードに設定
#define GPFSELOUTPUT(asel,no) asel->fsel##no = GPIOOUTPUT    //GPFSELn OUTPUTモードに設定

#define GPSETN(asel,no) asel->setn[no/31] = 0x1 << (no%31)    //GPSETn output ON 設定用
#define GPCLRN(asel,no) asel->clrn[no/31] = 0x1 << (no%31)  //GPSETn output OFF 設定用
#define GPLEVNbm(asel,no) asel->lev##no                        //GPLEVn pin level
#define GPLEVN(asel,no) ((0x1 << (no%31)) & (asel->levn[no/31]))

// GPIO(General Purpose I/O)仮想アドレス構造定義
struct gpregisters {
    unsigned fsel0:3;
    unsigned fsel1:3;
    unsigned fsel2:3;
    unsigned fsel3:3;
    unsigned fsel4:3;
    unsigned fsel5:3;
    unsigned fsel6:3;
    unsigned fsel7:3;
    unsigned fsel8:3;
    unsigned fsel9:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel10:3;
    unsigned fsel11:3;
    unsigned fsel12:3;
    unsigned fsel13:3;
    unsigned fsel14:3;
    unsigned fsel15:3;
    unsigned fsel16:3;
    unsigned fsel17:3;
    unsigned fsel18:3;
    unsigned fsel19:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel20:3;
    unsigned fsel21:3;
    unsigned fsel22:3;
    unsigned fsel23:3;
    unsigned fsel24:3;
    unsigned fsel25:3;
    unsigned fsel26:3;
    unsigned fsel27:3;
    unsigned fsel28:3;
    unsigned fsel29:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel30:3;
    unsigned fsel31:3;
    unsigned fsel32:3;
    unsigned fsel33:3;
    unsigned fsel34:3;
    unsigned fsel35:3;
    unsigned fsel36:3;
    unsigned fsel37:3;
    unsigned fsel38:3;
    unsigned fsel39:3;
    unsigned :0;
    unsigned fsel40:3;
    unsigned fsel41:3;
    unsigned fsel42:3;
    unsigned fsel43:3;
    unsigned fsel44:3;
    unsigned fsel45:3;
    unsigned fsel46:3;
    unsigned fsel47:3;
    unsigned fsel48:3;
    unsigned fsel49:3;
    unsigned :0;
    unsigned fsel50:3;
    unsigned fsel51:3;
    unsigned fsel52:3;
    unsigned fsel53:3;
    unsigned :0;
    unsigned reserved1;
    union{
        unsigned setn[2];        //設定にはこちらを使用すること
        struct{
            unsigned set0:1;    //setnは設定には使用してはいけない。
            unsigned set1:1;
            unsigned set2:1;
            unsigned set3:1;
            unsigned set4:1;
            unsigned set5:1;
            unsigned set6:1;
            unsigned set7:1;
            unsigned set8:1;
            unsigned set9:1;
            unsigned set10:1;
            unsigned set11:1;
            unsigned set12:1;
            unsigned set13:1;
            unsigned set14:1;
            unsigned set15:1;
            unsigned set16:1;
            unsigned set17:1;
            unsigned set18:1;
            unsigned set19:1;
            unsigned set20:1;
            unsigned set21:1;
            unsigned set22:1;
            unsigned set23:1;
            unsigned set24:1;
            unsigned set25:1;
            unsigned set26:1;
            unsigned set27:1;
            unsigned set28:1;
            unsigned set29:1;
            unsigned set30:1;
            unsigned set31:1;
            unsigned :0;
            unsigned set32:1;
            unsigned set33:1;
            unsigned set34:1;
            unsigned set35:1;
            unsigned set36:1;
            unsigned set37:1;
            unsigned set38:1;
            unsigned set39:1;
            unsigned set40:1;
            unsigned set41:1;
            unsigned set42:1;
            unsigned set43:1;
            unsigned set44:1;
            unsigned set45:1;
            unsigned set46:1;
            unsigned set47:1;
            unsigned set48:1;
            unsigned set49:1;
            unsigned set50:1;
            unsigned set51:1;
            unsigned set52:1;
            unsigned set53:1;
        };
    };
    unsigned :0;
    unsigned reserved2;

    union{
        unsigned clrn[2];            //設定にはこちらを使用するとこ
        struct{
            unsigned clr0:1;    //clrnは設定には使用してはいけない。
            unsigned clr1:1;
            unsigned clr2:1;
            unsigned clr3:1;
            unsigned clr4:1;
            unsigned clr5:1;
            unsigned clr6:1;
            unsigned clr7:1;
            unsigned clr8:1;
            unsigned clr9:1;
            unsigned clr10:1;
            unsigned clr11:1;
            unsigned clr12:1;
            unsigned clr13:1;
            unsigned clr14:1;
            unsigned clr15:1;
            unsigned clr16:1;
            unsigned clr17:1;
            unsigned clr18:1;
            unsigned clr19:1;
            unsigned clr20:1;
            unsigned clr21:1;
            unsigned clr22:1;
            unsigned clr23:1;
            unsigned clr24:1;
            unsigned clr25:1;
            unsigned clr26:1;
            unsigned clr27:1;
            unsigned clr28:1;
            unsigned clr29:1;
            unsigned clr30:1;
            unsigned clr31:1;
            unsigned :0;
            unsigned clr32:1;
            unsigned clr33:1;
            unsigned clr34:1;
            unsigned clr35:1;
            unsigned clr36:1;
            unsigned clr37:1;
            unsigned clr38:1;
            unsigned clr39:1;
            unsigned clr40:1;
            unsigned clr41:1;
            unsigned clr42:1;
            unsigned clr43:1;
            unsigned clr44:1;
            unsigned clr45:1;
            unsigned clr46:1;
            unsigned clr47:1;
            unsigned clr48:1;
            unsigned clr49:1;
            unsigned clr50:1;
            unsigned clr51:1;
            unsigned clr52:1;
            unsigned clr53:1;
        };
    };

    unsigned :0;
    unsigned reserved3;
    union {
        unsigned levn[2];
        struct{
            unsigned lev0:1;
            unsigned lev1:1;
            unsigned lev2:1;
            unsigned lev3:1;
            unsigned lev4:1;
            unsigned lev5:1;
            unsigned lev6:1;
            unsigned lev7:1;
            unsigned lev8:1;
            unsigned lev9:1;
            unsigned lev10:1;
            unsigned lev11:1;
            unsigned lev12:1;
            unsigned lev13:1;
            unsigned lev14:1;
            unsigned lev15:1;
            unsigned lev16:1;
            unsigned lev17:1;
            unsigned lev18:1;
            unsigned lev19:1;
            unsigned lev20:1;
            unsigned lev21:1;
            unsigned lev22:1;
            unsigned lev23:1;
            unsigned lev24:1;
            unsigned lev25:1;
            unsigned lev26:1;
            unsigned lev27:1;
            unsigned lev28:1;
            unsigned lev29:1;
            unsigned lev30:1;
            unsigned :0;
            unsigned lev31:1;
            unsigned lev32:1;
            unsigned lev33:1;
            unsigned lev34:1;
            unsigned lev35:1;
            unsigned lev36:1;
            unsigned lev37:1;
            unsigned lev38:1;
            unsigned lev39:1;
            unsigned lev40:1;
            unsigned lev41:1;
            unsigned lev42:1;
            unsigned lev43:1;
            unsigned lev44:1;
            unsigned lev45:1;
            unsigned lev46:1;
            unsigned lev47:1;
            unsigned lev48:1;
            unsigned lev49:1;
            unsigned lev50:1;
            unsigned lev51:1;
            unsigned lev52:1;
            unsigned lev53:1;
        };
    };

    unsigned :0;
    unsigned reserved4;
    unsigned eds0:1;
    unsigned eds1:1;
    unsigned eds2:1;
    unsigned eds3:1;
    unsigned eds4:1;
    unsigned eds5:1;
    unsigned eds6:1;
    unsigned eds7:1;
    unsigned eds8:1;
    unsigned eds9:1;
    unsigned eds10:1;
    unsigned eds11:1;
    unsigned eds12:1;
    unsigned eds13:1;
    unsigned eds14:1;
    unsigned eds15:1;
    unsigned eds16:1;
    unsigned eds17:1;
    unsigned eds18:1;
    unsigned eds19:1;
    unsigned eds20:1;
    unsigned eds21:1;
    unsigned eds22:1;
    unsigned eds23:1;
    unsigned eds24:1;
    unsigned eds25:1;
    unsigned eds26:1;
    unsigned eds27:1;
    unsigned eds28:1;
    unsigned eds29:1;
    unsigned eds30:1;
    unsigned :0;
    unsigned eds31:1;
    unsigned eds32:1;
    unsigned eds33:1;
    unsigned eds34:1;
    unsigned eds35:1;
    unsigned eds36:1;
    unsigned eds37:1;
    unsigned eds38:1;
    unsigned eds39:1;
    unsigned eds40:1;
    unsigned eds41:1;
    unsigned eds42:1;
    unsigned eds43:1;
    unsigned eds44:1;
    unsigned eds45:1;
    unsigned eds46:1;
    unsigned eds47:1;
    unsigned eds48:1;
    unsigned eds49:1;
    unsigned eds50:1;
    unsigned eds51:1;
    unsigned eds52:1;
    unsigned eds53:1;
    unsigned :0;
    unsigned reserved5;
    unsigned ren0:1;
    unsigned ren1:1;
    unsigned ren2:1;
    unsigned ren3:1;
    unsigned ren4:1;
    unsigned ren5:1;
    unsigned ren6:1;
    unsigned ren7:1;
    unsigned ren8:1;
    unsigned ren9:1;
    unsigned ren10:1;
    unsigned ren11:1;
    unsigned ren12:1;
    unsigned ren13:1;
    unsigned ren14:1;
    unsigned ren15:1;
    unsigned ren16:1;
    unsigned ren17:1;
    unsigned ren18:1;
    unsigned ren19:1;
    unsigned ren20:1;
    unsigned ren21:1;
    unsigned ren22:1;
    unsigned ren23:1;
    unsigned ren24:1;
    unsigned ren25:1;
    unsigned ren26:1;
    unsigned ren27:1;
    unsigned ren28:1;
    unsigned ren29:1;
    unsigned ren30:1;
    unsigned :0;
    unsigned ren31:1;
    unsigned ren32:1;
    unsigned ren33:1;
    unsigned ren34:1;
    unsigned ren35:1;
    unsigned ren36:1;
    unsigned ren37:1;
    unsigned ren38:1;
    unsigned ren39:1;
    unsigned ren40:1;
    unsigned ren41:1;
    unsigned ren42:1;
    unsigned ren43:1;
    unsigned ren44:1;
    unsigned ren45:1;
    unsigned ren46:1;
    unsigned ren47:1;
    unsigned ren48:1;
    unsigned ren49:1;
    unsigned ren50:1;
    unsigned ren51:1;
    unsigned ren52:1;
    unsigned ren53:1;
    unsigned :0;
    unsigned reserved6;
    unsigned fen0:1;
    unsigned fen1:1;
    unsigned fen2:1;
    unsigned fen3:1;
    unsigned fen4:1;
    unsigned fen5:1;
    unsigned fen6:1;
    unsigned fen7:1;
    unsigned fen8:1;
    unsigned fen9:1;
    unsigned fen10:1;
    unsigned fen11:1;
    unsigned fen12:1;
    unsigned fen13:1;
    unsigned fen14:1;
    unsigned fen15:1;
    unsigned fen16:1;
    unsigned fen17:1;
    unsigned fen18:1;
    unsigned fen19:1;
    unsigned fen20:1;
    unsigned fen21:1;
    unsigned fen22:1;
    unsigned fen23:1;
    unsigned fen24:1;
    unsigned fen25:1;
    unsigned fen26:1;
    unsigned fen27:1;
    unsigned fen28:1;
    unsigned fen29:1;
    unsigned fen30:1;
    unsigned :0;
    unsigned fen31:1;
    unsigned fen32:1;
    unsigned fen33:1;
    unsigned fen34:1;
    unsigned fen35:1;
    unsigned fen36:1;
    unsigned fen37:1;
    unsigned fen38:1;
    unsigned fen39:1;
    unsigned fen40:1;
    unsigned fen41:1;
    unsigned fen42:1;
    unsigned fen43:1;
    unsigned fen44:1;
    unsigned fen45:1;
    unsigned fen46:1;
    unsigned fen47:1;
    unsigned fen48:1;
    unsigned fen49:1;
    unsigned fen50:1;
    unsigned fen51:1;
    unsigned fen52:1;
    unsigned fen53:1;
    unsigned :0;
    unsigned reserved7;
    unsigned hen0:1;
    unsigned hen1:1;
    unsigned hen2:1;
    unsigned hen3:1;
    unsigned hen4:1;
    unsigned hen5:1;
    unsigned hen6:1;
    unsigned hen7:1;
    unsigned hen8:1;
    unsigned hen9:1;
    unsigned hen10:1;
    unsigned hen11:1;
    unsigned hen12:1;
    unsigned hen13:1;
    unsigned hen14:1;
    unsigned hen15:1;
    unsigned hen16:1;
    unsigned hen17:1;
    unsigned hen18:1;
    unsigned hen19:1;
    unsigned hen20:1;
    unsigned hen21:1;
    unsigned hen22:1;
    unsigned hen23:1;
    unsigned hen24:1;
    unsigned hen25:1;
    unsigned hen26:1;
    unsigned hen27:1;
    unsigned hen28:1;
    unsigned hen29:1;
    unsigned hen30:1;
    unsigned :0;
    unsigned hen31:1;
    unsigned hen32:1;
    unsigned hen33:1;
    unsigned hen34:1;
    unsigned hen35:1;
    unsigned hen36:1;
    unsigned hen37:1;
    unsigned hen38:1;
    unsigned hen39:1;
    unsigned hen40:1;
    unsigned hen41:1;
    unsigned hen42:1;
    unsigned hen43:1;
    unsigned hen44:1;
    unsigned hen45:1;
    unsigned hen46:1;
    unsigned hen47:1;
    unsigned hen48:1;
    unsigned hen49:1;
    unsigned hen50:1;
    unsigned hen51:1;
    unsigned hen52:1;
    unsigned hen53:1;
    unsigned :0;
    unsigned reserved8;
    unsigned len0:1;
    unsigned len1:1;
    unsigned len2:1;
    unsigned len3:1;
    unsigned len4:1;
    unsigned len5:1;
    unsigned len6:1;
    unsigned len7:1;
    unsigned len8:1;
    unsigned len9:1;
    unsigned len10:1;
    unsigned len11:1;
    unsigned len12:1;
    unsigned len13:1;
    unsigned len14:1;
    unsigned len15:1;
    unsigned len16:1;
    unsigned len17:1;
    unsigned len18:1;
    unsigned len19:1;
    unsigned len20:1;
    unsigned len21:1;
    unsigned len22:1;
    unsigned len23:1;
    unsigned len24:1;
    unsigned len25:1;
    unsigned len26:1;
    unsigned len27:1;
    unsigned len28:1;
    unsigned len29:1;
    unsigned len30:1;
    unsigned :0;
    unsigned len31:1;
    unsigned len32:1;
    unsigned len33:1;
    unsigned len34:1;
    unsigned len35:1;
    unsigned len36:1;
    unsigned len37:1;
    unsigned len38:1;
    unsigned len39:1;
    unsigned len40:1;
    unsigned len41:1;
    unsigned len42:1;
    unsigned len43:1;
    unsigned len44:1;
    unsigned len45:1;
    unsigned len46:1;
    unsigned len47:1;
    unsigned len48:1;
    unsigned len49:1;
    unsigned len50:1;
    unsigned len51:1;
    unsigned len52:1;
    unsigned len53:1;
    unsigned :0;
    unsigned reserved9;
    unsigned aren0:1;
    unsigned aren1:1;
    unsigned aren2:1;
    unsigned aren3:1;
    unsigned aren4:1;
    unsigned aren5:1;
    unsigned aren6:1;
    unsigned aren7:1;
    unsigned aren8:1;
    unsigned aren9:1;
    unsigned aren10:1;
    unsigned aren11:1;
    unsigned aren12:1;
    unsigned aren13:1;
    unsigned aren14:1;
    unsigned aren15:1;
    unsigned aren16:1;
    unsigned aren17:1;
    unsigned aren18:1;
    unsigned aren19:1;
    unsigned aren20:1;
    unsigned aren21:1;
    unsigned aren22:1;
    unsigned aren23:1;
    unsigned aren24:1;
    unsigned aren25:1;
    unsigned aren26:1;
    unsigned aren27:1;
    unsigned aren28:1;
    unsigned aren29:1;
    unsigned aren30:1;
    unsigned :0;
    unsigned aren31:1;
    unsigned aren32:1;
    unsigned aren33:1;
    unsigned aren34:1;
    unsigned aren35:1;
    unsigned aren36:1;
    unsigned aren37:1;
    unsigned aren38:1;
    unsigned aren39:1;
    unsigned aren40:1;
    unsigned aren41:1;
    unsigned aren42:1;
    unsigned aren43:1;
    unsigned aren44:1;
    unsigned aren45:1;
    unsigned aren46:1;
    unsigned aren47:1;
    unsigned aren48:1;
    unsigned aren49:1;
    unsigned aren50:1;
    unsigned aren51:1;
    unsigned aren52:1;
    unsigned aren53:1;
    unsigned :0;
    unsigned reserved10;
    unsigned afen0:1;
    unsigned afen1:1;
    unsigned afen2:1;
    unsigned afen3:1;
    unsigned afen4:1;
    unsigned afen5:1;
    unsigned afen6:1;
    unsigned afen7:1;
    unsigned afen8:1;
    unsigned afen9:1;
    unsigned afen10:1;
    unsigned afen11:1;
    unsigned afen12:1;
    unsigned afen13:1;
    unsigned afen14:1;
    unsigned afen15:1;
    unsigned afen16:1;
    unsigned afen17:1;
    unsigned afen18:1;
    unsigned afen19:1;
    unsigned afen20:1;
    unsigned afen21:1;
    unsigned afen22:1;
    unsigned afen23:1;
    unsigned afen24:1;
    unsigned afen25:1;
    unsigned afen26:1;
    unsigned afen27:1;
    unsigned afen28:1;
    unsigned afen29:1;
    unsigned afen30:1;
    unsigned :0;
    unsigned afen31:1;
    unsigned afen32:1;
    unsigned afen33:1;
    unsigned afen34:1;
    unsigned afen35:1;
    unsigned afen36:1;
    unsigned afen37:1;
    unsigned afen38:1;
    unsigned afen39:1;
    unsigned afen40:1;
    unsigned afen41:1;
    unsigned afen42:1;
    unsigned afen43:1;
    unsigned afen44:1;
    unsigned afen45:1;
    unsigned afen46:1;
    unsigned afen47:1;
    unsigned afen48:1;
    unsigned afen49:1;
    unsigned afen50:1;
    unsigned afen51:1;
    unsigned afen52:1;
    unsigned afen53:1;
    unsigned :0;
    unsigned reserved11;
    unsigned pud:2;
    unsigned :0;
    unsigned pudclk0:1;
    unsigned pudclk1:1;
    unsigned pudclk2:1;
    unsigned pudclk3:1;
    unsigned pudclk4:1;
    unsigned pudclk5:1;
    unsigned pudclk6:1;
    unsigned pudclk7:1;
    unsigned pudclk8:1;
    unsigned pudclk9:1;
    unsigned pudclk10:1;
    unsigned pudclk11:1;
    unsigned pudclk12:1;
    unsigned pudclk13:1;
    unsigned pudclk14:1;
    unsigned pudclk15:1;
    unsigned pudclk16:1;
    unsigned pudclk17:1;
    unsigned pudclk18:1;
    unsigned pudclk19:1;
    unsigned pudclk20:1;
    unsigned pudclk21:1;
    unsigned pudclk22:1;
    unsigned pudclk23:1;
    unsigned pudclk24:1;
    unsigned pudclk25:1;
    unsigned pudclk26:1;
    unsigned pudclk27:1;
    unsigned pudclk28:1;
    unsigned pudclk29:1;
    unsigned pudclk30:1;
    unsigned :0;
    unsigned pudclk31:1;
    unsigned pudclk32:1;
    unsigned pudclk33:1;
    unsigned pudclk34:1;
    unsigned pudclk35:1;
    unsigned pudclk36:1;
    unsigned pudclk37:1;
    unsigned pudclk38:1;
    unsigned pudclk39:1;
    unsigned pudclk40:1;
    unsigned pudclk41:1;
    unsigned pudclk42:1;
    unsigned pudclk43:1;
    unsigned pudclk44:1;
    unsigned pudclk45:1;
    unsigned pudclk46:1;
    unsigned pudclk47:1;
    unsigned pudclk48:1;
    unsigned pudclk49:1;
    unsigned pudclk50:1;
    unsigned pudclk51:1;
    unsigned pudclk52:1;
    unsigned pudclk53:1;
    unsigned :0;
    unsigned reserved12;
    unsigned test:4;
};



GPREGISTERS* get_gpio_map();



■printfの出力結果
sel:b6f65000
levn_mask:00400000
GPLEVN   :00400000
levn_mask :00400000
GPLEVNbm  :00000001
end.


環境


Raspberry Pi B Rev2 (china)

Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux


Eclipse IDE for C/C++ Developers
Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


 <?xml version="1.0"?>
-<Toolchain xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ToolchainName>Raspberry PI</ToolchainName>
      <ToolchainType>Linux</ToolchainType>
      <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
      <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
      <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
      <BinaryDirectory>bin</BinaryDirectory>
      <Prefix>arm-linux-gnueabihf-</Prefix>
      <Make>make.exe</Make>
      <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&target=arm-linux-gnueabihf&filter={0}</BSPIndexUrlFormat>
      <IsCygwinBased>false</IsCygwinBased>
      <GCCVersion>4.9.2</GCCVersion>
      <GDBVersion>7.10</GDBVersion>
      <Revision>1</Revision>
      <RelativeSysrootPath>arm-linux-gnueabihf\sysroot</RelativeSysrootPath>
 </Toolchain>

Raspberry Pi C++ GPIOのメモリマップ方式のテスト(備忘録)

Raspberry Pi GPIO出力ポートのメモリマップ方式によるテスト。

テストの要点


1.Raspberry PiのGPIOレジスタ構造をC++のstruct,ビットフィールドでモデル化する
2.メモリマップ方式での出力ポートの動作時間の測定

今回は、出力ポートのみ動作確認をしています。
入力ポートや他の機能について確認していません。

結果


■モデル化
(1)ビットフィールド
 1.GPIOレジスタのGPFSELnを3bitのビットフィールドとして扱う部分は成功していると思わる。
 2.GPCLRnを1bitのビットフィールドとして扱うと、代入時(書き込み)時にRaspbianがフリーズする。(※1)
 3.GPSELnを1bitのビットフィールドとして扱う部分については、一見正常に動作しているが、on/offの制御方式がGPCLRnと同じ為、フリーズする可能性がある。

(2)32bitフィールド
 1.GPSELn及びGPCLRnは32bitフィールドとして操作する。(※2)

(3)欠点
 1.利用するポートの割当がソースレベルで固定化される事である。実行時に任意に変えられない。

■動作時間
(1)出力ポートのon/off動作時間
 1.約21.8nsでon/off可能


■参考資料
 「BROACOM BCM2835 ARM Peripherals

■注
※1 ビットフィールド操作でのフリーズ
(1)推定理由

GPIOのoutput pinのデータをクリアするGPCLRnレジスタをビットフィールドでセットするとRaspberry Piがフリーズする。
C++のビットフィールドのbit操作は、データ操作単位である32bitを一旦読み込んで、目的のbitと目的外のビットをマージして再書込していると思われる。
「BROACOM BCM2835 ARM Peripherals」によるとGPCLRnレジスタはWriteのみ許さている(Page90)。
ただし、Page95のGPCLRnの詳細説明ではR/Wである。許されているのと可能なのとは異なる。
C++のmmapで得た仮想メモリからのGPCLRnの読み込みは0/1混在状態である。
Raspberry Piのシステム上、ユーザがOUTポートとして割当可能なポート以外のデータも帰ってくる。
この値がWriteのみ許さているポートなのでデタラメかもしれないし、正しい値なのかもしれない。
Page90に明記されているWriteの意味は「リードしてマージする必要はありませんよ」かもしれない。
しかし、本当のところは「Pin Set & Clear Regs」に対して、「0は状態を更新しない、1はSetする」という、回路設計上の都合を言い換えただけかもしれない。

したがって、保証されていない出力ポートを読んだ値で、目的bit以外を再書込すると"1"にセットされたレジスタが何らかの動作をし、
結果的にシステムの不具合を引き起こしていると思われる。

そもそも、Outputの状態を1bitで制御せずに、SETとCLRを別に設けている所を十分汲む必要がある。


(2)対策

1.必要に応じて、ビットフィールドを使用しない
GPSETn,GPCLRnのように、「x = No effect」との説明があるレジスタはビットフィールドを使用せずレジスタの一括ライトを行う。
「BROACOM BCM2835 ARM Peripherals」の説明は明らかにそのように指示している。

※2 ただし、あくまでOS上のアプリでの制御のため、割り込み等により動作時間の安定性は望めない。


動作時間



後述するテスト用プログラムでテストした時のGPIO27ポートの波形です。
動作が早いために、ソフトにてパルス幅を10倍に引き伸ばした時の波形です。したがって、最小の制御時間はこの結果の1/10となります。
Raspberry Pi C++ GPIOのメモリマップ方式のテスト(備忘録)
./test03 3 10 で実行した時の波形(したがって、 218ns÷10=21.8ns が制御可能な最小パルス幅の単位となります)


GPIOファイルで制御する場合の最小幅は「Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)」から
Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)
11.6usとなります。
したがって GPIOファイル制御の方が11.6us/21.8ns=532倍遅い事になります。


テスト用プログラム ソース



#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

typedef struct gpregisters GPREGISTERS;  //例 static volatile GPREGISTERS *sel;
typedef unsigned GPIODIRECTION;

//GPIO registers 定数
#define GPIOINPUT 0x0
#define GPIOOUTPUT 0x1

//    gpio register アドレス情報
#define GPIO_BASE    (0x20000000 + 0x200000)
#define BLOCK_SIZE  4096

//GPIO registers 設定用
#define GPSETN(asel,no) asel->setn[no/31] = 0x1 << (no%31)    //GPSETn output ON 設定用
#define GPCLRN(asel,no) asel->clrn[no/31] = 0x1 << (no%31)  //GPSETn output OFF 設定用
#define GPFSELOUTPUT(asel,no) asel->fsel##no = GPIOOUTPUT    //GPFSELn OUTPUTモードに設定

// GPIO(General Purpose I/O)仮想アドレス構造定義
struct gpregisters {
    unsigned fsel0:3;
    unsigned fsel1:3;
    unsigned fsel2:3;
    unsigned fsel3:3;
    unsigned fsel4:3;
    unsigned fsel5:3;
    unsigned fsel6:3;
    unsigned fsel7:3;
    unsigned fsel8:3;
    unsigned fsel9:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel10:3;
    unsigned fsel11:3;
    unsigned fsel12:3;
    unsigned fsel13:3;
    unsigned fsel14:3;
    unsigned fsel15:3;
    unsigned fsel16:3;
    unsigned fsel17:3;
    unsigned fsel18:3;
    unsigned fsel19:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel20:3;
    unsigned fsel21:3;
    unsigned fsel22:3;
    unsigned fsel23:3;
    unsigned fsel24:3;
    unsigned fsel25:3;
    unsigned fsel26:3;
    unsigned fsel27:3;
    unsigned fsel28:3;
    unsigned fsel29:3;
    unsigned :0;        //これがなくても次のbitはバウンダリ調整されるが、解りやすさと念のために記述
    unsigned fsel30:3;
    unsigned fsel31:3;
    unsigned fsel32:3;
    unsigned fsel33:3;
    unsigned fsel34:3;
    unsigned fsel35:3;
    unsigned fsel36:3;
    unsigned fsel37:3;
    unsigned fsel38:3;
    unsigned fsel39:3;
    unsigned :0;
    unsigned fsel40:3;
    unsigned fsel41:3;
    unsigned fsel42:3;
    unsigned fsel43:3;
    unsigned fsel44:3;
    unsigned fsel45:3;
    unsigned fsel46:3;
    unsigned fsel47:3;
    unsigned fsel48:3;
    unsigned fsel49:3;
    unsigned :0;
    unsigned fsel50:3;
    unsigned fsel51:3;
    unsigned fsel52:3;
    unsigned fsel53:3;
    unsigned :0;
    unsigned reserved1;
    union{
        unsigned setn[2];        //設定にはこちらを使用すること
        struct{
            unsigned set0:1;    //setnは設定には使用してはいけない。
            unsigned set1:1;
            unsigned set2:1;
            unsigned set3:1;
            unsigned set4:1;
            unsigned set5:1;
            unsigned set6:1;
            unsigned set7:1;
            unsigned set8:1;
            unsigned set9:1;
            unsigned set10:1;
            unsigned set11:1;
            unsigned set12:1;
            unsigned set13:1;
            unsigned set14:1;
            unsigned set15:1;
            unsigned set16:1;
            unsigned set17:1;
            unsigned set18:1;
            unsigned set19:1;
            unsigned set20:1;
            unsigned set21:1;
            unsigned set22:1;
            unsigned set23:1;
            unsigned set24:1;
            unsigned set25:1;
            unsigned set26:1;
            unsigned set27:1;
            unsigned set28:1;
            unsigned set29:1;
            unsigned set30:1;
            unsigned set31:1;
            unsigned :0;
            unsigned set32:1;
            unsigned set33:1;
            unsigned set34:1;
            unsigned set35:1;
            unsigned set36:1;
            unsigned set37:1;
            unsigned set38:1;
            unsigned set39:1;
            unsigned set40:1;
            unsigned set41:1;
            unsigned set42:1;
            unsigned set43:1;
            unsigned set44:1;
            unsigned set45:1;
            unsigned set46:1;
            unsigned set47:1;
            unsigned set48:1;
            unsigned set49:1;
            unsigned set50:1;
            unsigned set51:1;
            unsigned set52:1;
            unsigned set53:1;
        };
    };
    unsigned :0;
    unsigned reserved2;

    union{
        unsigned clrn[2];            //設定にはこちらを使用するとこ
        struct{
            unsigned clr0:1;        //clrnは設定には使用してはいけない。
            unsigned clr1:1;
            unsigned clr2:1;
            unsigned clr3:1;
            unsigned clr4:1;
            unsigned clr5:1;
            unsigned clr6:1;
            unsigned clr7:1;
            unsigned clr8:1;
            unsigned clr9:1;
            unsigned clr10:1;
            unsigned clr11:1;
            unsigned clr12:1;
            unsigned clr13:1;
            unsigned clr14:1;
            unsigned clr15:1;
            unsigned clr16:1;
            unsigned clr17:1;
            unsigned clr18:1;
            unsigned clr19:1;
            unsigned clr20:1;
            unsigned clr21:1;
            unsigned clr22:1;
            unsigned clr23:1;
            unsigned clr24:1;
            unsigned clr25:1;
            unsigned clr26:1;
            unsigned clr27:1;
            unsigned clr28:1;
            unsigned clr29:1;
            unsigned clr30:1;
            unsigned clr31:1;
            unsigned :0;
            unsigned clr32:1;
            unsigned clr33:1;
            unsigned clr34:1;
            unsigned clr35:1;
            unsigned clr36:1;
            unsigned clr37:1;
            unsigned clr38:1;
            unsigned clr39:1;
            unsigned clr40:1;
            unsigned clr41:1;
            unsigned clr42:1;
            unsigned clr43:1;
            unsigned clr44:1;
            unsigned clr45:1;
            unsigned clr46:1;
            unsigned clr47:1;
            unsigned clr48:1;
            unsigned clr49:1;
            unsigned clr50:1;
            unsigned clr51:1;
            unsigned clr52:1;
            unsigned clr53:1;
        };
    };

    unsigned :0;
    unsigned reserved3;
    unsigned lev0:1;
    unsigned lev1:1;
    unsigned lev2:1;
    unsigned lev3:1;
    unsigned lev4:1;
    unsigned lev5:1;
    unsigned lev6:1;
    unsigned lev7:1;
    unsigned lev8:1;
    unsigned lev9:1;
    unsigned lev10:1;
    unsigned lev11:1;
    unsigned lev12:1;
    unsigned lev13:1;
    unsigned lev14:1;
    unsigned lev15:1;
    unsigned lev16:1;
    unsigned lev17:1;
    unsigned lev18:1;
    unsigned lev19:1;
    unsigned lev20:1;
    unsigned lev21:1;
    unsigned lev22:1;
    unsigned lev23:1;
    unsigned lev24:1;
    unsigned lev25:1;
    unsigned lev26:1;
    unsigned lev27:1;
    unsigned lev28:1;
    unsigned lev29:1;
    unsigned lev30:1;
    unsigned :0;
    unsigned lev31:1;
    unsigned lev32:1;
    unsigned lev33:1;
    unsigned lev34:1;
    unsigned lev35:1;
    unsigned lev36:1;
    unsigned lev37:1;
    unsigned lev38:1;
    unsigned lev39:1;
    unsigned lev40:1;
    unsigned lev41:1;
    unsigned lev42:1;
    unsigned lev43:1;
    unsigned lev44:1;
    unsigned lev45:1;
    unsigned lev46:1;
    unsigned lev47:1;
    unsigned lev48:1;
    unsigned lev49:1;
    unsigned lev50:1;
    unsigned lev51:1;
    unsigned lev52:1;
    unsigned lev53:1;
    unsigned :0;
    unsigned reserved4;
    unsigned eds0:1;
    unsigned eds1:1;
    unsigned eds2:1;
    unsigned eds3:1;
    unsigned eds4:1;
    unsigned eds5:1;
    unsigned eds6:1;
    unsigned eds7:1;
    unsigned eds8:1;
    unsigned eds9:1;
    unsigned eds10:1;
    unsigned eds11:1;
    unsigned eds12:1;
    unsigned eds13:1;
    unsigned eds14:1;
    unsigned eds15:1;
    unsigned eds16:1;
    unsigned eds17:1;
    unsigned eds18:1;
    unsigned eds19:1;
    unsigned eds20:1;
    unsigned eds21:1;
    unsigned eds22:1;
    unsigned eds23:1;
    unsigned eds24:1;
    unsigned eds25:1;
    unsigned eds26:1;
    unsigned eds27:1;
    unsigned eds28:1;
    unsigned eds29:1;
    unsigned eds30:1;
    unsigned :0;
    unsigned eds31:1;
    unsigned eds32:1;
    unsigned eds33:1;
    unsigned eds34:1;
    unsigned eds35:1;
    unsigned eds36:1;
    unsigned eds37:1;
    unsigned eds38:1;
    unsigned eds39:1;
    unsigned eds40:1;
    unsigned eds41:1;
    unsigned eds42:1;
    unsigned eds43:1;
    unsigned eds44:1;
    unsigned eds45:1;
    unsigned eds46:1;
    unsigned eds47:1;
    unsigned eds48:1;
    unsigned eds49:1;
    unsigned eds50:1;
    unsigned eds51:1;
    unsigned eds52:1;
    unsigned eds53:1;
    unsigned :0;
    unsigned reserved5;
    unsigned ren0:1;
    unsigned ren1:1;
    unsigned ren2:1;
    unsigned ren3:1;
    unsigned ren4:1;
    unsigned ren5:1;
    unsigned ren6:1;
    unsigned ren7:1;
    unsigned ren8:1;
    unsigned ren9:1;
    unsigned ren10:1;
    unsigned ren11:1;
    unsigned ren12:1;
    unsigned ren13:1;
    unsigned ren14:1;
    unsigned ren15:1;
    unsigned ren16:1;
    unsigned ren17:1;
    unsigned ren18:1;
    unsigned ren19:1;
    unsigned ren20:1;
    unsigned ren21:1;
    unsigned ren22:1;
    unsigned ren23:1;
    unsigned ren24:1;
    unsigned ren25:1;
    unsigned ren26:1;
    unsigned ren27:1;
    unsigned ren28:1;
    unsigned ren29:1;
    unsigned ren30:1;
    unsigned :0;
    unsigned ren31:1;
    unsigned ren32:1;
    unsigned ren33:1;
    unsigned ren34:1;
    unsigned ren35:1;
    unsigned ren36:1;
    unsigned ren37:1;
    unsigned ren38:1;
    unsigned ren39:1;
    unsigned ren40:1;
    unsigned ren41:1;
    unsigned ren42:1;
    unsigned ren43:1;
    unsigned ren44:1;
    unsigned ren45:1;
    unsigned ren46:1;
    unsigned ren47:1;
    unsigned ren48:1;
    unsigned ren49:1;
    unsigned ren50:1;
    unsigned ren51:1;
    unsigned ren52:1;
    unsigned ren53:1;
    unsigned :0;
    unsigned reserved6;
    unsigned fen0:1;
    unsigned fen1:1;
    unsigned fen2:1;
    unsigned fen3:1;
    unsigned fen4:1;
    unsigned fen5:1;
    unsigned fen6:1;
    unsigned fen7:1;
    unsigned fen8:1;
    unsigned fen9:1;
    unsigned fen10:1;
    unsigned fen11:1;
    unsigned fen12:1;
    unsigned fen13:1;
    unsigned fen14:1;
    unsigned fen15:1;
    unsigned fen16:1;
    unsigned fen17:1;
    unsigned fen18:1;
    unsigned fen19:1;
    unsigned fen20:1;
    unsigned fen21:1;
    unsigned fen22:1;
    unsigned fen23:1;
    unsigned fen24:1;
    unsigned fen25:1;
    unsigned fen26:1;
    unsigned fen27:1;
    unsigned fen28:1;
    unsigned fen29:1;
    unsigned fen30:1;
    unsigned :0;
    unsigned fen31:1;
    unsigned fen32:1;
    unsigned fen33:1;
    unsigned fen34:1;
    unsigned fen35:1;
    unsigned fen36:1;
    unsigned fen37:1;
    unsigned fen38:1;
    unsigned fen39:1;
    unsigned fen40:1;
    unsigned fen41:1;
    unsigned fen42:1;
    unsigned fen43:1;
    unsigned fen44:1;
    unsigned fen45:1;
    unsigned fen46:1;
    unsigned fen47:1;
    unsigned fen48:1;
    unsigned fen49:1;
    unsigned fen50:1;
    unsigned fen51:1;
    unsigned fen52:1;
    unsigned fen53:1;
    unsigned :0;
    unsigned reserved7;
    unsigned hen0:1;
    unsigned hen1:1;
    unsigned hen2:1;
    unsigned hen3:1;
    unsigned hen4:1;
    unsigned hen5:1;
    unsigned hen6:1;
    unsigned hen7:1;
    unsigned hen8:1;
    unsigned hen9:1;
    unsigned hen10:1;
    unsigned hen11:1;
    unsigned hen12:1;
    unsigned hen13:1;
    unsigned hen14:1;
    unsigned hen15:1;
    unsigned hen16:1;
    unsigned hen17:1;
    unsigned hen18:1;
    unsigned hen19:1;
    unsigned hen20:1;
    unsigned hen21:1;
    unsigned hen22:1;
    unsigned hen23:1;
    unsigned hen24:1;
    unsigned hen25:1;
    unsigned hen26:1;
    unsigned hen27:1;
    unsigned hen28:1;
    unsigned hen29:1;
    unsigned hen30:1;
    unsigned :0;
    unsigned hen31:1;
    unsigned hen32:1;
    unsigned hen33:1;
    unsigned hen34:1;
    unsigned hen35:1;
    unsigned hen36:1;
    unsigned hen37:1;
    unsigned hen38:1;
    unsigned hen39:1;
    unsigned hen40:1;
    unsigned hen41:1;
    unsigned hen42:1;
    unsigned hen43:1;
    unsigned hen44:1;
    unsigned hen45:1;
    unsigned hen46:1;
    unsigned hen47:1;
    unsigned hen48:1;
    unsigned hen49:1;
    unsigned hen50:1;
    unsigned hen51:1;
    unsigned hen52:1;
    unsigned hen53:1;
    unsigned :0;
    unsigned reserved8;
    unsigned len0:1;
    unsigned len1:1;
    unsigned len2:1;
    unsigned len3:1;
    unsigned len4:1;
    unsigned len5:1;
    unsigned len6:1;
    unsigned len7:1;
    unsigned len8:1;
    unsigned len9:1;
    unsigned len10:1;
    unsigned len11:1;
    unsigned len12:1;
    unsigned len13:1;
    unsigned len14:1;
    unsigned len15:1;
    unsigned len16:1;
    unsigned len17:1;
    unsigned len18:1;
    unsigned len19:1;
    unsigned len20:1;
    unsigned len21:1;
    unsigned len22:1;
    unsigned len23:1;
    unsigned len24:1;
    unsigned len25:1;
    unsigned len26:1;
    unsigned len27:1;
    unsigned len28:1;
    unsigned len29:1;
    unsigned len30:1;
    unsigned :0;
    unsigned len31:1;
    unsigned len32:1;
    unsigned len33:1;
    unsigned len34:1;
    unsigned len35:1;
    unsigned len36:1;
    unsigned len37:1;
    unsigned len38:1;
    unsigned len39:1;
    unsigned len40:1;
    unsigned len41:1;
    unsigned len42:1;
    unsigned len43:1;
    unsigned len44:1;
    unsigned len45:1;
    unsigned len46:1;
    unsigned len47:1;
    unsigned len48:1;
    unsigned len49:1;
    unsigned len50:1;
    unsigned len51:1;
    unsigned len52:1;
    unsigned len53:1;
    unsigned :0;
    unsigned reserved9;
    unsigned aren0:1;
    unsigned aren1:1;
    unsigned aren2:1;
    unsigned aren3:1;
    unsigned aren4:1;
    unsigned aren5:1;
    unsigned aren6:1;
    unsigned aren7:1;
    unsigned aren8:1;
    unsigned aren9:1;
    unsigned aren10:1;
    unsigned aren11:1;
    unsigned aren12:1;
    unsigned aren13:1;
    unsigned aren14:1;
    unsigned aren15:1;
    unsigned aren16:1;
    unsigned aren17:1;
    unsigned aren18:1;
    unsigned aren19:1;
    unsigned aren20:1;
    unsigned aren21:1;
    unsigned aren22:1;
    unsigned aren23:1;
    unsigned aren24:1;
    unsigned aren25:1;
    unsigned aren26:1;
    unsigned aren27:1;
    unsigned aren28:1;
    unsigned aren29:1;
    unsigned aren30:1;
    unsigned :0;
    unsigned aren31:1;
    unsigned aren32:1;
    unsigned aren33:1;
    unsigned aren34:1;
    unsigned aren35:1;
    unsigned aren36:1;
    unsigned aren37:1;
    unsigned aren38:1;
    unsigned aren39:1;
    unsigned aren40:1;
    unsigned aren41:1;
    unsigned aren42:1;
    unsigned aren43:1;
    unsigned aren44:1;
    unsigned aren45:1;
    unsigned aren46:1;
    unsigned aren47:1;
    unsigned aren48:1;
    unsigned aren49:1;
    unsigned aren50:1;
    unsigned aren51:1;
    unsigned aren52:1;
    unsigned aren53:1;
    unsigned :0;
    unsigned reserved10;
    unsigned afen0:1;
    unsigned afen1:1;
    unsigned afen2:1;
    unsigned afen3:1;
    unsigned afen4:1;
    unsigned afen5:1;
    unsigned afen6:1;
    unsigned afen7:1;
    unsigned afen8:1;
    unsigned afen9:1;
    unsigned afen10:1;
    unsigned afen11:1;
    unsigned afen12:1;
    unsigned afen13:1;
    unsigned afen14:1;
    unsigned afen15:1;
    unsigned afen16:1;
    unsigned afen17:1;
    unsigned afen18:1;
    unsigned afen19:1;
    unsigned afen20:1;
    unsigned afen21:1;
    unsigned afen22:1;
    unsigned afen23:1;
    unsigned afen24:1;
    unsigned afen25:1;
    unsigned afen26:1;
    unsigned afen27:1;
    unsigned afen28:1;
    unsigned afen29:1;
    unsigned afen30:1;
    unsigned :0;
    unsigned afen31:1;
    unsigned afen32:1;
    unsigned afen33:1;
    unsigned afen34:1;
    unsigned afen35:1;
    unsigned afen36:1;
    unsigned afen37:1;
    unsigned afen38:1;
    unsigned afen39:1;
    unsigned afen40:1;
    unsigned afen41:1;
    unsigned afen42:1;
    unsigned afen43:1;
    unsigned afen44:1;
    unsigned afen45:1;
    unsigned afen46:1;
    unsigned afen47:1;
    unsigned afen48:1;
    unsigned afen49:1;
    unsigned afen50:1;
    unsigned afen51:1;
    unsigned afen52:1;
    unsigned afen53:1;
    unsigned :0;
    unsigned reserved11;
    unsigned pud:2;
    unsigned :0;
    unsigned pudclk0:1;
    unsigned pudclk1:1;
    unsigned pudclk2:1;
    unsigned pudclk3:1;
    unsigned pudclk4:1;
    unsigned pudclk5:1;
    unsigned pudclk6:1;
    unsigned pudclk7:1;
    unsigned pudclk8:1;
    unsigned pudclk9:1;
    unsigned pudclk10:1;
    unsigned pudclk11:1;
    unsigned pudclk12:1;
    unsigned pudclk13:1;
    unsigned pudclk14:1;
    unsigned pudclk15:1;
    unsigned pudclk16:1;
    unsigned pudclk17:1;
    unsigned pudclk18:1;
    unsigned pudclk19:1;
    unsigned pudclk20:1;
    unsigned pudclk21:1;
    unsigned pudclk22:1;
    unsigned pudclk23:1;
    unsigned pudclk24:1;
    unsigned pudclk25:1;
    unsigned pudclk26:1;
    unsigned pudclk27:1;
    unsigned pudclk28:1;
    unsigned pudclk29:1;
    unsigned pudclk30:1;
    unsigned :0;
    unsigned pudclk31:1;
    unsigned pudclk32:1;
    unsigned pudclk33:1;
    unsigned pudclk34:1;
    unsigned pudclk35:1;
    unsigned pudclk36:1;
    unsigned pudclk37:1;
    unsigned pudclk38:1;
    unsigned pudclk39:1;
    unsigned pudclk40:1;
    unsigned pudclk41:1;
    unsigned pudclk42:1;
    unsigned pudclk43:1;
    unsigned pudclk44:1;
    unsigned pudclk45:1;
    unsigned pudclk46:1;
    unsigned pudclk47:1;
    unsigned pudclk48:1;
    unsigned pudclk49:1;
    unsigned pudclk50:1;
    unsigned pudclk51:1;
    unsigned pudclk52:1;
    unsigned pudclk53:1;
    unsigned :0;
    unsigned reserved12;
    unsigned test:4;
};

GPREGISTERS* get_gpio_map(){
    int fd;
    void *gpio_map;

    //仮想メモリアドレスの取得
    fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd == -1) {
            return (GPREGISTERS*)-1;
    }

    gpio_map = mmap(NULL, BLOCK_SIZE,
                PROT_READ | PROT_WRITE, MAP_SHARED,
                fd, GPIO_BASE );

    if ((int)gpio_map == -1) {
            return (GPREGISTERS*)-1;
    }
    close(fd);

    return (GPREGISTERS*)gpio_map;
}

static volatile GPREGISTERS *sel;

int main(int argc, char *argv[], char *envp[]) {

    long loop = 1;
    long pulse_width = 1;

    if (argc == 3) {
        loop = atoi(argv[1]);
        pulse_width = atoi(argv[2]);
    }

    sel = get_gpio_map();
    if ((int)sel == -1) {
        return 1;
    }

    GPFSELOUTPUT(sel,27); //sel->fsel27 = 0x1;

    printf("sel:%08x\n",(unsigned)sel);


    for (int i1 = 0;i1 < loop;i1++){
        for (int i2 = 0;i2 < pulse_width;i2++){
            GPSETN(sel,27); //sel->setn[0] = 0x1 << 27;
        }
        for (int i2 = 0;i2 < pulse_width;i2++){
            GPCLRN(sel,27);    //sel->clrn[0] = 0x1 << 27;
        }
    }

    printf("end.\n");

    return 0;
}



環境


Raspberry Pi B Rev2 (china)

Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux


Eclipse IDE for C/C++ Developers
Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


 <?xml version="1.0"?>
-<Toolchain xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ToolchainName>Raspberry PI</ToolchainName>
      <ToolchainType>Linux</ToolchainType>
      <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
      <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
      <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
      <BinaryDirectory>bin</BinaryDirectory>
      <Prefix>arm-linux-gnueabihf-</Prefix>
      <Make>make.exe</Make>
      <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&target=arm-linux-gnueabihf&filter={0}</BSPIndexUrlFormat>
      <IsCygwinBased>false</IsCygwinBased>
      <GCCVersion>4.9.2</GCCVersion>
      <GDBVersion>7.10</GDBVersion>
      <Revision>1</Revision>
      <RelativeSysrootPath>arm-linux-gnueabihf\sysroot</RelativeSysrootPath>
 </Toolchain>

Raspberry Pi C++ gettimeofday 実行時間テスト (備忘録)

■ソース
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>

using namespace std;

int main (int argc, char *argv[],char *envp[])
{
    timeval *t;
    int loop = 0;
    int n = 0;

    printf("gettimeofday execution time test Optimization Level None(-O0) testno:0001\n");

    if (argc == 2){
        loop = atoi(argv[1]);
    }

    t = new timeval[loop+2];

    gettimeofday(t+loop, NULL);

    for (int i = 0; i < loop; i++) {
        gettimeofday(t+i, NULL);
    }
    gettimeofday(t+loop+1, NULL);

    printf(" loop=%1d\n",loop);
    printf(" n=%1d\n",n);
    printf("%ld(S)%06ld(usec) loop begin\n", (long)t[loop].tv_sec, (long)t[loop].tv_usec);
    printf("%ld(S)%06ld(usec) loop end\n", (long)t[loop+1].tv_sec, (long)t[loop+1].tv_usec);
    printf("%06ld(usec)/%1d loop\n", (long)t[loop+1].tv_usec - (long)t[loop].tv_usec,loop);
    if (loop > 0){
        printf("%06ld(usec)/one loop\n",((long)t[loop+1].tv_usec - (long)t[loop].tv_usec)/loop);
    }
    return 0;
}


■実施結果
■結果 10000回ループ
gettimeofday execution time test Optimization Level None(-O0) testno:0001
 loop=10000
 n=0
1449026262(S)032661(usec) loop begin
1449026262(S)051902(usec) loop end
019241(usec)/10000 loop
000001(usec)/one loop


■結果 0回ループ
gettimeofday execution time test Optimization Level None(-O0) testno:0001
 loop=0
 n=0
1449026749(S)405494(usec) loop begin
1449026749(S)405498(usec) loop end
000004(usec)/0 loop


■環境
Raspberry Pi B Rev2 (china)

Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux


Eclipse IDE for C/C++ Developers
Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


 <?xml version="1.0"?>
-<Toolchain xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ToolchainName>Raspberry PI</ToolchainName>
      <ToolchainType>Linux</ToolchainType>
      <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
      <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
      <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
      <BinaryDirectory>bin</BinaryDirectory>
      <Prefix>arm-linux-gnueabihf-</Prefix>
      <Make>make.exe</Make>
      <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&target=arm-linux-gnueabihf&filter={0}</BSPIndexUrlFormat>
      <IsCygwinBased>false</IsCygwinBased>
      <GCCVersion>4.9.2</GCCVersion>
      <GDBVersion>7.10</GDBVersion>
      <Revision>1</Revision>
      <RelativeSysrootPath>arm-linux-gnueabihf\sysroot</RelativeSysrootPath>
 </Toolchain>



※2015/12 実施


Raspberry Pi nanosleep関数の指定値と結果確認 C++ (備忘録)

Raspberry Pi B Rev2 (china)

最小指定単位:1nsec
オーバーヘッド:80~200μsec程度あり。

■ソース
#include 
#include 
#include 
#include 
#include 

using namespace std;

int main (int argc, char *argv[],char *envp[])
{
    timeval *t;
    int loop = 0;
    struct timespec req;
    int now_sec;

    printf("nanosleep execution time test Optimization Level None(-O0) testno:0001\n");

    req.tv_sec  = 0;
    req.tv_nsec = 0; // (ns)



    if (argc == 4){
        loop = atoi(argv[1]);
        req.tv_sec = atoi(argv[2]);
        req.tv_nsec = atoi(argv[3]);
    }

    t = new timeval[loop+2];

    gettimeofday(t+loop, NULL);
    for (int i = 0; i < loop; i++) {
        nanosleep(&req, NULL);
    }
    gettimeofday(t+loop+1, NULL);
    now_sec = t[loop].tv_sec;

    printf(" loop=%1d\n",loop);
    printf(" req.tv_sec=%1ld\n",req.tv_sec);
    printf(" req.tv_nsec=%1ld\n",req.tv_nsec);

    long begin_us =  ((long)t[loop].tv_sec - now_sec)*1000000 + (long)t[loop].tv_usec;
    printf("%09ld(usec) loop begin\n", begin_us);

    long end_us =  ((long)t[loop+1].tv_sec - now_sec)*1000000 + (long)t[loop+1].tv_usec;
    printf("%09ld(usec) loop end\n", end_us);

    printf("%09ld(usec)/%1d loop\n", end_us - begin_us,loop);
    if (loop <> 0){
        printf("%09ld(usec)/one loop\n",(end_us - begin_us)/loop);
    }
    return 0;
}



■結果
■0loop 0s 0nsec
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=0
 req.tv_sec=0
 req.tv_nsec=0
000451782(usec) loop begin
000451788(usec) loop end
000000006(usec)/0 loop

■1loop 0s 0ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=1
 req.tv_sec=0
 req.tv_nsec=0
000061557(usec) loop begin
000064010(usec) loop end
000002453(usec)/1 loop
000002453(usec)/one loop

■100loop 0s 0ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=100
 req.tv_sec=0
 req.tv_nsec=0
000453818(usec) loop begin
000462135(usec) loop end
000008317(usec)/100 loop
000000083(usec)/one loop

■100loop 0s 10ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=100
 req.tv_sec=0
 req.tv_nsec=10
000511593(usec) loop begin
000519952(usec) loop end
000008359(usec)/100 loop
000000083(usec)/one loop

■100loop 0s 100ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=100
 req.tv_sec=0
 req.tv_nsec=100
000803488(usec) loop begin
000812377(usec) loop end
000008889(usec)/100 loop
000000088(usec)/one loop

■100loop 0s 100000ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=100
 req.tv_sec=0
 req.tv_nsec=100000
000226126(usec) loop begin
000249288(usec) loop end
000023162(usec)/100 loop
000000231(usec)/one loop

■100loop 0s 100000000ns
nanosleep execution time test Optimization Level None(-O0) testno:0001
 loop=100
 req.tv_sec=0
 req.tv_nsec=100000000
000222490(usec) loop begin
010234174(usec) loop end
010011684(usec)/100 loop
000100116(usec)/one loop



■環境
Raspberry Pi B Rev2 (china)

Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux


Eclipse IDE for C/C++ Developers
Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


 <?xml version="1.0"?>
-<Toolchain xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ToolchainName>Raspberry PI</ToolchainName>
      <ToolchainType>Linux</ToolchainType>
      <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
      <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
      <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
      <BinaryDirectory>bin</BinaryDirectory>
      <Prefix>arm-linux-gnueabihf-</Prefix>
      <Make>make.exe</Make>
      <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&target=arm-linux-gnueabihf&filter={0}</BSPIndexUrlFormat>
      <IsCygwinBased>false</IsCygwinBased>
      <GCCVersion>4.9.2</GCCVersion>
      <GDBVersion>7.10</GDBVersion>
      <Revision>1</Revision>
      <RelativeSysrootPath>arm-linux-gnueabihf\sysroot</RelativeSysrootPath>
 </Toolchain>



※2015/12 実施

Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)

Raspberry Pi GPIO出力ポートのon/off制御で制御可能な最小時間についての方式比較です。

要点と結果


■テストの要点
1.valueファイルへの1,0書き込みによる方式
2.書き込み毎にファイルをcloseしない方式とcloseする方式の比較

■結果
一つ目のパルスがcloseしないで1/0を連続的に書き込む方式
二つ目のパルスは1または0を書き込む毎にcloseする方式

Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)
GPIO27ポートの波形

■注意点
valueファイルをcloseしないで、on/offをさせる場合、
"0"または"1"のみでは正しく動作しない。
必ず、改行が必要。

closeさせる場合は改行の必要はない。

個々の波形


Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)
closeしないで1/0を連続的に書き込む方式の場合

Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)
1または0を書き込む毎にcloseする方式

Raspberry Pi GPIO出力ポートの時間測定 C++ (備忘録)
一つ目のパルスがcloseしないで1/0を連続的に書き込む方式
二つ目のパルスは1または0を書き込む毎にcloseする方式

テスト方法


■ソース
main.cpp
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include "gpiotest101.h"

using namespace std;

int main(int argc, char *argv[],char *envp[]){
    string outgpiono = "27";
    string ingpiono = "22";

    // 出力用ポート生成
    if (gpiocreate(outgpiono,"out") == 0){
        cout << "outgpiocreate ok" << endl;
    } else {
        cout << "outgpiocreate error" << endl;
        return 1;
    }

    // 入力用ポート生成
    if (gpiocreate(ingpiono,"in") == 0){
        cout << "ingpiocreate ok" << endl;
    } else {
        cout << "ingpiocreate error" << endl;
        return 1;
    }

    //出力ポート動作時間測定(オシロスコープでの観測を目的としている)
    outportcycletest01(outgpiono,atoi(argv[1]));
    outportcycletest02(outgpiono,atoi(argv[1]));

    //出力ポート破棄
    if (gpiodestroy(outgpiono) == 0) {
        cout << "outgpiodestroy ok" << endl;
    } else {
        cout << "outgpiodestroy error" << endl;
        return 1;
    }

    //入力ポート破棄
    if (gpiodestroy(ingpiono) == 0) {
        cout << "ingpiodestroy ok" << endl;
    } else {
        cout << "ingpiodestroy error" << endl;
        return 1;
    }

    return 0;
}


gpiotest101.h
#include <string>
using namespace std;

#define GPIOPATH "/sys/class/gpio"
#define GPIOPORT GPIOPATH "/gpio%s"

int gpiooutput(string outfilename,string val);
int gpiocreate(string gpiono,string direction);
int gpiodestroy(string gpiono);
void outportcycletest01(string gpiono,int actuatingcycle);
void outportcycletest02(string gpiono,int actuatingcycle);


gpiocreate.cpp
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <string>
#include "gpiotest101.h"

using namespace std;

int gpiocreate(string gpiono,string direction){

    char c[256] = GPIOPATH "/export";
    if ((gpiooutput(c,gpiono)) == 0){
        cout << "export" << gpiono << " OK" << endl;
    } else {
        cout << "export" << gpiono << " error" << endl;
        return 1;
    }

    sprintf(c,GPIOPORT "/direction",gpiono.c_str());
    if (chmod(c,0x3ff) == 0) {
        cout << string(c) + " chmod ok" << endl;
    } else {
        cout << string(c) + " chmod error" << endl;
        return 1;
    }
    if ((gpiooutput(c,direction)) == 0) {
        cout << string(c) + " direction set ok" << endl;
    } else {
        cout << string(c) + " direction error ok" << endl;
    }

    sprintf(c,GPIOPORT "/value",gpiono.c_str());
    if (chmod(c,0x3ff) == 0) {
        cout << string(c) + " chmod ok" << endl;
    } else {
        cout << string(c) + " chmod error" << endl;
        return 1;
    }

    sprintf(c,GPIOPORT "/edge",gpiono.c_str());
    if (chmod(c,0x3ff) == 0) {
        cout << string(c) + " chmod ok" << endl;
    } else {
        cout << string(c) + " chmod error" << endl;
        return 1;
    }

    return 0;
}


gpiodestroy.cpp
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <string>
#include "gpiotest101.h"

using namespace std;

int gpiodestroy(string gpiono){

    char c[256] = GPIOPATH "/unexport";
    if ((gpiooutput(c,gpiono)) == 0){
        cout << "unexport" << gpiono << " OK" << endl;
    } else {
        cout << "unexport" << gpiono << " error" << endl;
        return 1;
    }
    return 0;
}


gpiooutput.cpp
//#include <sys/stat.h>

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int gpiooutput(string outfilename,string val){
    ofstream fout;

    fout.open(outfilename.c_str(), ios::out);
    if (!fout) {
        cout << outfilename + " Open error." << endl;
        return 1;
    }

    fout << val;
    if (!fout) {
        cout << outfilename + " write error." << endl;
        fout.close();
        return 1;
    }

    fout.close();
    return 0;
}


outportcycletest01.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "gpiotest101.h"
using namespace std;

void outportcycletest01(string gpiono,int actuatingcycle){
    ofstream fout;
    char outfilename[256];

    // value file open
    sprintf(outfilename,GPIOPORT "/value",gpiono.c_str()); //file path <- gpio no
    fout.open(outfilename, ios::out);
    if (!fout) {
        cout << string(outfilename) + " Open error." << endl;
        return;
    }

    // port on/off
    for (int n = 0;n < actuatingcycle;n++){
        fout << 1 << endl;
        if (!fout) {
            cout << string(outfilename) + " write(1) error." << endl;
            fout.close();
            return;
        }

        fout << 0 << endl;
        if (!fout) {
            cout << string(outfilename) + " write(0) error." << endl;
            fout.close();
            return;
        }
    }

    fout.close();
    return;
}


outportcycletest02.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "gpiotest101.h"
using namespace std;

void outportcycletest02(string gpiono,int actuatingcycle){
    ofstream fout;
    char outfilename[256];

    sprintf(outfilename,GPIOPORT "/value",gpiono.c_str());

     // port on/off
    for (int n = 0;n < actuatingcycle;n++){
        if (gpiooutput(outfilename,"1") != 0) {
            cout << string(outfilename) + " write(1) error." << endl;
        }
        if (gpiooutput(outfilename,"0") != 0) {
            cout << string(outfilename) + " write(0) error." << endl;
        }
     }

    return;
}



■環境
Raspberry Pi B Rev2 (china)

Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux


Eclipse IDE for C/C++ Developers
Version: Mars.1 Release (4.5.1)
Build id: 20150924-1200


 <?xml version="1.0"?>
-<Toolchain xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ToolchainName>Raspberry PI</ToolchainName>
      <ToolchainType>Linux</ToolchainType>
      <PathDetectionKeyStrip>0</PathDetectionKeyStrip>
      <GNUTargetID>arm-linux-gnueabihf</GNUTargetID>
      <ToolchainID>com.visualgdb.raspberry_pi</ToolchainID>
      <BinaryDirectory>bin</BinaryDirectory>
      <Prefix>arm-linux-gnueabihf-</Prefix>
      <Make>make.exe</Make>
      <BSPIndexUrlFormat>http://visualgdb.com/hwsupport/BSP/?autofetch=1&target=arm-linux-gnueabihf&filter={0}</BSPIndexUrlFormat>
      <IsCygwinBased>false</IsCygwinBased>
      <GCCVersion>4.9.2</GCCVersion>
      <GDBVersion>7.10</GDBVersion>
      <Revision>1</Revision>
      <RelativeSysrootPath>arm-linux-gnueabihf\sysroot</RelativeSysrootPath>
 </Toolchain>

お知らせ
■注意:Google Chrome以外のブラウザでは動作しない事もあります。
お好みに応じて
画像だけの表示でいいよ
やっぱり全部表示して
背景は黒がいいな
背景を元に戻して
サブジャンル
メモリアルマップ
My Favorite Photo
検索フォーム
プロフィール

otsu.usiwakamaru

Author:otsu.usiwakamaru
五条の橋でひらりひらりと欄干を飛び渡る牛若丸のように、興の向くまま電子回路にプログラミングに写真にと飛び回っています。

プロフィール詳細

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
キーワード
クリックしたキーワードの記事のみ表示します。

電池 試み IXY デザイン  改造 3D ミッキー 

最新記事
月別アーカイブ
全記事表示リンク

全ての記事を表示する

おすすめプログ(新着記事)
リンク


にほんブログ村
カテゴリ
ART (1)
橋 (0)
PIC (2)
カウンタ
訪問者数(UU)

アクセス数

現在の閲覧者数

tael no013用