L475移植,包括fal+easyflash+ulog_easyflash

发布于 2020-12-23 15:51:35

前言

这几天在搞手持端设备,用的主控是STM32L475RCT6,暂且先不管低功耗,先让设备跑起来。

本来想直接阐述问题,但是想想还是写一下过程,自己脑子不好使老是忘,放在网站上当做日记了,也方便大家,同时如果移植过程中有问题,大佬也会指出。

  1. 移植:

1.1. 看好自己板子的晶振,根据自己板子的晶振在STM32CubeMx中设置,并设置shell串口,把CubeMx生成的main.c中的“SystemClock_Config”复制到board.c中替换原有的。
1.2. shell 移植的过程中会发现,RTT提供的“uart_config.h”文件中只有LPUART1、UART1、UART2、UART3,L475明明支持5个串口呢,没办法谁让硬件工程师把调试串口画在了UART5上,增加如下代码段,关于这段代码的添加最好还是配合着看看“dma_config.h”,因为UART上有些DMA接口如果“dma_config.h”中没有,即使添加上也是没有用的。

#if defined(BSP_USING_UART5)
#ifndef UART5_CONFIG
#define UART5_CONFIG                                                \
    {                                                               \
        .name = "uart5",                                            \
        .Instance = UART5,                                          \
        .irq_type = UART5_IRQn,                                     \
    }
#endif /* UART5_CONFIG */

#if defined(BSP_UART5_RX_USING_DMA)
#ifndef UART5_DMA_RX_CONFIG
#define UART5_DMA_RX_CONFIG                                         \
    {                                                               \
        .Instance = UART5_RX_DMA_INSTANCE,                          \
        .request  = UART5_RX_DMA_REQUEST,                           \
        .dma_rcc  = UART5_RX_DMA_RCC,                               \
        .dma_irq  = UART5_RX_DMA_IRQ,                               \
    }
#endif /* UART5_DMA_RX_CONFIG */
#endif /* BSP_UART5_RX_USING_DMA */
        
#if defined(BSP_UART5_TX_USING_DMA)
#ifndef UART5_DMA_TX_CONFIG
#define UART5_DMA_TX_CONFIG                                        \
    {                                                              \
        .Instance = UART5_TX_DMA_INSTANCE,                         \
        .request  = UART5_TX_DMA_REQUEST,                          \
        .dma_rcc = UART5_TX_DMA_RCC,                               \
        .dma_irq = UART5_TX_DMA_IRQ,                               \
    }
#endif /* UART5_DMA_TX_CONFIG */
#endif /* BSP_UART5_TX_USING_DMA */
#endif /* BSP_USING_UART5 */

1.3. 下载观察现象
a.png

  1. 添加Fal组件管理片上Flash中
    这方面我之前在F4上移植过,但是L4和F4的Flash存储划分是不一样的,还是要看看的,包括512K和256K的还不一样,我用的是256K,如下所示。

b.png
c.png

2.1. 首先在board文件夹中的Kconfig中增加如下,不然fal管理还要自己实现read、write、erase函数。

    config BSP_USING_ON_CHIP_FLASH
        bool "Enable on-chip FLASH"
        default n

2.2. 在env中开启fal,我这里用的是片上,所以sfud没选择
c1.png

2.3. fal管理的存储列表在“fal_cfg.h”中,packages的inc文件夹中没有这个文件,程序检索不到,编译会报错,所以将“samplesporting”中的“fal_cfg”复制过来。

2.4. 添加完成你会打开工程你会看到,你想要的内容都在其中,如下:
d.png

2.5. 对应的填写fal_cfg.h 中列表如下,这几个名字要与“drv_flash_l4”中一致:
e.png

2.6. 在main中添加,如下代码段,这个"fal_test"函数我是直接从正点原子开发板复制过来的。

    /*init bsp components ---------------------------------------------------*/
    fal_init();

    if (fal_test("easyflash") == 0)
    {
        LOG_I("Fal partition (%s) test success!", "param");
    }
    else
    {
        LOG_E("Fal partition (%s) test failed!", "param");
    }

2.7. 下载验证
f.png

  1. 添加easyflash 组件,这里要注意一下

g.png
3.1. env中开启easyflash组件,这里2048是l4的页大小,我的env存储空间也是2048
h.png
3.2. 对应修改“packagesEasyFlash-v3.0.0SConscript”,为如下
i.png
3.3. 修改“ef_fal_port.c”中文件,并在main中加入如下测试代码
j.png

k.png

3.4. 下载验证
l.png
我们看着是成功了,但是问题:
EF_ENV_USING_LEGACY_MODE 我从头到位都没设置呢?

  1. ulog_easyflash移植

4.1. env中开启ulog_easyflash组件
m.png

n.png

4.2. 下载验证
o.png

4.3. 问题分析
这个时候,ulog的存储在flash上就有问题了,报警的问题是8字节对齐,和写入错误,查看drv_flash_l4.c 中的write发现了,如下:

int stm32_flash_write(rt_uint32_t addr, const uint8_t *buf, size_t size)
{
    size_t i, j;
    rt_err_t result = 0;
    rt_uint64_t write_data = 0, temp_data = 0;

    if ((addr + size) > STM32_FLASH_END_ADDRESS)
    {
        LOG_E("ERROR: write outrange flash size! addr is (0x%p)\n", (void*)(addr + size));
        return -RT_EINVAL;
    }

    if(addr % 8 != 0)
    {
        LOG_E("write addr must be 8-byte alignment");
        return -RT_EINVAL;
    }

    HAL_FLASH_Unlock();

    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR);

    if (size < 1)
    {
        return -RT_ERROR;
    }

    for (i = 0; i < size;)
    {
        if ((size - i) < 8)
        {
            for (j = 0; (size - i) > 0; i++, j++)
            {
                temp_data = *buf;
                write_data = (write_data) | (temp_data << 8 * j);
                buf ++;
            }
        }
        else
        {
            for (j = 0; j < 8; j++, i++)
            {
                temp_data = *buf;
                write_data = (write_data) | (temp_data << 8 * j);
                buf ++;
            }
        }

        /* write data */
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, addr, write_data) == HAL_OK)
        {
            /* Check the written value */
            if (*(uint64_t*)addr != write_data)
            {
                LOG_E("ERROR: write data != read data\n");
                result = -RT_ERROR;
                goto __exit;
            }
        }
        else
        {
            result = -RT_ERROR;
            goto __exit;
        }

        temp_data = 0;
        write_data = 0;

        addr += 8;
    }

__exit:
    HAL_FLASH_Lock();
    if (result != 0)
    {
        return result;
    }

    return size;
}

就是说,写入的时候是8字节对齐,但是作为后端的设备,我不能保证每次写入都是8字节对齐呢。

问题

  1. EF_ENV_USING_LEGACY_MODE 我从头到位都没设置呢?
  2. ulog_easyflash是不是不能在L4的片上flash使用,还是我思考的有问题呢,有大佬路过麻烦指点一下。

查看更多

关注者
1
被浏览
389
2 个回答
RemyShi
RemyShi 2021-01-26

遇到同样的问题。之前移植EasyFlash时,作者提示过STM32L4系列只能用V3版本。不知道ulog_easyflash有没有在L4系列上经过测试,地址对齐的问题我解决了部分。
ulog_easyflash_be.c

static void ulog_easyflash_backend_output(struct ulog_backend *backend, rt_uint32_t level, const char *tag, rt_bool_t is_raw,
        const char *log, size_t len)
{
    /* write some '\r' for word alignment */
    // 原代码为char write_overage_c[4] = { '\r', '\r', '\r', '\r'};
    char write_overage_c[8] = { '\r', '\r', '\r', '\r', '\r', '\r', '\r', '\r'};
    size_t write_size_temp = 0;
    EfErrCode result = EF_NO_ERR;

    /* saving level filter for flash log */
    if (level <= log_saving_lvl)
    {
        /* calculate the word alignment write size */
        // 源代码为write_size_temp = RT_ALIGN_DOWN(len, 4);
        write_size_temp = RT_ALIGN_DOWN(len, 8);

        result = ef_log_write((uint32_t *) log, write_size_temp);
        /* write last word alignment data */
        if ((result == EF_NO_ERR) && (write_size_temp != len))
        {
            memcpy(write_overage_c, log + write_size_temp, len - write_size_temp);
            ef_log_write((uint32_t *) write_overage_c, sizeof(write_overage_c));
        }
    }
}

能存储一部分log,之后亦出现写入错误问题。如果楼主解决问题,麻烦交流下经验。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览