这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 行业应用 » 汽车电子 » 【S32K146车规级MCU】使用S32DS适配FreeRTOS

共2条 1/1 1 跳转至

【S32K146车规级MCU】使用S32DS适配FreeRTOS

工程师
2025-02-21 17:36:47     打赏

简介

        S32K146 是恩智浦推出的 32 位微控制器,基于 ARM Cortex - M4 内核,主频最高达 112 MHz,带单精度浮点运算单元。它有 1 MB 闪存和 128 KB RAM,能满足程序与数据存储需求。外设丰富,含定时器、CAN、SPI 等通信接口及 ADC、DAC 模拟外设。具备硬件加密与多种安全机制保障数据安全。支持多种低功耗模式。广泛用于汽车电子、工业控制、消费电子等领域,搭配 S32 Design Studio 开发环境,还有评估板助力开发。

         开发STM32程序时我么习惯使用STM32CubeMX 来生成初始化配置代码,在NXP S32K146  的开发环境中使用S32 Design Studio 也可以支持clock/pin/外设的初始化配置,我们使用S32 Design Studio 生成硬件配置代码的方式来开发会大大提高效率。在开始之前我们先看下S32K1XX 系列的软件包(SDK)结构框图。、

image.png

从上述结构框图可以看出SDK 中包含OS部分,OS 和 驱动之间使用OSIF 来适配裸机和FreeRTOS的接口差异,从未将驱动库和OS进行解耦处理。S32 Design Studio 本地使用的3.5版本,SDK 使用的4.0.1,安装过程再此酒不多赘述。

时钟系统配置

时钟配置就像人的心脏一样,芯片要工作时钟系统首先要进行配置。本地的板子外接的XTAL为16M,修改时钟系统配置外部晶振源为16M,系统时钟使用PLL作为时钟源,以下是配置后的系统时钟,core clock 配置为80M.

image.png

生成的对应时钟配置结构代码如下

/**
* @page misra_violations MISRA-C:2012 violations
*
* @section [global]
* Violates MISRA 2012 Required Rule 9.4, Duplicate initialization of object element.
* It's the only way to initialize an array that is member of struct.
*
* @section [global]
* Violates MISRA 2012 Advisory Rule 8.7, External variable could be made static.
* The external variables will be used in other source files in application code.
*/

/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
product: Clocks v9.0
processor: S32K146
package_id: S32K146_LQFP144
mcu_data: s32sdk_s32k1xx_rtm_401
processor_version: 0.0.0
 * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/

#include "clock_config.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!Configuration
name: BOARD_BootClockRUN
called_from_default_init: true
outputs:
- {id: ADC0_CLK.outFreq, value: 8 MHz}
- {id: ADC1_CLK.outFreq, value: 8 MHz}
- {id: BUS_CLK.outFreq, value: 40 MHz}
- {id: CLKOUT.outFreq, value: 48 MHz}
- {id: CMP0_CLK.outFreq, value: 40 MHz}
- {id: CORE_CLK.outFreq, value: 80 MHz}
- {id: CRC0_CLK.outFreq, value: 40 MHz}
- {id: DMA0_CLK.outFreq, value: 80 MHz}
- {id: DMAMUX0_CLK.outFreq, value: 40 MHz}
- {id: EIM0_CLK.outFreq, value: 80 MHz}
- {id: ERM0_CLK.outFreq, value: 80 MHz}
- {id: EWM0_CLK.outFreq, value: 40 MHz}
- {id: FIRCDIV1_CLK.outFreq, value: 48 MHz}
- {id: FIRCDIV2_CLK.outFreq, value: 48 MHz}
- {id: FLASH_CLK.outFreq, value: 20 MHz}
- {id: FLEXCAN0_CLK.outFreq, value: 80 MHz}
- {id: FLEXCAN1_CLK.outFreq, value: 80 MHz}
- {id: FLEXCAN2_CLK.outFreq, value: 80 MHz}
- {id: FTFC0_CLK.outFreq, value: 20 MHz}
- {id: FTM0_CLK.outFreq, value: 8 MHz}
- {id: FTM1_CLK.outFreq, value: 8 MHz}
- {id: FTM2_CLK.outFreq, value: 8 MHz}
- {id: FTM3_CLK.outFreq, value: 8 MHz}
- {id: FTM4_CLK.outFreq, value: 8 MHz}
- {id: FTM5_CLK.outFreq, value: 8 MHz}
- {id: FlexIO0_CLK.outFreq, value: 8 MHz}
- {id: LPI2C0_CLK.outFreq, value: 8 MHz}
- {id: LPIT0_CLK.outFreq, value: 8 MHz}
- {id: LPO_1K_CLK.outFreq, value: 1 kHz}
- {id: LPO_CLK.outFreq, value: 128 kHz}
- {id: LPSPI0_CLK.outFreq, value: 8 MHz}
- {id: LPSPI1_CLK.outFreq, value: 8 MHz}
- {id: LPSPI2_CLK.outFreq, value: 8 MHz}
- {id: LPTMR0_CLK.outFreq, value: 8 MHz}
- {id: LPUART0_CLK.outFreq, value: 16 MHz}
- {id: LPUART1_CLK.outFreq, value: 16 MHz}
- {id: LPUART2_CLK.outFreq, value: 16 MHz}
- {id: MPU0_CLK.outFreq, value: 80 MHz}
- {id: MSCM0_CLK.outFreq, value: 80 MHz}
- {id: PDB0_CLK.outFreq, value: 80 MHz}
- {id: PDB1_CLK.outFreq, value: 80 MHz}
- {id: PORTA_CLK.outFreq, value: 40 MHz}
- {id: PORTB_CLK.outFreq, value: 40 MHz}
- {id: PORTC_CLK.outFreq, value: 40 MHz}
- {id: PORTD_CLK.outFreq, value: 40 MHz}
- {id: PORTE_CLK.outFreq, value: 40 MHz}
- {id: RTC0_CLK.outFreq, value: 40 MHz}
- {id: RTC_CLK.outFreq, value: 48 MHz}
- {id: SCGCLKOUT.outFreq, value: 48 MHz}
- {id: SIRCDIV1_CLK.outFreq, value: 8 MHz}
- {id: SIRCDIV2_CLK.outFreq, value: 8 MHz}
- {id: SOSCDIV1_CLK.outFreq, value: 16 MHz}
- {id: SOSCDIV2_CLK.outFreq, value: 16 MHz}
- {id: SPLLDIV1_CLK.outFreq, value: 80 MHz}
- {id: SPLLDIV2_CLK.outFreq, value: 40 MHz}
- {id: SPLL_CLK_OUT.outFreq, value: 160 MHz}
- {id: SYS_CLK.outFreq, value: 80 MHz}
- {id: TRACE_CLK.outFreq, value: 80 MHz}
settings:
- {id: 'HSRUN:SCG.DIVBUS.scale', value: '2', locked: true}
- {id: 'HSRUN:SCG.DIVCORE.scale', value: '1', locked: true}
- {id: 'HSRUN:SCG.DIVSLOW.scale', value: '4', locked: true}
- {id: 'HSRUN:SCG.SCSSEL.sel', value: SCG.SPLL_CLK}
- {id: PCC.LPTMR0_FRAC.scale, value: '1', locked: true}
- {id: PCC.LPUART0_CLK_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: PCC.LPUART1_CLK_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: PCC.LPUART2_CLK_SEL.sel, value: SCG.SOSCDIV2_CLK}
- {id: PCC.PREDIV.scale, value: '1', locked: true}
- {id: PCC.PREDIVTRACE.scale, value: '1', locked: true}
- {id: PCC.TRACE_FRAC.scale, value: '1', locked: true}
- {id: RTCCLKSEL.sel, value: SCG.FIRCDIV1_CLK}
- {id: 'RUN:SCG.DIVBUS.scale', value: '2', locked: true}
- {id: 'RUN:SCG.DIVCORE.scale', value: '2', locked: true}
- {id: 'RUN:SCG.DIVSLOW.scale', value: '4', locked: true}
- {id: 'RUN:SCG.SCSSEL.sel', value: SCG.SPLL_CLK}
- {id: SCG.DIVBUS.scale, value: '2', locked: true}
- {id: SCG.DIVCORE.scale, value: '2', locked: true}
- {id: SCG.DIVSLOW.scale, value: '4', locked: true}
- {id: SCG.FIRCDIV1.scale, value: '1', locked: true}
- {id: SCG.FIRCDIV2.scale, value: '1', locked: true}
- {id: SCG.PREDIV.scale, value: '1', locked: true}
- {id: SCG.SCSSEL.sel, value: SCG.SPLL_CLK}
- {id: SCG.SIRCDIV1.scale, value: '1', locked: true}
- {id: SCG.SIRCDIV2.scale, value: '1', locked: true}
- {id: SCG.SOSCDIV1.scale, value: '1', locked: true}
- {id: SCG.SOSCDIV2.scale, value: '1', locked: true}
- {id: SCG.SPLLDIV1.scale, value: '2', locked: true}
- {id: SCG.SPLLDIV2.scale, value: '4', locked: true}
- {id: SCG.SPLL_mul.scale, value: '20', locked: true}
- {id: 'VLPR:SCG.DIVBUS.scale', value: '1', locked: true}
- {id: 'VLPR:SCG.DIVCORE.scale', value: '4', locked: true}
- {id: 'VLPR:SCG.DIVSLOW.scale', value: '4', locked: true}
- {id: 'VLPR:SCG.SCSSEL.sel', value: SCG.SIRC}
sources:
- {id: SCG.SOSC.outFreq, value: 16 MHz, enabled: true}
 * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/

/* *************************************************************************
* Configuration structure for peripheral clock configuration 0
* ************************************************************************* */
/*! @brief peripheral clock configuration 0 */
peripheral_clock_config_t peripheralClockConfig0[NUM_OF_PERIPHERAL_CLOCKS_0] = {
    {
        .clockName = ADC0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = ADC1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPSPI0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPSPI1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPSPI2_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPUART0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SOSC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPUART1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SOSC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPUART2_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SOSC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPI2C0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPIT0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = LPTMR0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM2_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM3_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM4_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTM5_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV1,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FLEXIO0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_SIRC_DIV2,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = CMP0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = CRC0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = DMAMUX0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = EWM0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FTFC0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PDB0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PDB1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = RTC0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FlexCAN0_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FlexCAN1_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = FlexCAN2_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PORTA_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PORTB_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PORTC_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PORTD_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
    {
        .clockName = PORTE_CLK,
        .clkGate = true,
        .clkSrc = CLK_SRC_OFF,
        .frac = MULTIPLY_BY_ONE,
        .divider = DIVIDE_BY_ONE,
    },
};
/* *************************************************************************
* Configuration structure for Clock Configuration 0
* ************************************************************************* */
/*! @brief User Configuration structure clock_managerCfg_0 */
clock_manager_user_config_t clockMan1_InitConfig0 = {
    .scgConfig =
    {
        .sircConfig =
        {
            .initialize = true,
            .enableInStop = true,                 /* Enable SIRC in stop mode */
            .enableInLowPower = true,             /* Enable SIRC in low power mode */
            .locked = false,                      /* unlocked */
            .range = SCG_SIRC_RANGE_HIGH,         /* Slow IRC high range clock (8 MHz) */
            .div1 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* Slow IRC Clock Divider 1: divided by 1 */
            .div2 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* Slow IRC Clock Divider 3: divided by 1 */
        },
        .fircConfig =
        {
            .initialize = true,
            .regulator = true,                    /* FIRC regulator is enabled */
            .locked = false,                      /* unlocked */
            .range = SCG_FIRC_RANGE_48M,           /*!< RANGE      */
            .div1 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* Fast IRC Clock Divider 1: divided by 1 */
            .div2 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* Fast IRC Clock Divider 3: divided by 1 */
        },
        .rtcConfig =
        {
            .initialize = false,
        },
        .soscConfig =
        {
            .initialize = true,
            .freq = 16000000U,                    /* System Oscillator frequency: 16000000Hz */
            .monitorMode = SCG_SOSC_MONITOR_DISABLE,/* Monitor disabled */
            .locked = false,                      /* SOSC disabled */
            .extRef = SCG_SOSC_REF_OSC,           /* Internal oscillator of OSC requested. */
            .gain = SCG_SOSC_GAIN_LOW,            /* Configure crystal oscillator for low-gain operation */
            .range = SCG_SOSC_RANGE_HIGH,         /* High frequency range selected for the crystal oscillator of 8 MHz to 40 MHz. */
            .div1 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* System OSC Clock Divider 1: divided by 1 */
            .div2 = SCG_ASYNC_CLOCK_DIV_BY_1,     /* System OSC Clock Divider 3: divided by 1 */
        },
        .spllConfig =
        {
            .initialize = true,
            .monitorMode = SCG_SPLL_MONITOR_DISABLE,/* Monitor disabled */
            .locked = false,                      /* unlocked */
            .prediv = (uint8_t)SCG_SPLL_CLOCK_PREDIV_BY_1,/* Divided by 1 */
            .mult = (uint8_t)SCG_SPLL_CLOCK_MULTIPLY_BY_20,/* Multiply Factor is 20 */
            .src = 0U,
            .div1 = SCG_ASYNC_CLOCK_DIV_BY_2,     /* System PLL Clock Divider 1: divided by 2 */
            .div2 = SCG_ASYNC_CLOCK_DIV_BY_4,     /* System PLL Clock Divider 3: divided by 4 */
        },
        .clockOutConfig =
        {
            .initialize = true,
            .source = SCG_CLOCKOUT_SRC_FIRC,      /* Fast IRC. */
        },
        .clockModeConfig =
        {
            .initialize = true,
            .rccrConfig =
            {
                .src = SCG_SYSTEM_CLOCK_SRC_SYS_PLL,/* System PLL */
                .divCore = SCG_SYSTEM_CLOCK_DIV_BY_2,/* Core Clock Divider: divided by 2 */
                .divBus = SCG_SYSTEM_CLOCK_DIV_BY_2,/* Bus Clock Divider: divided by 2 */
                .divSlow = SCG_SYSTEM_CLOCK_DIV_BY_4,/* Slow Clock Divider: divided by 4 */
            },
            .vccrConfig =
            {
                .src = SCG_SYSTEM_CLOCK_SRC_SIRC, /* Slow IRC */
                .divCore = SCG_SYSTEM_CLOCK_DIV_BY_2,/* Core Clock Divider: divided by 2 */
                .divBus = SCG_SYSTEM_CLOCK_DIV_BY_1,/* Bus Clock Divider: divided by 1 */
                .divSlow = SCG_SYSTEM_CLOCK_DIV_BY_4,/* Slow Clock Divider: divided by 4 */
            },
            .hccrConfig =
            {
                .src = SCG_SYSTEM_CLOCK_SRC_SYS_PLL,/* System PLL */
                .divCore = SCG_SYSTEM_CLOCK_DIV_BY_1,/* Core Clock Divider: divided by 1 */
                .divBus = SCG_SYSTEM_CLOCK_DIV_BY_2,/* Bus Clock Divider: divided by 2 */
                .divSlow = SCG_SYSTEM_CLOCK_DIV_BY_4,/* Slow Clock Divider: divided by 4 */
            },
        },
    },
    .pccConfig =
    {
        .peripheralClocks = peripheralClockConfig0, /*!< Peripheral clock control configurations  */
        .count = NUM_OF_PERIPHERAL_CLOCKS_0, /*!< Number of the peripheral clock control configurations  */
    },
    .simConfig =
    {
        .clockOutConfig =
        {
            .initialize = true, /*!< Initialize    */
            .enable = true,                       /* enabled */
            .source = SIM_CLKOUT_SEL_SYSTEM_SCG_CLKOUT,/* SCG CLKOUT clock select: SCG slow clock */
            .divider = SIM_CLKOUT_DIV_BY_1,       /* Divided by 1 */
        },
        .lpoClockConfig =
        {
            .initialize = true, /*!< Initialize    */
            .enableLpo1k = true, /*!< LPO1KCLKEN    */
            .enableLpo32k = true, /*!< LPO32KCLKEN   */
            .sourceLpoClk = SIM_LPO_CLK_SEL_LPO_128K,/* 128 kHz LPO clock */
            .sourceRtcClk = SIM_RTCCLK_SEL_FIRCDIV1_CLK,/* FIRCDIV1 clock */
        },
        .platGateConfig =
        {
            .initialize = true, /*!< Initialize    */
            .enableEim = true, /*!< CGCEIM        */
            .enableErm = true, /*!< CGCERM        */
            .enableDma = true, /*!< CGCDMA        */
            .enableMpu = true, /*!< CGCMPU        */
            .enableMscm = true, /*!< CGCMSCM       */
        },
        .tclkConfig =
        {
            .initialize = false, /*!< Initialize    */
        },
        .traceClockConfig =
        {
            .initialize = true, /*!< Initialize    */
            .divEnable = true, /*!< TRACEDIVEN    */
            .source = CLOCK_TRACE_SRC_CORE_CLK, /*!< TRACECLK_SEL  */
            .divider = 0U, /*!< TRACEDIV      */
            .divFraction = false, /*!< TRACEFRAC     */
        },
    },
    .pmcConfig =
    {
        .lpoClockConfig =
        {
        .initialize = true,  /*!< Initialize    */
        .enable = true, /*!< Enable/disable LPO     */
        .trimValue = 0, /*!< Trimming value for LPO */
        },
    },
};

/*! @brief Array of pointers to User configuration structures */
clock_manager_user_config_t const * g_clockManConfigsArr[] = {
&clockMan1_InitConfig0
};

/*! @brief Array of pointers to User defined Callbacks configuration structures */
/* The tool do not support generate Callbacks configuration. It's always empty. */
clock_manager_callback_user_config_t * g_clockManCallbacksArr[] = {(void*)0};

对于时钟系统的配置再此在补充一句,上述时钟图是整个系统的时钟配置脉络,S32 Design Studio 对外设的时钟配置也有独立的配置方法,对应配置如下我们可以选择外设的时钟源及gate 信号的配置来开启或关闭外设的时钟,从而降低芯片运行时的功耗。

image.png

通过以下界面控制外设的gate 信号开启或关闭

image.png

FreeRTOS 系统配置

S32 Design Studio 中把FreeRTOS作为一个外设来对待进行管理,我们只要在外设管理工具中OS 中添加FreeRTOS,然后配置FreeRTOS 参数即可,整个FreeRTOS的配置过程就是如此,这个该界面的配置项目对应FreeRTOS 的config 文件(FreeRTOSConfig.h),至此对于FreeRTOS的配置内容就完成了。

image.png

配置上修改cpu频率设置,需修改为实际的cpu频率本地的频率为80M

image.png

生成的FreeRTOS 配置代码如下

/* ###################################################################
**     Copyright 2018 NXP 
**     All Rights Reserved.
**     
**     NXP Confidential. This software is owned or controlled by NXP and may only be
**     used strictly in accordance with the applicable license terms. By expressly
**     accepting such terms or by downloading, installing, activating and/or otherwise
**     using the software, you are agreeing that you have read, and that you agree to
**     comply with and are bound by, such license terms. If you do not agree to be
**     bound by the applicable license terms, then you may not retain, install,
**     activate or otherwise use the software. The production use license in
**     Section 2.3 is expressly granted for this software.
** ###################################################################*/

/* Component ID, used by S32 Configuration Tool *//* FSL_COMPONENT_ID "platform.os.freertos" *//* SDK_FREERTOS_DRIVER_VERSION (MAKE_VERSION(1, 0, 0)) */
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/**
* @page misra_violations MISRA-C:2012 violations
*
 * @section [global]
* Violates MISRA 2012 Advisory Directive 4.9, Function-like macro defined.
* The macro is used for development validation.
*
* @section [global]
* Violates MISRA 2012 Required Rule 3.1, C comment contains C++ comment.
* Detections are URL links from FreeRTOS header text.
*
* @section [global]
* Violates MISRA 2012 Advisory Rule 2.5, Global macro not referenced.
* The global macro will be used in function call of the module.
*/

/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/


#define configCPU_CLOCK_HZ                          ( 800000000UL )
#define configTICK_RATE_HZ                          ((TickType_t) 1000 )
#define configMAX_PRIORITIES                        5
#define configMINIMAL_STACK_SIZE                    ((unsigned short) 90 )
#define configMAX_TASK_NAME_LEN                     10
#define configUSE_16_BIT_TICKS                      0
#define configIDLE_SHOULD_YIELD                     1
#define configUSE_PREEMPTION                        1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS     0
#define configUSE_PORT_OPTIMISED_TASK_SELECTION     1
#define configUSE_TASK_NOTIFICATIONS                1
#define configUSE_TIME_SLICING                      1
#define configUSE_NEWLIB_REENTRANT                  0
#define configENABLE_BACKWARD_COMPATIBILITY         1
#define configUSE_POSIX_ERRNO                       0

/* Definition assert() function. */
#define configASSERT(x)                             if((x)==0) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ( 1 )

/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION             0
#define configSUPPORT_DYNAMIC_ALLOCATION            1
#define configTOTAL_HEAP_SIZE                       (( size_t ) 8192 )
#define configAPPLICATION_ALLOCATED_HEAP            0

/* Hook function related definitions. */
#define configUSE_IDLE_HOOK                         1
#define configUSE_TICK_HOOK                         1
#define configUSE_MALLOC_FAILED_HOOK                1
#define configCHECK_FOR_STACK_OVERFLOW              2
#define configUSE_DAEMON_TASK_STARTUP_HOOK          0

/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS               0
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()    
#define portGET_RUN_TIME_COUNTER_VALUE()            xTaskGetTickCount()
#define configUSE_TRACE_FACILITY                    0
#define configUSE_STATS_FORMATTING_FUNCTIONS        1

/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES                       0
#define configMAX_CO_ROUTINE_PRIORITIES             2

/* SEMAPHORES and MUTEXS */
#define configUSE_MUTEXES                           1
#define configUSE_RECURSIVE_MUTEXES                 1
#define configUSE_COUNTING_SEMAPHORES               1

/* Software timer related definitions. */
#define configUSE_TIMERS                            1
#define configTIMER_TASK_PRIORITY                   2
#define configTIMER_QUEUE_LENGTH                    10
#define configTIMER_TASK_STACK_DEPTH                180

/* Tickless Idle Mode */
#define configUSE_TICKLESS_IDLE                     0

/* QUEUE */
#define configQUEUE_REGISTRY_SIZE                   8
#define configUSE_QUEUE_SETS                        0

/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet                    1
#define INCLUDE_uxTaskPriorityGet                   1
#define INCLUDE_vTaskDelete                         1
#define INCLUDE_vTaskSuspend                        1
#define INCLUDE_vTaskDelayUntil                     1
#define INCLUDE_vTaskDelay                          1
#define INCLUDE_xTaskGetSchedulerState              1
#define INCLUDE_xTaskGetCurrentTaskHandle           1
#define INCLUDE_uxTaskGetStackHighWaterMark         1
#define INCLUDE_xTaskGetIdleTaskHandle              0
#define INCLUDE_eTaskGetState                       1
#define INCLUDE_xEventGroupSetBitFromISR            1
#define INCLUDE_xTimerPendFunctionCall              1
#define INCLUDE_xTaskAbortDelay                     1
#define INCLUDE_xTaskGetHandle                      1
#define INCLUDE_xTaskResumeFromISR                  1
#define INCLUDE_xQueueGetMutexHolder                1


/* Run time stats gathering definitions. */
#ifdef __GNUC__
    /* The #ifdef just prevents this C specific syntax from being included in
    assembly files. */
    void vMainConfigureTimerForRunTimeStats( void );
    unsigned long ulMainGetRunTimeCounterValue( void );
#endif

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
  #define configPRIO_BITS                         __NVIC_PRIO_BITS
#else
  #define configPRIO_BITS                         4
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY  (0x0F)

/* Interrupt priorities used by the kernel port layer itself.  These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
  #define configKERNEL_INTERRUPT_PRIORITY         (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8-configPRIO_BITS))  
#endif
  
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#ifndef configMAX_SYSCALL_INTERRUPT_PRIORITY
  #define configMAX_SYSCALL_INTERRUPT_PRIORITY    (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8-configPRIO_BITS))
#endif

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler                             SVC_Handler
#define xPortPendSVHandler                          PendSV_Handler
#define xPortSysTickHandler                         SysTick_Handler   


#endif /* FREERTOS_CONFIG_H */

配置完成后点击“更新源代码”就会生成我们上述配置的clock 和 FreeRTOS的配置内容了。

image.png

导入工程验证

本地使用IAR 来编译调试程序,使用S32 Design Studio 只是作为生成初始化配置代码来使用,我们将上述生成的代码和SDK的驱动库加载到IAR环境中,并添加如下的测试代码,启动两个task来验证RreeRTOS的任务是否正常被调度。

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"

/* SDK includes. */
#include "interrupt_manager.h"
#include "sdk_project_config.h"


#define START_TASK_PRIO        2
#define START_STK_SIZE         128
        TaskHandle_t StartTask_Handler;
        void start_task(void *pvParameters);

#define TASK1_TASK_PRIO        2
#define TASK1_STK_SIZE         128
        TaskHandle_t Task1Task_Handler;
        void start_task1(void *pvParameters);

void start_task(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(500);
    }
}


void start_task1(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(1000);
    }
}

int main(void)
{
    /* Initialize and configure clocks
     *  -   Setup system clocks, dividers
     *  -   see clock manager component for more details
     */
    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
                   g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);

    xTaskCreate((TaskFunction_t )start_task,
                (const char*    )"task1",
                (uint16_t       )START_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )START_TASK_PRIO,
                (TaskHandle_t*  )&StartTask_Handler);

    xTaskCreate((TaskFunction_t )start_task1,
                (const char*    )"task2",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_TASK_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);

    vTaskStartScheduler();

    return 0;
}

上述代码在进入main 函数后首先进行初始化时钟系统,之后创建两个任务之后启动调度器调度任务运行。为了形象的产看系统任务调度状况,我们使用IAR 的log 断电在任务中进行打印查看任务调度情况。通过log 断点查看task1 和 task2 的任务已经按照预期的周期配置调度运行了,至此基于S32K146芯片的FreeRtos已经运行起来了。

image.png



专家
2025-02-22 22:09:24     打赏
2楼

感谢分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]