S32K344具有锁步内核,可以将内核解耦以与具有不同应用的两个内核一起工作。下面介绍S32K344用于多核目的,每个内核都有自己的启动文件,也有自己的链接器件,其中根据应用程序将内存映射到每个内核。如果两个内核都已启用(根据Boot配置),它们同时运行,无论是在调试模式还是独立模式,一个内核都可以为两个内核配置时钟,并为彼此启用或禁用时钟,可以在内核时钟门控部分找到更多信息。如果有S32K344,可以将其解耦,并用新配置在UTEST中的新记录再次锁定器件。DCF记录存储在UTEST存储器中,有一些DCF由TE/PE在测试 Flash中编程,用户无法访问这些记录,锁步DCF记录编程在这上面。从偏移量200到6FF的区域仅可由HSE核和SBAF访问,如生命周期、OTA启用等配置均在该区域编程。可以在S32K3 SecureBAF和HSE手册文档中找到有关UTEST中编程的所有这些配置的更多详细信息。
器件配置格式Device Configuration Format (DCF 记录)
DCF记录包含在UTEST扇区中,UTEST扇区是一个8 KB OTP存储器,其中包含SoC的相关信息,作为保留配置或应用参数。在引导序列中,在系统引导期间读取DCF记录以配置芯片中的某些寄存器。DCF记录大小从地址0x1B000700开始,到0x1B001BFF结束。在这个区域内,可以找到6种DCF记录。LOCKSTEP_EN=0的新DCF记录必须编程到UTEST OTP存储器中。这可以通过C40 IP RTD驱动程序来完成。首先,通过调试器读取内存,在UTEST中找到当前的DCF记录。对于具有默认配置的器件,新记录的第一个可用空间(全部为0xFF)应为0x1B000768。
Start Record
Dcf_client_utest_misc
Dcf_client_reset_pad_dedicated
Dcf_client_dest_rst_esc
Dcf_client_sdid0-15
Dcf_client_instanceid
DCF_client_utest_misc
要在DCF_client中进行有效配置,需要一个控制字和一个数据字,图1显示了每个DCF客户端的控制字。
图1 DCF 控制字
DCF_client_utest_miscData对于某些配置有32位,其中一位是LOCKSTEP_EN,如下图2所示。
图2 UTEST Miscellaneous register.
为了解耦内核,需要写0到LOCKSTEP_EN 位中。
改变 LOCKSTEP_EN位
以下代码在UTEST扇区中写入LOCKSTEP_EN位,以解耦内核 。
/* Following macro defines chip mode
* 1 - Lockstep operation.
* 0 - Decoupled operation. */
#define LOCKSTEP_EN (0)
/* From here, user should not modify the code */
#define PROGRAM_DATA1 (0x00100004) /* UTEST_MISC DCF Control Word */
#if (LOCKSTEP_EN == 1)
#define PROGRAM_DATA0 (0x00000101) /* UTEST_MISC Data Word */
#elif (LOCKSTEP_EN == 0)
#define PROGRAM_DATA0 (0x00000100) /* UTEST_MISC Data Word */
#else
#error "Only two options are supported for LOCKSTEP_EN: [0, 1]."
#endif
/*UTest DCF Record Space : 5376 Bytes
* 0x1B000700 - 0x1B001BFF */
#define DCF_RECORD_START_ADDRESS (0x1B000700) /* UTEST DCF record start address */
#define DCF_RECORD_END_ADDRESS (0x1B001B00) /* UTEST DCF record end address */
/************************************************************************/
/* Global Variable definition*/
/************************************************************************/
/* UTEST Miscellaneous Register */
uint32_tutest_misc_dcf[ ] = {
(uint32_t)PROGRAM_DATA0, /* DCF Data word 8h [0:31] */
(uint32_t)PROGRAM_DATA1 /* DCF Control word Ch [32:63] */
};
/* status variables for main and express interfaces */
volatile tFLASH_STATUS status;
/* FUNCTION ********************************************************************
* Function Name : main
* Description : Main Function for CM7 Core
* END ************************************************************************/
int main(void)
{
uint64_t *DCF_Ptr;
DCF_Ptr = ( uint64_t *)DCF_RECORD_START_ADDRESS;
while (DCF_Ptr < ( uint64_t *)DCF_RECORD_END_ADDRESS)
{
if( *DCF_Ptr == 0xFFFFFFFFFFFFFFFFULL )
{
/* unlock UTEST data flash sector */
PFLASH_Unlock(PFLASH_BL5, PFLASH_SS0, PFLASH_S0);
/* write UtestWrite in UtestSector using main interface */
status = FLASH_Write (DCF_Ptr, /* Last DCF available */
utest_misc_dcf, /* SRC: UTEST-MISC */
sizeof(utest_misc_dcf)); /* Number of bytes */
if (status == 0x0000C000)
{
/* DCF record programming was successful */
printf("Successfully wrote at %08lx\n", ( uint32_t)DCF_Ptr);
printf("Status: %08lx\n", ( uint32_t)status);
while (1);
}
else
{
printf("Failed at %08lx\n", ( uint32_t)DCF_Ptr);
printf("Status: %08lx\n", ( uint32_t)status);
while (1);
}
}
DCF_Ptr++;
}
}
代码只为LOCKSTEP_EN位添加了新的配置,这是因为UTEST是OTP存储器,无法执行擦除。
图3 UTEST 块存储器映射
在上图3中,可以在地址0x1B000768中看到数据0x00000100,在0x1B00076C中看到控制字0x00100004,其中数据核已配置为在解耦模式下工作。在这个配置之后,可以看到橙色的其他配置,以便显示可以添加新的配置。在地址0x1B000770中,内核在Lockstep中再次配置,在地址0x1B000788中,数据0x08000101在Lockstep中配置内核,POR看门狗启用,并在旁路模式中绕过QSPI IAHB。地址0x1B000790中分配的最后一条记录是将会加载的有效记录。一旦内核被解耦,就可以使用两个内核来运行不同的任务。
多核工程
介绍如何使用RTD/SDK软件在S32DS中构建多核项目。首先创建 S32DS Application Project工程。如下图所示。
需要添加一个名称,并选择2核设备S32K324。“下一步”之后,如下图所示。在SDKs 中, 选择 PlatformSDK SW。
需要选择两个内核,点击完成将创建以下项目。
已经准备好使用主文件,并配置Multicore_M7_0.mex和Multicore_M7_1.mex。在本例中,将使用PIT计时器使用中断切换LED。第一步是配置打开.mex文件的必要模块,以便使用Config工具。对于Pins(引脚)窗口中的Multicore_M7_0,需要选择LED连接的引脚,需要选择LED的PTA31引脚,并将配置选择为具有输出方向的GPIO。将其标记为BLUE0。
下一步是添加将要使用的外围设备,在本例中,需要添加Siul2_Dio以使用所选引脚,并使用与引脚相关的API、Pit驱动程序来配置切换时间,以及IntCtrl_IP来配置Pit的中断处理程序。
对于PIT配置,需要选择PIT实例Channel并定义Callback。在例子中,将使用PIT_0的0通道,并定义Pit0_Ch0_Callback。
需要产生中断,因此使能IsrEnable。
在 InCtrl_Ip窗口,需要配置如下使能 PIT中断请求。
上述代码配置后,需要通过 Update Code按键更新产生代码.c 和.h 文件。
点击OK加载程序试图,在项目资源管理器中,可以使用下一个cfg.h文件。
可以使用.c文件中包含的API以及.h文件中定义的参数和结构。下图中可以看到Pit0_Ch0_Callback已经声明,并且有PIT实例0的结构和所做的配置的结构。
在 main文件里面实现代码,需要初始化每个模块。
/* Including necessary configuration files. */
#include "Mcal.h"
#include "Siul2_Dio_Ip.h"
#include "Siul2_Port_Ip.h"
#include "Pit_Ip.h"
#include "IntCtrl_Ip.h"
#include "Clock_Ip.h"
volatile int exit_code = 0;
/* User includes */
#define PIT_INSTANCE 0
#define PIT_CH 0
#define PIT_TIMEVAL 40000000 /* Due to AIPS_SLOW_CLK = 40 MHz */
ISR(PIT_0_ISR);
/* Callback for PIT0 Channel 0
* The BLUE0 LED is toggled every 1 second */
void Pit0_Ch0_Callback (uint8_t channel)
{
(void) channel;
Siul2_Dio_Ip_TogglePins(BLUE0_PORT, (1<<BLUE0_PIN));
}
int main(void)
{
/*Initialize configured clocks */
Clock_Ip_Init(&Mcu_aClockConfigPB[0]);
/* Port initialization for BLUE0 LED */
Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
/* PIT initialization for Instance 0 */
Pit_Ip_Init(PIT_INSTANCE, &PIT_0_InitConfig_PB);
/* PIT initialization for Channel 0 of Instance 0 */
Pit_Ip_InitChannel(PIT_INSTANCE, &PIT_0_ChannelConfig_PB[0U]);
/* The interrupt handler is loaded */
IntCtrl_Ip_InstallHandler(PIT0_IRQn, PIT_0_ISR, NULL_PTR);
/* PIT Instance 0 channel 0 interrupt is enable */
Pit_Ip_EnableChannelInterrupt(PIT_INSTANCE, PIT_CH);
/* PIT0 Interruption is enabled*/
IntCtrl_Ip_EnableIrq(PIT0_IRQn);
/* PIT0 Channel 0 Timer is started to run */
Pit_Ip_StartChannel(PIT_INSTANCE, PIT_CH, PIT_TIMEVAL);
for(;;)
{
if(exit_code != 0)
{
break;
}
}
return exit_code;
}
针对 Core M7_1,使用 PTB18实现 LED点灯,PIT1和Channel 1,需要在 MultiCore_M7_1.mex 里面按照上述配置再配置一遍,代码如下。
/* Including necessary configuration files. */
#include "Mcal.h"
#include "Siul2_Dio_Ip.h"
#include "Siul2_Port_Ip.h"
#include "Pit_Ip.h"
#include "IntCtrl_Ip.h"
#include "Clock_Ip.h"
volatile int exit_code = 0;
/* User includes */
#define PIT_INSTANCE 1
#define PIT_CH 1
#define PIT_TIMEVAL 40000000 /* Due to AIPS_SLOW_CLK = 40 MHz */
ISR(PIT_1_ISR);
static uint32_t Counter=0;
/* Callback for PIT1 Channel 1
* The RED LED is toggled every 1 second */
void Pit1_Ch1_Callback (uint8_t channel)
{
(void) channel;
Siul2_Dio_Ip_TogglePins(RED1_PORT, (1<<RED1_PIN));
}
int main(void)
{
/* Port initialization for RED1 LED */
Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
/* PIT initialization for Instance 1 */
Pit_Ip_Init(PIT_INSTANCE, &PIT_1_InitConfig_PB);
/* PIT initialization for Channel 1 of Instance 1 */
Pit_Ip_InitChannel(PIT_INSTANCE, &PIT_1_ChannelConfig_PB[0U]);
/* The interrupt handler is loaded */
IntCtrl_Ip_InstallHandler(PIT1_IRQn, PIT_1_ISR, NULL_PTR);
/* PIT Instance 1 channel 1 interrupt is enable */
Pit_Ip_EnableChannelInterrupt(PIT_INSTANCE, PIT_CH);
/* PIT1 Interruption is enabled*/
IntCtrl_Ip_EnableIrq(PIT1_IRQn);
/* PIT1 Channel 1 Timer is started to run */
Pit_Ip_StartChannel(PIT_INSTANCE, PIT_CH, PIT_TIMEVAL);
for(;;)
{
if(exit_code != 0)
{
break;
}
}
return exit_code;
}
选择调试配置debug configuration开始工程调试。
选择LaunchGroup以加载每个Core配置,可以通过打开各个调试选项来检查配置是否正确。按下调试按钮后,将看到以下窗口,其中包含调试两个内核选项。