がれすたさんのDIY日記

電子回路、Python、組み込みシステム開発、自作エフェクターを語るblog

MIMXRT10xxのUARTを使ってみる(ポーリングAPI)

今回はUARTについてやっていきたいと思います。
prinfに関しては評価ボードを使う限りは初期プロジェクト作成でリンクしてくれるので説明はしません。あくまでbyte転送APIで何か送るという感じですね。

環境としては以下を例に説明しますがRT1020でもRT1015でも同じシリーズならできると思います。

  • MCUXpressoIDE v11.0
  • Forlix MIMXRT1052CVL5B or MIMXRT1050-EVK: i.MX RT1050

プロジェクトの作成

新規プロジェクト(new project)作成をクリック

f:id:gsmcustomeffects:20190526045710p:plain
プロジェクトの作成

次にメモリ関連の設定です。
ここに関しては自分の環境にあったメモリ構成を作成して下さい

f:id:gsmcustomeffects:20190526045811p:plain
メモリ構成について

ForlinxのRT1052boardを使う場合のメモリ構成や起動に関してはここを読むといいと思います。

プロジェクト構成の確認とピン設定

前項まででプロジェクトの作成が終わっていると思うのでプロジェクト構成の確認をしていきます。
普通通りにプロジェクトを作成すると評価ボード用の設定がいろいろインサートされてると思います。(公式評価ボードのSDKおよびBSPをフォークして使っているため)

f:id:gsmcustomeffects:20190526054128p:plain
ピン設定ツール

CANとかCSIとかその辺いらないと思うので整理します。

f:id:gsmcustomeffects:20190526060145p:plain
ルーチンの整理
もとから入ってるBOARD_InitDEBUG_UARTPinsってのがあるのでそれはそのまま使うとして
LPUART1を使うのでそのピンが設定されていることを一応確認する。
(もし別のLPUART(2~8)を使いたい場合はそれのピン設定もしておくとよい)
f:id:gsmcustomeffects:20190526065817p:plain
BOARD_InitDEBUG_UARTPins

整理したら上のほうにあるupdate projectをクリックしてコードを吐き出します。

クロックの設定

次にクロックの確認をしていく
自分は工業グレードのMIMXRT1052CVL5Bを使っているのでメインクロックを528MHzにします。(コンシューマグレードの方は600MHzでいいと思う

f:id:gsmcustomeffects:20190527064643p:plain
メインクロックの設定

そしてLPUARTのクロックの設定を確認する。

f:id:gsmcustomeffects:20190528232809p:plain
LPUARTのクロック

ボーレート計算が以下の図のように計算されるのでボーレート誤差が大きいようなら元クロックを調整する必要があると思うがこの辺はブログ末尾のメモ読んでくれればいいと思う。

f:id:gsmcustomeffects:20190529073610p:plain
ボーレートの計算

※OSRはオーバーサンプリングレシオのことでBAUDレジスタで設定することが可能(SDKだと自動?
こちらも同様に終わったらupdate projectをクリックしてコードを出力しておく

ペリフェラルツールで設定する

最後にペリフェラルツールでLPUARTの設定をする。
右上のUSBマークアイコンをクリックして設定画面を開く。

f:id:gsmcustomeffects:20190530004528p:plain
ペリフェラルツール

LPUART画面のコンフィグタブでプリセットを選ぶとほぼ自動設定してくれる。
基本的な使い方をするならこれで十分なのでこういったアシストがあるのはうれしい

f:id:gsmcustomeffects:20190530005832p:plain
LPUART設定

こちらも同様に終わったらupdate projectをクリックしてコードを出力

コードを書いていく

最後にコードについてだが、初期化に関しては別ファイルで行われているので実質記述するのは数行でいい

/**
 * @file    uarttest2.c
 * @brief   Application entry point.
 */
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MIMXRT1052.h"
#include "fsl_debug_console.h"
/* TODO: insert other include files here. */

/* TODO: insert other definitions and declarations here. */

/*
 * @brief   Application entry point.
 */
uint8_t txbuff[] = "uart sample\r\n";
int main(void) {

  	/* Init board hardware. */
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
    BOARD_InitDEBUG_UARTPins();
  	/* Init FSL debug console. */
    //BOARD_InitDebugConsole();

    //PRINTF("Hello World\n");
    LPUART_WriteBlocking(LPUART_1_PERIPHERAL, txbuff, sizeof(txbuff) - 1);
    /* Force the counter to be placed into memory. */
    volatile static int i = 0 ;
    /* Enter an infinite loop, just incrementing a counter. */
    while(1) {
        i++ ;
    }
    return 0 ;
}

説明的なのをすると

uint8_t txbuff[] = "uart sample\r\n";

で送信するバッファを定義している。

BOARD_InitDEBUG_UARTPins();
/* Init FSL debug console. */
//BOARD_InitDebugConsole();

BOARD_InitDEBUG_UARTPins()で先ほど作ったピン設定をする。
BOARD_InitDebugConsole()はprintfとUARTをつないでくれるやつで今回は使わないのでコメントアウトしている。

最後にポーリングAPIです。

LPUART_WriteBlocking(LPUART_1_PERIPHERAL, txbuff, sizeof(txbuff) - 1);

受信はLPUART_ReadBlockingというAPIでできます。

uint8_t rxbuff[10] = {0};
LPUART_ReadBlocking(LPUART_1_PERIPHERAL, rxbuff, sizeof(rxbuff));

こんな感じでいいと思います。

Memo

ボーレート設定について

ボーレート値の計算はペリフェラルツール上で行ってるわけではなくLPUART_Initの冒頭でOSRとSBRの最適化を行う設計になっているため実行するまで実ボーレートがわからない仕様になっている。

f:id:gsmcustomeffects:20190529081358p:plain
LPUART_Init冒頭のボーレートにかかわるレジスタ値の最適値探索

そして探索後誤差を評価して返す

f:id:gsmcustomeffects:20190529081642p:plain
誤差評価

これかならず動く設定が決まってればいいけど可変ボーレートにした場合落ちる可能性もあるよね・・・・・
というよりmainでこのAPI呼んだ際にエラーコード見てない感じなのでサンプルとしてはそんなに優秀ではないかなという印象

エラーコードはこのように定義されているのでもとからあるアサートを利用するなりifで区切って無限ループで止めたりバグになりにくい設計にするといいかもしれない

f:id:gsmcustomeffects:20190530014303p:plain
LPUARTのエラーコード

MIMXRT10xxのADCを使ってみる

今回はMIMXRT10xxシリーズのADCを使ってみようと思う。
ペリフェラルの特徴としてまとめると

  • 1MS/sec sample rate
  • 1モジュールに8つのシングルエンド入力
  • single conversion と continuous conversionに対応
  • 12bit,10bit,8bitに対応
  • 下限値、上限値、値の一致、範囲内、範囲外の割り込みに対応
  • Hardware average functionを内蔵

な感じである。
個人的にはValue trigger , Hardware average functionが使えそうだなと感じた。

次に内部をのぞいてみる。

f:id:gsmcustomeffects:20190308162044p:plain
概略

Kinetisだと16bitだったんですが12bitになったんですね。

割り当てピンとしては以下の表を参考にしてほしい。
一つのチャンネルに対して16本の入力ピンがある感じなので好きなとこ使えばいいと思う
ただし、データレジスタの数が8つまでなのでADC1で使える本数は8個までそれ以上使う場合はADC2を使う。

signal descriptor pad
ADC1_IN0 ch1 input 0 GPIO_AD_B1_11
ADC1_IN1 ch1 input 1 GPIO_AD_B0_12
ADC1_IN2 ch1 input 2 GPIO_AD_B0_13
ADC1_IN3 ch1 input 3 GPIO_AD_B0_14
ADC1_IN4 ch1 input 4 GPIO_AD_B0_15
ADC1_IN5 ch1 input 5 GPIO_AD_B1_00
ADC1_IN6 ch1 input 6 GPIO_AD_B1_01
ADC1_IN7 ch1 input 7 GPIO_AD_B1_02
ADC1_IN8 ch1 input 8 GPIO_AD_B1_03
ADC1_IN9 ch1 input 9 GPIO_AD_B1_04
ADC1_IN10 ch1 input 10 GPIO_AD_B1_05
ADC1_IN11 ch1 input 11 GPIO_AD_B1_06
ADC1_IN12 ch1 input 12 GPIO_AD_B1_07
ADC1_IN13 ch1 input 13 GPIO_AD_B1_08
ADC1_IN14 ch1 input 14 GPIO_AD_B1_09
ADC1_IN15 ch1 input 15 GPIO_AD_B1_10

ADC2に関しては割愛(ref manualのTable 63-2. ADC external signalsを参照)

次に仕組み的なものを雑に紹介する。


やってみる

環境としてはForlinx RT1052評価ボードを使う。
写真左の多回転トリマーがADCにつながっていますのでそのピンを使って進めていきます。(ピン的にはGPIO_AD_B0_14

自分はこの環境だが購入とかも直接問い合わせとかでめんどくさいので普通の人は公式の評価ボードであるMIMXRT1050-EVKなんかを使うのがいいと思う。

f:id:gsmcustomeffects:20190401224949p:plain
Forlinx OK1052-C 評価ボード


ハードウエアの用意が終わったところでさっそくやって行きたいわけだがSDKプロジェクトにはADCのサンプルがついている。

  • adc_12b1msps_sar_polling
  • adc_12b1msps_sar_interrupt
  • adc_etc_software_trigger_conv
  • adc_etc_hardware_trigger_conv


これらのサンプルプロジェクトはAPIの使い方について大いに参考になるが別ファイルで記述されているクロックやピンファンクションなどの初期設定で何をやればいいのかわかりにくい。
そのため今回は空プロジェクトからadc_12b1msps_sar_pollingと同様なことをやってみたいと思う。
内容としてはソフトウエアでADCを開始してADC完了後ポーリングAPIにてADCデータレジスタから値の取得を行うというものです。

やることの整理とスキームをまとめると以下のようになります。

  • プロジェクトの作成
  • クロックの設定
  • ピンの設定
  • Conversionの設定
  • Calibrationの設定
  • 割り込みやチャンネルコンフィグの設定
  • コードの出力

ざっとまとめるとこんな感じになるのでクロックの設定からやって行くことにします

プロジェクトの作成

まずは自分の環境にあったチップを選んで新規プロジェクトを作成する。

f:id:gsmcustomeffects:20190430013137p:plain
新規プロジェクト

メモリなどの設定は以下のようにした

f:id:gsmcustomeffects:20190430013226p:plain
メモリコンフィグ

クロックの設定

まずはクロックということでそれの画面に遷移する。

f:id:gsmcustomeffects:20190430013651p:plain
クロック設定にかかわる画面
IMXRT10xxのADCにはクロックソースが3つある(正確には2つ)

  • IPG clock
  • IPG clock divided by 2
  • ADACK(ad asynchronous clock)

ADACKはADCペリフェラル内蔵のクロックソースで、MCUがstopモード中でも変換が可能となっている。
リセット時はIPG clockが設定されている。
ADCモジュール上でクロックに関連は以下の図の点線で囲った部分であり、後段に共通のディバイダを備えていることがわかる。

f:id:gsmcustomeffects:20190421232935p:plain
ADC block diagram

次に実際のクロック設定だが結構楽でペリフェラルツールでプルダウンメニューから選ぶだけで良い。
ちなみにIPGを選ぶ場合はクロックが早すぎると問題があるので設定に注意したい。

f:id:gsmcustomeffects:20190415025544p:plain
ペリフェラルツールの設定例

自分の場合はこのようにした。

  • Clock source : Asynchronous Clock
  • Clock source frequency : 10MHz
  • Clock source divider : Do not divide
  • sample time : 6 clocks(short sample mode)

Start asynchronous clock outputに関してはADCx_GCのADACKENに解説がありどちらでも動くには動く。

  • OFF:変換がアクティブ時にON
  • ON:asynchronous clockが常にONになるため初回変換時に数クロック分早くなる。(クロック起動サイクル分がなくなるため)

クロックについてさらに詳しく知りたければリファレンスマニュアルのCCMの章を読むといいだろう。

ピンの設定

特にこうしろってのはないので自分の使いたいピンを設定してください

f:id:gsmcustomeffects:20190429234550p:plain
ピンコンフィグ

Conversion設定

次にConversionの設定です。

Conversion Timeの計算方法はリファレンスマニュアルにも書いてあるが
\begin{equation}
ConversionTime = SFCAdder + AverageNum * (BCT + LSTAdder)
\end{equation}

で計算できる。変換部分を詰めるなら知っとくべきだが補助ツールでだいたいの設定はできてしまうので今回の例では設定部分だけ書く

f:id:gsmcustomeffects:20190429211654p:plain
ペリフェラル設定(Conversion)

Calibration設定

最後にADCの精度確保のために初期キャリブレーションを行う必要がある。

これに関してはペリフェラルツールだとチェック入れるだけ

f:id:gsmcustomeffects:20190429233243p:plain
ペリフェラル設定(キャリブレーション

割り込みやチャンネルコンフィグの設定

f:id:gsmcustomeffects:20190430010958p:plain
割り込み+コンフィグ設定

コード出力および記述

これで一通りの設定が終わったのでコードを出力する。

f:id:gsmcustomeffects:20190430014322p:plain
コードの出力

初期化部分が出力できたらコードを書いていく。

書くとは言っても結構コンパクトにおさまる。ADC結果をprintfしていく感じ

f:id:gsmcustomeffects:20190430015452p:plain
コードの記述と解説

UART出力を確認するとこんな感じ

f:id:gsmcustomeffects:20190430015842p:plain
Teratermでの出力

割り込みについて

割り込みに関してはツールでチェック入れるだけでできて簡単なのでコードとして何が出力されるか示す。
EnableIRQ APIをコールしARMコア自体に割り込みの有無を教える

EnableIRQ(ADC1_IRQn);
EnableIRQ(ADC2_IRQn);//使うほうを有効にする。両方有効ならそれでもいい

チャンネル設定構造体メンバに割り込み有効

adcChannelConfigStruct.enableInterruptOnConversionCompleted = true;
ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct);

ハンドラの定義

void ADC1_IRQHandler(void)//ADC2を使う場合は2のハンドラを使う
{
    g_AdcConversionDoneFlag = true;
    /* Read conversion result to clear the conversion completed flag. */
    g_AdcConversionValue = ADC_GetChannelConversionValue(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP);
    g_AdcInterruptCounter++;
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
    __DSB();
#endif
}

メモ

その他の機能について

サンプルプログラムとしてはSDK付属の物がいくつかあるのでそれを参考にするとハードウエアトリガーで動かすことも可能。
以下4つがSDKに含まれているので使う際は参考にするといい

  • adc_12b1msps_sar_polling
  • adc_12b1msps_sar_interrupt
  • adc_etc_software_trigger_conv
  • adc_etc_hardware_trigger_conv

2019年版 STM32環境構築方法

以前よりSTM32について結構な数の記事を書いてきました。
最近ではAtollicTrueStudioが無料になったり、CubeMXが5.0になったり
いろいろ変わった経緯もあり2019年版と題して新しく書いたほうが良いのでは?となったわけです。

そんなわけで僕なりの2019年度版環境構築を書いてみたという記事です。


目次的なやつ

AtollicTrueStudioのインストール

まずIDE統合開発環境)についてですがAtollicTrueStudioを使うのでそれのインストールをしていきます。
Macの人はSW4STM32しかないけど・・・Eclipseなので同じように進めればいいと思う。

atollic.com

上記のサイトに行き、ダウンロードしてもらってあとはインストールしてもらえればいいと思う

CubeMXのインストール

STM32にはマイコンを楽に使うためのライブラリ群がありSTはそれをCubeFxx(xxは数字F7ならCubeF7のような感じ)と呼んでいる。
んでそいつを内包しGUIペリフェラルを設定するためのツールとしてCubeMXというものを提供している。

www.st.com

ページの下のほうにダウンロードリンクがあるのでダウンロードする(登録が必要だったはず
んでインストール

STM32CubeProgのインストール

以前STM32Utilityとして提供していたものとその周辺のソフトが一体になった書き込みソフトとしてSTM32CubeProgが新しく提供された
デバッガとつながらくなった時に何かと便利なのでこれも入れておくのがいいでしょう

www.st.com


評価ボードを買う

次に実際に動かすハードウエアの話
STM32では格安評価ボードとしてNucleoというプラットフォームを提供している。

f:id:gsmcustomeffects:20190311010721p:plainf:id:gsmcustomeffects:20190311010644p:plainf:id:gsmcustomeffects:20190311010616p:plain
STM32 評価ボード

もちろんNucleo以外にもEVALボードやDiscoveryボードというものを用意しているがどちらかというともとからできる人向けのプラットフォーム感がある。

そんなわけで何でもいいんで好きなNucleoボードを買ってください

僕は秋月でも買えるしブレッドボードでも使えるSTM32F303K8をチョイスしてこれで説明していきます。
STM32 Nucleo Board STM32F303K8: マイコン関連 秋月電子通商-電子部品・ネット通販

CubeMXを起動する。

ここからが実際の作業です

起動するとこの画面が出てきます
f:id:gsmcustomeffects:20190311020003p:plain

Access to board selectorをクリックしてくださいそうするとこの画面が開きます。

f:id:gsmcustomeffects:20190311020131p:plain
ボードセレクト画面

次に303K8を探して選ぶとこの画面になると思います。

f:id:gsmcustomeffects:20190311020558p:plain
ボードインフォメーション

そうしましたら赤枠のStartprojectをクリックして進みます。

そうするとこういう画面が出てきます

f:id:gsmcustomeffects:20190311021026p:plain
基本画面

今回はLEDをちかちかしてみたいと思うのでピンの設定をしていきます。
PB3をアウトプットに設定、デバッグピンも設定

f:id:gsmcustomeffects:20190311024446p:plain
ピンの設定

ここでPB3に設定しているのはボード上のLEDを光らせる為です

f:id:gsmcustomeffects:20190312220730p:plain
Nucleo32の回路図(UM1956)

次にクロックの設定です。
まあ初期設定でも動くには動くんですがせっかくやるのでいじり方だけでも覚えておきましょう。
ここではメインクロックを64MHzにしています。

f:id:gsmcustomeffects:20190311021627p:plainf:id:gsmcustomeffects:20190311021923p:plain
クロックの設定(クリックで拡大できます)

次にプロジェクトの設定をします

f:id:gsmcustomeffects:20190311022511p:plainf:id:gsmcustomeffects:20190311022445p:plain
プロジェクトの設定

次にGenerateCodeをクリックしてコードを出力してください
上手くできていればこんな感じにファイルができているはずです
f:id:gsmcustomeffects:20190311023102p:plain

Atollic TrueStudioを起動する。

そうしましたら次はAtollicTrueStudioを起動します。

そして上部メニューからFile/インポートを選択し先ほど作ったプロジェクトをインポートする。

まずはプロジェクトをビルドする

f:id:gsmcustomeffects:20190311023705p:plain
プロジェクトのビルド

ビルドに成功しましたらコード追加します

f:id:gsmcustomeffects:20190311024815p:plain
コードの記述

次にデバッグボタンをクリックします。

f:id:gsmcustomeffects:20190311024922p:plain
デバッグボタンのクリック

そうすると画面が切り替わります。
画像に従ってブレークポイントを設定してあげてプログラムを進めるボタンを押してあげれば500msごとにプログラムが止まりボード上のLD3が光ったり消えたりすると思う
f:id:gsmcustomeffects:20190311025250p:plain

以上で入門は終了!

所感

2019年版の入門を書いたけど日に日にまじで楽になってるね。

軽いQ&A
Q:自分でチップ買ってきてそれに対して書き込むにはどうしたらよいの?
A:別途デバッガが必要です。

語弊があるので補足しておくとNucleo64やNucleo144はSTLINKV2-1ってのがついてるんで外部チップに向けてもデバッグしたり書き込んだりできる。

Q:どんなデバッガがあるの?おすすめは?
A:STLINKV2かV3

2018年まではSTLINKV2が主流だったけど2019年になってV3が出たので今はこれがお勧めです。

f:id:gsmcustomeffects:20190311030017p:plain
STLINKV3

ARMマイコンなので別のメーカー製のでも書き込みやデバッグはできますがSTM32CubeProgが使えるの考えると純正がいいです。

Q:STM32CubeProgは何が出来んの?
A:デバッガのファームウエアをアップデートしたり、書き込みしたりその他オプションをいじったりできます

繋いだ時こんな感じです
f:id:gsmcustomeffects:20190311030334p:plain

Q:他参考になる情報とかは?
A:僕のまとめサイトペリフェラルの説明はしてます

結構前にかいた記事もあるので適宜読み替えてくれればいいと思います。
開発環境の使い方は変わったけどAPIレベルではそんなに変わってないので以下のサイトは役立つはず

gsmcustomeffects.github.io

MIMXRT10xx series dcd table Tips part2

前回は解釈の仕方を書いたので今回はクロックに絞って全容をつらつら書く感じ。
ぶっちゃけ前回の記事で必要なことは書いたのでこれは読みたい人が読んでくれればいい。そんなmini tips的なやつ

本記事の環境は以下の通りです。

  • MIMXRT1050-EVK
  • SDK ver 2.5

クロックの設定

DCD tableを先頭から見ていくとdcd tableの0x09 ~ 0x57 bytes でクロック設定をしている。

dcd byte reg address reg name value
0x09~0x0F 0x400FC068 CCM_CCGR0 0xFFFFFFFF
0x10~0x17 0x400FC06C CCM_CCGR1 0xFFFFFFFF
0x18~0x1F 0x400FC070 CCM_CCGR2 0xFFFFFFFF
0x20~0x27 0x400FC074 CCM_CCGR3 0xFFFFFFFF
0x28~0x2F 0x400FC078 CCM_CCGR4 0xFFFFFFFF
0x30~0x37 0x400FC07C CCM_CCGR5 0xFFFFFFFF
0x38~0x3F 0x400FC080 CCM_CCGR6 0xFFFFFFFF
0x40~0x47 0x400D8030 CCM_ANALOG_PLL_SYS 0x00002001
0x48~0x4F 0x400D8100 CCM_ANALOG_PFD_528 0x001D0000
0x50~0x57 0x400FC014 CCM_CBCDR 0x00010D40

DCD tableにおけるクロックの設定を書きだすとこんな感じ

そしてこのTipで操作するクロックを示すとこんな感じ

f:id:gsmcustomeffects:20190301020411p:plain
本記事で操作する部分を示した図

CCM_CCGR(CCM Clock Gating Register)

CCM_CCGR0~CCM_CCGR6はクロックゲートレジスタのことで各モジュールのクロックを個別にON/OFFできる。
モジュールごとに2bit設けられてて設定値による効果は以下の画像の通り

f:id:gsmcustomeffects:20190228004604p:plain
Clock Activity Description

MIMXRT10xxの場合ペリフェラルが大量にあるので少し大変だがDCDでは全部ONにしているみたい。
except STOP modeとあるのでSTOPモード以外でクロックはONである。

CCM_ANALOG_PLL_SYS(Analog System PLL Control Register)

次にCCM_ANALOG_PLL_SYSの部分を見ていく

f:id:gsmcustomeffects:20190228020449p:plain
CCM_ANALOG_PLL_SYS
f:id:gsmcustomeffects:20190228020624p:plain
CCM_ANALOG_PLL_SYSn field descriptions

DCDtableにおけるセット値は0x00002001である。

ビットごとに分解してみていくと

BYPASSビットが0なのでPLLのバイパスはしないすなわちPLLを使用する設定。
BYPASS_CLK_SRCが00なので24MHzオシレータを使用する。
ENABLEが1なのでPLL出力が有効
DIV_SELECTが1なのでFout=Fref*22となる。

ここでCCM_ANALOG_PLL_SYS_NUMおよびDENOMというレジスタがあるがノーケアのためPOR(Power On Reset)初期値が使われFref * (22+(0/18))となり結局528MHzとなる。

この項で操作してるモジュールを示すとこんな感じ

f:id:gsmcustomeffects:20190301025840p:plain
CCM_ANALOG_PLL_SYS関連モジュール

CCM_ANALOG_PFD_528(528MHz Clock (PLL2) Phase Fractional Divider Control Register)

次にCCM_ANALOG_PFD_528を見ていく
PFDクロック生成のための設定をするレジスタで、fractional dividerの設定などができる。

bitごとの概要を以下の画像に示す。

f:id:gsmcustomeffects:20190301011808p:plain
CCM_ANALOG_PFD_528n register definition

PFDx_CLKGATEは1でOFF,0でON
PFDx_STABLEはread only bitで診断専用ビット。fractional dividerが有効になると値が反転する。
PFDx_FRACはfractional dividerの値

528*18/PFDx_FRAC where PFDx_FRAC is in the range 12-35.とあるので12~35の値を入れればいい

DCDtableにおけるセット値は0x001D0000であるためPFD2の部分をセットしてることになる。

field name[bit] set value description
PFD2_CLKGATE[23] 0b0 PFD2の有効
PFD2_STABLE[22] 0b0 read onlyのため関係ない
PFD2_FRAC[21-16] 0b011101 PFDx_FRAC =29

これで 528*18/29 = 327.72[MHz]となる。

CCM_CBCDR(CCM Bus Clock Divider Register)

最後にCCM Bus Clock Divider Registerについてである。
SEMCモジュールに一番近い部分のブロックでありクロックセレクトおよび分周器の設定が可能

f:id:gsmcustomeffects:20190301212223p:plain
CCM_CBCDR field descriptions


見たところ7種類ぐらい設定できるとこがある。
操作可能な部分を図で示すと以下の画像のようになる。

赤で示した部分がコア関連のクロック設定。
青で示す部分がSEMC関連。

f:id:gsmcustomeffects:20190301212508p:plain
CCM_CBCDRで操作可能なモジュール

DCD tableにおける設定値は0x00010D40となっている。

これもビットごとに分解して見ていこう

field name[bit] set value description
Reserved[31-30] 0b00 none
PERIPH_CLK2_PODF[29-27] 0b000 000なのでdivide by 1
Reserved[26] 0b0 none
PERIPH_CLK_SEL[25] 0b0 0なのでpre_periph_clk_selをセレクト
Reserved[24-19] 0b000000 none
SEMC_PODF[18-16] 0b001 001なのでdivide by 2
AHB_PODF[12-10] 0b011 011なのでdivide by 4
IPG_PODF[9-8] 0b01 01なのでdivide by 2
SEMC_ALT_CLK_SEL[7] 0b0 0なのでPLL2 PFD2がSEMC root clockとして使われる
SEMC_CLK_SEL[6] 0b1 1なのでSEMC alternative clock がSEMC clock root
Reserved[5-0] 0b000000 none

ここで上のほうは無視するとしてSEMCを見ていきます。
SEMC_ALT_CLK_SELでPLL2 PFD2、SEMC_CLK_SELでSEMC alternative clockとあるのでこのように選ばれます。

f:id:gsmcustomeffects:20190301230521p:plain
セレクターの動き

SEMC_PODFがdivide by 2なので327.72/2 = 163.86MHzとなる。
SEMCのスペックは166MHzなのでほぼ最大値でセットされるということがわかる。

f:id:gsmcustomeffects:20190301230336p:plain
SEMCのスペック

これでクロックの設定は終了。
冒頭にあるようにそのまま全容をつらつら書きましたがいかがでしたか?

正直起動関連部分なのでこういうのは公式が書いてほしいものですが
本記事で少しでも力になれれば幸いという感じです。

もちろんDCDは1000byte近くあるのでこの後にピン設定などが続きますので今後はそれを書いていこうと思います。

memo

クロックのPower modeには

  • RUN mode
  • WAIT mode
  • STOP mode

がある

詳細についてはリファレンスマニュアルのChapter 13 Clock Controller Module (CCM)を参照

ref

MIMXRT1050のリファレンスマニュアルの

  • Chapter 13 Clock Controller Module (CCM)
  • Chapter 23 External Memory Controllers
  • Chapter 24 Smart External Memory Controller

MIMXRT10xx series dcd table Tips part1

MIMXRT10xxシリーズは内部ROMを持たないわけで起動するのにひと手間かかる。

MIMXRT10xxにはIVT(image ventor table)なるものがあってそいつを設定してあげる必要がある。
そうすることで内部ROMのブートローダー(IMXRTの内蔵ブートローダーのこと)が値を解釈して起動およびそれに必要なペリフェラルの初期化をやってくれる。

f:id:gsmcustomeffects:20190224004034p:plain
Image Vector Table

主な設定はSDKが行ってくれるのだがいくつかはユーザーがケアしないといけない部分もある。
以下に示す2つがおおまかにユーザーケアが必要な部分である。(評価ボードを使う場合何もいじらなくていい

  • 外部フラッシュの初期化
  • 外部SDRAM制御用のSEMCコントローラレジスタセット

評価ボードにない外部フラッシュを使う場合オペレーションコマンドが互換の場合は容量のセットだけでよいが違う場合はフラッシュコンフィグをいじらないといけない。
フラッシュコンフィグに関しては以下の記事でも触れているしNXP Communityで同様な質問がいくつかあるのでそちらを参考にするといいだろう
gsmcustomeffects.hatenablog.com


同様にSDRAMもそうでチップによって容量も違えば動作条件も違う
SDRAMの場合はDCD(Device Configuration Data)テーブルをセットすることで起動時に必要なSEMCレジスタをセットする事が可能である。
SDRAMに関数を配置したり、SDRAM上に変数を配置したりする場合この機能を使うことで実現可能である。
そんなわけで今回はDCDに特化してTipsをまとめる。

DCD(Device Configuration Data )

Upon reset, the chip uses the default register values for all peripherals in the system.
However, these settings typically are not ideal for achieving the optimal system performance and there are even some peripherals that must be configured before they can be used.
The DCD is a configuration information contained in the program image (external to the ROM) that the ROM interprets to configure various peripherals on the chip.
For example, some components (such as SDRAM) require some sequence of register programming as a part of the configuration before it is ready to be used. The DCD featurecan be used to program the SEMC register to the optimal settings.

  • リセットされると、チップはシステム内のすべての周辺機器に対してデフォルトのレジスタ値を使用する。
  • 実際には初期レジスタ値の使用は最適ではない可能性がある。
  • SDRAMのようなコンポーネントでは一連の設定レジスタが必要である。
  • DCDはプログラムイメージ(ROMの外部)に含まれる構成情報である。

説明はこのぐらいにして実際のサンプルを見てみると

f:id:gsmcustomeffects:20190224010523p:plain
evkbimxrt1050_sdram_ini_dcd.cの一部

すげーわかりにくい

NXP本家もそういった設定ツール用意してないから自分用ってことで解釈の仕方をメモしておきます。

コマンドの種類

というわけでバイト列を解釈するためにコマンドの解説をします。
コマンドには

  • Write Command
  • Check Command
  • NOP Command

の3つがあります。

Write Command

格納はビッグエンディアンです。

f:id:gsmcustomeffects:20190224011035p:plain
Write command format

f:id:gsmcustomeffects:20190224011529p:plain
parameter format

f:id:gsmcustomeffects:20190224011623p:plain
flag format

  • TAG : 0xCC
  • length : 2byte(big endian)
  • parameter : 1byte(flag[7-3],byte[2-0])
  • Address : 4byte(registerのアドレス)
  • value : 書き込む値(or bitマスク)

flagだけ特殊で3bit目がMask、4bit目がSetを意味する。

Check Command

f:id:gsmcustomeffects:20190224011842p:plain
Check command format

f:id:gsmcustomeffects:20190224011913p:plain
parameter format

f:id:gsmcustomeffects:20190224011935p:plain
flag format

  • TAG : 0xCF
  • length : 2byte(big endian)
  • parameter : 1byte(flag[7-3],byte[2-0])
  • Address : 4byte(registerのアドレス)
  • Mask : bitマスク
  • count : オプションのカウント数

カウントが指定されていない場合、このコマンドは終了条件が満たされるまで無期限にポーリングします。 count = 0の場合、このコマンドはNOPと同じように動作します。

NOP Command

f:id:gsmcustomeffects:20190224012419p:plain
NOP Command format

  • TAG : 0xC0
  • length : 2byte(big endian 4に固定)
  • Undefined: 1byte なんでもいい

実際に読み進めていく

/*
 * Copyright 2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "evkbimxrt1050_sdram_ini_dcd.h"

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.xip_board"
#endif

#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)
#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__)
__attribute__((section(".boot_hdr.dcd_data")))
#elif defined(__ICCARM__)
#pragma location = ".boot_hdr.dcd_data"
#endif
/*************************************
 *  DCD Data
 *************************************/
const uint8_t dcd_data[] = {
    /*0000*/ DCD_TAG_HEADER,
    0x04,//length
    0x30,//length
    0x41,//version

    0xCC,//write command
    0x03,//length
    0xAC,//length -> 940byte
    0x04,//param
    0x40,//add[31-24]
    0x0F,//add[23-16]
    0xC0,//add[15-8]
    0x68,//add[7-0]     -> (0x400FC068) -> CCM Clock Gating Register 0 (CCM_CCGR0)
    0xFF,//レジスタの値もbig endianで格納
    0xFF,
    0xFF,
    0xFF,

    /*0010*/ 0x40,//add[31-24]
    0x0F,//add[23-16]
    0xC0,//add[15-8]
    0x6C,//add[7-0]      -> (0x400FC06C) -> CCM Clock Gating Register 1 (CCM_CCGR1)
    0xFF,
    0xFF,
    0xFF,
    0xFF,


//このあと900byteぐらい続くけどあとは略
};
#else
/*************************************
 *  DCD Data
 *************************************/
const uint8_t dcd_data[] = {0x00};
#endif /* XIP_BOOT_HEADER_DCD_ENABLE */
#endif /* XIP_BOOT_HEADER_ENABLE */

最初の4byteはDCDタグとdcdの全体のテーブル長さ、versionを表している

num data description
1 0xD2 DCD_TAG
2 0x04 length
3 0x30 length
4 0x41 version

lengthからdcd tableは0x430(1072bytes)の長さであるとわかる。

次が

num data description
1 0xCC write command
2 0x03 length
3 0xAC length
4 0x04 parameter
5 0x40 add[31-24]
6 0x0F add[23-16]
7 0xC0 add[15-8]
8 0x68 add[7-0]
9 0xFF value
10 0xFF value
11 0xFF value
12 0xFF value


コマンドはwrite command
長さは0x3AC(940bytes)
書き込みアドレスはCCM Clock Gating Register 0 (CCM_CCGR0)(0x400FC068)
であるとわかる。

リセット値が0xFFFFなのでそのままってことになる。

f:id:gsmcustomeffects:20190225210816p:plain
CCM_CCGR0
940bytesとあるので、あとは連続してaddress,valueが続いていく感じ。

見た感じクロックに関するレジスタを順繰りに設定していって最後の方でSEMCのレジスタいじってCheck Command を送っている感じ。
興味のある方がいたら例に従って見ていくといいだろう。

MCUXpressoIDE ライブラリ変更方法(ex. redlib->newlib)

library変更もProject setting項目からできる

f:id:gsmcustomeffects:20190223154025p:plain
libraryの変更

プロジェクトのsetting画面からもできる(プロジェクトを右クリック->propertyをクリック)

f:id:gsmcustomeffects:20190223154559p:plain

newlibを使うとmalloc関連もできる。

f:id:gsmcustomeffects:20190223154117p:plain
malloc.hの利用