Dear All, I'm experiencing a strange problem that is for sure due to a wrong clock configuration but I'm struggling to solve it. Basically I have a board with a KE16F256 and a 24MHz Crystal. Everything was fine untill I started working with the flash (I'm writing a bootloader). So I decided to follow the provided sample fro program flash access.
The problem is that if I try to run the FLASH_Init function before configuring the clock the flash init function returns kStatus_FLASH_Success but if I call the FLASH_Init after (as it is supposed to be) the BOARD_InitBootClocks function generated by the MCUXpresso clock configuration tool the flash cannot be initializated correctly. I attached the screenshot oh the clock configuration. The following is my clock_config.c file:
/*
* How to setup clock using clock driver functions:
*
* 1. Call CLOCK_InitXXX() to configure corresponding SCG clock source.
* Note: The clock could not be set when it is being used as system clock.
* In default out of reset, the CPU is clocked from FIRC(IRC48M),
* so before setting FIRC, change to use another avaliable clock source.
*
* 2. Call CLOCK_SetXtal0Freq() to set XTAL0 frequency based on board settings.
*
* 3. Call CLOCK_SetXxxModeSysClkConfig() to set SCG mode for Xxx run mode.
* Wait until the system clock source is changed to target source.
*
* 4. If power mode change is needed, call SMC_SetPowerModeProtection() to allow
* corresponding power mode and SMC_SetPowerModeXxx() to change to Xxx mode.
* Supported run mode and clock restrictions could be found in Reference Manual.
*/
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
product: Clocks v3.0
processor: MKE16F256xxx16
package_id: MKE16F256VLH16
mcu_data: ksdk2_0
processor_version: 2.0.0
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
#include "fsl_smc.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define SIM_CHIPCTL_CAN_FLT_CLKSEL_SIRC 1U /*!< CAN filter clock select: SIRC clock */
/*******************************************************************************
* Variables
******************************************************************************/
/* System clock frequency. */
extern uint32_t SystemCoreClock;
/*******************************************************************************
* Code
******************************************************************************/
/*FUNCTION**********************************************************************
*
* Function Name : CLOCK_CONFIG_SetCanFltClock
* Description : Set the FlexCAN filter clock.
* Param src : The selected clock source.
*
*END**************************************************************************/
static void CLOCK_CONFIG_SetCanFltClock(uint8_t src)
{
SIM->CHIPCTL = ((SIM->CHIPCTL & ~SIM_CHIPCTL_CAN_FLT_CLK_SEL_MASK) | SIM_CHIPCTL_CAN_FLT_CLK_SEL(src));
}
/*FUNCTION**********************************************************************
*
* Function Name : CLOCK_CONFIG_FircSafeConfig
* Description : This function is used to safely configure FIRC clock.
* In default out of reset, the CPU is clocked from FIRC(IRC48M).
* Before setting FIRC, change to use SIRC as system clock,
* then configure FIRC. After FIRC is set, change back to use FIRC
* in case SIRC need to be configured.
* Param fircConfig : FIRC configuration.
*
*END**************************************************************************/
static void CLOCK_CONFIG_FircSafeConfig(const scg_firc_config_t *fircConfig)
{
scg_sys_clk_config_t curConfig;
const scg_sirc_config_t scgSircConfig = {.enableMode = kSCG_SircEnable,
.div1 = kSCG_AsyncClkDisable,
.div2 = kSCG_AsyncClkDivBy2,
.range = kSCG_SircRangeHigh};
scg_sys_clk_config_t sysClkSafeConfigSource = {
.divSlow = kSCG_SysClkDivBy4, /* Slow clock divider */
.divBus = kSCG_SysClkDivBy1, /* Bus clock divider */
.divCore = kSCG_SysClkDivBy1, /* Core clock divider */
.src = kSCG_SysClkSrcSirc /* System clock source */
};
/* Init Sirc. */
CLOCK_InitSirc(&scgSircConfig);
/* Change to use SIRC as system clock source to prepare to change FIRCCFG register. */
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
/* Wait for clock source switch finished. */
do
{
CLOCK_GetCurSysClkConfig(&curConfig);
} while (curConfig.src != sysClkSafeConfigSource.src);
/* Init Firc. */
CLOCK_InitFirc(fircConfig);
/* Change back to use FIRC as system clock source in order to configure SIRC if needed. */
sysClkSafeConfigSource.src = kSCG_SysClkSrcFirc;
CLOCK_SetRunModeSysClkConfig(&sysClkSafeConfigSource);
/* Wait for clock source switch finished. */
do
{
CLOCK_GetCurSysClkConfig(&curConfig);
} while (curConfig.src != sysClkSafeConfigSource.src);
}
/*******************************************************************************
************************ BOARD_InitBootClocks function ************************
******************************************************************************/
void BOARD_InitBootClocks(void)
{
ClocksConfig();
}
/*******************************************************************************
************************* Configuration ClocksConfig **************************
******************************************************************************/
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!Configuration
name: ClocksConfig
called_from_default_init: true
outputs:
- {id: Bus_clock.outFreq, value: 75 MHz}
- {id: CANFLTCLKIN.outFreq, value: 8 MHz, locked: true, accuracy: '0.001'}
- {id: Core_clock.outFreq, value: 150 MHz}
- {id: Flash_clock.outFreq, value: 18.75 MHz}
- {id: LPO1KCLK.outFreq, value: 1 kHz}
- {id: LPO_clock.outFreq, value: 128 kHz}
- {id: PCC.PCC_ADC0_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_FTM0_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_FTM1_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_FTM2_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_LPSPI0_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_LPSPI1_CLK.outFreq, value: 150 MHz}
- {id: PCC.PCC_LPUART0_CLK.outFreq, value: 24 MHz}
- {id: PCC.PCC_LPUART1_CLK.outFreq, value: 24 MHz}
- {id: PCC.PCC_LPUART2_CLK.outFreq, value: 24 MHz}
- {id: PLLDIV1_CLK.outFreq, value: 150 MHz}
- {id: PLLDIV2_CLK.outFreq, value: 150 MHz}
- {id: SIRC_CLK.outFreq, value: 8 MHz}
- {id: SOSCDIV1_CLK.outFreq, value: 24 MHz}
- {id: SOSCDIV2_CLK.outFreq, value: 24 MHz}
- {id: SOSC_CLK.outFreq, value: 24 MHz}
- {id: System_clock.outFreq, value: 150 MHz}
settings:
- {id: SCGMode, value: SPLL}
- {id: powerMode, value: HSRUN}
- {id: CANClkConfig, value: 'yes'}
- {id: PCC.PCC_ADC0_SEL.sel, value: SCG.PLLDIV2_CLK}
- {id: PCC.PCC_FTM0_SEL.sel, value: SCG.PLLDIV1_CLK}
- {id: PCC.PCC_FTM1_SEL.sel, value: SCG.PLLDIV1_CLK}
- {id: PCC.PCC_FTM2_SEL.sel, value: SCG.PLLDIV1_CLK}
- {id: PCC.PCC_LPSPI0_SEL.sel, value: SCG.PLLDIV2_CLK}
- {id: PCC.PCC_LPSPI1_SEL.sel, value: SCG.PLLDIV2_CLK}
- {id: PCC.PCC_LPUART0_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: PCC.PCC_LPUART1_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: PCC.PCC_LPUART2_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: SCG.CLKOUTSEL.sel, value: SCG.SOSC}
- {id: SCG.DIVBUS.scale, value: '2', locked: true}
- {id: SCG.DIVCORE.scale, value: '1', locked: true}
- {id: SCG.DIVSLOW.scale, value: '8', locked: true}
- {id: SCG.FIRC_TRIMDIV.scale, value: '1', locked: true}
- {id: SCG.PREDIV.scale, value: '2', locked: true}
- {id: SCG.SCSSEL.sel, value: SCG.SPLL_DIV2_CLK}
- {id: SCG.SOSCDIV1.scale, value: '1', locked: true}
- {id: SCG.SOSCDIV2.scale, value: '1', locked: true}
- {id: SCG.SPLLDIV1.scale, value: '1'}
- {id: SCG.SPLLDIV2.scale, value: '1', locked: true}
- {id: SCG.SPLL_mul.scale, value: '25', locked: true}
- {id: 'SCG::RCCR[DIVBUS].bitField', value: Divide-by-2}
- {id: 'SCG::RCCR[DIVSLOW].bitField', value: Divide-by-8}
- {id: 'SCG::RCCR[SCS].bitField', value: System PLL (SPLL_CLK)}
- {id: SCG_SIRCCSR_SIRCSTEN_CFG, value: Enabled}
- {id: SCG_SOSCCFG_OSC_MODE_CFG, value: ModeOscLowPower}
- {id: SCG_SOSCCFG_RANGE_CFG, value: High}
- {id: SCG_SOSCCSR_SOSCEN_CFG, value: Enabled}
- {id: SCG_SOSCCSR_SOSCLPEN_CFG, value: Enabled}
- {id: SCG_SOSCCSR_SOSCSTEN_CFG, value: Enabled}
- {id: SCG_SPLLCSR_SPLLEN_CFG, value: Enabled}
- {id: SIM.CANFLTCLKSEL.sel, value: SCG.SIRC_CLK}
- {id: SIM.CLKOUTDIV.scale, value: '2', locked: true}
- {id: SIM.CLKOUTSEL.sel, value: PMC.LPO_CLK}
sources:
- {id: SCG.SOSC.outFreq, value: 24 MHz, enabled: true}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/*******************************************************************************
* Variables for ClocksConfig configuration
******************************************************************************/
const scg_sys_clk_config_t g_sysClkConfig_ClocksConfig =
{
.divSlow = kSCG_SysClkDivBy8, /* Slow Clock Divider: divided by 8 */
.divBus = kSCG_SysClkDivBy2, /* Bus Clock Divider: divided by 2 */
.divCore = kSCG_SysClkDivBy1, /* Core Clock Divider: divided by 1 */
.src = kSCG_SysClkSrcSysPll, /* System PLL is selected as System Clock Source */
};
const scg_sosc_config_t g_scgSysOscConfig_ClocksConfig =
{
.freq = 24000000U, /* System Oscillator frequency: 24000000Hz */
.enableMode = kSCG_SysOscEnable | kSCG_SysOscEnableInStop | kSCG_SysOscEnableInLowPower,/* Enable System OSC clock, Enable System OSC in stop mode, Enable System OSC in low power mode */
.monitorMode = kSCG_SysOscMonitorDisable, /* Monitor disabled */
.div1 = kSCG_AsyncClkDivBy1, /* System OSC Clock Divider 1: divided by 1 */
.div2 = kSCG_AsyncClkDivBy1, /* System OSC Clock Divider 2: divided by 1 */
.workMode = kSCG_SysOscModeOscLowPower, /* Oscillator low power */
};
const scg_sirc_config_t g_scgSircConfig_ClocksConfig =
{
.enableMode = kSCG_SircEnable | kSCG_SircEnableInStop | kSCG_SircEnableInLowPower,/* Enable SIRC clock, Enable SIRC in stop mode, Enable SIRC in low power mode */
.div1 = kSCG_AsyncClkDisable, /* Slow IRC Clock Divider 1: Clock output is disabled */
.div2 = kSCG_AsyncClkDisable, /* Slow IRC Clock Divider 2: Clock output is disabled */
.range = kSCG_SircRangeHigh, /* Slow IRC high range clock (8 MHz) */
};
const scg_firc_config_t g_scgFircConfig_ClocksConfig =
{
.enableMode = kSCG_FircEnable, /* Enable FIRC clock */
.div1 = kSCG_AsyncClkDisable, /* Fast IRC Clock Divider 1: Clock output is disabled */
.div2 = kSCG_AsyncClkDisable, /* Fast IRC Clock Divider 2: Clock output is disabled */
.range = kSCG_FircRange48M, /* Fast IRC is trimmed to 48MHz */
.trimConfig = NULL, /* Fast IRC Trim disabled */
};
const scg_spll_config_t g_scgSysPllConfig_ClocksConfig =
{
.enableMode = kSCG_SysPllEnable, /* Enable SPLL clock */
.monitorMode = kSCG_SysPllMonitorDisable, /* Monitor disabled */
.div1 = kSCG_AsyncClkDivBy1, /* System PLL Clock Divider 1: divided by 1 */
.div2 = kSCG_AsyncClkDivBy1, /* System PLL Clock Divider 2: divided by 1 */
.src = kSCG_SysPllSrcSysOsc, /* System PLL clock source is System OSC */
.prediv = 1, /* Divided by 2 */
.mult = 9, /* Multiply Factor is 25 */
};
/*******************************************************************************
* Code for ClocksConfig configuration
******************************************************************************/
void ClocksConfig(void)
{
scg_sys_clk_config_t curConfig;
/* Init SOSC according to board configuration. */
CLOCK_InitSysOsc(&g_scgSysOscConfig_ClocksConfig);
/* Set the XTAL0 frequency based on board settings. */
CLOCK_SetXtal0Freq(g_scgSysOscConfig_ClocksConfig.freq);
/* Init FIRC. */
CLOCK_CONFIG_FircSafeConfig(&g_scgFircConfig_ClocksConfig);
/* Set HSRUN power mode. */
SMC_SetPowerModeProtection(SMC, kSMC_AllowPowerModeAll);
SMC_SetPowerModeHsrun(SMC);
while (SMC_GetPowerModeState(SMC) != kSMC_PowerStateHsrun)
{
}
/* Init SIRC. */
CLOCK_InitSirc(&g_scgSircConfig_ClocksConfig);
/* Init SysPll. */
CLOCK_InitSysPll(&g_scgSysPllConfig_ClocksConfig);
/* Set SCG to SPLL mode. */
CLOCK_SetHsrunModeSysClkConfig(&g_sysClkConfig_ClocksConfig);
/* Wait for clock source switch finished. */
do
{
CLOCK_GetCurSysClkConfig(&curConfig);
} while (curConfig.src != g_sysClkConfig_ClocksConfig.src);
/* Set SystemCoreClock variable. */
SystemCoreClock = CLOCKSCONFIG_CORE_CLOCK;
/* Set CAN filter clock source. */
CLOCK_CONFIG_SetCanFltClock(SIM_CHIPCTL_CAN_FLT_CLKSEL_SIRC);
/* Set PCC ADC0 selection */
CLOCK_SetIpSrc(kCLOCK_Adc0, kCLOCK_IpSrcSysPllAsync);
/* Set PCC LPSPI0 selection */
CLOCK_SetIpSrc(kCLOCK_Lpspi0, kCLOCK_IpSrcSysPllAsync);
/* Set PCC LPSPI1 selection */
CLOCK_SetIpSrc(kCLOCK_Lpspi1, kCLOCK_IpSrcSysPllAsync);
/* Set PCC LPUART0 selection */
CLOCK_SetIpSrc(kCLOCK_Lpuart0, kCLOCK_IpSrcSysOscAsync);
/* Set PCC LPUART1 selection */
CLOCK_SetIpSrc(kCLOCK_Lpuart1, kCLOCK_IpSrcSysOscAsync);
/* Set PCC LPUART2 selection */
CLOCK_SetIpSrc(kCLOCK_Lpuart2, kCLOCK_IpSrcSysOscAsync);
/* Set PCC FTM0 selection */
CLOCK_SetIpSrc(kCLOCK_Ftm0, kCLOCK_IpSrcSysPllAsync);
/* Set PCC FTM1 selection */
CLOCK_SetIpSrc(kCLOCK_Ftm1, kCLOCK_IpSrcSysPllAsync);
/* Set PCC FTM2 selection */
CLOCK_SetIpSrc(kCLOCK_Ftm2, kCLOCK_IpSrcSysPllAsync);
}
Hi Giovanni,
This is because ""Attempts to write to the FlexRAM in HSRUN mode will be trapped with the ACCERR flag being set." Please search "HSRUN" in the reference manual. You'll find many restriction descriptions.
Regards
jing
Yes, got. Now I have another problem. The FLASH_Init function I found in the example, after initializing the flash performs an erase to test the flash. When the flash erase reach the callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); function pointer inside "flash_command_sequence(config);" the mcu resets itself. I report the body of the flash erase function and flash_command_sequence:
status_t FLASH_Erase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
{
uint32_t sectorSize;
flash_operation_config_t flashOperationInfo;
uint32_t endAddress; /* storing end address */
uint32_t numberOfSectors; /* number of sectors calculated by endAddress */
status_t returnCode;
flash_get_matched_operation_info(config, start, &flashOperationInfo);
/* Check the supplied address range. */
returnCode = flash_check_range(config, start, lengthInBytes, flashOperationInfo.sectorCmdAddressAligment);
if (returnCode)
{
return returnCode;
}
/* Validate the user key */
returnCode = flash_check_user_key(key);
if (returnCode)
{
return returnCode;
}
start = flashOperationInfo.convertedAddress;
sectorSize = flashOperationInfo.activeSectorSize;
/* calculating Flash end address */
endAddress = start + lengthInBytes - 1;
/* re-calculate the endAddress and align it to the start of the next sector
* which will be used in the comparison below */
if (endAddress % sectorSize)
{
numberOfSectors = endAddress / sectorSize + 1;
endAddress = numberOfSectors * sectorSize - 1;
}
flash_cache_clear_process(config, kFLASH_CacheClearProcessPre);
/* the start address will increment to the next sector address
* until it reaches the endAdddress */
while (start <= endAddress)
{
/* preparing passing parameter to erase a flash block */
kFCCOBx[0] = BYTES_JOIN_TO_WORD_1_3(FTFx_ERASE_SECTOR, start);
/* calling flash command sequence function to execute the command */
returnCode = flash_command_sequence(config);
/* calling flash callback function if it is available */
if (config->PFlashCallback)
{
config->PFlashCallback();
}
/* checking the success of command execution */
if (kStatus_FLASH_Success != returnCode)
{
break;
}
else
{
/* Increment to the next sector */
start += sectorSize;
}
}
flash_cache_clear(config);
return (returnCode);
}
static status_t flash_command_sequence(flash_config_t *config)
{
uint8_t registerValue;
#if FLASH_DRIVER_IS_FLASH_RESIDENT
/* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
status_t returnCode = flash_check_execute_in_ram_function_info(config);
if (kStatus_FLASH_Success != returnCode)
{
return returnCode;
}
/* We pass the ftfx_fstat address as a parameter to flash_run_comamnd() instead of using
* pre-processed MICRO sentences or operating global variable in flash_run_comamnd()
* to make sure that flash_run_command() will be compiled into position-independent code (PIC). */
callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT));
#else
/* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register */
FTFx->FSTAT = FTFx_FSTAT_RDCOLERR_MASK | FTFx_FSTAT_ACCERR_MASK | FTFx_FSTAT_FPVIOL_MASK;
/* clear CCIF bit */
FTFx->FSTAT = FTFx_FSTAT_CCIF_MASK;
/* Check CCIF bit of the flash status register, wait till it is set.
* IP team indicates that this loop will always complete. */
while (!(FTFx->FSTAT & FTFx_FSTAT_CCIF_MASK))
{
}
#endif /* FLASH_DRIVER_IS_FLASH_RESIDENT */
/* Check error bits */
/* Get flash status register value */
registerValue = FTFx->FSTAT;
/* checking access error */
if (registerValue & FTFx_FSTAT_ACCERR_MASK)
{
return kStatus_FLASH_AccessError;
}
/* checking protection error */
else if (registerValue & FTFx_FSTAT_FPVIOL_MASK)
{
return kStatus_FLASH_ProtectionViolation;
}
/* checking MGSTAT0 non-correctable error */
else if (registerValue & FTFx_FSTAT_MGSTAT0_MASK)
{
return kStatus_FLASH_CommandFailure;
}
else
{
return kStatus_FLASH_Success;
}
}
At the end I cannot figure out why, the call: callFlashRunCommand((FTFx_REG8_ACCESS_TYPE)(&FTFx->FSTAT)); causes the reset of the mcu almost always when I try to debug it. Sometimes no. This is really hard to understand to me.
I think I found the problem. I think interrupts must be disabled during flash erase.
Giovanni, did disabling the interrupts during flash erase solve your issue? When did you disable the interrupts? Prior to call to FLASH_Erase? Also, did you disable global?