<< 前のページ
2015年1月31日(土) 21:32
何ヶ月も費やして、フライトコントローラーに必要な入出力の単体検証が完了した。
いよいよ、全体を組み合わせての検証だ。すべてのペリフェラルに関して初期化を行い、すべてのペリフェラルに対して情報を遣り取りする。
そのために、プログラムを整理する。そして、センサーを読めるかどうか、1つずつ確認。
ソフトウェアSPIにぶら下がっている2つのセンサーが読めない。接続ピンを変更したのに、プログラムの書き換えがまだだった。修正すると、あっさりOK。さすがソフトウェアSPIは紛れがない。
こうして、2つのトラブルが残った。
1つは、PX4FLOW と通信できない。唯一のI2C接続である。少なくとも、ハードウェアSPI2に接続していたフラッシュRAMを移動する前までは動いていた。ハンダ付け作業で配線がどこか外れたか、それとも内蔵ペリフェラル間に干渉が発生したか。内蔵ペリフェラルは、自由に幾らでも使えるものではない。設定次第では、同時に使えない場合がある。I2C2と何かが、リソースの奪い合いやってるかもしれない。
もう1つは、以前から判明していた問題である。
気圧センサーは気圧として妥当な値を返して来るが、温度が明らかにおかしい。外は雪が降っているのに、80度超えててどうする?(汗)
些細な番外として、バッテリー電圧の取得はUSB給電では機能しない。バッテリーで動作させねば測定できない。まあこれは仕方ない。
written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]
2015年1月30日(金) 21:20
頼むよほんと、コアがM7といいつつ演算器が倍精度になっていなかったら意味ないだろ。
さて、gcc + CoIDE では Visual C++ とほぼソースコードを共用できるから便利である。リードソロモン符号化みたいにひたすら計算やるような場合だと、固有ヘッダーの1行か2行だけ別にして丸ごと共用できたのには感動した。
しかし、SDカードに出力したファイルを解析する場合、構造体のアライメントが問題となる。32ビットCPUでは、変数をアドレスの4バイト境界に置くのが性能的に有利なので、構造体のメンバー変数が隙間無く詰まっていない。そうすると、メモリーイメージのまま読み書きするとズレが発生する。だから、メンバー変数を隙間無く詰めるようにコンパイラーに指示せねばならない。この指示方法が、さすがに
gcc と VC では異なっている。
だが運用上は大した問題ではなく、Windows PC 側では Visual C++ で解析プログラム作れば良いだろう。
256バイトを1万ページ吐き出して、大きさ 2560000 バイトのファイル1つになっているものをPCにコピー。読み込んでリードソロモン復号を行い、ページごとのエラー発生数を調べる。結果は、1万ページすべてエラー0だった。このエラー頻度ならば、ページごとに最大4バイトまでのエラー訂正能力は十分と言えるだろう。
恐ろしいのはバイト化けではなく、バイト抜けである。どこかで1バイト脱落してそれ以降が1バイトずれると、エラー訂正能力などフッ飛んでしまう。これに関しては、SDカードに書き込んだ後でファイルサイズを確認すれば良いと思われる。万全を期すのであれば、ベリファイすれば良い。しかし、エラー頻度と処理時間の増大を天秤に掛けると、そこまでは必要ないだろう。
今回、フラッシュRAMがら読み込んだものをそのままSDカードに書き込んだ。つまり、フラッシュRAMへの読み書き一往復に加えて、SDカードへの片道におけるエラーまで蓄積し、それでエラー0だった。フラッシュRAMがら読み込んだ段階でいったんエラー訂正を行い、それからSDカードへ書き出すようにすれば万全だろう。エラー訂正にはもちろん時間を要するが、エラーが無い場合はオーバーヘッドは比較的小さい。
いずれにしろ、DMAを使用しない場合はハードウェアSPIの信頼性確保と手順がやたら煩雑で大騒ぎだったが、DMAを使うと単純で速くて言うこと無しだったというオチ。ここに辿り着くまでは大変だったが、ようやく報われた。
written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]
2015年1月29日(木) 21:07
シリアルフラッシュRAMには32768ページ存在し、書き込む前には消去せねばならない。効率を考えると、順番に使って行って一通り書き込みに使った段階でチップ全消去というのが良い。
10ページ使って、書き込みが行われているかを試験。
100ページ使って、書き込み時間の集計を試す。書き込みもできているようだ。
DMA転送の所要時間 | ||
最小 | 0.79 | ms |
最大 | 0.80 | ms |
平均 | 0.7975 | ms |
フラッシュRAMへの書き込み | ||
最小 | 1.54 | ms |
最大 | 1.57 | ms |
平均 | 1.5495 | ms |
DMA転送+書き込み時間 | ||
最小 | 2.34 | ms |
最大 | 2.36 | ms |
平均 | 2.347 | ms |
そこで、いよいよ本試験。10000ページを書き込んで、所要時間のみならずエラー発生頻度を調べる。
DMA転送の所要時間 | ||
最小 | 0.79 | ms |
最大 | 0.80 | ms |
平均 | 0.797557 | ms |
フラッシュRAMへの書き込み | ||
最小 | 1.54 | ms |
最大 | 1.57 | ms |
平均 | 1.555305 | ms |
DMA転送+書き込み時間 | ||
最小 | 2.34 | ms |
最大 | 2.36 | ms |
平均 | 2.352862 | ms |
所要時間は、驚くほど安定している。100ページから10000ページへと増やしても、最大値最小値は変わらない。平均は、僅かに増大しているが誤差の範囲内だろう。突発的に長時間を要するという事態が発生していない事実が重要だ。また、書き込み待ちのループなどのタイムアウトは2ミリ秒なので、10000回のページ書き込みを行ってタイムアウトが皆無であることも分かる。
DMA転送はSPIの原理上、タイムアウトは発生しない。転送先はフラッシュRAM内蔵バッファであり、書き込み遅延はない。
内蔵バッファに蓄積された書き込みデーターが、実際にフラッシュRAMに書き込まれるのに必要な時間が表の中段である。
データーシートでは、書き込み所要時間は典型1.5ミリ秒(最大3ミリ秒)となっている。関数呼び出し等のオーバーヘッドも考えると、ピッタリだ。
本番フライトではラジコンパルスに合わせ、処理ループ1回が16ミリ秒を想定している。それに比べると、十分に短時間であり問題なく実用できそうだ。エラーさえ発生しなければ、だが。
written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]
2015年1月28日(水) 21:24
初期化には、関数2つが必須だと判明。
DMA_InitStructure は1回目の初期化で値を保存しておいて、使い回す。
DMA_DeInit(DMA1_Stream4);
DMA_Init(DMA1_Stream4, &DMA_InitStructure);
関数の中身を更に検証することで、本当に急所となる初期化の核心部分を洗い出すことは可能である。だが、将来の移植性を考えるとレジスター直接操作は最小限に留めたい。
この関数全体を実行しても、DMAの再実行を行う間隔は3マイクロ秒にまで短縮された。
これなら十分に速い。保守性と性能のバランスで、まずまずの妥協点である。
クロックに関しては、DMAを使用しない場合には8ビットごとに間合いが発生した。さもないと、正常にデーターを遣り取りできない。それに対し、DMAを使うとクロックがびっしりと連続する。それだけ、短時間で転送できる。SPIの仕様上は問題なしだが、STM32で本当大丈夫なのか。データーが化ける頻度を調査せねばならない。
大量の試行を行わないと判明しない信頼性の些細な差というものが、STM32では存在する。だから厄介だ。
そして、この手の調査は準備が面倒。せっせとソフトいじるだけなので、時間は食うが金は食わないのだけは助かる。
written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]
2015年1月27日(火) 21:17
どれほど頑張っても頑として働こうとしないDMA転送の謎は解けた。前と同じ現象だった。
すなわち、DMA転送は成功していたが2回目以降は失敗していたのだ。
1回目のDMA転送だけは、綺麗にクロックが発生している。フラッシュRAMへの書き込みも成功している。
経緯は、こういうことである。
転送チャンネルを間違っていたため、クロックが発生せず書き込みも失敗していた。
転送チャンネルが違うことに気付き、修正した。
しかしその後の動作試験では、クロック波形だけ調べて失敗と判断していた。
2回目以降は失敗してクロックが発生しなかったため、1回目だけ成功し書き込みも成功していたのを見落とした。
書き込みが成功したことを確認するのは面倒なので、オシロでクロック波形見ただけで失敗と判定した。
とはいえフライトレコーダーなのだから、1回目しか成功しないのでは成功したとは言えない。
これはショッキングで、とにかく死に物狂いで調べまくったので、DMA転送が2回目以降失敗する可能性も自分は明白に認識していた。だからその対策も講じていたのだ。それなのに、2回目の罠にハマっていたとは。これだからマイコンの扱いは厄介だ。不完全な情報しか転がっていない。
256バイトを転送するには、コマンドとアドレスを加えた260バイトを転送することになる。それには0.8ミリ秒しか要しておらず、更にクロックを半減させても良さそうだ。
2回目以降は失敗するという現象は、当たり前だが毎回初期化すれば大丈夫だった。しかし、転送のたびに初期化すると15マイクロ秒程度を要する。許容可能なロスであるとはいえ、ちょっと目障りなロスでもある。となると、2回目以降の成否にどの部分が絡んでいるのかを調べるべきだ。
2回目以降のDMA転送を成功させるための条件は、ネットにも書籍にも誤った情報ばかり転がっている。こんなもの、公式で分かり易い情報があれば済む話である。実際は、誰もが独自に試行錯誤していて、個人個人の環境次第でたまたま動いたり駄目だったりするのだろう。困ったものだ。
written by higashino [マルチローター] [この記事のURL] [コメントを書く] [コメント(0)] [TB(0)]
<< 前のページ
Generated by MySketch GE 1.4.1
Remodelling origin is MySketch 2.7.4