2016年01月03日

mbed: SDFileSystemのDMA化 Nucleo-F030R8編 2016

mbed: SDFileSystemのDMA化 Nucleo-F030R8編 2016
* はじまり
* SDFileSystemライブラリの種類
    Official版と思われる :D SDFileSystem:
    Neilさんが改良した"Neilさん版SDFileSystem":
    DMA対応:
* 手持ちSDカードのCrystalMark値
* SDFileSystem: Neilさん版 ノーマルSPI NUCLEO-F411RE
* Official版SDFileSystem ノーマルSPI NUCLEO-F030R8
* Official版SDFileSystem + DMA改造 SPI NUCLEO-F030R8
* 結果
    Transcendは爆速だった!:
    Sonyは激遅だった!:
    Good-Jがグッジョブ!:
    SanDisk (^^)/:
    GREEN HOUSE orz orz:
* UHS-I でSPIモード
* SDカードリーダ

* マルチ・セクタリード!!


* はじまり
今回使用したボードはこれ。Nucleo-F030R8
https://developer.mbed.org/platforms/ST-Nucleo-F030R8/
mbedで使われているSDカード用のライブラリ,SDFileSystemを
DMA化した時のメモ。

* SDFileSystemライブラリの種類
mbedフォーラムに登録されているものは多数あるがここでは以下の2種類だけ。
Official版と思われる :D SDFileSystem:
    https://developer.mbed.org/teams/mbed/code/SDFileSystem/
    以下のNeilさんが酷評しているオフィシャル版だ。
    気に入らない点,
    (1) デフォルトでSPIクロックが1MHzに固定されていて,
        ライブラリのソースを修正しないと高速化できない。orz
    (2) エラー処理を省略しすぎ。 orz
    歴史の古いライブラリだからアレだけど,まぁなんというか,
    速度が重要でないなら,それなりの用途には使えると思います。

Neilさんが改良した"Neilさん版SDFileSystem":
    https://developer.mbed.org/users/neilt6/code/SDFileSystem/
    名前が同じなのでややこしい。
    (1) Official版がアレ過ぎなので,いろいろ改善した版。
    (2) 結構人気あるみたい。
    (3) これ使ったことある。
    (4) 最近のは動かなかった。orz
    (5) エラー処理はやっぱり手薄。というかもっと上位層の改良が必..(ry
    この版が動くなら :D こっちを使ったほうが良いと思う。
DMA対応:
    上記ライブラリはDMA対応していないが,
    LPC1768/9については改造版が存在する様だ。
    今回はSTM32系なので取り上げない。

* 手持ちSDカードのCrystalMark値
SDカードといっても手持ちは,ほとんど全部「microSD」カード。
まずは、PC上のCrystalMarkを使ってシーケンシャルリードの速度を計測した。
SDカードはClass4/6/10(@4/6/10)と不明な物(@?)がある。
この結果は一部を除いて以下のコピペである。
WAVE/PCM再生: mbed: NUCLEO-F411RE で11bit PWM音楽再生
(単位: KB:Kilo byte ; MB:Mega byte)
    メーカ
    Good-J      16G FAT32 SDHC  @10: seq read: 19.5MB/s , write: 12.3MB/s
    Victor       4G FAT32 SDHC   @4: seq read: 17.8MB/s , write: 11.3MB/s
    BUFFALO     16G FAT32 SDHC   @4: seq read: 17.8MB/s , write:  4.3MB/s
    Sony         8G FAT32 SDHC   @4: seq read: 16.2MB/s , write:  4.7MB/s
    SanDisk     16G FAT32 UHS-I  @6: seq read: 16.6MB/s , write:  8.7MB/s
    Green House 16G FAT32 UHS-I @10: seq read: 16.4MB/s , write:  4.1MB/s
    IO DATA      1G FAT   SD     @?: seq read: 11.9MB/s , write:  2.4MB/s
    Transcend    2G FAT   SD     @?: seq read:  9.9MB/s , write:  5.3MB/s
    Sony         4G FAT   SDHC   @4: seq read:  5.4MB/s , write:  4.9MB/s
* SDFileSystem: Neilさん版 ノーマルSPI NUCLEO-F411RE 以下は、SDFileSystemライブラリ用のベンチマーク結果。 これはDMAを使わないNeilさんのバージョンをNUCLEO-F411REで動かしたときの速度だ。 https://developer.mbed.org/users/neilt6/code/SDFileSystem/ この結果は以下のコピペである WAVE/PCM再生: mbed: NUCLEO-F411RE で11bit PWM音楽再生 NUCLEO-F411RE SysClock=100MHz 読出しバッファサイズは512バイト、SPIクロックは12MHzとした。 測定に使ったファイルサイズは1MByteとした。(ファイルサイズは以降同一で1MByte)
Normal  Good-J   16G FAT32 SDHC @10: SPI SCLK 12MHz: buf=512byte read: 510KB/s write: 81KB/s
Normal  Victor    4G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 507KB/s write: 46KB/s
Normal  Sony      4G FAT   SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 462KB/s write: 21KB/s
Normal  BUFFALO  16G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 456KB/s write: 87KB/s
Normal  Sony      8G FAT32 SDHC  @4: SPI SCLK 12MHz: buf=512byte read: 302KB/s write: 19KB/s 
(容量2Gバイト以下のSDカードは読み書きできませんでした。) orz 高速マイコンなのとNeilさん版の効果か, DMAなしでも"自分用の音出し工作"に十分使える速度を出している。 というのが, 2014年の11月ごろの状況。 で, 2015年末にNeilさんの最新版SDFileSystemを使ってNUCLEO-F030R8で動かそうと試みたが 全く動作せず。orz 原因は未追求。 試しに, Official版のSDFileSystemにしたらサクッと動いたので, 以下は主にOfficial版SDFileSystemの話。 * Official版SDFileSystem ノーマルSPI NUCLEO-F030R8 Official版SDFileSystemをそのままNUCLEO-F030R8で動かしたときの速度だ。 SDFileSystem Official https://developer.mbed.org/teams/mbed/code/SDFileSystem/ NUCLEO-F030R8 SysClock=48MHz 読出しバッファサイズは512バイトとした。 SPIクロックは、1.5MHz - 24MHzまで5ポイントを計測した。
Normal  Good-J    16G FAT32 SDHC @10: SPI SCLK  24MHz: buf=512byte read: 290KB/s write: 65KB/s
Normal  Good-J    16G FAT32 SDHC @10: SPI SCLK  12MHz: buf=512byte read: 262KB/s write: 61KB/s
Normal  Good-J    16G FAT32 SDHC @10: SPI SCLK   6MHz: buf=512byte read: 219KB/s write: 56KB/s
Normal  Good-J    16G FAT32 SDHC @10: SPI SCLK   3MHz: buf=512byte read: 176KB/s write: 49KB/s
Normal  Good-J    16G FAT32 SDHC @10: SPI SCLK 1.5MHz: buf=512byte read: 120KB/s write: 39KB/s
このデータは下記グラフで一番下の線になる。(Without DMA: Good-J 16GB SDHC ) * Official版SDFileSystem + DMA改造 SPI NUCLEO-F030R8 これはOfficial版SDFileSystemを改造してDMA対応にしたもの。 SDFileSystemDMA ライブラリ SDFileSystemDMA テストプログラム 今回はリードだけDMAを使ってNUCLEO-F030R8で動かしたときの速度だ。 ライトはノーマルSPI状態である。 リード/ライトにDMA対応しました。(2016/02) NUCLEO-F030R8 SysClock=48MHz 読出しバッファサイズは512バイトとした。 SPIクロックは、1.5MHz - 24MHzまで5ポイントを計測した。 sdfilesystemdma-speed-test3-read-buffer-512byte.png * 結果 あくまで工作用で使うSPI接続の評価。 でも, 古いTranscendを除けばPC上のベンチ結果になんとなく追従している気がする? 微妙なんだけどね。傾向として。なんというか。:D Transcendは爆速だった!: Transcend はえーっ! 2GBのSDだからかなり古いカードだけど, SPIクロック24MHzだと1.2MByte/sec も出てる。 SPIで1MB/sec超えたの初めて見た。 Transcendについては当初FATでフォーマットしてあったが, 試しにFAT32でフォーマットして計測してみたが,ほとんど違いは出なかった。 Sonyは激遅だった!: SonyのSDカードは買わないことにした。xD DMA使ってSPI 24MHzで450KB/secってヒドイ。 orz Good-Jがグッジョブ!: Good-Jのカードがライトも含めて高パフォーマンスだった (^^)/ SanDisk (^^)/: Class6 のUHS-Iだけどなかなか良い感じ。書き込み速度も速い。 最近の大容量カードとしては一番優秀だ。 製品名: Mobile Ultra / microSDHC UHS-I カード GREEN HOUSE orz orz: Class10のUHS-Iだけど,ダメダメだ。このメーカは二度と買わない。 xD PC上ではUHS-I非対応のSDカードリーダを使ったからアレだけど, とても期待できそうにない気がする。 これ高かったから損した気分。 orz orz
DMA     Transcend  2G FAT   SD  @?: SPI SCLK   24MHz: buf=512byte read: 1286KB/s write: 79KB/s
DMA     Transcend  2G FAT   SD  @?: SPI SCLK   12MHz: buf=512byte read:  879KB/s write: 74KB/s
DMA     Transcend  2G FAT   SD  @?: SPI SCLK    6MHz: buf=512byte read:  544KB/s write: 66KB/s
DMA     Transcend  2G FAT   SD  @?: SPI SCLK    3MHz: buf=512byte read:  310KB/s write: 57KB/s
DMA     Transcend  2G FAT   SD  @?: SPI SCLK  1.5MHz: buf=512byte read:  165KB/s write: 43KB/s

DMA     Transcend  2G FAT32 SD  @?: SPI SCLK   24MHz: buf=512byte read: 1280KB/s write: 62KB/s
DMA     Transcend  2G FAT32 SD  @?: SPI SCLK   12MHz: buf=512byte read:  875KB/s write: 60KB/s
DMA     Transcend  2G FAT32 SD  @?: SPI SCLK    6MHz: buf=512byte read:  543KB/s write: 55KB/s
DMA     Transcend  2G FAT32 SD  @?: SPI SCLK    3MHz: buf=512byte read:  309KB/s write: 46KB/s
DMA     Transcend  2G FAT32 SD  @?: SPI SCLK  1.5MHz: buf=512byte read:  165KB/s write: 34KB/s

DMA     SanDisk    16G FAT32 UHS-I @6: SPI SCLK   24MHz: buf=512byte read: 1058KB/s write: 88KB/s
DMA     SanDisk    16G FAT32 UHS-I @6: SPI SCLK   12MHz: buf=512byte read:  766KB/s write: 83KB/s
DMA     SanDisk    16G FAT32 UHS-I @6: SPI SCLK    6MHz: buf=512byte read:  498KB/s write: 73KB/s
DMA     SanDisk    16G FAT32 UHS-I @6: SPI SCLK    3MHz: buf=512byte read:  294KB/s write: 62KB/s
DMA     SanDisk    16G FAT32 UHS-I @6: SPI SCLK  1.5MHz: buf=512byte read:  161KB/s write: 44KB/s

DMA     Good-J    16G FAT32 SDHC @10: SPI SCLK  24MHz: buf=512byte read: 916KB/s write: 65KB/s
DMA     Good-J    16G FAT32 SDHC @10: SPI SCLK  12MHz: buf=512byte read: 691KB/s write: 62KB/s
DMA     Good-J    16G FAT32 SDHC @10: SPI SCLK   6MHz: buf=512byte read: 467KB/s write: 57KB/s
DMA     Good-J    16G FAT32 SDHC @10: SPI SCLK   3MHz: buf=512byte read: 282KB/s write: 49KB/s
DMA     Good-J    16G FAT32 SDHC @10: SPI SCLK 1.5MHz: buf=512byte read: 157KB/s write: 39KB/s

DMA     Victor     4G FAT32 SDHC  @4: SPI SCLK  24MHz: buf=512byte read: 936KB/s write: 25KB/s
DMA     Victor     4G FAT32 SDHC  @4: SPI SCLK  12MHz: buf=512byte read: 702KB/s write: 24KB/s
DMA     Victor     4G FAT32 SDHC  @4: SPI SCLK   6MHz: buf=512byte read: 470KB/s write: 22KB/s
DMA     Victor     4G FAT32 SDHC  @4: SPI SCLK   3MHz: buf=512byte read: 284KB/s write: 19KB/s
DMA     Victor     4G FAT32 SDHC  @4: SPI SCLK 1.5MHz: buf=512byte read: 158KB/s write: 15KB/s

DMA     BUFFALO   16G FAT32 SDHC  @4: SPI SCLK  24MHz: buf=512byte read: 774KB/s write: 70KB/s
DMA     BUFFALO   16G FAT32 SDHC  @4: SPI SCLK  12MHz: buf=512byte read: 607KB/s write: 66KB/s
DMA     BUFFALO   16G FAT32 SDHC  @4: SPI SCLK   6MHz: buf=512byte read: 428KB/s write: 60KB/s
DMA     BUFFALO   16G FAT32 SDHC  @4: SPI SCLK   3MHz: buf=512byte read: 268KB/s write: 52KB/s
DMA     BUFFALO   16G FAT32 SDHC  @4: SPI SCLK 1.5MHz: buf=512byte read: 153KB/s write: 40KB/s

DMA     Green House    16G FAT32 UHS-I @10: SPI SCLK   24MHz: buf=512byte read: 663KB/s write: 64KB/s
DMA     Green House    16G FAT32 UHS-I @10: SPI SCLK   12MHz: buf=512byte read: 495KB/s write: 58KB/s
DMA     Green House    16G FAT32 UHS-I @10: SPI SCLK    6MHz: buf=512byte read: 375KB/s write: 53KB/s
DMA     Green House    16G FAT32 UHS-I @10: SPI SCLK    3MHz: buf=512byte read: 248KB/s write: 47KB/s
DMA     Green House    16G FAT32 UHS-I @10: SPI SCLK  1.5MHz: buf=512byte read: 146KB/s write: 37KB/s

DMA     Sony       4G FAT   SDHC  @4: SPI SCLK  24MHz: buf=512byte read: 455KB/s write: 18KB/s
DMA     Sony       4G FAT   SDHC  @4: SPI SCLK  12MHz: buf=512byte read: 391KB/s write: 17KB/s
DMA     Sony       4G FAT   SDHC  @4: SPI SCLK   6MHz: buf=512byte read: 307KB/s write: 16KB/s
DMA     Sony       4G FAT   SDHC  @4: SPI SCLK   3MHz: buf=512byte read: 224KB/s write: 15KB/s
DMA     Sony       4G FAT   SDHC  @4: SPI SCLK 1.5MHz: buf=512byte read: 145KB/s write: 12KB/s

DMA     Sony       8G FAT32 SDHC  @4: SPI SCLK  24MHz: buf=512byte read: 426KB/s write: 18KB/s
DMA     Sony       8G FAT32 SDHC  @4: SPI SCLK  12MHz: buf=512byte read: 370KB/s write: 17KB/s
DMA     Sony       8G FAT32 SDHC  @4: SPI SCLK   6MHz: buf=512byte read: 294KB/s write: 17KB/s
DMA     Sony       8G FAT32 SDHC  @4: SPI SCLK   3MHz: buf=512byte read: 208KB/s write: 16KB/s
DMA     Sony       8G FAT32 SDHC  @4: SPI SCLK 1.5MHz: buf=512byte read: 120KB/s write: 14KB/s
* UHS-I でSPIモード UHS-I対応のSDHCカードでもSPIモードで動くことが判った. というか,SD仕様書にはUHS-I対応の物は"「shall」でSPI対応"と書いてあったので :D 大丈夫だろうと踏んだ。 OKだった。(^^)/ * SDカードリーダ 今回使ったPC用のSDカードリーダは3年くらい前に買ったもので, 当然UHS-I速度など対応している物ではない。USB2.0接続仕様の物。 * マルチ・セクタリード!! 実は,オフィシャルなSDFileSystemは「マルチ・セクタリード/ライト」に未対応だった。 上のグラフは読み出しバッファが512バイトの時で,これをいくら増やしても読み出し速度に 変化がないので,アレ? なんか変だなぁ。。。 :D ChaNさんのFatFsのページを読み直してようやく気づいた。 http://elm-chan.org/fsw/ff/ja/appnote.html#fs2 SDFileSystemのソースにもシングル・セクタモードしか使わないとちゃんと書いてあった。 (^^; で, 今のところマルチ・セクタリードのみ対応した。 今回はSPIクロック(DMA)を最高48MHzまで,転送バッファ16KBまで計測できるように, NUCLEO-F411REを使った。 sdfilesystemdma-speed-test-buffer-vs-spi-clock.png ば,爆速になった (^^)/ 結果: な,なんとダメダメと思われたGreenHouseのUHS-Iカードがマルチセクタ効果と SPIクロック48MHz効果で爆速になった。(^^)/ Sonyも高速になったけど,やっぱりイマイチ感がある。 Good-Jはやっぱり好印象。 SanDisk: SanDiskはSPIクロック48MHzで読み出しバッファ16KBの時, な,なんとGreenHouseの2倍の8.5Mbyte/secをたたき出していたが, 挙動が不安定なので今回は除外した。 不安定な理由はブレッドボードワイヤ接続であることは明かなんだけど, (コラ めんどくさいので今のところは除外する。 SPI clock 48MHz動作: SPI clockはどうやら25MHzが上限らしいので上の図で48MHzの線は規格外の参考値とします。(^^; * NeilさんのSDFileSystem vs SDFileSystemDMA NeilさんのSDFileystem: DMAを使わずにある程度高速化できたのは,ざっくり (1) SPIの転送単位を16bitにした。 (2) マルチセクタ転送に対応した。 その他として, (1) SDカードの挿抜に対応した。 (2) etc. ということが分かりましたが, 注意ポイントとして, (1) 低速なマイコンだと転送速度が遅い。 本家のものより高速だが,マイコンの動作速度に転送速度がかなり依存してしまう。 高速なマイコンなら(個人的には)そこそこ満足できる速度が出るとも言える。 (2) 最新版と苦戦中。(2016/02) (^^; (3) 最新版でもやっぱりTrancendの2GB SDカードは読めなかった。 orz 本家SDFileSystemは全く問題なく読める。 SDFileystemDMA: (1) DMAによりマイコンの速度に依存しない高速転送を実現。 (2) 従って、低速マイコンでも高速転送可能。 というか,マイコンの速度によらずSPIクロック速度のみに依存します。 (3) DMA転送中は他の処理が割り込めないので,処理全体としても余裕ができる。 (4) 本家Officialベースなので本家との互換性が高い。 注意ポイントとしては, (1) mbed STMicroのSTM32マイコン専用であること。
               |
               +
             |:|:|

          |
        |
      |

|-+-|  
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | mbed | このブログの読者になる | 更新情報をチェックする

2015年12月29日

mbed: コンストラクタと初期化に関するメモ 2015/12

mbed: コンストラクタの初期化に関するメモ 2015/12
* はじまり
このメモは2015年12月末頃の物なので,mbed側でそのうち修正されるかも。
されないかも。:D

以下は,STM32F0系(Nucleo/DISCO)だけしか見てません。

* mbed2.0のグローバル・コンストラクタとクロックアップ問題
グローバル・コンストラクタ(スタティック・コンストラクタも含む)
C++言語の場合,リセットスタート直後に以下の処理を大体この順に行う必要がある。
    (1) .bss/.data領域の初期化。
    (2) SystemInit()の呼び出し。
    (3) PLLでシステムクロックを指定 or 最高速度にクロックアップ。
    (4) C++コンストラクタの呼び出し。
    (5) main() へジャンプ。 

実は,現時点で上記の順になっていないことが判ったのだった。orz
で,以下の様になっている。
オンラインコンパイラ(armcc)/uVision4(MDK-ARM)(armcc export)の場合:
    (1) SystemInit()の呼び出し。
    (2) .bss/.data領域の初期化。
    (3) C++コンストラクタの呼び出し。
    (4) PLLでシステムクロックを指定 or 最高速度にクロックアップ。
    (5) main() へジャンプ。 
問題:
上記の様にクロックアップとコンストラクタ呼び出しが逆になっている。(注1)
(armccの場合,"デフォルト"では(2)と(3)は不可分で(2)の部分をスキャッタ・ローディングと言うらしい。)
そうすると,
コンストラクタでシステムクロック値を参照してクラスの初期化をしている場合,
間違ったクロック(内蔵クロック:HSI)でクラスが初期化されたままmain()に実行が移り不具合となる。
で,
パッチ的にmain()に飛ぶ前あたりでクロック依存のクラス,現時点では
Serialクラスのボーレトジェネレータ再設定指示を出して回避してたりするのだった。
もしユーザレベルで新規にクラスを作成し,そのコンストラクタ内でシステムクロック値(SystemCoreClock)を参照した場合,
同様の不具合に見舞われる。
以前,プルリクエストのコメント欄で
「何でそこでSystemCoreClockUpdate()を使う必要があるわけ?」
というツッコミを見かけたが,ようやく解せた。
orz

根本的な対応armcc (1):
初期化順を変えるにはソース非公開のアセンブラレベルの変更が必要で,
できなくはないが。。。う〜〜んどうでしょう。
スキャッタ・ローディング呼ばずに自前でメモリの初期化を
する方法もあるにはあるものの,
いまのところ自分がやるべきことではないという判断。xD
別の回避策があるかどうか。

もう少し詳しく書くとクロックアップルーチンは以下の(2)-(a)と(2)-(b)の
間に実行されなければならない。
(1) SystemInit()
(2) __main
    (a) __scatterload(アセンブラ) : .bss/.data領域の初期化 (スキャッタローディング)
    (b) __rt_entry(アセンブラ)    : C++コンストラクタの呼び出し
    (c) $Sub$$main()              : main()の直前の処理をした後、(3)へジャンプ
(3) main() の実行
で,(2)-(a)を自前で作ったものにして,その後クロックアップルーチンを実行,次に
直接__rt_entryに飛ばす方法を使う。
この方法だと.data領域の圧縮機能が効かなくなるのでFlash容量が増える可能性がある。
参考:
アプリケーションの起動
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203ij/Beigcihd.html
リセットと初期化
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471fj/CHDJGDAD.html
スキャッタファイルを使用したスタックとヒープの指定
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474fj/CJAJBEFD.html

デバッガで逆アセンブル結果を見た後の考察:
__main関数内で最初に呼ばれる _main_scatterload関数がサブルーチンなので
(i)  __main関数全体をコピペして__main_replacement関数と名付ける。
(ii) __main_replacementを改造して_main_scatterloadの直後にクロックアップ・サブルーチンの
     呼び出しを追加。
(iii)リセット直後に__mainの代わりに__main_replacementを呼ぶ様に変更。
やってみたわけではないけど,これでOKそう。

根本的な対応armcc (2): orz
GCCの場合,各コンストラクタにインデックスを付けて実行順を制御できるが,
armccの場合はできない様だ。これができれば最初に実行されるコンストラクタを
クロックアップ・コンストラクタ(自前で作る)に指定すれば解決なんだけど... orz

1.8.2 C++ の初期化、構築、および破棄
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0808c/chr1358938934921.html
2.5.1. C/C++ プログラムでのライブラリ関数の使用方法
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0349bj/Cihfddfg.html

* 挙動確認プログラム
#include "mbed.h"

class ClockTest {
    public:
    ClockTest(){
        SystemCoreClockUpdate();
        _startupClock = SystemCoreClock;
    }

    void show(){
        printf("\nmbed-lib rev.%d", MBED_LIBRARY_VERSION);
        printf("\nSystem Clock in constructor    = %8u Hz", _startupClock);
        SystemCoreClockUpdate();
        printf("\nCurrent System Clock in main() = %8u Hz", SystemCoreClock );
        fflush(stdout);
    }
    private:
    uint32_t _startupClock;
};

ClockTest test;

int main() {
    test.show();
    while(1);
    return 0;
}
上のプログラムをmbed(ムベッド)のオンラインコンパイラでコンパイルして 実行してみます。結果はUARTに9600bpsで出力されます。 以下の様に周波数値が違う場合,不具合に遭遇する可能性あり。
System Clock in constructor    =  8000000 Hz
Current System Clock in main() = 48000000 Hz
というか明らかにバ...以下(ry システム的なバグなんだけど,現時点の仕様とも言う。xD (注意点は上記の周波数が一致したからといって全てOKということではない。 というところが微妙) orz 上にも書いたけど,原理上armcc with C++で"デフォルト"の__mainを呼び出す物は ほとんどこのバグ(仕様 :D)を持つことになると思われる。 orz GCCの場合: ExportされたGCCプロジェクトの場合も同様だが, さらに別の不具合も混ざってもう少しヒドイい状況になっているのだった。:D orz orz それは。。。こう, (注1) (1),(2)も逆だけどSystemInit()内でグローバル,スタティック変数を使わない限り 大丈夫。実はこれも危ない部分。 |-o-| - - - -
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | mbed | このブログの読者になる | 更新情報をチェックする

2015年11月26日

mbed 3.0 OS 15.11 Technology Preview版を試してみたときのメモ 2015

mbed 3.0 OS 15.11 Technology Preview版を試してみたときのメモ 2015
* はじまり
* mbed OS TP版のバージョン表記
* mbed OS 新リンク
    mbed 3.0:
    mbed 2.0:

* mbed2.0 から mbed3.0への移行の話
* タスクスケジューラ minar
    minarスケジューラ:
    minarのポイント:

* ユーザアプリケーション app_start
* LED Blink テスト
    app.cpp:
    問題点:

* コードサイズ

* uVisor
    uVisorのコードサイズ:
    uVisorのドキュメント:
    uVisorのサンプルコード:

* yottaの使い方メモ
    yottaコマンドは「yt」と省略できる:
    yotta自身のアップデート:
    yotta自身のバージョンを表示:
    現在の対象モジュールのバージョンを表示:
    更新可能なライブラリやモジュールがあるかを確認:
    make clean的なもの:
    サポートされているターゲットをリストアップする:
    基板の選択:
    現在のターゲットの確認:
    mbedライブラリやドライバのアップデート:
    ターゲットが使用するライブラリやドライバの依存関係とバージョンを表示

* コンパイル・オプションを追加する方法
* サンプルコードとドキュメント
* mbed client は巨大だった!?
* mbed2.0のオンラインAPIドキュメント?
* 参考ブログ

* はじまり
次世代mbed(ムベッド)のmbed 3.0 OS 15.11 Technology Preview版 をコンパイルしてみた時のメモ。
https://www.mbed.com/en/development/software/mbed-os/releases/mbed-os1511/
https://www.mbed.com/en/development/software/mbed-os/releases/
以下mbed3.0と記す。
ちなみに従来のmbed2.0は「Classic mbed」や「mbed SDK」と表現されているが,
以下mbed2.0と記す。
また以下の記述は現時点のTechnology Preview版(以下TP版)ドキュメントをざっと見て認識した内容なので
正確にはオリジナル・ドキュメントを参照してください。

* mbed OS TP版のバージョン表記
https://github.com/ARMmbed/mbed-os
によると,今までmbed OS 3.0と呼ばれていたものは
TP版の mbed OS 15.11
に改名されたが,このメモでは 
mbed 3.0 = mbed OS 3.0 =  mbed 3.0 OS = mbed OS 15.11 = mbed OS TP版
とする。

* mbed OS 新リンク
mbed OS gitリポジトリ
https://github.com/ARMmbed/mbed-os
mbed 3.0:
    https://www.mbed.com
    上記のURLが今後メインストリームになる。
    新フォーラム
    http://forums.mbed.com/
    サポートされている基板(Platform)のページ
    https://www.mbed.com/en/development/hardware/boards/
mbed 2.0:
    ちなみに,今までのmbed 2.0は以下の様に表現されている
    mbed Classic Developer site
    https://www.mbed.com/en/development/developer-classic-site/

* mbed2.0 から mbed3.0への移行の話
https://www.mbed.com/en/development/software/mbed-os/mbed-os-migration-plan/
将来,最終的にはmbed2.0は公式にはサポートされなくなる様です。
(1) 今あるボード/プラットフォーム(以下,基板)がmbed3.0側で正式対応された時点で,
    そのボードのmbed2.0に於けるサポート(バグフィックスやドライバのアップデート)は
    終了するということです。
(2) さらに,最終的にmbed2.0のフォーラム(https://developer.mbed.org/)はリードオンリーに
    設定され書き込みできなくなります。
上記(1)は,基板によっては数ヶ月先に起こる事態だけど...
まぁ,しばらくは大丈夫でしょう。 :D
(2)は,全ての移行が完了した時なのでもう少し余裕がありそう。
結局mbedの意向としては,mbed2.0は過去の記憶とし,
これからはmbed3.0で行こう
ということの様だ。
mbed2.0の「クラウド・コンパイラIDE」がどういうタイミングで使えなくなる?かは不明。
mbed3.0用の「クラウド・コンパイラIDE」も開発中の様だ。
あと,既存のIDE(MDK-ARM,LPXpresso等々)に対するエクスポート機能が先に出る気もする。

* タスクスケジューラ minar
https://github.com/ARMmbed/minar
mbed3.0から標準でイベント(タスク)・スケジューラの「minar」というものが装備された。
スケジューラの名称が「minar」。
ユーザーコードは基本的にこのスケジューラ・ベースで記述することになる。
mbed2.0との完全互換性はなさそうと思われるので 移行時には書き直しが必要だろう。
ただ,ここを見ると
https://github.com/ARMmbed/mbed-drivers/tree/master/mbed-drivers
例えばDigitalOut()等々の最上位のmbedライブラリは一見そのまま使えそうな感じがする。

minarスケジューラ:
(1) シングルタスクの非リアルタイム・スケジューラ。
    ノンプリエンプティブ型です。
(2) イベント(タスク)をこのスケジューラのキューに登録する。
    登録時にdelay時間や繰り返し周期等を指定可能。
(3) スケジューラはキューからイベント(タスク)を取り出して順に実行する。
(4) キューにすぐ実行できるイベントが無ければSleepモードに移行する。
(5) 各種割り込みハンドラ内でコールバック関数がスケジューラにキューイングされ実行される。
minarのポイント:
(1) 非リアルタイムOS(非RTOS)なので,RTOSに起因する同時処理の複雑性を回避することが
    できる。タスクが増えたときのスタックの消費も少なくて済むだろう。
(2) イベント(タスク)は「無限ループ形式」で書いてはいけない。
    (無限ループを書くとスケジューラが破綻する) 必ず関数としてリターンする必要がある。
(3) mbedライブラリやドライバはノンブロッキング処理に対応している。
(4) イベント(タスク)はできるだけ速くその関数を抜ける必要がある。
    ある処理が長すぎると,他のイベントの実行開始時間が次々に遅れて行く。

従来のmain()関数は以下の様に変化した。
extern "C" int main(void) {
    // "app_start"という最初のユーザ関数がスケジューラにキューイングされる。
    minar::Scheduler::postCallback(
        FunctionPointer2<void, int, char**>(&app_start).bind(0, NULL)
    );
    // 以下,minarスケジューラが無限ループで実行される。
    return minar::Scheduler::start();
}
minarスケジューラの中身を単純化して書くと以下の様になる。
while (true) {
    while ( event_available_to_schedule() ){
        schedule_event();
    }
    sleep();
}
* ユーザアプリケーション app_start mbed3.0のユーザ側(アプリ側)のメイン関数(最初のイベント)は 上述の様にapp_start関数になるのでこの関数の中で 初期化や各種イベント登録などを行います。 このapp_start関数もただのイベントなので必要な処理が終わり次第直ちに終了する必要があります。 * LED Blink テスト ボタンを押す度にLEDの点滅速度が500msec,200msec,100msecと変化します。 同時にUART(USB-CDC)に115200bpsで点滅速度とマイコンの動作クロックを表示し続けます。
 ...
 00025: Delay = 500 msec: SystemCoreClock = 84000000 Hz
 00026: Delay = 500 msec: SystemCoreClock = 84000000 Hz
 00027: Delay = 500 msec: SystemCoreClock = 84000000 Hz
 00028: Delay = 500 msec: SystemCoreClock = 84000000 Hz
 ...
app.cpp: 以下のプログラム(app.cpp)をsourceフォルダに置いて app.cpp
$ yotta build
でコンパイルします。
/*
 * app.cpp
 * LED blink and UART test.
 * Written by audin. 2015/11 
 */
#include "mbed-drivers/mbed.h"

static Serial pc( USBTX, USBRX );
static InterruptIn button( BUTTON1 );
//InterruptIn button( SW2 );    /* For FRDM-K64F ? */

static int delay = 500;

/* Event for blinking LED */
void blinky() {
    static DigitalOut led1( LED1 );

    led1 = !led1;
    minar::Scheduler::postCallback( blinky )
        .delay( minar::milliseconds( delay ) );
}

/* Event for display */
void dispEvent(){
    static int num = 0;

    pc.printf("\n %05d: Delay = %d msec: SystemCoreClock = %u Hz" 
            ,num++,delay,(unsigned int)SystemCoreClock);
}

/* Event setting delay time */
void btn1Event(){
    static int id = 0;
    int dDelay[ 3 ]={500, 200, 100};

    id++;
    if( id > 2){
        id = 0;
    }
    delay = dDelay[ id ];
}

/* Interrupt by pushing button */
void btn1Intr(){
    /* Throw buttn evet function */
    minar::Scheduler::postCallback( btn1Event );
}

/* Program start point */
void app_start( int, char** ) {
    pc.baud( 115200 );
    button.rise( &btn1Intr );
    minar::Scheduler::postCallback( blinky );
    minar::Scheduler::postCallback( dispEvent ).period( minar::milliseconds( 500 ) );
}
問題点: 点滅速度が100msecの時,点滅周期が大きく変化し安定しません。 orz printf()文を実行しなければ問題なさそうなので,STM32のシリアルドライバにまだ問題がありそうです。 * コードサイズ GCC version is: 4.9.3 を使用。最適化はデフォルトで「-Os」でした。 上のapp.cppをコンパイルした*.binのサイズは 31.5Kバイト でした。 現在テクニカルプレビュー版なのでF401REは以下のuVisorを含んでいません。 従って,リリース時には40kbyte弱になると思われます。 ちなみに, コンパイラをarmccに変えればコードサイズはこれよりかなり減ると思われます。 gccの場合,printf()関連と浮動小数関連のオーバーヘッドが大きいことが その理由と思われます。 * uVisor uVisorはCortex-M3以上が持つMPU(メモリ保護機能)を使ってセキュリティを 向上させる機能です。 マルウエアや外部から不正侵入された時に,認証鍵等の秘匿情報の流出を防ぐ ことが可能となる様です。 Cortex-M0にこの機能はありません。 uVisorのコードサイズ: uVisorモジュール部分のコードサイズは,出力されたアセンブラコードをざっと見たところ, 6kバイト〜7kバイト程度 と思われます。(gccの場合) uVisorのドキュメント: https://github.com/ARMmbed/uvisor uVisorのサンプルコード: https://github.com/ARMmbed/uvisor-helloworld * yottaの使い方メモ yottaはコマンドラインで動く統合ビルドツールです。 mbed3.0用のクラウド・コンパイラIDEが一般に使用可能になるまではyottaを 使ってビルドするしかない様です。 まずmbedにユーザ登録が必要です。ログイン認証が強制されます。 yotta init実行時やmbed-driversをダウンロードする時に認証が必要な様です。 yottaコマンドはWindows上ならMS-DOSコマンド・プロンプト上で実行するのがひとまず無難です。 (1) Msys/MinGW+minttyで,特にmintty上だとyotta initが先に進みませんでした。 orz orz orz その先に進んでも結局エラーになり挫折中。 但し,一度MS-DOSコマンドライン上でビルドが成功すると, その後Msys/MinGW+mintty上でも yotta コマンドが動く様だ。やっぱりダメだ。orz (2) Cygwin上では,最後のリンク(ld)時にコケる。 cmd.exeがどうのこうのといわれる。 orz yottaコマンドは「yt」と省略できる: $ yotta build は, $ yt build と同じ。 yotta自身のアップデート: yottaコマンド自体を更新します。 $ pip install --upgrade yotta 気づいた時にそれなりのタイミングで :D 更新していくのが無難。 yotta自身のバージョンを表示: $ yotta --version 現在の対象モジュールのバージョンを表示: $ yotta version 更新可能なライブラリやモジュールがあるかを確認: $ yotta outdated make clean的なもの: $ yotta clean サポートされているターゲットをリストアップする: 以下で,「--limit 1000」の部分がないと表示数が少なくてアセる。 orz $ yotta search --limit 1000 target さらに使いかたが今ひとつ?で,上記だとst-nucleo-f401re-gccが出てこない。 でも以前は出ていた様な気もする。 で, 以下の様にするとnucleo関連が出力される。
$ yotta search --limit 1000 nucleo
st-nucleo-f401re-gcc 0.2.0:
    Official mbed build target for the mbed ST Nucleo f401re development board.
    mbed-target:nucleo-f401re, mbed-official, nucleo-f401re, nucleo, gcc
st-nucleo-f401re-st-ble-gcc 0.1.2:
    Compound target: NUCLEO-F401RE plus X-NUCLEO-IDB0XA1.
    nucleo-f401re, nucleo, x-nucleo, ST, STM, gcc, expansion, board, Bluetooth, BLE, x-nucleo-idb0xa1
stm32f411re-nucleo-gcc 0.1.1:
    Official mbed build target for the mbed st-nucleo-f411re development board.
    mbed-target:nucleo-f411re, mbed-official, stm32f411re-nucleo, gcc
x-nucleo-common 1.0.2:
    Common library for X-NUCLEO expansion boards.
    i2c, debug, spi, mcu, nucleo, generic, common, ST, STM, x-nucleo
    wolfgang.betz@st.com
x-nucleo-iks01a1 1.0.3:
    Firmware Library for X-NUCLEO-IKS01A1 (MEMS Inertial & Environmental Sensors) Expansion Board.
    expansion, board, x-nucleo, nucleo, ST, STM, mems, motion, sensors, sensor, temperature, humidity, magnetometer, pressure, accelerometer, gyroscope, LSM6DS0, LIS3MDL, HTS221, LPS25H, LSM6DS3
    wolfgang.betz@st.com
x-nucleo-sensors 1.0.4:
    Library for STMicroelectronics' Sensors.
    x-nucleo, nucleo, sensor, component, ST, STM, sensors, mems, motion, temperature, humidity, magnetometer, pressure, accelerometer, gyroscope, LSM6DS0, LIS3MDL, HTS221, LPS25H, LSM6DS3
    wolfgang.betz@st.com
x-nucleo-idb0xa1 1.1.3:
    ST driver for the mbed BLE API.
    expansion, board, x-nucleo, nucleo, ST, STM, Bluetooth, BLE
    Andrea Palmieri
frdm-k64f-st-ble-gcc 0.1.4:
    Compound target: FRDM-K64F plus X-NUCLEO-IDB0XA1.
    k64f, frdm-k64f, x-nucleo, ST, STM, gcc, expansion, board, Bluetooth, BLE, x-nucleo-idb0xa1
mbed-hal-st-stm32f401re 0.1.1:
    mbed HAL for stm32f401re microcontrollers
    mbed, hal, stm, f401re, nucleo
    wolfgang.betz@st.com
st-stm32f439zi-gcc 0.0.6:
    Official mbed build target for the st stm32f439zi microcontroller.
    mbed-target:nucleo-f439zi, mbed-official, stm32f439i, gcc
あと, $ yt search --limit 1000 armcc $ yt search --limit 1000 gcc の様に黄色い部分をいろいろ変えて探してみる。 基板の選択: 自分が持っているのはNUCLEO-F411REだけど,F401REのプログラムもひとまず動作するので 「st-nucleo-f401re-gcc」を選択した。 $ yotta target st-nucleo-f401re-gcc 現在のターゲットの確認:
$ yotta target
    st-nucleo-f401re-gcc 0.2.0
    mbed-gcc 0.1.3 
mbedライブラリやドライバのアップデート:
$ yotta update
    info: get versions for st-nucleo-f401re-gcc
    info: get versions for mbed-gcc
    info: get versions for mbed-drivers
    info: get versions for mbed-hal
    info: get versions for cmsis-core
    info: get versions for ualloc
    info: get versions for minar
    info: get versions for core-util
    info: get versions for compiler-polyfill
    info: get versions for mbed-hal-st
    info: get versions for mbed-hal-st-stm32f4
    info: get versions for uvisor-lib
    info: get versions for mbed-hal-st-stm32cubef4
    info: get versions for mbed-hal-st-stm32f401re
    info: get versions for cmsis-core-st
    info: get versions for cmsis-core-stm32f4
    info: get versions for cmsis-core-stm32f401xe
    info: get versions for dlmalloc
    info: get versions for minar-platform
    info: get versions for minar-platform-mbed
ターゲットが使用するライブラリやドライバの依存関係とバージョンを表示 yotta listは yotta lsと同じ。
$ yotta ls
    blinky 0.0.0
    \_ mbed-drivers 0.11.3
      |_ mbed-hal 1.2.0 yotta_modules\mbed-hal
      | \_ mbed-hal-st 1.0.0 yotta_modules\mbed-hal-st
      |   \_ mbed-hal-st-stm32f4 1.1.0 yotta_modules\mbed-hal-st-stm32f4
      |     |_ uvisor-lib 1.0.9 yotta_modules\uvisor-lib
      |     |_ mbed-hal-st-stm32cubef4 1.0.2 yotta_modules\mbed-hal-st-stm32cubef4
      |     \_ mbed-hal-st-stm32f401re 0.1.1 yotta_modules\mbed-hal-st-stm32f401re
      |_ cmsis-core 1.1.0 yotta_modules\cmsis-core
      | \_ cmsis-core-st 1.0.0 yotta_modules\cmsis-core-st
      |   \_ cmsis-core-stm32f4 1.0.4 yotta_modules\cmsis-core-stm32f4
      |     \_ cmsis-core-stm32f401xe 0.1.0 yotta_modules\cmsis-core-stm32f401xe
      |_ ualloc 1.0.2 yotta_modules\ualloc
      | \_ dlmalloc 1.0.0 yotta_modules\dlmalloc
      |_ minar 1.0.1 yotta_modules\minar
      | \_ minar-platform 1.0.0 yotta_modules\minar-platform
      |   \_ minar-platform-mbed 1.0.0 yotta_modules\minar-platform-mbed
      |_ core-util 1.0.1 yotta_modules\core-util
      \_ compiler-polyfill 1.1.1 yotta_modules\compiler-polyfill 
* コンパイル・オプションを追加する方法 フォルダ構造は以下とする。
blinky
    build
    source
    test
    yatta_modules
    yotta_target
上記sourceフォルダに拡張子".cmake"でファイル名は任意のファイルを作る。 ここでは,cflags.cmakeとする。中身に以下を書いて普通にyotta buildする。
 set_target_properties( blinky
            PROPERTIES COMPILE_FLAGS "-g3" )
上は「-g3」フラグを追加した例。そのあと, $ yotta clean $ yotta build します。 gccの場合,あとから追加記述されたオプションが有効になるので "-O0"を追加すればデバッグ用に最適化なしでコンパイルできるはずです。 "はずです"というのは,ここに書いた記述がドライバも含め,全てのソースコンパイルに適用されるか どうかは未確認だからです。そのうち確認しよう。 :D まだまだ続く... * サンプルコードとドキュメント https://www.mbed.com/en/development/getting-started/get-code/ * mbed client は巨大だった!? このmbed clientのサンプルを https://github.com/ARMmbed/mbed-client-examples frdm-k64f-gccで試しにコンパイルしてバイナリサイズを見てみたら, arm-none-eabi-gcc で約257Kバイトだった。 (OoO) orz armccでも200Kバイト程度にはなりそう。 ということは,必要なFlash ROMは256Kバイトだと足りないので,次は512Kバイトになってしまう。 ちとデカい。 なにが巨大なのかよく見てないけど,Ethernet,TCP/IP関係は Wiznetのハード・モジュールを使った方が http://www.wiznet.co.kr/product/ 速度は落ちるけどROM容量は減るんじゃないかと予想してみる。 ていうか, ESP−WROOM−02があればいいのか? :D ところで, yottaでコンパイルしたら予想に反して xD LEDチカチカが NUCLEO-F411REで あっさり動いてしまいました。 コンパイルしたモジュール名は, st-nucleo-f401re-gcc なんだけど, NUCLEO-F411REに書き込んだら普通に動いた (^^)/ * mbed2.0のオンラインAPIドキュメント? 以前はWeb上で自由に見られたんだけど,今は見られない。 ログインしないとだめなのか? orz 囲い込み ? orz * 参考ブログ Todotaniのはやり物Log さんのブログ mbed OSでLチカ http://todotani.cocolog-nifty.com/blog/ 工作とかプログラミングとか さんのブログ mbed OS ベータ版でLチカしてみる http://mia-0032.hatenablog.jp/entry/2015/10/26/221949 * 参考ページ RTOSとは? http://www.semicon.panasonic.co.jp/micom/realtimeos/feature.html
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | mbed | このブログの読者になる | 更新情報をチェックする

2014年11月18日

mbed: GR-PEACHなメモ 2014

mbed: gcc: オフラインコンパイル注意点 2014
mbed GR-PEACH
http://www.core.co.jp/product/m2m/gr-peach/

(2014/11)
(1) 値段不明。
(2) GCCは非対応。Cortex-Aシリーズは、Launchpad gccが未対応 orz。
て、事はオフライン・コンパイルがGCCでできない。詳細未調査。
オフラインの場合、純正コンパイラが制限なしで使えるとは思えないし。 orz
オリジナルのGCC自体は対応している模様。Launchpadはorz。
Linuxとかならできるのかもしれない。
Linaro gcc  
http://www.linaro.org/downloads/
(3) デバッガは? OpenOCDとかSWDとかつながるんだろうか? 未調査。
(4) 高性能すぎる!! 未調査 (爆

ここまでの感想。
安ければ、もう少し調査してみるか。 (オイ

 (2014/12)
 (1) 実は、Launchpad gccで普通にオフラインコンパイルできるらしい。
    参考:フォーラム
    http://developer.mbed.org/forum/team-886-GR-PEACH_producer_meeting-community/topic/5311/
    コンパイル方法
    https://github.com/ksekimoto/mbed
    参考:本家
    https://github.com/mbedmicro/mbed/tree/master/libraries/mbed/targets/cmsis/TARGET_RENESAS/TARGET_RZ_A1H/TOOLCHAIN_GCC_ARM








posted by Copyright (C) avrin All Rights Reserved. at 23:19| Comment(0) | mbed | このブログの読者になる | 更新情報をチェックする

2014年10月19日

mbed: NUCLEO-F411REのメモ 2014

mbed: NUCLEO-F411REのメモ 2014
* NUCLEO-F411REのシステムクロック系
2014/10/19現在、NUCLEO-F411REのクロック系は、 
mbed-sdk rev89に於いて以下の様な設定になっている。
システムクロック: 100MHz
これだとUSBは使えないが、これが現状。
nucleo-f411re-clocking-100mhz.png
もし、USBを使うなら以下の様な設定になるだろう。 システムクロック:96MHz
nucleo-f411re-clocking-96mhz.png
mbedの場合、クロック系はユーザからの要望によって勝手に :-) 変わる場合があるので、 将来的にどうなるかは予測不能なものの、結局は96MHzにならざるを得ないと思うのだった。 F411REは出たばかりなので観測中。 上の図で見にくいけど、 PLL_N = 192 * 現状調査 と、思ってmbedフォーラムを検索してみると、 こんなのを発見。 * (2015/06) システムクロック 96MHzに変更された mbedライブラリのrev98に於いて、 システムクロックが100MHzから96MHzに変更されました。orz NUCLEO-F411RE USB clock frequency fix https://github.com/mbedmicro/mbed/commit/f522ea7967185b865505a17692c33b5806fa0a06 結局、上のクロック構成図と同じになりました。
posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | mbed | このブログの読者になる | 更新情報をチェックする