8 years, 3 months ago.

NUCLEO-F303K8のADC初期化エラーについて

AnalogInを使おうとしたのですがADCCannot initializeというエラーがシリアルポートから出力されます。

A0-A2とA3-A7 の二つのグループにどうも分けられるようでA0からA2をグループα、A3からA7をグループβとするとαとβのグループ両方を使うとエラーがでます。

例1:A0,A2をつかう OK 例2:A4,A0をつかう NG

AnalogInかピン定義ファイルのエラーだと思うのですが、どなたかお力を貸してください。

F303K8ボードを持っていないため、確実なことが解りませんが、下記は回答ではなくヒントとして記します。
1)mbedのライブラリーを削除し、mbed-devの最新ライブラリーをインポートしてみてください。
2)A0-A7の指定でなく、PA_0などピン名を変更してみたらいかがでしょうか?
もし、これらの変更で相変わらず状況が良くならないと、mbed最新ライブラリーでも内在するBUGと思われます。
次の対策ですが、「Cannot initialize ADC」は、
/mbed-dev/targets/hal/TARGET_STM/TARGET_STM32F3/analog_api.c
内、Line120辺りで発生させている初期化エラーです。
AnalogInのコンストラクター宣言をmain関数のループ内に持ってきて症状が改善するかも次のトライアルとしては面白いですが、多分だめでしょう。
ここまで来てしまったら、流れを解析して行くしかありませんが、analog_api.c内で、

#if defined(ADC1)
    static int adc1_inited = 0;
#endif
#if defined(ADC2)
    static int adc2_inited = 0;
#endif
#if defined(ADC1)
    if ((obj->adc == ADC_1) && adc1_inited) return;
    if (obj->adc == ADC_1) {
        __ADC1_CLK_ENABLE();
        adc1_inited = 1;
    }
#endif
#if defined(ADC2)
    if ((obj->adc == ADC_2) && adc2_inited) return;
    if (obj->adc == ADC_2) {
        __ADC2_CLK_ENABLE();
        adc2_inited = 1;
    }
#endif

などと定義別判断しているところがあるので、この#if部分がちゃんとコンパイラに認識されているかちょっとわかりません。
少なくてもADC2(ADC1)の判断を削除してどんな状況でもADC1とADC2の関係部分がコンパイルされるようにしてみたらいかがでしょうか?
これでだめだとしたら、EmBitz0.42が良いと思いますが、オフラインでデバッガーでの調査へ移行ですね。
ボードがないので解りませんが、F411などはそのままDEBUG出来ます。
仕様書ちょっと流し読みしたところ、お持ちのボードNUCLEO-F302R8とNUCLEO-F303K8ではADCに大きな差があるのですね!
STMに本格的に対応してもらわないとだめかな?

posted by Kenji Arai 19 Feb 2016

助言ありがとうございます。 ToyomasaさんのAnswerやmbed-devの中身をみつつ修正して無事ADCできました。2)のようにピン名を変えてもうまくいかなかったのでバグなのかなとおもいます。

posted by Sho Ishihara 20 Feb 2016

1 Answer

8 years, 3 months ago.

こんにちは。

おそらくこちらで報告されていることと同じ不具合だと思われます。
https://developer.mbed.org/questions/67841/Multiple-analogIn-not-working/

デバッガで追いかけてみたのですが、おそらくAdcHandleハンドラのステートが複数のインスタンスでの使用が考慮されていないようです。 二つ目のインスタンス初期化時にステートが既に初期化済みになっており、HAL内部のコードでエラーがセットされていました。

analogin_api.c の analogin_init() 内からHAL_ADC_Init()を呼び出す直前に初期化するコードを追加することで、ステートがリセットされ、ADC Cannot initialize エラーが発生しなくなることを確認しました。

void analogin_init(analogin_t *obj, PinName pin)
{

// snip

    // Configure ADC
    AdcHandle.Instance = (ADC_TypeDef *)(obj->adc);
    AdcHandle.Init.ClockPrescaler        = ADC_CLOCKPRESCALER_PCLK_DIV2;
    AdcHandle.Init.Resolution            = ADC_RESOLUTION12b;
    AdcHandle.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
    AdcHandle.Init.ScanConvMode          = DISABLE;
    AdcHandle.Init.EOCSelection          = EOC_SINGLE_CONV;
    AdcHandle.Init.LowPowerAutoWait      = DISABLE;
    AdcHandle.Init.ContinuousConvMode    = DISABLE;
    AdcHandle.Init.NbrOfConversion       = 1;
    AdcHandle.Init.DiscontinuousConvMode = DISABLE;
    AdcHandle.Init.NbrOfDiscConversion   = 0;
    AdcHandle.Init.ExternalTrigConv      = ADC_EXTERNALTRIGCONV_T1_CC1;
    AdcHandle.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;
    AdcHandle.Init.DMAContinuousRequests = DISABLE;
    AdcHandle.Init.Overrun               = OVR_DATA_OVERWRITTEN;

// Added handle state reset code as below
    __HAL_ADC_RESET_HANDLE_STATE(&AdcHandle);

    if (HAL_ADC_Init(&AdcHandle) != HAL_OK) {
        error("Cannot initialize ADC");
    }
}


mbedライブラリの代わりにmbe-devライブラリを使用して、該当するコードを変更してご確認下さい。

テスト用に以下のプログラムをpublishしましたので、こちらでも確認できると思います。
https://developer.mbed.org/users/MACRUM/code/F303K8_AnalogIn_test/

以上、宜しくお願いします。

Accepted Answer

詳しい調査と対策ありがとうございます! mbed-devライブラリの存在を知らなかったためエラー箇所がわからずお手上げでした…… mbed-srcとは違うんですね…… 重ねてですが本当にありがとうございました!

posted by Sho Ishihara 20 Feb 2016