PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)

PIC 16F1827をI2Cスレーブとして用い、かつ通常はスリープしている場合の動作メモです。
クロックは内部発振器16MHzで動作させています。

※注意 本記事に私的な解釈です。間違っている可能性は十分にありますので内容についての責任は持てません。

背景


Raspberry PiのGPIOで周辺ハードウェアーを制御するには、OSを介してのハード制御の為、信号のタイミング制御が難しいようです。
そちらはOSのないPICに任せ、Raspberry PiなどのOSの存在するハードは情報処理を行という機能分担が望ましいという結論になりました。

そこで、Raspberry PiとPIC間の通信をI2Cで行う場合の実機テストをする事にしました。

省電力の意味でPICのSLEEP(※1)を利用する場合のテスト結果のメモです。

※1 I2Cは機器内通信が前提の為、電源も同一系統でマスタ、スレーブ共に電源が立ち上がり、立ち下がりも同時になることが暗黙の了解であると思われます。
各電源が別系統の場合、例えば、Raspberry Piの電源がONでPICの電源がOFFの状態が長時間続く場合、I2Cの信号線を通じて、Raspberry Piの電源→プルフップ抵抗→PICの寄生ダイオードを通じてPICに電源が供給され、PICは起動してしまいます。もちろん、安定動作はしません。
その為、十分な電力が供給される事が前提のRaspberry Piシステムで、PICを節電目的でSLEEP動作させる必要性は大変少ないのではないかと思われますが、ここではあえてSLEEPさせた場合の動作をメモしています。

テスト環境


■PIC16F1827はI2Cスレーブとして動作
リード(R)を受信すると2byteのデータ(0xd0,0xd1)を順次送信する。
■I2CマスタはRaspberry Pi
1byteのデータ(0xAA)をスレーブ(16F1827)に送信し、その後2byteのデータを受信する。


結論


I2Cのスタートbitによる割り込みを受けた時から、ストップbit割り込みを受けるまでの間はSLEEPしてはならない。


テスト方法


■main()でSLEEPのルーブをする。SLEEPしない場合はNOPのループをする。
■割り込み処理時、各レジスタの値を記録する。
■RA0~4にパルスを出力し、ソース上の通過を外部に知らせる。

■ロジックアナライザ ZEROPLUS LAP-C(16064)により下記の信号を観測
(1)SCL I2Cクロック
(2)SDA I2Cデータ
(3)RA0 割り込み処理開始を知らせるパルス
(4)RA1 レジスタ値の記録完了を知らせるパルス
(5)RA2 I2C制御完了を知らせるパルス(この後、割り込み処理を抜ける)
(6)RA3 main()のループ内処理の開始を知らせるパルス(SLEEP前)
(7)RA4 main()のループ内処理の終了を知らせるパルス(SLEEP後)
(8)CLKOUT PICクロック

PIC ソースはこちらをクリック





テスト



割り込み終了の度にSLEEPした場合


この場合、クロックストレッチが発生しない箇所ができる。
その為、次の送信データをセットする時間的余裕がなく、本来送信すべきデータが送信されない。


■クロックストレッチが発生しない箇所がある
PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)



第一群はWモードでマスターのRaspberry Piが1byteのデータを送信してきます。
アドレス受信後、SCLがLOWになりクロックストレッチ(黄色矢印)が発生しています。

第二郡はRモードでPICは2BYTEのデータを送信します。
アドレスと1byte目の間のACKはクロックストレッチ(黄色矢印)が発生していますが、
1byte目と2byte目の間のACKではクロックストレッチ(赤色矢印)は発生していません。
下図は第二郡の部分を拡大したものです。


■クロックストレッチの生成は誰の責任
PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)

■PICハードがクロックストレッチの開始を行う例
例えば、上図の赤枠の部分はPICがアドレス+Rを受取り、A-ACKを返し、割り込みを生成し、割り込みルーチンに制御が移るシーンです。
ここでSCLをLOWにしクロックストレッチを行っているのはPICのハードです。

時間順に見ていくと、
(1)ACKのクロック(SCL)の立ち下がりで割り込みを生成し、PICのスリープを解除しています。
(2)それにより、PICのクロック(CLKOUT)(白い部分)が起動されています。
(3)PICハードでの割り込み遷移処理後、割り込みルーチに入った事を示す、RA0のパルス(5)が出力されています。

割り込み処理に入った時点で多くの時間が経っており、PICハードによるクロックストレッチがなければソフトにより直接クロックSCLをLOWにしてクロックストレッチするには間に合いません。
したがってクロックストレッチの開始はPICハードの責任です。ソフトでは直接SCLをLOWにしていません。
ソフトはSSP1CON1レジスタのCKPを1にする事により、停止されているクロックを有効化し再び転送動作を再開させる事(クロックストレッチの解除)のみです。上図の時間軸上では赤枠を過ぎた右側のRA2のパルスの位置です。

■クロックストレッチが開始されない例
上図の青枠の部分はPICがアドレス+Rを受取った後、1byte目のD-ACKを返す箇所です。
この例ではA-ACKの時のようなクロックストレッチは発生していません。

ACKのクロック(SCL)の立ち下がりで割り込みが生成された以後の動作はA-ACKの時と同じシーケンスを辿ります。
ソフトでCKP=1によるクロック有効化も行っていますが、既に意味はありません。

■各割り込み時点でのCKP(SSP1CON1-bit4)の状態
PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)
ssp1con1[0] unsigned char 0x3E
ssp1con1[1] unsigned char 0x2E
ssp1con1[2] unsigned char 0x2E
ssp1con1[3] unsigned char 0x3E
ssp1con1[4] unsigned char 0x3E
ssp1con1[5] unsigned char 0x2E
ssp1con1[6] unsigned char 0x2E
ssp1con1[7] unsigned char 0x3E
PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)ssp1con1配列の添字はRA0のパルス番号

クロックストレッチが発生するA-ACKの割り込み時点のssp1con[5]のbit4はOFFでクロックストレッチ中(Holds clock low (clock stretch))を示しています。
クロックストレッチが発生しない、1byte目のD-ACKの割り込み時点でもssp1con1[6]のbit4はOFFです。
にも、かかわらずクロックストレッチは発生しません。


I2Cスタートからストップ間はSLEEPを禁止した場合



レジスタの設定環境も正しいと思われ、ssp1con1[6]のbit4はOFFになっている事からハード上の環境としてSLEEPの影響を疑い、I2Cのスタートからストップの間、SLEEPをしない様にしました。

PIC 16F1827 I2C-SLAVEモードとSLEEPの動作確認(備忘録)

上図の様にクロックストレッチが発生しデータも目的通り0xD1が送信されました。

■最後のD-NACK
2byte目送信後のD-NACKではNACKの為、データの転送は終了であり、次の送信データセットの為の時間稼ぎは必要なく、クロックストレッチは発生しません。
マスター(Raspberry Pi)はこの時レシーバであり、必要量のデータを受信した事を送信者であるスレーブ(PIC)に伝える為にNACKを送っています。



感想


A-ACKの時とD-ACKの時の違いが何なのか遂に判りませんでした。
対処方法としてこれが正しいのかも判りません。
が、無理に割り込み終了都度、SLEEPさせる必要性もそれほど無いと思われるので、これでよしとします。

今までなら、記事にもせずに何処かにメモって置くだけなのですが、それだと整理もせずに結果だけで後で何だったか全く不明という状態でした。
当ブログのような僻地ブログでも公開するとなると少しは纏めようとするので、結果自分にとっても有益です。
万一、どなたかの役に立つなら望外の喜びです。

しかし、自分ならこんな長い記事は読む気がしません。

スポンサーサイト

Eclipse Raspberry Pi(Raspbian) リモートデバック設定(備忘録)

Windows上のEclipseでRaspberry Pi用のC++作成時のデバッグ設定のメモ。


設定


Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)

Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)

■「Main」タブ
Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)
※Connection欄の新規設定は下方に別途書いています。
※コピペ用 sudo chmod a+x /home/pi/work/b ←転送するファイルはこのように(b)ファイル名を変えてもよい。

■「Debugger」タブ
Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)
※コピペ用 arm-linux-gnueabihf-gdb


■Connection欄の新規設定方法
Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)

Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)

Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)



Debug実行


「Debug Dconfigurations」ダイアログの「Debug」ボタンをクリックする。


Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)

「F6」ハー押下で1step進めると
Eclipse Raspberry Pi(Raspbian) デバック設定(備忘録)


環境


Eclipse IDE for C/C++ Developers

Version: Neon.3 Release (4.6.3)
Build id: 20170314-1500



感想


「#include 」を使用すと、「Debug」でエラーとなります。
原因については調べていません。

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Windows上のEclipseでRaspberry Piのソフトを開発している時にIDE内でSSHにてRaspberry Piに接続する時に設定方法のメモ。

設定


Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

下記「My Home」をダブルクリックする
Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)



切断


Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)



再接続


Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)



Terminal接続


Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

Eclipse Raspberry Pi(Raspbian) SSH接続方法(備忘録)

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登録完了。


C++ 名前マングリング(Name mangling)(備忘録)

「名前マングリング(Name mangling)」について、実機で挙動確認をした時のメモです。



名前マングリング(Name mangling)


■C++の場合、シンボル名に「名前マングリング(Name mangling)」と呼ばれる処理が施される為に、
共有ライブラリーを利用する時には、関数名の指定はその「名前マングリング」された名前を指定しなければならない。

もしくは、共有ライブラリー側で「名前マングリング」を抑止(デマングル)し、関数名のママとする必要がある。

■C言語の場合は、名前マングリングは行われない。



先にまとめ


■名前マングリングの結果
0000067c T _Z9SOtest005c ← SOtest005はこのようになる
00000680 T _Z9SOtest006i ← SOtest006はこのようになる

目的はオーバーロードの実現の為と思われる。



■デマングル
ヘッダファイルをCとC++で共有するために
#ifdef __cplusplus
extern "C" {
#endif
ここにexternの定義をする。複数可能。
#ifdef __cplusplus
}
#endif

結果は
00000668 T SOtest002
00000670 T SOtest003
00000678 T SOtest004
のように「名前マングリング」されない。



■CPP側のextern指定
ヘッダファイル側とCPPファイル側の両方でextern指定をすると、「名前マングリング」の抑止(デマングル)指定をしても、
「名前マングリング」された事があった。ただし、再現できなかった。記憶の片隅に置いておく事にします。



■extern指定なしのシンボル名(今回は関数名)
FreePascal側で宣言している

function SOtest006(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name '_Z9SOtest006i';

はCPP,h側では extern は指定していない。
しかし、利用出来る。
ただし、シンポル名は「名前マングリング」された名前となる。



■FreePascal側でのオーバーロード

(1)宣言
function SOtest002(a : integer; b : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest002';
function SOtest002(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';

(2)呼び出し
c := SOtest002(3,6);
memo1.lines.add('SOtest002(3,6) : ' + inttostr(c));

c := SOtest002(2);
memo1.lines.add('SOtest002(2) : ' + inttostr(c));

(3)結果
SOtest002(3,6) : -3
SOtest002(2) : 702

この事から「デマングル」はしない方がよいかもしれない。



環境


■Eclipse IDE for C/C++ Developers
Version: Neon.3 Release (4.6.3)
Build id: 20170314-1500
(Windows 10 64bitで実行)

■ハード: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

■Lazarus
バージョン #:1.2.4+dfsg2-1
FPCバージョン 2.6.4
(Raspberry Pi 3で実行)




テスト


■ソース
(1)共有ライブラリー
xxx.cpp
#include "RaspbianSOtest001.h"

int SOtest002(int a,int b) {return a - b;}
int SOtest003(void) {return 3;}
extern void SOtest004(void){}
void SOtest005(char a){}
int SOtest006(int a){return a + 600;}
int SOtest007(int a){return a + 700;}



ヘッダファイル
RaspbianSOtest001.h

#ifdef __cplusplus
extern  "C"  {
#endif
extern int SOtest002(int a,int b);
extern int SOtest003(void);
extern void SOtest004(void);
//extern int SOtest007(int a);
#ifdef __cplusplus
}
#endif

extern void SOtest005(char a);
extern "C" {int SOtest007(int a);}




(2)共有ライブラリーを使用するFreePascal
unit u_app;

{$mode objfpc}{$H+}

interface

uses
  dl,
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

function SOtest002(a : integer; b : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest002';
function SOtest006(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name '_Z9SOtest006i';
function SOtest007(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';
function SOtest002(a : integer) : integer; cdecl; external 'RaspbianSOtest001' name 'SOtest007';


type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  lib : pointer;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  c : integer;
begin
  c := 123;
  //c := SOtest002(10,5);
  //SOtest004;

  c := SOtest002(3,6);
  memo1.lines.add('SOtest002(3,6) : ' + inttostr(c));

  c := SOtest006(6);
  memo1.lines.add('SOtest006(6) : ' + inttostr(c));

  c := SOtest007(70);
  memo1.lines.add('SOtest007(70) : ' + inttostr(c));

  c := SOtest002(2);
  memo1.lines.add('SOtest002(2) : ' + inttostr(c));

end;
begin
end.




■実行結果
Memo1
SOtest002(3,6) : -3
SOtest006(6) : 606
SOtest007(70) : 770
SOtest002(2) : 702




■シンボル名確認 nm libRaspbianSOtest001.so 実行結果
root@rp3a:/usr/lib# nm libRaspbianSOtest001.so
00000668 T SOtest002
00000670 T SOtest003
00000678 T SOtest004
00000688 T SOtest007


0000067c T _Z9SOtest005c
00000680 T _Z9SOtest006i




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 で成功しました。


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


PIC12F675 GPIO port change interrupt 処理のループと対策(備忘録)

PIC 12F675の割り込み処理がうまく動作しないので調べてみました。

GPIO port change interrupt 処理がループしている模様です。
割り込み処理を一旦抜けるものの再度割り込み処理に入る。これを永遠に繰り返します。

開発環境 : MPLAB X IDE v3.51、Microchip MPLAB XC8 C Compiler (Free Mode) V1.40、ICD3です。

■結果
GPIO port change interrupt の割り込み処理内でGPIOレジスタに何らかのアクセスを すると、割り込み処理ループの現象は無くなりました。

調査


■発生時のソース

※下記ソースは現象確認の為のもので、この現象に気づいた時のものではありません。

GP5がport change 監視の対象ピン(外部からパルス信号を与える)
GP1はオシロによるデバック目的の出力ピン(今回のレポートでは使用していません)
GP4はCLKOUTとして、クロックを監視(目的は割り込み処理内での現象把握の為)

/*
 * GPIO割り込みテスト
 * Created on 2017/02/11, 8:17
 */

// CONFIG
#pragma config FOSC = INTRCCLK  // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)


#include <xc.h>

char time_count;

void interrupt intservice() {
    INTCONbits.GIE = 0;
    if (INTCONbits.GPIE && INTCONbits.GPIF) {
        INTCONbits.GPIF = 0;

        if (time_count++ > 10) {
            INTCON = 0x00;
            SLEEP();
        }

        //asm("MOVF GPIO,W");
    }
    INTCONbits.GIE = 1;
}

void main(void) {
    GPIO = 0x00;
    ANSEL = 0x00;
    CMCON = 0X07; //Comparator Off (Lowest power) CM2:CM0 = 111
    TRISIO = 0b00100000; //GPIO5:input
    GPIO = 0x00; //GPIOクリア
    INTCON = 0x00; //割り込み不許可
    OPTION_REG = 0x00;
    IOC = 0x00;
    PIE1 = 0x00;
    ADCON0 = 0x00;

    GPIObits.GP1 = 0;
    GPIObits.GP2 = 0;
    INTCON = 0x88;  //Enables all unmasked interrupts;
                    //Enables the GPIO port change interrupt
    IOC = 0b00100000; //IOC5 : enable an interrupt-on-change

    time_count = 0;
    while (1) {
        asm("MOVF GPIO,W");
        //asm("MOVWF GPIO");
    }

    return;
}


■発生時のオシロ波形

※CH1(黄) GP5がport change 監視の対象ピン(外部からパルス信号を与える)
※CH2(青) GP1はオシロによるデバック目的の出力ピン(今回のレポートでは使用していません)
※CH3(紫) GP4はCLKOUTとして、クロックを監視(目的は割り込み処理内での現象把握の為)
PIC12F675 GPIO port change interrupt 処理のループと対策(備忘録)
(1)CH1(黄) GP5入力端子にパルスが入り、信号レベルが変化すると、
(2)interrupt intservice()に制御が移る。
(3)intservice()内で、time_count++により割り込み回数をカウントし、
(4)一定回数(10回)を超えると、SLEEPさせる。(注1)
(5)SLEEPより、内部クロックが停止しCH3(紫) GP4のCLKOUT波形は停止する。これによりSLEEPを通過したことを確認した。

※注1:GP1にパルスを出す方法では、GP1へのアクセスそのものがこの現象を妨げる要因になるので、SLEEPを使用し内部クロックを停止する事により、ポイント通過を確認しました。


■現象要約
一度の割り込みであるにもかかわらず、連続して10回以上の割り込みが発生する。
time_countを100回カウントしても同様。


発生要素


(1)mainのループ、この場合while(1)内でGPIOレジスタにアクセスし、かつ
(2)interrupt intservice()内で、GPIOレジスタにアクセスしていない場合
に発生する。

対策


interrupt intservice()内で、asm("MOVF GPIO,W"); によりGPIOに空アクセスする。
main()内でGPIOへのアクセス制限はかけられない為。


感想


■この対策に気づいた理由は、

PIC12F675 GPIO port change interrupt 処理のループと対策(備忘録)
出典:MICROCHIP社のPIC12F629/675 Data Sheet

↓上図の拡大
PIC12F675 GPIO port change interrupt 処理のループと対策(備忘録)

入力はすでに安定しているにもかかわらず、Interrupt-on-Changeが発生するということは、上図右下の2つのDフリップフロップよるchange検出回路が動作していない、すなわち、RD PORTが出ていない。
よって、GPIOを空読みしたらいいのでは。
これで解決しましたが、このRD PORTは単にポートを読む時だけではなさそうです。mainでのwhile(1)よる空ループではGPIOのリードをしなくても、changeを検出しています。

■さらに詳細は
その後、色々試みましたが良く判りませんでした。





Thread間通信 Handler Message Looper(android studio)(Android)(備忘録)

メインスレッドが生成する二つのサブスレッドに於いて
SubThread1はSubThread2からの情報を受取り内部データを更新する。
SubThread2は何らかの情報を指定されたThreadに引き渡す役目を持つ。

SubThread1はインスタンスが生成され実行されるとLooperがループし、 メーセージを待つ。
また、SubThread1は自身のThreadで実行されるHandlerを生成し要求元へ引き渡す機能をもつ。
生成されたHandlerは他のThreadから送られてきたMessageの内容に従って特定の処理を実行するhandleMessage()を持つ。
このHandlerを生成する関数を複数種用意する事により、異なった機能を持たせる事ができる。

SubThread2はSubThread1が生成したHandlerを受け取り、自身が生成したデータをMessageに載せ、HandlerをsendMessage()でSubThread1に送る。
SubThread2は送ったハンドルを誰(Thread)が受け取りどの様に処理されるかは知らない。

メインスレッドはデータを処理する者(SubThread1)とデータを提供する者(SubThread2)の関係を制御するスレッドとなる。

※下記sampleはスレッドの実行順序の不正によるエラーは考慮していない。

■MainActivity

package jp.no4393.loopertest002;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

private SubThread1 subThread1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void bt1onClick(View view){
Log.d("LT002","B1-----start.");
subThread1 = new SubThread1();
subThread1.start();
Log.d("LT002","B1-----end.");
}

public void bt2onClick(View view){
Log.d("LT002","B2-----start.");
SubThread2 st2 = new SubThread2(subThread1.getHandler());
st2.start();
Log.d("LT002","B2-----end.");
}
}





■subThread1

package jp.no4393.loopertest002;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class SubThread1 extends Thread{

private String mark;
private Looper myLooper;

SubThread1(){
}

public void run(){
Log.d("LT002","T1 run.");
Looper.prepare();
myLooper = Looper.myLooper();
Looper.loop();
Log.d("LT002","T1 run end.");
}

public Handler getHandler(){
Log.d("LT002","T1 getHandler.");
mark = "SubThead1 getHandler.";
return new Handler(myLooper) {
public void handleMessage(Message msg) {
mark = String.valueOf(msg.what) + " mark=" + (String) msg.obj;
Log.d("LT002", mark);
}
};
}

}




■SubThread2

package jp.no4393.loopertest002;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class SubThread2 extends Thread {

private Handler toHandler;

SubThread2(Handler toHandler){
this.toHandler = toHandler;
}

public void run(){
Log.d("LT002","ST2 run sendMessage.");
try{
Thread.sleep(2000);
}catch(InterruptedException e){}
Message msg = new Message();
msg.what = 123;
msg.obj = "ST2 run message obj. myThreadId=" + String.valueOf(Thread.currentThread().getId());
toHandler.sendMessage(msg);
Log.d("LT002","ST2 run end.");
}

}




■log

Button1をタッチ後、Button2を三回連続タッチした時のlog

10-30 09:07:02.110 4768-4768/jp.no4393.loopertest002 D/LT002: B1-----start.
10-30 09:07:02.110 4768-4768/jp.no4393.loopertest002 D/LT002: B1-----end.
10-30 09:07:02.110 4768-5001/jp.no4393.loopertest002 D/LT002: T1 run.
10-30 09:07:03.241 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----start.
10-30 09:07:03.241 4768-4768/jp.no4393.loopertest002 D/LT002: T1 getHandler.
10-30 09:07:03.241 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----end.
10-30 09:07:03.241 4768-5075/jp.no4393.loopertest002 D/LT002: ST2 run sendMessage.
10-30 09:07:03.812 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----start.
10-30 09:07:03.812 4768-4768/jp.no4393.loopertest002 D/LT002: T1 getHandler.
10-30 09:07:03.822 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----end.
10-30 09:07:03.822 4768-5107/jp.no4393.loopertest002 D/LT002: ST2 run sendMessage.
10-30 09:07:04.383 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----start.
10-30 09:07:04.383 4768-4768/jp.no4393.loopertest002 D/LT002: T1 getHandler.
10-30 09:07:04.383 4768-4768/jp.no4393.loopertest002 D/LT002: B2-----end.
10-30 09:07:04.383 4768-5146/jp.no4393.loopertest002 D/LT002: ST2 run sendMessage.
10-30 09:07:05.244 4768-5075/jp.no4393.loopertest002 D/LT002: ST2 run end.
10-30 09:07:05.244 4768-5001/jp.no4393.loopertest002 D/LT002: 123 mark=ST2 run message obj. myThreadId=519
10-30 09:07:05.834 4768-5107/jp.no4393.loopertest002 D/LT002: ST2 run end.
10-30 09:07:05.834 4768-5001/jp.no4393.loopertest002 D/LT002: 123 mark=ST2 run message obj. myThreadId=520
10-30 09:07:06.385 4768-5146/jp.no4393.loopertest002 D/LT002: ST2 run end.
10-30 09:07:06.385 4768-5001/jp.no4393.loopertest002 D/LT002: 123 mark=ST2 run message obj. myThreadId=521





■環境
Thread間通信 Handler Message Looper(android studio)(Android)(備忘録)


Thread間通信 Handler Message Looper(android studio)(Android)(備忘録)


Thread間通信 Handler Message Looper(android studio)(Android)(備忘録)

お知らせ
■注意: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用