Răsfoiți Sursa

[bsp][bouffalo] add hwtimer & flash driver support (#7203)

* add hwtimer & flash driver support
WCX 2 ani în urmă
părinte
comite
b2f2825456

+ 66 - 0
bsp/bouffalo_lab/bl808/m0/applications/dfs_mnt_sample.c

@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2023-04-08     wcx1024979076     first version
+ */
+ /*
+ * 程序清单:这是一个 dfs 虚拟文件系统挂载文件系统使用例程
+ * 例程导出了 mnt_init 命令到应用初始化中
+ * 程序功能:挂载 elm 文件系统到片上flash filesystem 分区中
+ * 使用前参考文章 https://blog.csdn.net/h451884098/article/details/118544347 和 https://blog.csdn.net/u013213069/article/details/117384971 开启以下配置:
+ * 1、修改 menuconfig 打开RT_USING_DFS 和 elm-chan 文件系统并修改扇区 sector 大小为 4096
+ * 2、修改 components/dfs/dfs_v1/include/dfs.h 和 components/dfs/dfs_v2/include/dfs.h 中 SECTOR_SIZE 改为 4096
+ * 3、修改芯片外设配置打开 BSP_USING_ON_CHIP_FLASH
+ * 4、修改 menuconfig 打开 RT_USING_FAL 配置
+*/
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef RT_USING_DFS
+#ifdef RT_USING_FAL
+#ifdef BSP_USING_ON_CHIP_FLASH
+
+#include "dfs_file.h"
+#include "fal.h"
+
+int mnt_init(void)
+{
+    struct rt_device *rootfs = RT_NULL;
+
+    /* 使用 filesystem 分区创建块设备,块设备名称为 filesystem */
+    rootfs = fal_blk_device_create("filesystem");
+    if(rootfs == RT_NULL)
+        return -RT_ERROR;
+
+    /* 将 elm fat 文件系统挂载 filesystem 分区 */
+    if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0)
+    {
+        rt_kprintf("file system initialization done!\n");
+    }
+    else
+    {
+        if(dfs_mkfs("elm", "filesystem") == 0)
+        {
+            if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0)
+            {
+                rt_kprintf("file system initialization done!\n");
+            }
+            else
+            {
+                rt_kprintf("file system initialization failed!\n");
+            }
+        }
+    }
+
+    return RT_EOK;
+}
+
+INIT_APP_EXPORT(mnt_init);
+
+#endif /* RT_USING_DFS */
+#endif /* RT_USING_FAL */
+#endif /* BSP_USING_ON_CHIP_FLASH */

+ 91 - 0
bsp/bouffalo_lab/bl808/m0/applications/hwtimer_sample.c

@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2023-04-01     wcx1024979076  first version.
+ */
+/*
+ * 程序清单:这是一个 hwtimer 设备使用例程
+ * 例程导出了 hwtimer_sample 命令到控制终端
+ * 命令调用格式:hwtimer_sample
+ * 程序功能:硬件定时器超时回调函数周期性的打印当前tick值,2次tick值之差换算为时间等同于定时时间值。
+*/
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#ifdef RT_USING_HWTIMER
+
+#define HWTIMER_DEV_NAME   "timer0"     /* 定时器名称 */
+
+/* 定时器超时回调函数 */
+static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
+{
+    rt_kprintf("this is hwtimer timeout callback fucntion!\n");
+    rt_kprintf("tick is :%d !\n", rt_tick_get());
+
+    return 0;
+}
+
+static int hwtimer_sample(int argc, char *argv[])
+{
+    rt_err_t ret = RT_EOK;
+    rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
+    rt_device_t hw_dev = RT_NULL;   /* 定时器设备句柄 */
+    rt_hwtimer_mode_t mode;         /* 定时器模式 */
+    rt_uint32_t freq = 10000;               /* 计数频率 */
+
+    /* 查找定时器设备 */
+    hw_dev = rt_device_find(HWTIMER_DEV_NAME);
+    if (hw_dev == RT_NULL)
+    {
+        rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEV_NAME);
+        return -RT_ERROR;
+    }
+
+    /* 以读写方式打开设备 */
+    ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("open %s device failed!\n", HWTIMER_DEV_NAME);
+        return ret;
+    }
+
+    /* 设置超时回调函数 */
+    rt_device_set_rx_indicate(hw_dev, timeout_cb);
+
+    /* 设置计数频率(若未设置该项,默认为1Mhz 或 支持的最小计数频率) */
+    rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);
+    /* 设置模式为周期性定时器(若未设置,默认是HWTIMER_MODE_ONESHOT)*/
+    mode = HWTIMER_MODE_PERIOD;
+    ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("set mode failed! ret is :%d\n", ret);
+        return ret;
+    }
+
+    /* 设置定时器超时值为2s并启动定时器 */
+    timeout_s.sec = 2;      /* 秒 */
+    timeout_s.usec = 0;     /* 微秒 */
+    if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
+    {
+        rt_kprintf("set timeout value failed\n");
+        return -RT_ERROR;
+    }
+
+    /* 延时1500ms */
+    rt_thread_mdelay(1500);
+
+    /* 读取定时器当前值 */
+    rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
+    rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
+
+    return ret;
+}
+/* 导出到 msh 命令列表中 */
+MSH_CMD_EXPORT(hwtimer_sample, hwtimer sample);
+
+#endif /* RT_USING_HWTIMER */

+ 35 - 0
bsp/bouffalo_lab/bl808/m0/board/fal_cfg.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2023-04-08     wcx1024979076  the first version
+ */
+
+#ifndef _FAL_CFG_H_
+#define _FAL_CFG_H_
+
+#include <rtconfig.h>
+#include <board.h>
+
+/* ===================== Flash device Configuration ========================= */
+extern const struct fal_flash_dev _onchip_flash;
+
+/* flash device table */
+#define FAL_FLASH_DEV_TABLE                                          \
+{                                                                    \
+    &_onchip_flash,                                                  \
+}
+/* ====================== Partition Configuration ========================== */
+#ifdef FAL_PART_HAS_TABLE_CFG
+/* partition table */
+#define FAL_PART_TABLE                                                                       \
+{                                                                                            \
+    {FAL_PART_MAGIC_WORD,         "bl", "bflb_onchip",               0, 8 * 1024 * 1024, 0}, \
+    {FAL_PART_MAGIC_WORD, "filesystem", "bflb_onchip", 8 * 1024 * 1024, 8 * 1024 * 1024, 0}, \
+}
+#endif /* FAL_PART_HAS_TABLE_CFG */
+
+#endif /* _FAL_CFG_H_ */

+ 17 - 0
bsp/bouffalo_lab/libraries/rt_drivers/Kconfig

@@ -158,5 +158,22 @@ menu "General Drivers Configuration"
                 default n
         endif
 
+    menuconfig BSP_USING_HWTIMER
+        bool "Enable HWTIMER"
+        default n
+        select RT_USING_HWTIMER
+        if BSP_USING_HWTIMER
+            config BSP_USING_TIMER0
+                bool "Enable TIMER0"
+                default n
+            config BSP_USING_TIMER1
+                bool "Enable TIMER1"
+                default n
+        endif
+
+    config BSP_USING_ON_CHIP_FLASH
+        bool "Enable on-chip FLASH"
+        default n
+    
 endmenu
 

+ 6 - 0
bsp/bouffalo_lab/libraries/rt_drivers/SConscript

@@ -24,6 +24,12 @@ if GetDepend('RT_USING_PWM'):
 if GetDepend('RT_USING_WDT'):
     src += ['drv_wdt.c']
 
+if GetDepend('BSP_USING_HWTIMER'):
+    src += ['drv_hwtimer.c']
+
+if GetDepend('BSP_USING_ON_CHIP_FLASH'):
+    src += ['drv_flash.c']
+
 group = DefineGroup('rt_drivers', src, depend = [''], CPPPATH = CPPPATH)
 
 objs = [group]

+ 145 - 0
bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.c

@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2023-04-08     wcx1024979076     first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#ifdef BSP_USING_ON_CHIP_FLASH
+#include "drv_flash.h"
+
+#ifdef RT_USING_FAL
+    #include "fal.h"
+#endif /* RT_USING_FAL */
+
+#define DBG_LEVEL DBG_LOG
+#define LOG_TAG  "DRV.FLASH"
+#include <rtdbg.h>
+
+#define BFLB_FLASH_START_ADRESS 0x58000000
+#define BFLB_FLASH_SIZE         16 * 1024 * 1024
+#define BFLB_FLASH_PAGE_SIZE    4 * 1024
+#define BFLB_FLASH_END_ADDRESS  0x59000000
+
+int _flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
+{
+    rt_err_t result = RT_EOK;
+
+    if ((addr + size) > BFLB_FLASH_END_ADDRESS)
+    {
+        LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
+        return -RT_EINVAL;
+    }
+
+    result = bflb_flash_read(addr - BFLB_FLASH_START_ADRESS, buf, size);
+
+    if(result != RT_EOK)
+    {
+        LOG_E("READ ERROR result = %d, addr = %d, addr1 = %d, len = %d", result, addr, addr - BFLB_FLASH_START_ADRESS, size);
+        return -RT_ERROR;
+    }
+    else
+    {
+        return size;
+    }
+}
+
+int _flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
+{
+    rt_err_t result        = RT_EOK;
+    rt_uint32_t end_addr   = addr + size;
+
+    if (addr % 4 != 0)
+    {
+        LOG_E("write addr must be 4-byte alignment");
+        return -RT_EINVAL;
+    }
+
+    if ((end_addr) > BFLB_FLASH_END_ADDRESS)
+    {
+        LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
+        return -RT_EINVAL;
+    }
+
+    result = bflb_flash_write(addr - BFLB_FLASH_START_ADRESS, buf, size);
+
+    if(result != RT_EOK)
+    {
+        LOG_E("WRITE ERROR result = %d, addr = %d, addr1 = %d, len = %d", result, addr,  addr - BFLB_FLASH_START_ADRESS, size);
+        return -RT_ERROR;
+    }
+    else
+    {
+        return size;
+    }
+}
+
+int _flash_erase(rt_uint32_t addr, size_t size)
+{
+    rt_err_t result = RT_EOK;
+    rt_uint32_t end_addr = addr + size;
+    rt_uint32_t page_addr = 0;
+
+    if ((end_addr) > BFLB_FLASH_END_ADDRESS)
+    {
+        LOG_E("erase outrange flash size! addr is (0x%p)", (void *)(addr + size));
+        return -RT_EINVAL;
+    }
+
+    result = bflb_flash_erase(addr - BFLB_FLASH_START_ADRESS, size);
+
+    if (result != RT_EOK)
+    {
+        LOG_E("ERASE ERROR result = %d, addr = %d, addr1 = %d, size = %d", result, addr,  addr - BFLB_FLASH_START_ADRESS, size);
+        return -RT_ERROR;
+    }
+    else
+    {
+        return size;
+    }
+}
+
+#ifdef RT_USING_FAL
+
+static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size);
+static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size);
+static int fal_flash_erase(long offset, size_t size);
+
+const struct fal_flash_dev _onchip_flash =
+{
+    "bflb_onchip",
+    BFLB_FLASH_START_ADRESS,
+    BFLB_FLASH_SIZE,
+    BFLB_FLASH_PAGE_SIZE,
+    {
+        NULL,
+        fal_flash_read,
+        fal_flash_write,
+        fal_flash_erase
+    }
+};
+
+static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size)
+{
+    return _flash_read(_onchip_flash.addr + offset, buf, size);
+}
+
+static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size)
+{
+    return _flash_write(_onchip_flash.addr + offset, buf, size);
+}
+
+static int fal_flash_erase(long offset, size_t size)
+{
+    return _flash_erase(_onchip_flash.addr + offset, size);
+}
+
+INIT_DEVICE_EXPORT(fal_init);
+#endif /* RT_USING_FAL */
+#endif /* BSP_USING_ON_CHIP_FLASH */

+ 21 - 0
bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.h

@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2023-04-08     wcx1024979076     first version
+ */
+
+#ifndef __DRV_FLASH_H__
+#define __DRV_FLASH_H__
+
+#include "bflb_flash.h"
+#include "board.h"
+
+int _flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size);
+int _flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size);
+int _flash_erase(rt_uint32_t addr, size_t size);
+
+#endif  /* __DRV_FLASH_H__ */

+ 199 - 0
bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.c

@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date             Author           Notes
+ * 2023-04-01       wcx1024979076    first version
+ */
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define DBG_LEVEL   DBG_LOG
+#include <rtdbg.h>
+#define LOG_TAG "DRV.HWTIMER"
+
+#ifdef RT_USING_HWTIMER
+
+#include "drv_hwtimer.h"
+
+typedef struct _gptimer
+{
+    const char *name;
+    rt_hwtimer_t timer;
+    struct bflb_device_s *bflb_timer;
+} _gptimer_t;
+
+static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state);
+static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode);
+static void _hwtimer_stop(rt_hwtimer_t *timer);
+static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer);
+static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args);
+
+static void _hwtmr_isr(_gptimer_t *gptmr);
+
+static const struct rt_hwtimer_ops _hwtimer_ops = {
+    .init = _hwtimer_init,
+    .start = _hwtimer_start,
+    .stop = _hwtimer_stop,
+    .count_get = _hwtimer_count_get,
+    .control = _hwtimer_control
+};
+
+static const struct rt_hwtimer_info _hwtimer_info = {
+    .maxfreq = 1000000UL,
+    .minfreq = 1000000UL,
+    .maxcnt = 0xFFFFFFFFUL,
+    .cntmode = HWTIMER_MODE_PERIOD
+};
+
+#ifdef BSP_USING_TIMER0
+static _gptimer_t timer0 = {.name = "timer0"};
+#endif /* BSP_USING_TIMER0 */
+#ifdef BSP_USING_TIMER1
+static _gptimer_t timer1 = {.name = "timer1" };
+#endif /* BSP_USING_TIMER1 */
+
+static _gptimer_t *s_gptimers[] = {
+#ifdef BSP_USING_TIMER0
+       &timer0,
+#endif  /* BSP_USING_TIMER0 */
+#ifdef BSP_USING_TIMER1
+       &timer1,
+#endif /* BSP_USING_TIMER1 */
+    };
+
+#ifdef BSP_USING_TIMER0
+void timer0_isr(int irq, void *arg)
+{
+    _hwtmr_isr(&timer0);
+}
+#endif  /* BSP_USING_TIMER0 */
+
+#ifdef BSP_USING_TIMER1
+void timer1_isr(int irq, void *arg)
+{
+    _hwtmr_isr(&timer1);
+}
+#endif  /* BSP_USING_TIMER1 */
+
+static void _hwtmr_isr(_gptimer_t *timer)
+{
+    bool hwtmr_stat = bflb_timer_get_compint_status(timer->bflb_timer, TIMER_COMP_ID_0);
+    if (hwtmr_stat)
+    {
+        rt_device_hwtimer_isr(&timer->timer);
+        bflb_timer_compint_clear(timer->bflb_timer, TIMER_COMP_ID_0);
+    }
+}
+
+static void _hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
+{
+    _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
+
+    struct bflb_timer_config_s cfg;
+    cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
+    cfg.clock_source = TIMER_CLKSRC_XTAL;
+    cfg.clock_div = 40;
+    cfg.trigger_comp_id = TIMER_COMP_ID_0;
+    cfg.comp0_val = 0;
+    cfg.comp1_val = 0;
+    cfg.comp2_val = 0;
+    cfg.preload_val = 0;
+
+    bflb_timer_init(_gptmr->bflb_timer, &cfg);
+}
+
+static rt_err_t _hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
+{
+    _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
+
+    struct bflb_timer_config_s cfg;
+    if(mode == HWTIMER_MODE_ONESHOT)
+        cfg.counter_mode = TIMER_COUNTER_MODE_UP;
+    else
+        cfg.counter_mode = TIMER_COUNTER_MODE_PROLOAD;
+    cfg.clock_source = TIMER_CLKSRC_XTAL;
+    cfg.clock_div = 40;
+    cfg.trigger_comp_id = TIMER_COMP_ID_0;
+    cfg.comp0_val = cnt;
+    cfg.comp1_val = cnt;
+    cfg.comp2_val = cnt;
+    cfg.preload_val = 0;
+
+    bflb_timer_init(_gptmr->bflb_timer, &cfg);
+    bflb_irq_enable(_gptmr->bflb_timer->irq_num);
+    bflb_timer_start(_gptmr->bflb_timer);
+
+    return RT_EOK;
+}
+
+static void _hwtimer_stop(rt_hwtimer_t *timer)
+{
+    _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
+    bflb_timer_stop(_gptmr->bflb_timer);
+}
+
+static rt_uint32_t _hwtimer_count_get(rt_hwtimer_t *timer)
+{
+    _gptimer_t *_gptmr = (_gptimer_t*)timer->parent.user_data;
+
+    rt_uint32_t current_cnt = bflb_timer_get_countervalue(_gptmr->bflb_timer);
+
+    return current_cnt;
+}
+
+static rt_err_t _hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
+{
+    rt_err_t err = RT_EOK;
+    _gptimer_t *_gptmr = (_gptimer_t*) timer->parent.user_data;
+    switch (cmd)
+    {
+    case HWTIMER_CTRL_FREQ_SET:
+        err = -RT_ERROR;
+        break;
+    case HWTIMER_CTRL_INFO_GET:
+        *(rt_hwtimer_t*)args = _gptmr->timer;
+        break;
+    case HWTIMER_CTRL_MODE_SET:
+        _gptmr->timer.mode = *(rt_uint32_t*)args;
+        break;
+    case HWTIMER_CTRL_STOP:
+        bflb_timer_stop(_gptmr->bflb_timer);
+        break;
+    }
+
+    return err;
+}
+
+
+int rt_hw_hwtimer_init(void)
+{
+    int ret = RT_EOK;
+    for (uint32_t i = 0; i < sizeof(s_gptimers) / sizeof(s_gptimers[0]); i++)
+    {
+        s_gptimers[i]->timer.info = &_hwtimer_info;
+        s_gptimers[i]->timer.ops = &_hwtimer_ops;
+        s_gptimers[i]->bflb_timer = bflb_device_get_by_name(s_gptimers[i]->name);
+        ret = rt_device_hwtimer_register(&s_gptimers[i]->timer, s_gptimers[i]->name, s_gptimers[i]);
+        if (ret != RT_EOK)
+        {
+            LOG_E("%s register failed", s_gptimers[i]->name);
+        }
+    }
+
+#ifdef BSP_USING_TIMER0
+    bflb_irq_attach(bflb_device_get_by_name("timer0")->irq_num, timer0_isr, NULL);
+#endif  /* BSP_USING_TIMER0 */
+
+#ifdef BSP_USING_TIMER1
+    bflb_irq_attach(bflb_device_get_by_name("timer1")->irq_num, timer1_isr, NULL);
+#endif  /* BSP_USING_TIMER1 */
+
+    return ret;
+}
+
+INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
+#endif /* RT_USING_HWTIMER */

+ 19 - 0
bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.h

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date             Author           Notes
+ * 2023-04-01       wcx1024979076    first version
+ */
+
+#ifndef DRV_HWTIMER_H
+#define DRV_HWTIMER_H
+#include "bflb_timer.h"
+#include "bflb_mtimer.h"
+#include "board.h"
+
+int rt_hw_hwtimer_init(void);
+
+#endif /* DRV_HWTIMER_H */