がれすたさんのDIY日記

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

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 を送っている感じ。
興味のある方がいたら例に従って見ていくといいだろう。