1

LPCマイコンとmbed関係の個人的メモ

Pocket

自分のためのメモです。今回はオーディオは全く関係ありません。基本的にmbedをLPCXpressoで使った時のTips的内容になる雰囲気です。何か気づいたことがあったら随時追加していきます。

LPC824のmbed-srcをLPCXpressoで使う時の問題

すごく限定条件なきがしますが初期状態ではタイマーが正しく動作しません。これの原因は初期設定の関数が呼び出されていないために、CPUクロックが規定の30Mhzより低い状態で動作してしまうからです。

1

デバッガで追いかけてみるとSystemInit();が呼び出されません。

該当部のソースを見ると、defineに__USE_CMSISと__USE_LPCOPENのどちらかがないと初期化関数が呼び出されないようになっていて、LPC824のmbed-srcをLPCXpressoにインポートした場合には、何故かデフォルトではこの部分が呼び出されない状態になっているようです。

2

正しく動作させるためにはこちらの画面で__USE_CMSISを追加するか、cr_startup_lpc82x.cppのdefine条件自体を削除することで対応できます。

LPC15XXで内蔵EEPROMを使う時にハマったこと

LPC1549等のLPC15XXシリーズで内蔵EEPROMをmbedライブラリと合わせて使おうと思った時に詰まるポイントが2箇所あったのでメモしておきます。ネット上では海外含めて具体的に解決策を解説しているサイトがなさそうなのでここにまとめておきます。

LPCシリーズの内蔵EEPROM書き込みには内蔵フラッシュと同じような手続き(IAP)が必要のようで、なかなか手数が多い印象でAVRの内蔵EEPより大分めんどくさい感じです。でもせっかく内蔵しているので使いたいところです。

まずEEPROM書き込みに使用するソースはこちら。

https://developer.mbed.org/users/okini3939/code/eeprom/

ただしこのソースは11シリーズ用なので書き込みアドレスが異なっており、1500シリーズ用に書き換える必要があります。あまり使用者の多くないCPUみたいなのでノウハウの情報が少ないのが難点ですが、LPC1549はUSBもスイッチマトリクスもついていてピン数もそこそこあってRAM容量も大きいという、お手軽ライブラリのmbedと相性がすごく良いと個人的に思っているところです。

該当部はこちら。eeprom.cppの中身。

マニュアルと、オンライン検索で見つかる幾つかのソースでは、IAP_LOCATIONが0x3000200になっていますが、実は0x3000205が正しいので注意!最初デバッガで追いかけてみるとiap_entryのタイミングでHardfaultになってしまい何が原因か全くわからなかったのですが、ねむいさんのOpenOCDソース改定履歴にこの内容の指摘があって間違いに気付きました。まずはここがハマるポイントです。

http://openocd.zylin.com/#/c/2304/

ここを治すことでとりあえずHardFaultは起きなくなります。実は本家LPCOpenのLPC1500版にもEEPROMのライブラリが含まれていたのですが、ライブラリのファイルをみてもIAP_CALLの初期設定がどこに書いてあるのかなかなか発見できませんでした…。LPCOpenのライブラリは初期定義があちこち拡散していていったい何がどこで宣言されているのか探すのに苦労します。結局動いた後で記述を見つけたのですけどわかりにくすぎます。その点mbedのソースのほうが宣言と関数がよく整理されている印象です。mbedライブラリだとCPUの深層や固有機能に触れることは出来ませんが、SPIとかAD含めて汎用的な機能の制御ならmbedライブラリを使っていくほうが後から見て分かりやすいコードが書けるのが良いです。STMシリーズにあとから乗り換えとかしても出来るだけmbedで書いておけばプログラム書き直しもしなくてよいですし。

話がそれました。ということで一つ目はこれでOKなのですが、LPC1500シリーズでEEPROMを動かすために必要な手続きはまだ終わりではありません。もう一つ必要な初期化設定があります。必要な部分をLPCOpenのライブラリから抜粋します。

こちらのコードをeepromのライブラリに追加するか、または別途定義すればOKです。

動作テストに成功したときのサンプルコードです。

これを実行すると無事rbufにwbufの内容がコピーされました。Chip_EEPROM_initの初期化なしだとrbufの中身は0のままです。

LPC1549でタッチパネルを読み取るときの問題と解決法

これは抵抗膜式タッチパネルをmbedのADCポートで読む時に起きる特有の問題です。しかもスイッチマトリクスではないCPU向けのmbedライブラリではおそらく問題になりません。

動作検証に使用したライブラリはこちら。

https://developer.mbed.org/users/king33jp/code/SX032QVGA008/

これをこのまま動かすとLPC1549ではアナログの値が全然取得できません。しかし自分でポートを固定定義してAD値を取得するとちゃんと取れます。なぜでしょうか?

問題の箇所はここです。

実はこの問題の原因はスイッチマトリクスでADCを定義した後にmbedライブラリではスイッチマトリクスの設定がクリアされないことにあります。mbedのAnalogInのソースを見ると初期定義は下記リンク内のanalogin_initが実体なのですが、使用後の開放処理がどこにも見当たらないので一度ADポートとして定義されると開放されないような雰囲気です。

https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC15XX/analogin_api.c

LPC_SWM->PINENABLE0 &= ~(1UL << obj->adc);

ここでスイッチマトリクスにADCの機能定義しているのですが、これの開放が見当たりませんでした。LPC15XXでのADC割り付けはリセットするまでピン設定はこのままということのようです。

だから実は最初だけ正しく値が取得できるのですが、ポート設定を入れ替えていく度にAD入力に切り替わっていき、最後には使用している全部のポートがAD入力になってどのピンからも抵抗膜に電圧をかけられない状態になっていたということのようです。

改良のためにはmbedライブラリを直接改造してもいいのですが、ライブラリがバージョンアップしたあとのことを考えるとライブラリ自体に変更はあまり加えたくありません。となるとタッチパネルのライブラリから手動で毎回開放するように改良したいところです。

ということで途中経過はバッサリ省いてうまく行ったコードを貼り付けておきます。

analogin_api.c内部でしか定義されていないピン情報はどうしても参照できないので仕方なく再定義していますが、AnalogInのクラス内にある内部データを格納する構造体は継承でアクセスしています。この構造体をprotected宣言にして最後のアクセス手段を残してくれたのはさすがmbedライブラリ、分かっているじゃないかと感じました。

補足ですが、このソースだけじゃなくてヘッダファイルのクラス定義にもclass SX032QVGA008: protected AnalogInのように追加するのを忘れないようにしてください。