2021年12月12日日曜日

GPU

仕事の都合上で触ることはあれど、それにあんまりディープに関わることは無いかな〜と思っていたものの、やはり画像を扱う「ブツ」を取り扱っている以上、そこから逃げているわけにもいかず…。

ということで、仕事で扱っているメーカーが、画像認識用のリファレンスデザインをできれば販売したいと考えているとのことで、そのリファレンスデザイン(以下単に「アプリ」)のセットアップを行う必要が出ました。

いっちばん最初はもう2年くらい前で、その時は、メーカー自身がセットアップしたラップトップPC(正確には、ゲーミングノートPC、と言うカテゴリ)を使っていたのだけども、「アプリの次世代ができてるんで、そっちでセットアップしてデモに使ってね」、とメーカーは言う…。


ラップトップPC

 ubuntuにCUDAその他認識で使用するツール一式、何分2年以上前のセットアップなので、ubuntu自体xenialだしcudaも8なので、そこからupdate必要、ということで、まずubuntuはbionicにupgradeで問題なく終わった!と思って再起動してその先に進めていると、何かのはずみにoopsを起こす。
おや???と思っているうちに立ち上がらなくなってしまいました。

このoops、単にプロセスがクラッシュしている旨のメッセージでしかなく、再起動しているうちに、起動できるときとできないときに遭遇することに。
起動できればoops起こさない限り使えてるし、これって、なんかのはずみにsleep状態から抜け出せなくなってんでない?と思ったのが問題解決から遠のく運の尽き。

3週間ほど、もしかしてストレージ(SSD)が壊れた?壊れてない?と、M.2 SSDを着脱、2.5"HDDいれてみたりメモリ全部抜き差しするなどの試行錯誤。

そして、最後の最後に突き止めたのは、8G×2 SODIMMのうち一枚がお亡くなり(なりかけている)、ということ。

メモリって、2枚組ではいっていると、あんまり、一枚ずつさしてみてどうか?って、見ないって事無いですか?

そいつを外してようやく進捗…。
なお、このラップトップにはGTX1080が搭載されています。

CUDA

 現時点で最新のCUDAは11.5だと思いますが、このアプリが要求するのは10.2。これは逆に、他に、そのソフトウエアセットアップを検討しているプラットホームの観点ではbetterな話だと思ったので、10.2インストールに勤しむことに。
しかし、このアプリでは、微妙に古いnvidia-driverが推奨となっており、CUDA vs. nvidia-driverのセットアップに悩むことに。推奨バージョンのnvidia-driverはパッケージとして存在しておらず。もしかして、CUDAはソースからbuildするの???

デスクトップPC

 デモセットアップって、常に私が使えるわけではないので、何か聞かれたときに、同一のアプリをインストールしている類似環境が存在していないと質問に答えられなくなってしまう。
そのため、社内で余剰になっていたデスクトップPCを一台譲り受ける。
当然、そんな業務用のデスクトップにはチップセット内蔵GPUが使われていて、nVidiaのGPUなんて搭載されてない。
ということで、GPU調達をすることになるわけですが、当然「お高い」ので、可能な限りローコスト、とにかく動かせること、レベルをターゲットにして、まずGT1030で、何が起こるかお試しすることに。

GT1030

 こいつはCUDAサポートのリストには無い、ということは知っててあえて試した状況。GDDRメモリバス幅が狭いので、そもそもパフォーマンスは期待できない、とは思ってました。
で。
このボード調達前に、デスクトップにはbionicのセットアップは終わらせてあったので、そこにこのボードを追加、CUDAインストールから試すんですが、この時点で、「あること」を知らずにおり、アプリ推奨に近い版のnvidia-driverインストール後再起動すると、GUIが立ち上がらない、persistencedが動作しない、結果としてCUDAを利用できない、スケジュールも厳しい、という焦りに負けて、3日でgive up、CUDAサポートリストにあるGPUを調達することに。

GTX1650

 土曜に秋葉原に出かけ、GTX1050tiとGTX1650、どちらを選ぶか、1050tiの方が安いなー、ラップトップは1080だから同じ世代だしなー、ではあったんですが、設計古いことから消費電力とコア数で、GTX1650を選定。
「あること」をちゃんとわかってなかったのだけど、週明けにnvidia-driverの比較的新しい版をインストールした状態で、GT1030を試していた時点で残してあったCUDA10.2の組み合わせで、今から思えば不幸にも動いてしまったため、その先に進めることに。

いよいよアプリインストール

 このアプリは2つのアプリで構成されていて、一つ目のアプリが動作した上で、二つ目のアプリをセットアップすることができる。
一つ目のアプリでは、GTX1650で動いてしまった関係で、ラップトップに戻ってセットアップ…すると、動かねー。
ラップトップとデスクトップのセットアップの違いは、GPUの違いに基づくnvidia-driverの違い。つまり、そこで何か間違えたことをやってる、ということ…。

「あること」

 それって、GPUガンガン回すゲームとかAIとかやってる人にはおそらく常識、「nouveauは使わない」、です…。それでラップトップを設定し直し、二つのアプリ、両方とも、デモ可能な状態にできました、まだ調整は必要だけど。
デスクトップの方は、CUDAを使用する他の利用目的もあることと、パッケージをマニュアルで足したり消したり様々試したため、再インストールの予定です。


行き先のなくなったGT1030は…

 過剰になった部品を経費で落とすわけにはいかないこともあり、中古にだすのも気が引けて、引き取ることにしました。
で。以上、確立したインストール手法をもとに今現在、E450でCUDAサンプルをbuild中。動かせるじゃーん、ということで、しかし一方、元々CPUが非力すぎるため恩恵もあまりなく、もしかすると、AI関係のスタディにもっとも寄与してくれる存在になるかもしれません。
Jetson nano、結構安いんで一つ買っても良いかなーとは思ってたんですが、GT1030の方がGPU世代が新しいこともあり(nanoは5.3、1030は6.1)、まー、それもありかな〜、と言うところです。

…、それにしてもGPU高い。ラップトップの価格を考えると、グラボとしてGPU調達するより、ゲーミングノートを買った方が多分効率よいよね…。

2021年9月30日木曜日

BL190HW、いい加減にしてくれ…

 最近、突然宅内ネットから『外』が見えなくなる。在宅勤務中に起こるととっても困る…。

なんでなのか結構しばらく悩んでたんだけど、BL190HWを再起動すると正常になる。で、設定をざっと確認してみると、異常時IPv4 DNSサーバー欄が空欄になっている。こいつが問題。

再起動から最短数時間は問題ない一方で、こいつはログをとれないことから、外側のDHCPサーバーからアドレス更新されたから、とか、そういう確認は全くできない。何せ突然DNSサーバー欄が空白になる。

auのサービスに連絡したところで、お決まりの、『WAN側サーバーに異常ログは無い』『電源入れ直せ』『初期化しろ』、挙句には『見に行く』『交換する』というお決まりのルートになる(今回はとりあえず『初期化しろ』で踏みとどまった)。auは原因究明するつもりがあるのかどうか? そんなことを電話で言ったところで、電話受けてるコールセンターさんが困るだけでらちが開かない。

これ、うちだけなら確かに個体の問題かもしれないけど、どうやらそうではない。『BL190HW DNS 空欄』あたりで調べると、やはり他にもお困りの方がいる。

とりあえず、あんまり引っかかってほしくない一台だけ8.8.8.8を見てもらって、その他はdnscacheを立てて、そちらを参照するようdhcpを変更しようと思う…。dnscacheなんて、だいぶ長いこと使ってないや。

2021年9月9日木曜日

GY-521

  春頃に使ったGY-521、amazonでまとめて5個買いだったこともありまだ残っています。ちょっと思いついたコトがあって、新しいものを開封して、試験的に動かしてみました。

前回は、あんまり深く考えずにi2cをそのままパタパタさせてたんですが、今回はその目的のライブラリを使うに際しi2cまわりも一緒に存在しているので、ライブラリ付属のコードをそのまま頂いて動かして見ようとしてたんですが、うんともすんとも言わない。

元のコードが例によってmbed2用なので、、mbed6用に書き換えたりしてはいますが、基本線は変わらないわけで、調べてみるとwhoamiで引っかかってる。デバイスの応答は、0x68じゃなくて0x98。こんな中途半端なビット化け?と思って調べて見つつ、改めてしげしげモジュール眺めてみると、デバイスにはMPU6050Aと刻印されている。ふーんと思ってinvensense/TDK調べてみるとそんなデバイスは出てない様子。

参照:https://forum.arduino.cc/t/mpu-6050-a-module-problems-who-am-i-reports-0x98-not-0x68-as-it-should-fake-mpu-6050/861956

Amazonにある写真では、MPU6050になってるんだけどね…。

春に使ったときも、whoami最初は見たような記憶があるんだけど、あんまり気にせずだったと思います。今回はこれに磁気センサを追加してAHRSとして動かすことも考えてたんですけどね…。はてさて。

2021年7月31日土曜日

Time server

 半分仕事でやったことなんでここには書いてなかったんですが、これをやっていたとき、並行して、GPSから出力されるppsを使ったタイムサーバーを、NanoPi NEOを使って仕立ててました。

さすが外部のntpサーバーを見ているより高い精度の時刻が得られているようですが、何分バラックセットで運用しているので、ケーブル引っ掛けたり何だりしてしまう関係で、箱に入れることを考えつつ、ただ箱が置かれると、家族的には『なにこれ?』となることを請け合いなので、何か表示でもしておこう、というところに取りかかることにしました。

LCDつなげる

実際、ntpサーバーって地味ですよね…。ただ動いていることを示しておきたいだけなので、今まで、手元にはありつつ、Arduinoで使おうかなーと思いつつ調達したものの、眠っていたキャラクタLCDを使ってみることにしました。たしか、こちらだと思いますが、バックライト用のピン位置が標準とは違うものです。

4ビットモードで使えるだろうとはいえ、Linuxサイドからなるべく簡単にコトませたいので、アマゾン頼みI2C I/Fを調達し手搭載(このLCDでは、バックライト端子のみ別配線する工夫が必要ですが…)、NanoPiへの配線も4線で。Osoyoさんのサンプルコードを使って、表示確認まで済ませました。

何を表示するのか?

キャラクタLCD、16文字2桁しかないし、つけっぱなしで寿命どのくらいなんかなーと言うことが若干気になりつつもまぁ5年くらいは動くのかな…。

で、表示内容は、こいつがなんなのか(つまり"Time Server")、GPSから得られるその日付時刻(UTCですが…)、測位モードにエアの状態、衛星は見えてるかいくつ? くらい、さすればこのntpは今GPS使えてるか自走モードかくらいは判別できるので、その辺繰り返し表示しておけばよいかなー。

どやって表示するか?

ntpサーバーはgpsd使っているし、表示テストに使ったサンプルコードはpythonだしそれなら後で表示内容簡単に変えられるし、そこにgps情報を付け加えればえっかなと、ざっくり。"python gpsd"でググるとgps3というpythonパッケージが目に止まって動かしてみる。何々?十分な情報とれそうだ、でもそんなに色々情報使いはしないけど、と思って使ってみると、測位に使っている衛星個数情報を取り出せない。ま、測位モードだけ判れば良いかとおもい、その表示を行わせてみると、時間更新がうまくいかないし、どうもgpsdから与えられる情報にゴミが含まれることがあるのか、クラッシュする(pythonプログラムが落ちるわけではないが止まってしまう)。使っているGPSその物に依存する可能性はあるけど、これじゃちょっと辛い…。

改めて検索しこれを試すと、シンプルだし時刻データもちゃんと更新される。osoyoのコードそれを付け加えたのが次のコード。gps3が問題なく動くなら、satellitesも同じようにリストになってると思うので、それ調べて測位に使われているならカウントしてやれば良いだろうと思う。


#
# Project Tutorial Url:http://osoyoo.com/?p=1031
#
# GPSd related codes: class GpsPoller() etc.
# Written by Dan Mandle http://dan.mandle.me September 2012
# License: GPL 2.0
#  
import smbus
import time
import threading
from gps import *
gpsd = None
class GpsPoller(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        global gpsd
        gpsd = gps(mode=WATCH_ENABLE)
        self.current_value = None
        self.running = True

    def run(self):
        global gpsd
        while gpsp.running:
            gpsd.next()
# Define some device parameters
I2C_ADDR  = 0x27 # I2C device address, if any error, change this address to 0x3f
LCD_WIDTH = 16   # Maximum characters per line
# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

LCD_BACKLIGHT  = 0x08  # On
#LCD_BACKLIGHT = 0x00  # Off
ENABLE = 0b00000100 # Enable bit
# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005
#Open I2C interface
bus = smbus.SMBus(0)  # NanoPi NEO / Rev 1 Pi uses 0
#bus = smbus.SMBus(1) # Rev 2 Pi uses 1

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD) # 110011 Initialise
  lcd_byte(0x32,LCD_CMD) # 110010 Initialise
  lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
  lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off 
  lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
  lcd_byte(0x01,LCD_CMD) # 000001 Clear display
  time.sleep(E_DELAY)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = the data
  # mode = 1 for data
  #        0 for command

  bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
  bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT
  # High bits
  bus.write_byte(I2C_ADDR, bits_high)
  lcd_toggle_enable(bits_high)

  # Low bits
  bus.write_byte(I2C_ADDR, bits_low)
  lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
  # Toggle enable
  time.sleep(E_DELAY)
  bus.write_byte(I2C_ADDR, (bits | ENABLE))
  time.sleep(E_PULSE)
  bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
  time.sleep(E_DELAY)
def lcd_string(message,line):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")

  lcd_byte(line, LCD_CMD)

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def main():
  # Main program block

  # Initialise display
  lcd_init()

  gpsp.start()

  while True:
    gps_satellites = gpsd.satellites
    num_sats_available = 0
    for item in gps_satellites:
        satdata = str(item)
        num_sats_available = num_sats_available + satdata.count("Used: y")
    lcd_string("GPS time server ",LCD_LINE_1)
    gps_mode = gpsd.fix.mode
    if gps_mode == 1:
        mode_string = "SATs not fixed"
    elif gps_mode == 2:
        mode_string = "2D mode, "+str(num_sats_available)+"SATs"
    elif gps_mode == 3:
        mode_string = "3D mode, "+str(num_sats_available)+"SATs"
    else:
        mode_stroing = "Unknown"
    lcd_string(mode_string, LCD_LINE_2)

    time.sleep(2)
  
    # next page display -- time
    gps_time = gpsd.utc
    dt_today = gps_time[:10]
    dt_time = gps_time[11:20]+"(UTC)"

    lcd_string(dt_today,LCD_LINE_1)
    lcd_string(dt_time,LCD_LINE_2)
 
    # next page display -- time
    gps_time = gpsd.utc
    dt_today = gps_time[:10]
    dt_time = gps_time[11:20]+"(UTC)"

    lcd_string(dt_today,LCD_LINE_1)
    lcd_string(dt_time,LCD_LINE_2)

    time.sleep(3)


if __name__ == '__main__':
  gpsp = GpsPoller()
  try:
    main()
  except (KeyboardInterrupt, SystemExit):
      print ("\nKilling Thread...")
      gpsp.running = False
      gpsp.join()
  finally:
     lcd_byte(0x01, LCD_CMD)


以上、テストラン中。後は箱作りですが、それはまた今度。最悪、LCDバックライト寿命については、ジャンパでon/offできるので、トグルスイッチでもつけるかな…。

2021年6月14日月曜日

Lichee Zero Dock その1

 カメラ、というか動画をいじろう、ということを前から思ってて、カメラモジュールも持ってるものの、なかなか手をつけられずにおりました。手元のボードコンピュータたち、カメラI/F、いわゆるCSIがあるのは、ラズパイ3Bと、PineA64なんですが、ラズパイは言わずと知れた「指定センサ以外はまず使えない」、A64は別の仕事をしている関係で容易に使えず。ということで、何かないかなー、A64は8bitパラレルCSIはOKだけどMIPIは使えないなーと思ってた所に、次の2つを見つけました。

別段新登場、ということではなく、今までそういう目で探してなかった、ということなんですが、一つはM1n、もう一つはLichee Zero Dock、どちらもSipeed製。2枚合わせてもラズパイ買うより安い…(いや比べる事自体正しくない)。で、M1nは、Linuxはちょっと難しそうでRTOS必要そう、かつ、目的がちょっと違うので、一旦置いておいて、Licheeからいじってみることにしました。

 

Lichee Zero Dock

 Lichee Pi Zero? Lichee Zero? どっちでも良いみたいですが、それをコアにして、すこーし周辺I/Fコネクタを追加したもの、と言って良いかと思います。ただ、Zeroはブレボに刺して使うイメージですが、Dockはさらにコネクタなどが乗っている都合で、ブレボに刺してもあんまり嬉しい状況にはなりません。Ethernetを使えてほしかった関係で、ZeroではなくZero Dockを調達してます。そういうわけで、最低限必要そうなUARTだけとりあえず引きだすためのボードを用意しました。

電源も、UARTのところから引けるんですが、母艦側がちょっと苦しいので、5V電源を追加してあります(UART側は当然外します)。以下では省いてるんですが、最初、ちょっとLCDをつないでみたときは、LCDバックライト依存性あるとはいえ電源が窮屈だったようでした。

 

OSと初期設定

Sipeedのサイト から mindb_dd.tar.gzをダウンロード、tar xfして出てくるlichee_zero-mindb_alpha.ddをmicroSDにdd。起動してみると、このddイメージはDebian Jessieです。
 

この段階ではethernetは生きていません。でもネットにはつなぎたいので、Wi-Fiどうかなと思いTL-WN725NをUSBにつなぐと、r8188euで認識してくれました。
『最小パッケージ』なので、NetworkManagerとかいないので、interfacesとwpa_suppliant.confを作成してまずは動かします。
 wpa_supplicant.confのスケルトンはあるので、wpa_passphraseでssidとパスコードからpskを作らせます。
 /etc/network/interfacesにwlan0を追加し、wpa-confがwpa_supplicant.confを示すようにしてやります。これでネットワークにつながりました。

 armbianみたいにパーティション自動最大化とかはしてくれないので、マニュアルでパーティションサイズ変更してresize2fs実施します。
    fdisk /dev/mmcblk0
    /用パーティション一旦削除して、改め最大値で確保します。
    write→quit→reboot(partprobeとかないので)
    立ち上がり後resize2fs -f /dev/mmcblk0p2

Lichee Zeroには、内蔵メモリ64Mしかないのでswap足しておきます(128M追加)。
    dd if=/dev/zero of=<filename> bs=1M count=128
    swapon
  /etc/fstabに追加して再起動時でも有効にします。

さすがにDebian JessieはLTS的にも切れてるので、せめてstretchにupgrade。カーネルは4.10.2のまま。stretchにupgradeするときには、debian-keyringのupdateが必要なことを忘れがち、ということと、多分、Wi-Fiがfirmware必要なので、追加しておきます(大丈夫だったかもしれない)。しかし、ethernetが使えないのは痛い…。


ethernet


 サイズ的な大小はあるにせよ、こういう「規模」が当たり前だった昔ならいざ知らず、いまだとこのクラスのマシン用イメージはセルフではなくクロスビルドが普通だよな…と思いつつ、こちらのサイトに、ethernetを有効とする手順紹介があるので、それを元にセルフビルドしてやります。中国語は読めないので、Web翻訳使いながら読みます。
u-bootはdenxではなく同じサイトにリンクがあるこちらこちらを使います。


makeできたら次で書き込む。
 dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8

u-boot直しただけではu-bootレベルで触れる、と言うだけなので、Linux側も、ドライバ、デバイスツリーを修正します。そのため、カーネルソース、次を利用
 
時間計らなかったけど半日は掛からなかったようです。
make install modules_installではなく、dtbとzImageを/bootにcpしてreboot → お、LEDが点灯& ethernet稼働!

 

カーネルをより新しく…


 これで4.12.0-rc1。しかし、それにしてもこのカーネルはちょいと古く、linux-sunxiサイト見ても、主目的であるカメラサポートは5.0以降となっている。そのため、このイメージはここでストップして、改めて5.10のイメージ作成にチャレンジする。
最新u-bootにすべきかもしれないけど、device treeが結構違っているようで、マージには相当手間が掛かりそうなので一旦捨て置いて、Linuxカーネルソース5.10.42をcloneして、sunxi_defconfigしてbuild、ほぼ5時間で終了。
/bootにdts、zImageをcpして、make modules_install、rebootで5.10.42は起動しました。
なお、カーネルdevice treeには、u-boot同様の変更が必要です(Linuxサイドが新しいので、一部、語を変更する必要がある。)

次の問題


 だが、USBが動いていない模様で、u-bootで有効にできていないようであることが判明。u-bootを使った確認方法


U-Boot 2017.01-rc2-00057-g32ab1804cd-dirty (Jun 13 2021 - 15:14:29 +0900) Allwinner Technology

CPU:   Allwinner V3s (SUN8I 1681)
Model: Lichee Pi Zero
DRAM:  64 MiB
MMC:   SUNXI SD/MMC: 0
*** Warning - bad CRC, using default environment

Setting up a 480x272 lcd console (overscan 0x0)
dotclock: 10000kHz = 10000kHz: (1 * 3MHz * 20) / 6
In:    serial@01c28000
Out:   serial@01c28000
Err:   serial@01c28000
Net:   phy interface0
eth0: ethernet@1c30000
starting USB...
USB0:   musb_init_controller failed with status -22
probe failed, error -5
USB error: all controllers failed lowlevel init
Hit any key to stop autoboot:  0
=>

ということなので、ここのレベルでUSBを有効にできていない。mindbにあるu-bootではちゃんと使えているのだが、.configがなく…。

結構、config様々試してみたんですが動いてくれず。素人目なので確実ではないけども、u-bootのUSBまわりを追ってみると、V3sのサポートが足らないような気がする。Ethernetについても、最新のu-bootでもまだのようなので(patchが流れていた)、V3s自体、まだ十分にサポートされてはいないようです。

がまぁ、ネットワークは動いていることだし、カメラをつなぐことを考えてみたいと思います。

とりあえず今回ここまで。

2021年3月28日日曜日

BL190HWとArcher C6

 …、どうもC6経由のdhcp割り当てがうまくない。有線clientがいるのでBL190HWにdhcpやらせてC6はブリッジモード運用なんだが、時にC6経由で中継されるリクエストがきっかけなのか、BL190がアドレスを振り出さなくなってしまう。

こうなるとBL190の再起動が必要。日に数回発生し得るので、ファイルサーバーにもdhcpサーバーをやらせて、しばらく割り当て状況を監視、だな。

2021年3月12日金曜日

Nucleo64+ArduinoLCD+MPU6050の明日はどっちだ? (承前。GPS追加搭載。)

前回、加速度センサつなげて温度計つなげて、って所までで止めてて、GPSもつなぎたいな…というところで終わりにしていたんですが、その時までにGPSを試していなかったのか、と言うと、そういうわけではなく、GPS側の設定の問題と、シリアルの取扱い方が判らなくて、詰まってたんです。

手元にあるのはUART接続の古いGPSモジュールなので、UART経由でデータを読んでやる必要があります。

ArduinoにはTinyGPSPlusと言う優れものがあり、年末のArduino UNOではそれ使いました。mbedにもそのポーティングがあるんですが、先だって書いたとおり、それがmbedいくつ向けか、という微妙な点があります。それに纏わり引っかかった、mbedにおけるシリアルの取り扱いの変遷があります。

 リアルタイム性を含めてのことなのかなとも思いますが、シリアルやらでデータを交換する時に、C言語までの知識ではgetc()/putc()使う、って教わるように思うんですが(本職の皆さん違ってたらごめんなさい)、getc()もputc()も、mbed 2にはあれど、mbed 6には存在しないんです。
おまけに、mbedには、2014年頃まで、トラ技誌に付録でついたLPC11U35のボードのおかげか(そいつが前回記事で、なんとmbed 6はサポート外なんかい…となったきっかけなんですけど)、日本国内で流行った時期があった関係で、概ね2016年以前のmbed実績のblogなどは、mbed 2、ほぼそれで書かれており、getc()/putc()を使用、せいぜい、serialとrawserialという区分けまでで、はて、mbed 6はどうしたら…となっていたわけです。

Mbedサイトで、シリアルにはBufferedとUnbufferedがあって、getc()じゃなくてread()で取り込む…てのは読んで判ったわけですが、どちら使ってもOSが落ちhaltしちゃう。前回の時は、そこまで追求できなかったんです。
で、改め、unbufferedの時、何で落ちてるのか調べようと思って始めたのが今回なんですが、なぜかdebuggerを使うようbuildすると、もうdebuggerとの通信の時点でOSが落ちちゃう。OSが吐くログは、STLink絡みで問題があるようだけど、とてもそんな所までデバッグする能力はないので、bufferedでどこまで動くか見てみよう、ということで、取り込んだものをprintfさせてみると、どうもnon-printable charを拾っている感じ。これはもしかして、TinyGPSPlusが要求するNMEAを喋ってないんじゃないの?とようやく思い当たりました。


GPSモジュール自体は、NMEAを出力するよう設定して、バックアップバッテリを接続していたので、NMEAのままだと思い込んでいたんですが(古いので、それがないと、電源投入時に、NMEAではない初期状態の出力になっちゃう)、何かのはずみにバッテリへの結線が外れてたんです…。つまりGPSデフォルトで出力していました。それでTinyGPSPlusが解釈できていないことが原因だったと。

それを直し、改めてNMEAを出力するよう設定して走らせてみると…
右の写真ではまだ衛星補足していませんが、時間が取れていることから、ようやく、GPSが出力するデータを読めるようになったようです。衛星捕捉できれば、ちゃんとLAT・LNG表示してくれます。

写真では分かり辛いですが、Arduino LCDを載せたF411RE、SK-16に、クッション付き両面テープを置いて張り付け、その左がわちょうどUSBコネクタの下あたりにGY-521を、同じように両面テープで張り付け、手前側にGPSバックアップ用CR1220が張り付けてあります。 
GPSと、Arduino LCDに搭載されているmicroSDへの書き込み開始スイッチを蓋に張り付けてやって、なんとか収まるようにしました(LCD+F411REの背が微妙に高いのと、ちょいと配線量が多くて、ふたがちゃんとしまりきらないですが…)。

これでも、LM75Aによると、F411REとLCDの間は、LCDバックライトで温められてるとはいえども36℃ほどで収まっているようです。

それにしても、ここに持ってくるまでに、こんなに時間掛かるとは…(何分古いGPSなので、時計はrolloverしてます…)。mbedにはだいぶ悩まされました。
性質的には、GPSはunbufferedで動かす必要があるようには思うんですけど、OSクラッシュは、GPSがNMEA話しているかどうかには関係なく、私程度のソフトウエア知識では対応できましぇーん!


3/29追記:

 昨晩、なぜUnbufferedSerialだとクラッシュするのか、はっと気づきました。プログラムフロー的に非同期な扱いをする部分で、同期乗り換えを必要とすることやっちゃダメっすよね。
さっきそれ直して、UnbufferedSerialを使ってGPSを読み、エンコードし、加速度センサなどの出力と併せて表示できるようにできました。
これで、GPSの時刻データも毎秒表示されます(buffered serialで、バッファしたもの解釈させると、取りこぼしの上数分単位でしか更新できなかったんです…)。

サンプルコードがあるからって、それを鵜呑みにしといちゃダメすね…。特にBuffered Serial / Unbuffered Serialみたいなtiming issueがある実装に対しては。