Hello everyone,
I am working with the S32K396 board and trying to enable the FIRC clock using low-level programming. However, I have found that there is limited information available, and I haven't had much success.
My goal is to enable this clock using the MC_ME and MC_CGM modules, but I haven't been able to make it work properly. I have been referring to the Reference Manual, and while I selected a suitable MUX, I'm not sure if the registers I’m using are correct.
Has anyone worked with low-level programming on the S32K396?
I’ve attached my main code for review. My plan is to first enable the FIRC clock and then proceed with configuring the PLL and FXOSC.
#include <stdint.h>
#include <stdio.h>
#define PORT_WRITE32(address, value) (*(volatile uint32_t *)(address) = (value))
#define PORT_WRITE8(address, value) (*(volatile uint8_t *)(address) = (value))
#define PORT_READ32(address) (*(volatile uint32_t *)(address))
// Base addresses for the registers (these should be adjusted based on your MCU documentation)
#define MC_CGM_BASE 0x402D8000U // Base address of the Clock Generation Module (MC_CGM)
#define MC_ME_BASE 0x402DC000U // Base address of the Clock Management Module (MC_ME)
#define SIUL2_BASE 0x40290000U // Base address of the SIUL2 for GPIO
// Registers of the MC_CGM (Clock Generation Module)
#define MC_CGM_MUX_6_CSC (MC_CGM_BASE + 0x480U)
#define MC_CGM_MUX_6_CSS (MC_CGM_BASE + 0x484U)
#define MC_CGM_MUX_6_DC_0 (MC_CGM_BASE + 0x488U)
// Registers of the MC_ME (Clock Management Module)
#define MC_ME_PRTN0_COFB1_CLKEN (MC_ME_BASE + 0x134U) //0x402DC134
#define MC_ME_PRTN0_PUPD (MC_ME_BASE + 0x104U) //0x402DC104
#define MC_ME_CTL_KEY (MC_ME_BASE + 0x000U) //0x402DC000
#define MC_ME_PRTN0_STAT (MC_ME_BASE + 0x108U) //0x402DC108
#define MC_ME_GS (MC_ME_BASE + 0x008U) //0x402DC008
#define MC_ME_PRTN0_PCONF (MC_ME_BASE + 0x100U) //0x402DC100
#define MC_ME_PRTN0_COFB1_STAT (MC_ME_BASE + 0x114U) //0x402DC114
#define MC_ME_KEY 0x5AF0U
#define MC_ME_INVKEY 0xA50FU
// Registers of the SIUL2 (GPIO Control)
#define SIUL2_MSCR231 0x402905DC
#define SIUL2_GPDO231 0x402913E4
#define asm __asm__
// Initialize the clock using direct register access
void CLOCK_InitFIRC(void)
{
// Enable FIRC
uint32_t temp;
temp = PORT_READ32(MC_ME_PRTN0_COFB1_STAT); // Read current status
if ((temp & (1 << 5)) == 0) {
PORT_WRITE32(MC_ME_PRTN0_COFB1_CLKEN, (1 << 1)); // Enable FIRC
PORT_WRITE32(MC_ME_PRTN0_PCONF, (1 << 0)); // Enable FIRC
PORT_WRITE32(MC_ME_PRTN0_PUPD, (1 << 1)); // Enable update
PORT_WRITE32(MC_ME_CTL_KEY, MC_ME_KEY); // Unlock control register
PORT_WRITE32(MC_ME_CTL_KEY, ~MC_ME_KEY); // Lock control register
}
// Wait for FIRC stabilization
do {
temp = PORT_READ32(MC_CGM_MUX_6_CSS); // Read the current clock source selection
} while ((temp & 0x0F) != 0x0); // Check if FIRC is selected (FIRC should have 0x0)
// Configure MUX6 to use FIRC as the clock source
PORT_WRITE32(MC_CGM_MUX_6_CSC, 0x0); // Select FIRC as clock source for MUX6
PORT_WRITE32(MC_CGM_MUX_6_DC_0, 0x0); // Set divisor to 1 (no division)
// Check the status of the clock
uint32_t status_clk = PORT_READ32(MC_CGM_MUX_6_CSS); // Read current clock status
}
int main(void)
{
// Initialize the clock
CLOCK_InitFIRC();
// Initialize the GPIO for the LED
PORT_WRITE32(SIUL2_MSCR231, 0x200000);
while(1)
{
PORT_WRITE8(SIUL2_GPDO231, 0x1);
for(uint32_t i = 0; i < 20e6; i++)
{
asm("nop");
}
PORT_WRITE8(SIUL2_GPDO231, 0x0);
for(uint32_t i = 0; i < 20e6; i++)
{
asm("nop");
}
}
return 0;
}
Any help or suggestions would be greatly appreciated.
Thank you in advance!