1159_S32K148 FEE的实现

    S32K148中的FEE实现方式有一定的硬件机制存在,因此在实现上跟之前接触到的FEE多少有一些不同。在此之前接触到的FEE,比如说MPC5644上的FEE,基本上是Flash驱动加纯软件策略来实现的。而S32K148上面则不同,在这个MCU上有专门的硬件实现机制,虽然也用到了Flash但是Flash是表现上其实看上去更像是真实的EEPROM,用户只需要直接写入或者读取RAM即可。

    具体的原理分析在《001_Flash例程分析》、《002_S32K148 Flash相关文档解读》、《003_FlexRAM与EEPROM大小关系》这三份笔记中做了详细的整理。

    接下来,看一下我自己在软件设计应用中的一部分尝试。

void fee_lld_init(void)

{

    status_t ret; /* Store the driver APIs return code */

    POWER_SYS_SetMode(RUN, POWER_MANAGER_POLICY_AGREEMENT);

    /* Install interrupt for Flash Command Complete event */

    INT_SYS_InstallHandler(FTFC_IRQn, CCIF_Handler, (isr_t *)0);

    INT_SYS_EnableIRQ(FTFC_IRQn);

    /* Always initialize the driver before calling other functions */

    ret = FLASH_DRV_Init(&Flash1_InitConfig0, &flashSSDConfig);

    DEV_ASSERT(STATUS_SUCCESS == ret);

    if (flashSSDConfig.EEESize == 0u)

    {

        /* Configure FlexRAM as EEPROM and FlexNVM as EEPROM backup region,

         * DEFlashPartition will be failed if the IFR region isn't blank.

         * Refer to the device document for valid EEPROM Data Size Code

         * and FlexNVM Partition Code. For example on S32K148:

         * - EEEDataSizeCode = 0x02u: EEPROM size = 4 Kbytes

         * - DEPartitionCode = 0x04u: EEPROM backup size = 64 Kbytes */

        ret = FLASH_DRV_DEFlashPartition(&flashSSDConfig, 0x02u, 0x04u, 0x0u, false, true);

        DEV_ASSERT(STATUS_SUCCESS == ret);

        /* Re-initialize the driver to update the new EEPROM configuration */

        ret = FLASH_DRV_Init(&Flash1_InitConfig0, &flashSSDConfig);

        DEV_ASSERT(STATUS_SUCCESS == ret);

        /* Make FlexRAM available for EEPROM */

        ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);

        DEV_ASSERT(STATUS_SUCCESS == ret);

    }

    else /* FLexRAM is already configured as EEPROM */

    {

        ret = FLASH_DRV_DEFlashPartition(&flashSSDConfig, 0x02u, 0x04u, 0x0u, false, true);

        DEV_ASSERT(STATUS_SUCCESS == ret);

        /* Make FlexRAM available for EEPROM, make sure that FlexNVM and FlexRAM

         * are already partitioned successfully before */

        ret = FLASH_DRV_SetFlexRamFunction(&flashSSDConfig, EEE_ENABLE, 0x00u, NULL);

        DEV_ASSERT(STATUS_SUCCESS == ret);

    }

    /* Set callback function before a long time consuming flash operation

     * (ex: erasing) to let the application code do other tasks while flash

     * in operation. In this case we use it to enable interrupt for

     * Flash Command Complete event */

    pCallBack = (flash_callback_t)CCIF_Callback;

    flashSSDConfig.CallBack = pCallBack;

    /* Disable Callback */

    flashSSDConfig.CallBack = NULL_CALLBACK;

    POWER_SYS_SetMode(HSRUN, POWER_MANAGER_POLICY_AGREEMENT);

    (void)ret;

}

    初始化函数的设计其实就是例程中的框架,没有什么太多的变化。这里有一个时钟的修改,至于为什么改后面再说。

void fee_lld_write(uint32_t reletive_addr, uint32_t size, uint8_t *p_data)

{

    uint32_t address;

    status_t ret; /* Store the driver APIs return code */

    if (flashSSDConfig.EEESize != 0u)

    {

        POWER_SYS_SetMode(RUN, POWER_MANAGER_POLICY_AGREEMENT);

        address = flashSSDConfig.EERAMBase + reletive_addr;

        ret = FLASH_DRV_EEEWrite(&flashSSDConfig, address, size, p_data);

        DEV_ASSERT(STATUS_SUCCESS == ret);

        POWER_SYS_SetMode(HSRUN, POWER_MANAGER_POLICY_AGREEMENT);

    }

    else

    {

        /* no code */

    }

    (void)ret;

}

void fee_lld_read(uint32_t reletive_addr, uint32_t size, uint8_t *p_data)

{

    uint32_t address;

    if (flashSSDConfig.EEESize != 0u)

    {

        POWER_SYS_SetMode(RUN, POWER_MANAGER_POLICY_AGREEMENT);

        address = flashSSDConfig.EERAMBase + reletive_addr;

        memcpy(p_data, (uint8_t *)address, size);

        POWER_SYS_SetMode(HSRUN, POWER_MANAGER_POLICY_AGREEMENT);

    }

    else

    {

        /* no code */

    }

}

    写入以及读取稍微做了一下处理,因为这个机制的运行其实有一定的先决条件。具体的文档信息前面整理过,这里把这个相关点再拿出来看一下。

    在这两种模式下,Flash驱动是不能够操作的。而这个FEE既然用到了flash做记录的保存,其实还是脱离不了flash驱动的使用。很多产品或者系统设计的时候很重要的一个目标其实是性能,因此会直接在HSRUN模式下运行。这样就会导致Flash写入的错误,其实读取倒是没有特别的说明。那么为什么我这里多个地方也加了相应的模式切换呢?这就需要回答前面初始化的时候埋下的问题了:为什么初始化的时候改了时钟?答案很简单,我在调试的时候发现其实HSRUN模式下初始化然后进行EEPROM的操作也会失败!那么,安全起见,自然全都离开这种模式会好一些。

static void fee_lld_fill_eeprom_with_same_bytes(uint8_t byte_data)

{

    uint8_t data[512];

    memset(data, byte_data, 512);

    fee_lld_write(512 * 0, 512, data);

    fee_lld_write(512 * 1, 512, data);

    fee_lld_write(512 * 2, 512, data);

    fee_lld_write(512 * 3, 512, data);

}

void fee_lld_clear_eeprom(void)

{

    fee_lld_fill_eeprom_with_same_bytes(0x00U);

}

void fee_lld_format_eeprom(void)

{

    fee_lld_fill_eeprom_with_same_bytes(0xFFU);

}

    清除以及格式化分了两个函数,而两个函数又调用了另一个共用的静态函数。如果在以前,或许我就是两个函数复制一份就结束了,但是SICP看了一个开篇之后,对这方面开始越来越在意了。计算机的工作的确是应该当成魔法、艺术来对待,不能够做成搬砖类的工作。

    整个调试比较简单,测试的信息不再放了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值