通勤中にご飯が炊ける弁当箱 サーモスJBS-360を買ったらとてもよかったお話
時間がない
組み込みの記事しか書かないこのブログで書くネタじゃないかも何ですが、大体の方は会社勤め、学校通いですよね。
おひるごはん。
外食までもないとしてもコンビニ弁当おにぎりに頼りがち。
今から急いで客先に向かわなくては!…となるとカ□リーメイトのお世話に…
僕らは時間がないのです。朝に弁当の準備できるわけもない。んな時間あったらぎりぎりまで寝てるわ
Twitterでも話題になってた通勤中に御飯が炊けるThermos JBS-360。
通勤中にゴハンが炊ける弁当箱、サーモスが9月発売。お米の「おねば」を制御、美味しく炊けます - Engadget 日本版
9月の初めに東急ハンズで買いました。それが結構よかったんです。
みんな白米食おうぜ。QoL上がるよ。
これまでも電子レンジで御飯が炊ける触れ込みの容器、土鍋って結構あっていろんなものを試したのですが…
ぶっちゃけ言わしてもらうと、耐熱容器に水と米入れて、少し重めの蓋してチンすれば米くらい炊けます。
問題は、その吹きこぼれ。米を炊く度に電子レンジ毎回掃除するの、結構いやなので、やめてしまいました。
こいつは吹きこぼれないぞ!
あと、この吹きこぼれに粘度のある水分(おねば)が御飯をおいしくするそうで、吹きこぼれでレンジ汚さないだけではなく、ちゃんと吹き上がったおねばを戻してくれるのが良いところ。
使ってみる
開けます。今回はブラックを買いました。保温ケースがかっこいい。
使い方説明が簡潔に書かれています。
透明のごはん容器の目盛りに従い、米と水を入れます。今回は無洗米。柔らかめが好きな人は少しごはんの量減らして同量の水とかにすると良いのかも。
この商品の要、炊飯パーツを取り付け
電子レンジへ。500Wで8分です。朝の忙しい時間でも顔洗って歯を磨いて髪セットして着替えする時間より短いはず。
レンジアップ完了。吹きこぼれも全くなくて感動しました
あたりまえですが、容器がめっちゃ熱くなってます。無理矢理炊飯パーツと容器分離するとやけどします。分離せず、そのまま保温ケースにいれてから外します
すぐに容器フタをします
専用ポーチにいれて完成。行ってきます。(今気づいたけど値札とれよ>俺)
iPad版Swift Playgroundsでsocket通信する
ネットワークにつながる組み込み機器とスマホを繋げるネタは数多ありますが、ほとんどがAndroid機器のようです。iOSデバイスがそのような所謂"低レベル通信"のほとんどをユーザーに開放してないというのが理由のようです。
あとXCode使う=Mac買わなきゃ & お布施とかそういうやつ。
W5500(サーバー側)とiPad Pro(クライアント)だけでTCP/IPソケット通信できるといいなぁと探したらありました。
perl - How to implement a socket connection using a swift playground? - Stack Overflow
上記情報が古いバージョンのSwiftでいろいろ修正が必要でしたが、動作したのでメモがてら。
iPadのSwift Playgroundsアプリだけでプログラムできます。
これを現行のSwift 3.1用に修正しました。
下記例ではサーバーアドレス192.168.0.123:4567ポートと通信しています。(IP固定)
/* Socket communication on Static IP Works on Swift 3.1 + playgrounds support */ import UIKit import PlaygroundSupport let addr = "192.168.0.123" let port = 4567 //PORT Num var buffer = [UInt8](repeating: 0, count: 255) var inp : InputStream? var out : OutputStream? Stream.getStreamsToHost(withName: addr, port: port, inputStream: &inp, outputStream: &out) if inp != nil && out != nil { let inputStream : InputStream = inp! let outputStream : OutputStream = out! inputStream.open() outputStream.open() if outputStream.streamError == nil && inputStream.streamError == nil { let queryString = "クライアントから送信したいデータ" let queryData = [UInt8](queryString.utf8) while true { UnsafePointer<UInt8>(queryData) outputStream.write(queryData, maxLength: queryData.count) var readChars: Int = inputStream.read(&buffer, maxLength: buffer.count) if (readChars > 0) { let readString: String = NSString(data: NSData(bytes:buffer, length:readChars) as Data, encoding: String.Encoding.utf8.rawValue)! as String print(readString) // サーバから受信したデータ usleep(300 * 1000) //300ms待つ(適当 } } else { print ("server closed connection") inputStream.close() outputStream.close() break } } } else { print ("could not create socket") } } else { print ("could not initialize stream") }
通信中の切断に対する適切な対応とかタイムアウトとか全然考えてないので、そこら辺はご容赦。
受信したデータをprint()するだけの用途はあまりないと思うのでちょいと応用です。
趣味で作っている透過率測定器の結果をiPadに出力しました。この測定器はクライアントから「data?\r\n」という文字列を受信すると、ダイオードアレイのADCデータを「datais?t+1234567」という形式でクライアントへ送信します(欲しいデータは+1234567)。文字列から数値だけを抽出したいので、分割します。
先ほどの
print(readString) // サーバから受信したデータ
を下記のコードに置き換えます。
//print(readString) // サーバから受信したデータ if (readString.contains("datais?t")) { let strSep = readString.components(separatedBy: "?t") let rval = (strSep[1] as NSString).integerValue usleep(300 * 1000) //300ms }
こちらのコードも変更
//let queryString = "クライアントから送信したいデータ" let queryString = "data?\r\n"
Swift Playgroundsの便利機能で、変数の値変化をグラフの形でスコープ出来る(データ数上限あり)ので、簡単な確認なら気合い入れてグラフ描画コード書かなくても良い。
自分はWiznet W5500とWiFiルータ経由で通信をテストしました。
最近はやりのESP32とかXbee WifiとかWiFiが使えるデバイスで試した方がいれば、動作結果など是非お聞かせ願えれば。
Raspberry Pi 3でUrJTAGを使う
とりあえずRasPi3でUrJTAGが動くようにする
MAX10を出先や遠隔でコンフィグしたりするときRaspiでUrJTAGが使えたらなあと調べたら使えたのでメモ
RasPiだとGPIOでもバウンダリスキャンできるらしいので便利かもしれない。
apt install urjtagでインストールしたらUSB Blasterがうまく動かなかったので、仕方なくビルド。
参考はこちらUniversal JTAG library, server and tools / Discussion / Using UrJTAG: raspberry pi gpio port
準備
上記を参考に必要なパッケージをインストールする
$ sudo apt install autoconf autopoint libtool libreadline-dev python-dev libusb-dev libusb-1.0-0-dev flex libftdi-dev bison git
flex,bisonはBSDLをUrJTAGに食わせるのに共に必要なので追加しました。
D2XXのインストール。FTDIのサイトのREADMEを参考に行う。RasPi3は今のところOSが32bitなのでARMv7版を使うようだ。
$ wget http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx-arm-v7-hf-1.4.6.tgz $ tar xvf libftd2xx-arm-v7-hf-1.4.6.tgz $ cd release/build $ sudo cp libftd2xx.* /usr/local/lib $ sudo chmod 0755 /usr/local/lib/libftd2xx.so.1.4.6 $ sudo ln -sf /usr/local/lib/libftd2xx.so.1.4.6 /usr/local/lib/libftd2xx.so
補足:Raspberry Pi Zero/Pi 1/Compute Module(CM1)で同様のことをする場合
検索ワードから「Illegal instruction」でここに来られる方が多いです。このエラーメッセージが出てしまった場合はアーキテクチャが違うことを意味します。
Raspi Zero/Pi 1/Compute Module(CM1)はCPUがARM11系なのでアーキテクチャがARMv6になります。以下のようにしてください。
$ wget http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx-arm-v6-hf-1.4.8.tgz $ tar xvf libftd2xx-arm-v6-hf-1.4.8.tgz $ cd release/build $ sudo cp libftd2xx.* /usr/local/lib $ sudo chmod 0755 /usr/local/lib/libftd2xx.so.1.4.8 $ sudo ln -sf /usr/local/lib/libftd2xx.so.1.4.8 /usr/local/lib/libftd2xx.so
----補足ここまで----
ftd2xx.h,WinTypes.hがないとUrJTAGビルドでエラーになるのでコピーしておく
$ cd ../examples $ sudo cp ftd2xx.h /usr/include/ $ sudo cp WinTypes.h /usr/include/
UrJTAGのビルド。下記サイトの内容そのまま
Universal JTAG library, server and tools / Discussion / Using UrJTAG: raspberry pi gpio port
$ cd ~/ $ git clone git://git.code.sf.net/p/urjtag/git urjtag-git $ cd urjtag-git
ビルドの前にcmd_bfin.cの内容を修正
$ cd urjtag/src/cmd $ nano cmd_bfin.c
cmd_bfin.cソースコード先頭に下記を追加する
#ifndef _SYS_UCONTEXT_H #define _SYS_UCONTEXT_H #endif
ctrl-o,ctrl-xで保存後エディタ終了
UrJTAGのビルド
$ cd ../../ $ ./autogen.sh
Warningはちゃんと見ておくべし。
使いたい項目がyesになっているか確認する。
今回はUSB Blasterを使いたいのでD2XX関連とBSDL,SVFはyesになっているか確認。
urjtag is now configured for Libraries: libusb : 1.0 libftdi : yes (no async mode) libftd2xx : yes inpout32 : no Subsystems: SVF : yes BSDL : yes STAPL : no
問題なかったらmakeする
$ make $ sudo make install
動かん……
$ sudo jtag jtag: error while loading shared libraries: liburjtag.so.0: cannot open shared object file: No such file or directory
共有ライブラリとして認識されてないんじゃないかな…
$ sudo ldconfig
$ sudo jtag UrJTAG 0.10 # Copyright (C) 2002, 2003 ETC s.r.o. Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors UrJTAG is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. There is absolutely no warranty for UrJTAG. warning: UrJTAG may damage your hardware! Type "quit" to exit, "help" for help. jtag>
動いた…
RStudioで標準入出力するとなんか変
RStudioがハングする
R-3.4.0をWindows10で使っているのですが、ユーザからのコンソールを受け付けるのに以下のように書いていました
#! /usr/bin/env Rscript # lines = readLines("stdin") # 以下 linesに代入された文字列の処理
ところが、RStudioそのものが動作停止し、タスクマネージャから強制的に終了しないといけなくなる顛末。
確かこれで動いてたはず…
とおもったらRStudioのリダイレクトの所為だったようです。"stdin"ではなく stdin()に書き換え。
参考:linux - Use stdin from within R studio - Stack Overflow
#! /usr/bin/env Rscript # while (TRUE) { line = readLines(stdin(), n=1); if(line == "q")break cat(line, "\n") } # break後の処理 #
無事動きました
W5500でTCP/IP:send() , recv()をそれぞれ独立に行う
W5500でTCPソケット送受信をそれぞれ独立にしたい
ArduinoでもすっかりおなじみになったWiznetのSPI-PHYシリーズですが、思い出しては忘れを繰り返すので、自分への開発時短効果を期待してメモがわり。
W5100/5200/5500のioLibraryドライバ
GitHub - Wiznet/ioLibrary_Driver: Create a repository of WIZnet ioLibrary.
これを自分の使ってるマイコンに移植して、こんな感じで動かすと思います。
#include <____my_mcu_headers____.h> #include "socket.h" #include "loopback.h" ///////////////////////////////////////// // SOCKET NUMBER DEFINION for Examples // ///////////////////////////////////////// #define SOCK_TCPS 0 // .... /////////////////////////////////// // Default Network Configuration // /////////////////////////////////// volatile wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0xAB, 0xCD, 0xEF, 0x01, 0x23}, .ip = {192,168,1,111}, .sn = {255,255,255,0}, .gw = {192, 168, 1, 1}, .dns = {0,0,0,0}, .dhcp = NETINFO_STATIC}; // (中略) int main(void){ int32_t ret = 0; uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}}; // 初期化処理もろもろ for(;;) { if( (ret = loopback_tcps(SOCK_TCPS, gDATABUF, 5000)) < 0) { // Port=5000 (= 192.168.1.111:5000) printf("SOCKET ERROR : %ld\r\n", ret); } // ...... } }
こんな感じでloopback_tcpsをポーリングで動かしてるとおもいます。
loopbackサンプルプログラムを動かして喜んでそのまま積み基板化することが多いのですが、
loopbackのサンプルプログラムを元にsend(), recv()を独立に動かすの、前知識なしではしんどい。
前知識:TCPの状態遷移図
基礎から学ぶWindowsネットワーク:第16回 信頼性のある通信を実現するTCPプロトコル(3) (3/4) - @IT
でもほかにリソース割かなくてはならないし読んでられないよ...何のためにWiznet(ryなので、loopback.cのloopback_tcps()を下記に示すコードに置き換えるだけでrecv(),send()のみできるプログラムを急ごしらえで作成しました。
send/recvの同時発生でバッファの内容を破壊しないような配慮はしてないので各自で書き換えてほしい。
bufに文字列がある場合、文字列をsend()します。bufが空の場合(buf[0]='\0')受信データがあるか確認し、あったらrecv()します。ループバックはしません。なので関数名がおかしくなります。はい。ちゃんと直せよ(殴
#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port) { int32_t ret; uint16_t size = 0, sentsize=0; #ifdef _LOOPBACK_DEBUG_ uint8_t destip[4]; uint16_t destport; #endif switch(getSn_SR(sn)) { case SOCK_ESTABLISHED : if(getSn_IR(sn) & Sn_IR_CON) { #ifdef _LOOPBACK_DEBUG_ getSn_DIPR(sn, destip); destport = getSn_DPORT(sn); printf("%d:Connected - IP:%d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport); #endif setSn_IR(sn,Sn_IR_CON); } if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur. { if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; ret = recv(sn, buf, size); if(ret <= 0){ return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY. } // sentsize = 0; // while(size != sentsize) // { // ret = send(sn, buf+sentsize, size-sentsize); // if(ret < 0) // { // close(sn); // return ret; // } // sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. // } }else if((size = getSn_TX_FSR(sn)) > 0){ size = strlen((const char*)buf); sentsize = 0; while(size != sentsize) { ret = send(sn, buf+sentsize, size-sentsize); if(ret < 0) { close(sn); return ret; } sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. } } break; case SOCK_CLOSE_WAIT : #ifdef _LOOPBACK_DEBUG_ //printf("%d:CloseWait\r\n",sn); #endif if((ret = disconnect(sn)) != SOCK_OK) return ret; #ifdef _LOOPBACK_DEBUG_ printf("%d:Socket Closed\r\n", sn); #endif break; case SOCK_INIT : #ifdef _LOOPBACK_DEBUG_ printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port); #endif if( (ret = listen(sn)) != SOCK_OK) return ret; break; case SOCK_CLOSED: #ifdef _LOOPBACK_DEBUG_ //printf("%d:TCP server loopback start\r\n",sn); #endif if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret; #ifdef _LOOPBACK_DEBUG_ //printf("%d:Socket opened\r\n",sn); #endif break; default: break; } return 1; }
main関数などからループで呼び出してやればOK。
send()したい文字列があればbufにそのポインタを指定し、なければ空のバッファのポインタを指定しておく
呼び出し後にbufの中身を消しておくのを忘れずに。
PQI Air Pen向けにmips-linux-gnu-gccをソースビルドした話
事の発端
年末にNTT-XストアでPQI Air Penが破格の値段でした。
これ、有線/無線でFTPサーバーになるWi-Fiアダプタなのですが、なにより、弄り倒し甲斐のあるLinuxが入ったMIPSマイコンボードな訳です。
nttxstore.jp
そして心強いmoyashi兄さんのブログ
hitoriblog.com
もう買うしかない。正月休みに遊ぶネタが出来たわけです。
飽きてもこれだったら部屋のWiFiルータにはなります。
で、クロスコンパイラはSourcery CodeBench Lite Edition for MIPS GNU/Linuxがあるので別に必要ないのですが、
Ubuntu xenial(16.04LTS)はgcc-5-mips-linux-gnuが提供されているのでこれでビルドし、PQI Air Penで動作させようとすると、
~ #./a.out FATAL: kernel too old Bus error ~ #
致命的エラー:カーネルおじさんめっちゃ老けてるぞ
よーし、一人だけgcc野良ビルドする苦行2017選手権やるか
正月休みにおすすめしたいとても有益な時間の浪費方法です。絶対やめた方がいい。おすすめです。
Rなんとか社のRXマイコンの時は会社でも家でも散々野良rx-gccビルド大会してましたね。このブログのアクセス解析が某軽子坂からのアクセスだらけになってたのはいい思い出です。あんな共用体地獄ライブラリ付きうんこマイコン金輪際ビルドしてやらねぇ。
息をするように野良ビルドするのも考え物ですがカーネルバージョンに合わせて自分でビルドできるので、時には必要な事もあるのかも。
まず、PQI Air Pen(ファームウェアはv0.1.24に変更済み)のカーネルを確認します
~ # cat /proc/version Linux version 2.6.31.AirPen_V0.1.22-g5eca71a (dio@dio) (gcc version 4.3.3 (GCC) ) #324 Thu Feb 7 17:36:23 CST 2013 ~ #
mips-linux-gnuのビルド
ホスト
ビルドおよび動作確認したのは以下の環境です
- Ubuntu trusty (14.04LTS) 仮想化環境(VMware 12) / デュアルブート の両環境
- Ubuntu xenial (16.04LTS) 仮想化環境(VMware 12) / デュアルブート の両環境
ubuntuはメインで使っている14.04で動くことを目指しました。(結局16.04でもビルドできた。詳細後述)
16.04LTSいろいろ難しい…
どちらも前もってインストールしておくパッケージ
$ sudo apt-get update $ sudo apt-get install build-essential m4 gawk g++ make
GCCビルド成功した組み合わせ
GMP,MPC,MPFRを別個にwgetしてもいいのですがGCCフォルダ内の
contrib/download_prerequisites
を起動して自動取得しています。
Ubuntu 16.04LTSがbinutilsのビルドからこけやがる件
本当は根本的な解決をするべきなのでしょうが、よくわからないところで警告出してエラー終了しているので-Wno-errorで回避していまいます。
CFLAGS=-Wno-error binutils-${BINUTILSVERSION}/configure (中略) --disable-warnings-as-errors
スクリプトかいた
出来てしまうと大したことはないのですが、すごくめんどくさいのと大したことないのは別問題なので(?)スクリプト書きました。めっちゃ適当に書いてるので、詳しい人書き直して。
ビルド前にmips-linux-gnuをすでにインストールしている場合はアンインストールするか、$PATHをunsetしておきましょう
#!/bin/bash -ev # see https://www.linux-mips.org/wiki/Toolchains#Roll-your-own # see http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ # see also http://www.hs-augsburg.de/~beckmanf/dokuwiki/doku.php?id=mips_cross_compiler export WDIR=$HOME/tmp export TARGET=mips-linux-gnu export PREFIX=$HOME/mips-cross export TARCH=mips export PATH="${PATH}":${PREFIX}/bin # ------------------------------ # enviroments # ------------------------------ echo ${WDIR} echo ${TARGET} echo ${PREFIX} echo ${PATH} # ------------------------------ mkdir -p ${PREFIX} mkdir -p $WDIR cd $WDIR mkdir -p ${TARGET}-toolchain cd ${TARGET}-toolchain # version BINUTILSVERSION="2.24" GCCVERSION="4.9.2" #GDBVERSION="7.7" ISLVERSION="0.12.2" CLOOGVERSION="0.18.1" #GLIBCVERSION="2.20" #PORTSVERSION="2.20" GLIBCVERSION="2.19" PORTSVERSION="2.19" #KERNELVERSION="3.17.2" #KERNELVERSION="2.6.27.62" #KERNELVERSION="2.6.32.60" KERNELVERSION="2.6.30" # wget if [ ! -e "binutils-${BINUTILSVERSION}.tar.bz2" ] ; then wget http://ftp.gnu.org/gnu/binutils/binutils-${BINUTILSVERSION}.tar.bz2 fi if [ ! -e "gcc-${GCCVERSION}.tar.bz2" ] ; then wget http://ftp.gnu.org/gnu/gcc/gcc-${GCCVERSION}/gcc-${GCCVERSION}.tar.bz2 fi << COMMENTOUT if [ ! -e "gdb-${GDBVERSION}.tar.bz2" ] ; then wget http://ftp.gnu.org/gnu/gdb/gdb-${GDBVERSION}.tar.bz2 fi COMMENTOUT if [ ! -e "linux-${KERNELVERSION}.tar.xz" ] ; then # wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.27/linux-${KERNELVERSION}.tar.xz # wget https://www.kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.32/linux-${KERNELVERSION}.tar.xz # wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-${KERNELVERSION}.tar.xz wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-${KERNELVERSION}.tar.xz fi # ---------------------- # wget kernel-headers # ---------------------- if [ ! -d "linux-${KERNELVERSION}" ] ; then tar -Jxvf linux-${KERNELVERSION}.tar.xz fi # ---------------------- # binutils # ---------------------- if [ ! -d "binutils-${BINUTILSVERSION}" ] ; then tar xjf binutils-${BINUTILSVERSION}.tar.bz2 fi # ---------------------- # gcc # ---------------------- if [ ! -d "gcc-${GCCVERSION}" ] ; then tar xjf gcc-${GCCVERSION}.tar.bz2 fi #----------------------- # get infrastructure # gmp, mpfr, gmp #----------------------- if [ ! -d "gmp" ] ; then gcc-${GCCVERSION}/contrib/download_prerequisites fi # get isl if [ ! -e "isl-${ISLVERSION}.tar.bz2" ] ; then wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-${ISLVERSION}.tar.bz2 fi if [ ! -d "isl-${ISLVERSION}" ] ; then tar -xvjf isl-${ISLVERSION}.tar.bz2 fi # get cloog if [ ! -e "cloog-${CLOOGVERSION}.tar.gz" ] ; then wget ftp://gcc.gnu.org/pub/gcc/infrastructure/cloog-${CLOOGVERSION}.tar.gz fi if [ ! -d "cloog-${CLOOGVERSION}" ] ; then tar -xvf cloog-${CLOOGVERSION}.tar.gz fi # get glibc if [ ! -e "glibc-${GLIBCVERSION}.tar.xz" ] ; then wget ftp://ftp.gnu.org/gnu/glibc/glibc-${GLIBCVERSION}.tar.xz fi if [ ! -d "glibc-${GLIBCVERSION}" ] ; then tar -Jxvf glibc-${GLIBCVERSION}.tar.xz fi << COMMENTOUT # get glibc-ports if [ ! -e "glibc-ports-${PORTSVERSION}.tar.bz2" ] ; then wget http://ftp.gnu.org/gnu/libc/glibc-ports-${PORTSVERSION}.tar.bz2 fi if [ ! -d "glibc-ports-${PORTSVERSION}" ] ; then tar -xvjf glibc-ports-${PORTSVERSION}.tar.bz2 fi COMMENTOUT #ln -sf glibc-ports-${PORTSVERSION} glibc-${GLIBCVERSION}/ports # cd glibc-${GLIBCVERSION} # ln -sf ../glibc-ports-${GLIBCVERSION} ports # cd .. # -------------------------------------------------------- # Build step 0: make symbolic link # mpfr, gmp, mpc, mpfr, isl, cloog # -------------------------------------------------------- cd gcc-${GCCVERSION} ln -sf ../mpfr mpfr ln -sf ../gmp gmp ln -sf ../mpc mpc ln -sf ../isl-${ISLVERSION} isl ln -sf ../cloog-${CLOOGVERSION} cloog cd .. # -------------------------------------------------------- # Build step 1: make Binutils # configure & make & install # -------------------------------------------------------- mkdir -p build-binutils cd build-binutils if [ ! -e "config.status" ] ; then CFLAGS=-Wno-error ../binutils-${BINUTILSVERSION}/configure --target=${TARGET} --prefix=${PREFIX} --disable-warnings-as-errors fi if [ ! -e "${PREFIX}/bin/${TARGET}-ld" ] ; then make make install fi cd .. # -------------------------------------------------------- # Build step 2: make Linux Kernel Headers # make headers_install # -------------------------------------------------------- cd linux-${KERNELVERSION} make ARCH=${TARCH} INSTALL_HDR_PATH=${PREFIX}/${TARGET} headers_install cd .. # -------------------------------------------------------- # Build step 3: Build GCC but libraries # make all-gcc && make install-gcc # -------------------------------------------------------- mkdir -p build-gcc cd build-gcc ../gcc-${GCCVERSION}/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c,c++ --disable-multilib make all-gcc make install-gcc cd .. # -------------------------------------------------------- # Build step 4: Standard C library Headers and Startup Files # make (removed --enable-add-ons=ports, --disable-sanity-checks--with-tls --disable-versioning --disable-profile) # -------------------------------------------------------- mkdir -p build-glibc cd build-glibc ../glibc-${GLIBCVERSION}/configure --prefix=${PREFIX}/${TARGET} --build=${MACHTYPE} --host=${TARGET} --target=${TARGET} --with-headers=${PREFIX}/${TARGET}/include --disable-multilib libc_cv_forced_unwind=yes make install-bootstrap-headers=yes install-headers make csu/subdir_lib install csu/crt1.o csu/crti.o csu/crtn.o ${PREFIX}/${TARGET}/lib ${TARGET}-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o ${PREFIX}/${TARGET}/lib/libc.so touch ${PREFIX}/${TARGET}/include/gnu/stubs.h cd .. # -------------------------------------------------------- # Build step 5: Compiler Support library # make # -------------------------------------------------------- cd build-gcc make all-target-libgcc make install-target-libgcc cd .. # -------------------------------------------------------- # Build step 6: Standard C library # make # -------------------------------------------------------- cd build-glibc make make install cd .. # -------------------------------------------------------- # Build step 7: Standard C++ library # make # -------------------------------------------------------- cd build-gcc make make install cd ..
ビルドが無事終わったら忘れないうちに.bashrcにPATHを通しておいた方がいいと思います。PCはCore-i5 5200Uが乗っているWindows7ノートでやったのですが、
ビルド時間はubuntuのパッケージバージョンには関係なく
VMware環境 2時間半
デュアル環境 40分
でした。仮想環境結構遅いんだね。
#include <stdio.h> int main(int argc, char *argv[]){ printf("hello world.\nThis is PQI Air Pen.\n"); return 0; }
という何の変哲もないコードをhello.cなどと保存し、
$ mips-linux-gnu-gcc -g -O2 -Wall -pedantic -march=24kc -static -o hello hello.c
とすれば、3MB以上もある巨大バイナリが完成する。(staticビルドだからしかたない)
これをmicroSDにコピーするか、FTP経由でPQI Air Penにアップロードする。
telnetでPQI Air Penにログイン
hoge@ubuntu:~$ telnet 192.168.200.1 Trying 192.168.200.1... Connected to 192.168.200.1. Escape character is '^]'. (none) login: root Password: (パスワード:pqiap) BusyBox v1.01 (2013.02.07-09:36+0000) Built-in shell (ash) Enter 'help' for a list of built-in commands. ~ # cd /tmp/www/ftp/sda1/ /tmp/www/ftp/sda1 # ./hello hello world. This is PQI Air Pen. /tmp/www/ftp #
ncursesをtelnet使ってパイプする方法がわかればslコマンドでも、と思ったのですが、いかんせんよくわからず…
また時間のあるときに、Luaでもビルドしてみよう。
おしまい。
参考サイト
https://www.linux-mips.org/wiki/Toolchains#Roll-your-own MIPSクロスコンパイラをビルドするのに最低限必要な内容
http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ Linux上で動作するクロスコンパイラをビルドのするのに必要な知識
http://www.hs-augsburg.de/~beckmanf/dokuwiki/doku.php?id=mips_cross_compiler bare-metalなMIPSコンパイラを作る時に必要な知識
NXPのUART-I2CブリッジSC18IM700でLチカ
すべての道はLチカに通ず
このチップの存在を知ったとき、あまり使うことはないかなとスルーしてたのですが、かなり使い道があると思ったのでちょっとだけ。
UARTさえあれば、プログラミングせずにI2Cデバイスと通信できるのでC言語とかVerilogとかぜんぜんぜんっ知らない僕でも使えちゃいます。ガハハハハ。
やめて石投げないで
気をつけるべきはRESETとWAKEUPの端子のプルアップくらいでしょうか。SC18IM700はデフォルトで9600baud、8N1で通信するので特に気にする部分もありません。って偉そうにいってSC18IM700の通信コマンド間違えてて動かない動かないと3時間唸っていたのでした。
とりあえずGPIOでも動かしてみる
SC18IM700+秋月のFT231XボードでTeraTermからLチカしてみました。
なお、SC18IM700のリセット後、'OK'という文字が送信されます。SC18IM700が動作しないように思えるときはこの文字が受信できているかまず確認します。
もしできていれば受信はOKなので、I2Cバスのプルアップ・速度が問題か、GPIOが動作していないのであればPortConfの設定を見直せばいいことになります。
詳細はデータシート参照のこと
TeraTermからコマンド送信
FT231X(USB-UARTで5V/3.3V系ならなんでもOKのはず)のTX/RXをSC18IM700のRX/TXと接続します。写真は秋月FT231X基板とダイセン変換基板に載せたSC18IM700です。
SC18IM700では文字データ以外の16進数も送受信するため、任意のバイナリデータを送受信できるようTeraTermの設定を変更します。
(1)debug=on にする
デフォルトでは C:\Program Files (x86)\teraterm\TERATERM.INI が設定ファイルになっていると思いますが、このINIファイルの
debug=off
の行を見つけ出し、(自分は475行目付近にあった)
debug=on
に書き換えて上書き保存する。
(2) 送受信エンコードをSJISに変更する
設定(S) -> 端末(T) -> 漢字ー受信(K)と漢字ー送信(J)のエンコードを両者ともSJISに変更する
(3) 16進表示モードに切り替える。
通信中にSHIFT + ESCを何回か押すと切り替わるはず。実動作に問題はないので切り替えは実際に通信が始まってからでOK
(4) 送信コマンドのマクロを書く
(例)UARTで0x12, 0x34 , 0x56を送信したい場合、
send $12$34$56
とマクロファイル(.ttl)に記述すればいい。
今回は以下のように書きました
send $57$02$AA$03$AA$50 ; GPIO全ピンを出力モード(push-pull)にする send $52$02$03$50 ; GPIO config(PortConf1,PortConf2)をリードする :blink send $4F$00$50 ; GPIOに0x00をライトする send $49$50 ; GPIOのピン状態をリードする(ライトした'00'がリードされるはず) mpause 1000 ; 1秒待つ send $4F$FF$50 ; GPIOに0xFFをライトする send $49$50 ; GPIOのピン状態をリードする(ライトした'FF'がリードされるはず) mpause 1000 ; 1秒待つ goto blink ; 繰り返し
上記のマクロをメモ帳などで記述し、 foobar.ttlみたいなファイル名で保存。
TeraTermのコントロール(O) -> マクロ(M)でfoobar.ttlを呼び出す。
TeraTermの画面はこうなるはず
GPIO0~7にLEDをつけて確認すれば2秒周期でLEDがブリンクしているのが確認できるはず。
mbedで動かないものはデバイスに非ず
SC18IM700が動かずにウンウン唸っていたところ、非合法組織クソコード撲滅委員会北関東支部のクマーおさんに助けていただきました。
https://developer.mbed.org/users/okano/code/SC18IM700_GPIO_pin_operation_sample/file/16ad158dc535/main.cpp
ホントに助かりました。ありがとうございます。マヨネーズ反対!
I2Cは?
手元にI2Cデバイスがないので動作を確認できないのですが、オシロで信号を見てみました。TeraTermマクロは以下の通り。
I2Cアドレス0xA0に1バイトデータ0xAAを送信するマクロです。
send $53$A0$01$AA$50 ; write I2C (S(0x53) + Address(W:LSB=0) + Num of Byte + DATA + P(0x50)) send $52$0A$50 ; read I2C Status
信号波形。
デバイスが接続されていないので当たり前ですが、アドレスに対してACKが返ってきてないのでエラーで終わっています。この状態でSC18IM700のI2C Statusをリードすると、'F1'=I2C_NACK_ON_ADDRESS が返ってきます。詳細はデータシートの9.2.7参照。
次回は、本命のI2Cデバイスを動かしてみます