こんにちは、
S32K314HMSカスタムボードで、16MHzの外部水晶発振器が動作しないという問題に直面しています。S32 Design Studioで作成したビルドを使っています。プラットフォームバージョン:3.6.9 ビルドID:260624。下記のmain.cで基板の機能をテストするために生コードを使っています。
#include
/* Corrected Raw Hardware Register Addresses for S32K314 */
#define SIUL2_MSCR_PTB5 (*(volatile uint32_t*)(0x40290294U))
#define MC_CGM_CLKOUT_CNTRL (*(volatile uint32_t*)(0x402D4000U))
/* --- CORRECTED FXOSC REAL ADDRESSES --- */
#define FXOSC_CTRL_REG (*(volatile uint32_t*)(0x40288000U)) /* Corrected from 402D4000 */
#define FXOSC_STAT_REG (*(volatile uint32_t*)(0x40288004U)) /* Corrected from 402D4004 */
volatile uint32_t rawTimeoutCounter = 0;
volatile uint32_t crystalStableResult = 0;
int main(void)
{
/* 1. RAW PIN SETUP: Configure PTB5 as a High-Drive Output mapped to CLKOUT */
SIUL2_MSCR_PTB5 = (5U << 0) | (1U << 21) | (1U << 19);
/* 2. RAW CLOCK ROUTING: Route the Raw FXOSC clock directly to the CLKOUT hardware block */
MC_CGM_CLKOUT_CNTRL = (1U << 24) | (0U << 16); /* Source = FXOSC_CLK, Divider = 1, Enable = 1 */
/* 3. RAW HARDWARE KICKSTART: Power on the External Crystal (FXOSC) analog circuitry */
FXOSC_CTRL_REG |= 0x01U;
/* 4. NON-BLOCKING SOFTWARE POLL
We read the raw hardware status register. If a crystal is physically
oscillating, the status register will flip a hardware bit or report a non-zero value. */
for (rawTimeoutCounter = 0; rawTimeoutCounter < 800000U; rawTimeoutCounter++)
{
/* Check if the FXOSC status register reports it is locked and stable (Bit 31) */
if ((FXOSC_STAT_REG & 0x80000000U) != 0U)
{
crystalStableResult = 1; /* HW SUCCESS: Crystal is alive and shaking! */
break;
}
}
/* 5. PASS / FAIL EVALUATION PADS */
if (crystalStableResult == 1)
{
/* --- CRYSTAL HARDWARE PASSED --- */
for (;;)
{
__asm("NOP"); /* Put a breakpoint here for success */
}
}
else
{
/* --- CRYSTAL HARDWARE FAILED --- */
for (;;)
{
__asm("NOP"); /* Put a breakpoint here for a safe failure catch */
}
}
return 0;
} 参考までに基板の回路図を添付いたします。
board_schematic.pngboard_schematic.pngboard_schematic.pngboard_schematic.pngboard_schematic.pngボードの概略図.png
.mexファイルも添付します参考までに設定内容を記載します。
こんにちは、 @sksingh4476 さん、
16 MHzのクリスタルはS32K3ファミリーのサポートFXOSCクリスタル周波数範囲内にあるため、クリスタル周波数自体が問題になることはありません。しかし、生のコードスニペットからは、完全なFXOSC構成が適用されているかどうかは明確ではありません。特に、FXOSCゲイン/相互コンダクタンス設定(GM_SEL)を確認してください。水晶発振モードでは、GM_SEL = 0000b を使用しないでください。これは相互コンダクタンスがゼロになることを意味し、発振器が起動しない、または安定しない可能性があります。
mexファイルについて:生成されたクロック初期化コードはアプリケーションによって呼び出されなければなりません。テストコードが生成されたRTD初期化をバイパスし、少数のレジスタのみを手動で書き込む場合、GM_SELを含むすべての必須FXOSC設定も手動で構成する必要があります。
まずは、標準的なS32DS/RTDのサンプルプロジェクトを作成し、クロック設定ツールを使用してFXOSCを設定することをお勧めします。生成されたRTDクロック初期化コードを使用して、外部水晶発振器が正しく起動するかどうかを確認してください。これは、最小限の生レジスタテストから直接始めるよりも優れたベースラインです。なぜなら、生成される構成には、発振器モードやゲイン構成など、必要なすべてのFXOSC設定が含まれるはずだからです。
標準的な例がうまくいけば、生成されたFXOSCレジスタの値と最小コードを比較し、徐々に最小の必要シーケンスにコードを減らすことができます。標準的な例でも動作しない場合は、次のステップはハードウェア側、特に結晶パラメータ、ESR、PCBの静電容量を含む負荷コンデンサ、EXTAL/XTAL周辺のレイアウト、そしてゲインマージン計算を確認することです。データシートでは、gmXOSC > 5 * gm_critを用いて発振器の構築条件を規定しているため、選択された結晶および外部部品はこの要件に照らして検証されるべきです。
よろしくお願いいたします。
パベル
こんにちは、 @sksingh4476 さん、
アップデート情報と両方の設定を共有していただきありがとうございます。
2つのコード例の間に重要な違いがあることに気づきました。最小限のテストでは Clock_Ip_Init() のみが呼び出されますが、実際のプロジェクトではその直後に Siul2_Port_Ip_Init() も呼び出されます。外部ピンのCLKOUT信号を観測してFXOSCが動作しているかどうかを判断する場合、対応するSIUL2ピンもCLKOUT代替機能用に構成する必要があります。Clock_Ip_Init() はクロックツリーを設定しますが、それ自体では物理的な出力ピンを設定するわけではありません。
よろしくお願いいたします。
パベル
こんにちは、PavelLさん。
迅速なご対応、ありがとうございました。
RTDの例コードを探しましたが、S32K314 MCU用のものは見つかりませんでした。
メイン関数内でクロック初期化関数を呼び出してみましたが、水晶発振器がまだ動作しません。
#include "Clock_Ip.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "Siul2_Port_Ip.h"
#define LED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define WELCOME_MSG_1 "hello world uart dma\r\n"
int counter, accumulator = 0, limit_value = 1000000;
void Led_Task( void *pvParameters )
{
(void)pvParameters;
for( ;; )
{
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
int main(void) {
Clock_Ip_StatusType Status_Init_Clock = CLOCK_IP_ERROR;
Status_Init_Clock = Clock_Ip_Init(Clock_Ip_aClockConfig);
if (Status_Init_Clock != CLOCK_IP_SUCCESS)
{
while(1); /* Error during initialization. */
}
xTaskCreate( Led_Task , ( const char * const ) "Led_Task", configMINIMAL_STACK_SIZE, (void*)0, LED_TASK_PRIORITY, NULL );
vTaskStartScheduler();
for( ;; );
return 0;
}
uint8_t Sys_GetCoreID(void)
{
return 0U; /* Force return Core 0 (Primary ARM Cortex-M7 Core) */
}FXOSC_CTRLの場合、GM_SELの値はデフォルト値の1100です。参考として、添付の時計設定画像をご参照ください。
clock_config.pngclock_config.pngclock_config.pngclock_config.png
参考資料として、時計の設定ファイルclockYamlを添付いたします。
別のオープンソースプロジェクトが同じ基板上で結晶を動作させることが可能であることに気づきました。main.cで使用されているコードは以下のとおりです。ファイル。クロック構成が我々のものとほぼ同じであることを確認した。参考までに、時計の設定ファイルを添付しました。
/* Including necessary configuration files. */
#include "Clock_Ip.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "Siul2_Port_Ip.h"
#include "Siul2_Dio_Ip.h"
//including uart+dma+interrupt files
#include "Lpuart_Uart_Ip.h"
#include "Lpuart_Uart_Ip_Irq.h"
#include "string.h"
#include "IntCtrl_Ip.h"
#include "lpuart0.h"
#include "Dma_Ip.h"
#include "Dma_Ip_Irq.h"
#include "CDD_Rm.h"
#define LED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define WELCOME_MSG_1 "hello world uart dma\r\n"
void Led_Task( void *pvParameters )
{
(void)pvParameters;
for( ;; )
{
Lpuart_Uart_Ip_SyncSend(LPUART_UART_IP_INSTANCE_USING_0, (const uint8 *)WELCOME_MSG_1, 20, 0XFFFF);
Siul2_Dio_Ip_TogglePins(USER_LED0_PORT, (1 << USER_LED0_PIN));
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
int main(void)
{
/* Initialize Clock */
Clock_Ip_StatusType Status_Init_Clock = CLOCK_IP_ERROR;
Status_Init_Clock = Clock_Ip_Init(Clock_Ip_aClockConfig);
if (Status_Init_Clock != CLOCK_IP_SUCCESS)
{
while(1); /* Error during initialization. */
}
/* Initialize all pins using the Port driver */
Siul2_Port_Ip_PortStatusType Status_Init_Port = SIUL2_PORT_ERROR;
Status_Init_Port = Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);
if(Status_Init_Port != SIUL2_PORT_SUCCESS)
{
while(1); /* Error during initialization. */
}
//Init Interrupt Control
IntCtrl_Ip_Init(&IntCtrlConfig_0);
//Init lpuart0
Lpuart_Uart_Ip_Init(LPUART_UART_IP_INSTANCE_USING_0, &Lpuart_Uart_Ip_xHwConfigPB_0);
//DMA init
Dma_Ip_Init(&Dma_Ip_Sa_xDmaInitPB);
/* Initialize Rm driver for using DmaMux*/
Rm_Init(&Rm_Config);
//turn of AsyncReceive of uart dma, this code must behind Rm_Init(&Rm_Config);
Lpuart_Uart_Ip_AsyncReceive(LPUART_UART_IP_INSTANCE_USING_0, Lpuart0_Receive_Buffer, LPUART0_RECV_BUF_LEN);
xTaskCreate( Led_Task , ( const char * const ) "Led_Task", configMINIMAL_STACK_SIZE, (void*)0, LED_TASK_PRIORITY, NULL );
vTaskStartScheduler();
for( ;; );
return 0;
}どのクロック構成がこの違いを生むのか気になっています。
ありがとうございます
スニル
こんにちは、PavelLさん。
ご返信ありがとうございます。
あなたの指摘のおかげで、Siul_port_dioモジュールをプロジェクトに追加してみようという方向性が見えてきました。このポートを追加して初期化すると、クロックが動作するようになるようです。しかし、なぜこれが違いを生むのか、私にはまだ理解できません。
私たちはオシロスコープを使って水晶発振器の周波数を直接測定しています。また、クロックの初期化中にデバッガーが停止してしまうことも確認しました。
ありがとうございます
スニル
こんにちは、 @sksingh4476 さん、
SIUL2ポートの初期化は、選択したCLKOUT信号をMCUクロック出力から物理ピンにルーティングするために必要です。Clock_Ip_Init() はクロックソース、マルチプレクサ、分周器を設定しますが、ピンマルチプレクサは設定しません。したがって、ピン上のCLKOUT信号を評価する前に、Siul2_Port_Ip_Init()を呼び出す必要があります。
デバッガーの問題に関してですが、最初のテストでは Clock_Ip_Init() をステップ実行することは避けてください。関数の直前と直後にそれぞれブレークポイントを設定し、その間を走行します。2番目のブレークポイントに到達しない場合は、デバッガーを一時停止し、現在のプログラムカウンタとコールスタックを確認して、コードがクロックタイムアウトループ内で待機しているか、ハードフォルトハンドラに入ったか、またはデバイスがリセットされたかを判断してください。また、ブレークポイントなしでアプリケーションを実行しても同じ動作が起こるかどうかも確認してください。
よろしくお願いいたします。
パベル