MCXN947 DLLの自動調整機能が動作しません こんにちは、 私はFlexSPI経由でMCXN947とOctalRAM(IS66WVO32M8DALL-200BLI)を使用しています。 FlexSPIのルートクロックはPLL1を介して150MHzで供給され、RAMはDDRモードで動作するため、出力クロックレートは75MHzになります。 `flexspi_device_config_t`には以下のパラメータがあります。 flexspi_device_config_t psram_config =
{
.flexspiRootClk = 150000000U,
.isSck2Enabled = false,
.flashSize = OCTALRAM_ISSI_SIZE,
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
.CSInterval = 2,
.CSHoldTime = 2,
.CSSetupTime = 2,
.dataValidTime = 2,
.columnspace = 4,
.enableWordAddress = false,
.AWRSeqIndex = HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA,
.AWRSeqNumber = 1,
.ARDSeqIndex = HYPERRAM_CMD_LUT_SEQ_IDX_READDATA,
.ARDSeqNumber = 1,
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
.AHBWriteWaitInterval = 0,
.enableWriteMask = true,
}; FlexSpiの初期化には、SDK FLEXSPI_DRIVERバージョン2.6.0を使用しています。 自動調整機能(マニュアル10.3.15.6節「サンプリングのためのDLL構成」)でディレイセルを以下の値で設定すると、 • SLVDLYTARGET=0x0F(分算器16/32 * root_clock = 3.33 ns) • REFPHASEGAP=0x02 • DLLEN=0x01 • OVRDEN=0x01 ASLVLOCKとAREFLOCKのロックビットを待った後、ASLVSELには0x01、AREFSELには0x00が返されました。その結果、設定された遅延時間が約120psであるため、RAMの読み書き機能は動作しません。 /* Configure DLL. */
configValue = FLEXSPI_CalculateDll(base, config);
base->DLLCR[index] = configValue;
/* DLL neu kalibrieren */
base->DLLCR[0] |= FLEXSPI_DLLCR_DLLRESET_MASK;
base->DLLCR[0] &= ~FLEXSPI_DLLCR_DLLRESET_MASK;
/* Exit stop mode. */
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
/* Lock abwarten */
while ((base->STS2 &
(FLEXSPI_STS2_AREFLOCK_MASK |
FLEXSPI_STS2_ASLVLOCK_MASK)) !=
(FLEXSPI_STS2_AREFLOCK_MASK |
FLEXSPI_STS2_ASLVLOCK_MASK))
{
}
SDK_DelayAtLeastUs(10U, CLOCK_GetCoreSysClkFreq()); SLVDLYTARGETに異なる値を使用しても、ASLVLOCKとAREFLOCKの出力は変わりません。 しかし、レジスタOVRDEN=0x01とOVRDVAL=0x1bを使用して遅延時間を固定値(約3.36ナノ秒の遅延時間に相当)に設定すると、RAMからの読み書きは問題なく動作します。 しかし、ルートクロックが100 MHzを超えるため、NXPはDLLの自動調整機能の使用を推奨しています。 残念ながら、正しい遅延時間を判断できないようです! 通信・制御(I3C |I2C |SPI |FlexCAN |イーサネット |FlexIO) コアとメモリ MCX N Re: MCXN947 DLL auto-adjusted function not working こんにちは、 @IbhDanielさん
投稿ありがとうございます!
MCXNx4リファレンスマニュアルによると、シリアルルートクロックはFlexSPIコアクロックであることが示されています(表79参照)。時計の使用状況)。あなたの場合、このクロックは150 MHzに設定されています。
また、DLLサンプリング構成を実装しており、自動キャリブレーションパスが正しいアプローチのようです。設定値SLVDLYTARGET = 0x0FおよびDLLEN = 0x01は正しく構成されています。唯一特定された問題は、OVRDENが0x00ではなく0x01であり、これにより自動キャリブレーション出力経路が無効化され、SLVDLYTARGET値に関係なくASLVSEL=0x01、AREFSEL=0x00となります。
上記の分析結果が貴社の実装にも当てはまるかどうか確認させてください。以下を確認してください:MCR0[RXCLKSRC] = 3h(フラッシュメモリ提供の読み取りストロボとDQSパッドからの入力)があなたの構成で使用されているか?
Re: MCXN947 DLL auto-adjusted function not working こんにちは、カルロスさん。 ご返信ありがとうございます。 すみません、誤字で、OVRDENビットを0に設定しました。MCUレジスタのスクリーンショットを見ると、OVRDENが値0に設定されているのもわかります。 私はOctalRam IS66WVO32M8DALL-200BLIを使っています。もし理解が正しければ、このモジュールはDQS信号をMCUに送っているようです。 Re: MCXN947 DLL auto-adjusted function not working 再度確認したところ、MCUのMCR0[RXCLKSRC]ビットは3時間に設定されています。 Re: MCXN947 DLL auto-adjusted function not working こんにちは、 @IbhDaniel さん。
あなたの構成でMCR0[RXCLKSRC] = 3h(DQSパッドからのフラッシュメモリ提供の読み取りストロボ入力)が使われているか確認していただけますか?
この点は重要です。なぜなら、自動調整・キャリブレーションはDQS信号が外部DQSパッドから送信される場合にのみサポートされるからです。RXCLKSRCの設定が異なると、自動遅延調整機構は期待どおりに動作しません。
Re: MCXN947 DLL auto-adjusted function not working こんにちは、 @IbhDanielさん
確認ありがとうございます。社内チームと検討いたします。これには時間がかかる場合があります。ご理解とご協力に感謝いたします。 それまでの間は、手動キャリブレーションで見つけた回避策をご利用ください。 ご迷惑をおかけして申し訳ございません。 Re: MCXN947 DLL auto-adjusted function not working こんにちは@IbhDaniel。 flexspi_config_tを教えていただけますか? これは、あなたが直面している現象を再現するためのものです。 また、UpdateDllValue と FLEXSPI_SetFlashConfig() の後に SDK_DelayAtLeastUs を 10us 追加してみてください。
BR Re: MCXN947 DLL auto-adjusted function not working こんにちは、カルロスさん。 `flexspi_config_t`構造体で使用するパラメータに関する情報は以下のとおりです。
flexspi_config_t config;
/* Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;
/*Set AHB buffer size for reading data through AHB bus. */
config.ahbConfig.enableAHBPrefetch = true;
config.ahbConfig.enableAHBBufferable = true;
config.ahbConfig.enableAHBCachable = true;
config.ahbConfig.enableReadAddressOpt = true;
for (uint8_t i = 1; i < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1; i++)
{
config.ahbConfig.buffer[i].bufferSize = 0;
}
config.ahbConfig.buffer[0].masterIndex = 4; /* DMA0 */
config.ahbConfig.buffer[0].bufferSize = 512; /* Allocate 512B bytes for DMA0 */
config.ahbConfig.buffer[0].enablePrefetch = true;
config.ahbConfig.buffer[0].priority = 0;
/* All other masters use last buffer with 512B bytes. */
config.ahbConfig.buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 1].bufferSize = 512;
#if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
config.enableCombination = true;
#endif
FLEXSPI_Init(BUNNY_FLEXSPI, &config); 以下は、「SDK_DelayAtLeastUs」関数と「FLEXSPI_SetFlashConfig」関数のコードです。 SDK_DelayAtLeastUs(10U, CLOCK_GetCoreSysClkFreq());
/*!
* @brief Delay at least for some time.
* Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
* effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
* coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
* up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
*
* @Param delayTime_us Delay time in unit of microsecond.
* @Param coreClock_Hz Core clock frequency with Hz.
*/
void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
{
uint64_t count;
if (delayTime_us > 0U)
{
count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
assert(count <= UINT32_MAX);
#if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
MSDK_EnableCpuCycleCounter();
/* Calculate the count ticks. */
count += MSDK_GetCpuCycleCount();
if (count > UINT32_MAX)
{
count -= UINT32_MAX;
/* Wait for cyccnt overflow. */
while (count < MSDK_GetCpuCycleCount())
{
}
}
/* Wait for cyccnt reach count value. */
while (count > MSDK_GetCpuCycleCount())
{
}
#else
/* Divide value may be different in various environment to ensure delay is precise.
* Every loop count includes three instructions, due to Cortex-M7 sometimes executes
* two instructions in one period, through test here set divide 1.5. Other M cores use
* divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
* not matter because other instructions outside while loop is enough to fill the time.
*/
#if (__CORTEX_M == 7)
count = count / 3U * 2U;
#else
count = count / 4U;
#endif
DelayLoop((uint32_t)count);
#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
}
}
/*!
* brief Configures the connected device parameter.
*
* This function configures the connected device relevant parameters, such as the size, command, and so on.
* The flash configuration value cannot have a default value. The user needs to configure it according to the
* connected device.
*
* param base FLEXSPI peripheral base address.
* param config Flash configuration parameters.
* param port FLEXSPI Operation port.
*/
void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
{
uint32_t configValue = 0;
uint8_t index = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
/* Wait for bus to be idle before changing flash configuration. */
while (!FLEXSPI_GetBusIdleStatus(base))
{
}
/* Configure flash size and address shift. */
#if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT)
base->FLSHCR0[port] = config->flashSize | FLEXSPI_FLSHCR0_ADDRSHIFT(config->addressShift);
#else
base->FLSHCR0[port] = config->flashSize;
#endif /* FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT */
/* Configure flash parameters. */
base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
/* Configure AHB operation items. */
configValue = base->FLSHCR2[port];
configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_ARDSEQID_MASK);
configValue |=
FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
if (config->AWRSeqNumber > 0U)
{
configValue |= FLEXSPI_FLSHCR2_AWRSEQID((uint32_t)config->AWRSeqIndex) |
FLEXSPI_FLSHCR2_AWRSEQNUM((uint32_t)config->AWRSeqNumber - 1U);
}
if (config->ARDSeqNumber > 0U)
{
configValue |= FLEXSPI_FLSHCR2_ARDSEQID((uint32_t)config->ARDSeqIndex) |
FLEXSPI_FLSHCR2_ARDSEQNUM((uint32_t)config->ARDSeqNumber - 1U);
}
base->FLSHCR2[port] = configValue;
/* Configure DLL. */
FLEXSPI_UpdateDllValue(base, config, port);
/* Step into stop mode. */
base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
/* Configure write mask. */
if (config->enableWriteMask)
{
base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
}
else
{
base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
}
if (index == 0U) /*PortA*/
{
base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
}
#if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB)) && (FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB))
else
{
base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
}
#endif
/* Exit stop mode. */
base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
/* Wait for bus to be idle before use it access to external flash. */
while (!FLEXSPI_GetBusIdleStatus(base))
{
}
} サポートいただき、本当にありがとうございます! よろしくお願いいたします。 ダニエル
查看全文