Sfoglia il codice sorgente

Merge pull request #4255 from greedyhao/bluetrum

[bsp][bluetrum] add sdio support
Bernard Xiong 4 anni fa
parent
commit
e81f1a0eec
24 ha cambiato i file con 1398 aggiunte e 275 eliminazioni
  1. 7 0
      bsp/bluetrum/ab32vg1-ab-prougen/.config
  2. 125 152
      bsp/bluetrum/ab32vg1-ab-prougen/.cproject
  3. 6 6
      bsp/bluetrum/ab32vg1-ab-prougen/README.md
  4. 1 1
      bsp/bluetrum/ab32vg1-ab-prougen/applications/main.c
  5. 49 9
      bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c
  6. 0 17
      bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c
  7. 19 0
      bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig
  8. 24 7
      bsp/bluetrum/ab32vg1-ab-prougen/link.lds
  9. 2 5
      bsp/bluetrum/ab32vg1-ab-prougen/makefile.targets
  10. 2 0
      bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h
  11. 6 2
      bsp/bluetrum/libraries/hal_drivers/SConscript
  12. 9 0
      bsp/bluetrum/libraries/hal_drivers/config/pwm_config.h
  13. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_common.h
  14. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_gpio.c
  15. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_gpio.h
  16. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_log.h
  17. 658 0
      bsp/bluetrum/libraries/hal_drivers/drv_sdio.c
  18. 140 0
      bsp/bluetrum/libraries/hal_drivers/drv_sdio.h
  19. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_usart.c
  20. 2 2
      bsp/bluetrum/libraries/hal_drivers/drv_usart.h
  21. 1 1
      bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_conf.h
  22. 50 12
      bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_sd.h
  23. 21 1
      bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_ll_sdio.h
  24. 266 50
      bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c

+ 7 - 0
bsp/bluetrum/ab32vg1-ab-prougen/.config

@@ -381,6 +381,7 @@ CONFIG_RT_USING_LIBC=y
 # CONFIG_PKG_USING_UC_MODBUS is not set
 # CONFIG_PKG_USING_PPOOL is not set
 # CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_RT_PRINTF is not set
 
 #
 # peripheral libraries and drivers
@@ -501,11 +502,17 @@ CONFIG_RT_USING_LIBC=y
 CONFIG_BSP_USING_USB_TO_USART=y
 CONFIG_BSP_USING_AUDIO=y
 CONFIG_BSP_USING_AUDIO_PLAY=y
+# CONFIG_BSP_USING_SDCARD is not set
 
 #
 # On-chip Peripheral Drivers
 #
 CONFIG_BSP_USING_UART0=y
+# CONFIG_BSP_USING_SDIO is not set
+
+#
+# On-chip Peripheral Drivers
+#
 
 #
 # Board extended module Drivers

File diff suppressed because it is too large
+ 125 - 152
bsp/bluetrum/ab32vg1-ab-prougen/.cproject


+ 6 - 6
bsp/bluetrum/ab32vg1-ab-prougen/README.md

@@ -12,7 +12,7 @@
 
 ## 开发板介绍
 
-ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核的开发板,最高主频为 120Mhz,该开发板芯片为 AB5301A
+ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核的开发板,最高主频为 120Mhz,该开发板芯片为 AB32VG1
 
 开发板外观如下图所示:
 
@@ -20,7 +20,7 @@ ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核
 
 该开发板常用 **板载资源** 如下:
 
-- MCU:AB5301A,主频 120MHz,可超频至 192MHz,4Mbit FLASH ,192KB RAM。
+- MCU:AB32VG1,主频 120MHz,可超频至 192MHz,8Mbit FLASH ,192KB RAM。
 - 常用外设
   - LED: RGB灯
   - 按键: 3 个, USER(s2,s3) and RESET(s1)
@@ -33,9 +33,9 @@ ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核
 | **板载外设** | **支持情况** | **备注**    |
 | :----------- | :----------: | :---------- |
 | USB 转串口   |     支持     |             |
-| SD卡         |   即将支持   |             |
+| SD卡         |     支持     |             |
 | IRDA         |   即将支持   |             |
-| 音频接口     |   即将支持   |             |
+| 音频接口     |     支持     |             |
 | **片上外设** | **支持情况** | **备注**    |
 | GPIO         |     支持     | PA PB PE PF |
 | UART         |     支持     | UART0/1/2   |
@@ -73,11 +73,11 @@ ab32vg1-prougen 是 中科蓝讯(Bluetrum) 推出的一款基于 RISC-V 内核
 
 #### 编译下载
 
-运行 `scons` 编译得到 `.dcf` 固件,通过 `downloader` 进行下载
+通过 `RT-Thread Studio` 或者 `scons` 编译得到 `.dcf` 固件,通过 `Downloader` 进行下载
 
 #### 运行结果
 
-下载程序成功之后,系统会自动运行,观察开发板上 LED 的运行效果,红色 LED 常亮、绿色 LED 会周期性闪烁。
+下载程序成功之后,系统会自动运行,观察开发板上 LED 的运行效果,红色 LED 会周期性闪烁。
 
 连接开发板对应串口到 PC , 在终端工具里打开相应的串口(115200-8-1-N),复位设备后,可以看到 RT-Thread 的输出信息:
 

+ 1 - 1
bsp/bluetrum/ab32vg1-ab-prougen/applications/main.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
+ * Copyright (c) 2020-2021, Bluetrum Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *

+ 49 - 9
bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c

@@ -1,21 +1,61 @@
+/*
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021/01/21     greedyhao    The first version
+ */
+
 #include <rtthread.h>
 
-#ifdef RT_USING_DFS
+#ifdef BSP_USING_SDIO
+
+#include <dfs_elm.h>
 #include <dfs_fs.h>
-#include "dfs_romfs.h"
+#include <dfs_posix.h>
+#include "drv_gpio.h"
+
+// #define DRV_DEBUG
+#define DBG_TAG "app.card"
+#include <rtdbg.h>
+
+void sd_mount(void *parameter)
+{
+    while (1)
+    {
+        rt_thread_mdelay(500);
+        if(rt_device_find("sd0") != RT_NULL)
+        {
+            if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)
+            {
+                LOG_I("sd card mount to '/'");
+                break;
+            }
+            else
+            {
+                LOG_W("sd card mount to '/' failed!");
+            }
+        }
+    }
+}
 
-int mnt_init(void)
+int ab32_sdcard_mount(void)
 {
-    if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0)
+    rt_thread_t tid;
+
+    tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,
+                           1024, RT_THREAD_PRIORITY_MAX - 2, 20);
+    if (tid != RT_NULL)
     {
-        rt_kprintf("ROM file system initializated!\n");
+        rt_thread_startup(tid);
     }
     else
     {
-        rt_kprintf("ROM file system initializate failed!\n");
+        LOG_E("create sd_mount thread err!");
     }
-
-    return 0;
+    return RT_EOK;
 }
-INIT_ENV_EXPORT(mnt_init);
+INIT_APP_EXPORT(ab32_sdcard_mount);
 #endif

+ 0 - 17
bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c

@@ -1,17 +0,0 @@
-/* Generated by mkromfs. Edit with caution. */
-#include <rtthread.h>
-
-#ifdef RT_USING_DFS
-#include <dfs_romfs.h>
-
-
-
-static const struct romfs_dirent _romfs_root[] = {
-    {ROMFS_DIRENT_FILE, "ab32vg1", RT_NULL, 0}
-};
-
-const struct romfs_dirent romfs_root = {
-    ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, sizeof(_romfs_root)/sizeof(_romfs_root[0])
-};
-
-#endif

+ 19 - 0
bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig

@@ -19,6 +19,18 @@ menu "Onboard Peripheral Drivers"
             default y
         endif
 
+    config BSP_USING_SDCARD
+        bool "Enable SDCARD"
+        select BSP_USING_SDIO
+        default n
+
+    if BSP_USING_SDCARD
+    config SDIO_MAX_FREQ
+        int "sdio max freq"
+        range 0 24000000
+        default 24000000
+    endif
+
 endmenu
 
 menu "On-chip Peripheral Drivers"
@@ -28,6 +40,13 @@ menu "On-chip Peripheral Drivers"
         select RT_USING_SERIAL
         default y
 
+    config BSP_USING_SDIO
+        bool "Enable SDIO"
+        select RT_USING_SDIO
+        select RT_USING_DFS
+        select RT_USING_DFS_ELMFAT
+        default n
+
 endmenu
 
 menu "Board extended module Drivers"

+ 24 - 7
bsp/bluetrum/ab32vg1-ab-prougen/link.lds

@@ -34,9 +34,17 @@ SECTIONS
     } > init
 
     .ram1 __ram1_vma : {
-        *components*drivers**.o(.text* .rodata*)
-        *device.o(.text*)
-        . = ALIGN(32);
+        . = ALIGN(4);
+        PROVIDE(__ctors_start__ = .);
+        KEEP (*(SORT(.init_array.*)))
+        KEEP (*(.init_array))
+        PROVIDE(__ctors_end__ = .);
+
+        . = ALIGN(4);
+        *components*drivers**.o (.text*)
+        *device.o (.text*)
+        *components.o (.text*)
+        *idle.o (.text*)
     } > ram1 AT > flash
 
     .rti : {
@@ -60,15 +68,23 @@ SECTIONS
     } > ram1 AT > flash
 
     .comm : {
+        . = ALIGN(4);
         KEEP(*(.vector))
-        EXCLUDE_FILE(*components*finsh**.o *components*libc**.o *romfs.o *lib_a**.o) *(.text*)
+        EXCLUDE_FILE(*components*finsh**.o *components*libc**.o *romfs.o 
+        *lib_a**.o *divdi3.o *moddi3.o *divdf3.o *muldf3.o *eqtf2.o *getf2.o
+        *letf2.o *multf3.o *subtf3.o *fixtfsi.o *floatsitf.o *extenddftf2.o
+        *trunctfdf2.o *_clzsi2.o *cp-demangle.o *unwind*.o) *(.text)
         *finsh*shell.o (.text*)
-        EXCLUDE_FILE (*components*libc**.o *romfs.o *lib_a**.o) *(.rodata*)
-        *(.srodata*)
+        *(.text.unlikely)
+        *(.text.startup)
+        EXCLUDE_FILE (*components*libc**.o *romfs.o *lib_a**.o *cp-demangle.o
+        *divdf3.o *muldf3.o *multf3.o *unwind*.o *_clz.o) *(.rodata)
+        *(.rodata.name)
+        EXCLUDE_FILE(*lib_a**.o *cp-demangle.o) *(.rodata.str1.4)
+        EXCLUDE_FILE(*lib_a**.o *unwind*.o) *(.srodata)
         *(.rela*)
         *(.data*)
 	    *(.sdata*)
-        . = ALIGN(512);
     } > comm AT > flash
 
     .bss (NOLOAD):
@@ -98,6 +114,7 @@ SECTIONS
     .flash : {
         *(.text*)
         *(.rodata*)
+        *(.srodata*)
         . = ALIGN(512);
     } > flash
 }

+ 2 - 5
bsp/bluetrum/ab32vg1-ab-prougen/makefile.targets

@@ -1,13 +1,10 @@
-rtthread.siz:
-	riscv64-unknown-elf-size --format=berkeley "rtthread.elf"
+all2: all
 	sh ../pre_build.sh
 	riscv32-elf-xmaker -b rtthread.xm
 	riscv32-elf-xmaker -b download.xm
-
+	
 clean2:
 	-$(RM) $(CC_DEPS)$(C++_DEPS)$(C_UPPER_DEPS)$(CXX_DEPS)$(SECONDARY_FLASH)$(SECONDARY_SIZE)$(ASM_DEPS)$(S_UPPER_DEPS)$(C_DEPS)$(CPP_DEPS)
 	-$(RM) $(OBJS) *.elf
 	-@echo ' '
 
-
-*.elf: $(wildcard D:/Softwares/RT-ThreadStudio/workspace/ab32vg1/link.lds)

+ 2 - 0
bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h

@@ -176,6 +176,8 @@
 
 #define BSP_USING_UART0
 
+/* On-chip Peripheral Drivers */
+
 /* Board extended module Drivers */
 
 #define BOARD_BLUETRUM_EVB

+ 6 - 2
bsp/bluetrum/libraries/hal_drivers/SConscript

@@ -4,7 +4,8 @@ from building import *
 
 cwd     = GetCurrentDir()
 src     = []
-CPPPATH = [cwd]
+path    = [cwd]
+path   += [cwd + '/config']
 
 if GetDepend('RT_USING_PIN'):
     src += ['drv_gpio.c']
@@ -12,7 +13,10 @@ if GetDepend('RT_USING_PIN'):
 if GetDepend('RT_USING_SERIAL'):
     src += ['drv_usart.c']
 
-group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+if GetDepend('RT_USING_SDIO'):
+    src += ['drv_sdio.c']
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
 
 objs = [group]
 

+ 9 - 0
bsp/bluetrum/libraries/hal_drivers/config/pwm_config.h

@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2021/01/18     greedyhao    The first version
+ */

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_common.h

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_gpio.c

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_gpio.h

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_log.h

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 658 - 0
bsp/bluetrum/libraries/hal_drivers/drv_sdio.c

@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-11-30     greedyhao         first version
+ */
+
+#include "drv_sdio.h"
+#include "interrupt.h"
+#include <rthw.h>
+
+#ifdef BSP_USING_SDIO
+
+// #define DRV_DEBUG
+#define LOG_TAG             "drv.sdio"
+#include <drv_log.h>
+
+#define SDIO_USING_1_BIT
+
+static struct ab32_sdio_config sdio_config[] =
+{
+    {.instance = SDMMC0_BASE,
+    },
+};
+static struct rt_mmcsd_host *host = RT_NULL;
+
+#define RTHW_SDIO_LOCK(_sdio)   rt_mutex_take(&(_sdio)->mutex, RT_WAITING_FOREVER)
+#define RTHW_SDIO_UNLOCK(_sdio) rt_mutex_release(&(_sdio)->mutex);
+
+struct sdio_pkg
+{
+    struct rt_mmcsd_cmd *cmd;
+    void *buff;
+    rt_uint32_t flag;
+    rt_uint32_t xfer_blks;
+};
+
+struct rthw_sdio
+{
+    struct rt_mmcsd_host *host;
+    struct ab32_sdio_des sdio_des;
+    struct rt_event event;
+    struct rt_mutex mutex;
+    struct sdio_pkg *pkg;
+};
+
+ALIGN(SDIO_ALIGN_LEN)
+static rt_uint8_t cache_buf[SDIO_BUFF_SIZE];
+
+static uint8_t sd_baud = 119;
+
+uint8_t sysclk_update_baud(uint8_t baud);
+
+static rt_uint32_t ab32_sdio_clk_get(hal_sfr_t hw_sdio)
+{
+    return (get_sysclk_nhz() / (sd_baud+1));
+}
+
+/**
+  * @brief  This function get order from sdio.
+  * @param  data
+  * @retval sdio  order
+  */
+static int get_order(rt_uint32_t data)
+{
+    int order = 0;
+
+    switch (data)
+    {
+    case 1:
+        order = 0;
+        break;
+    case 2:
+        order = 1;
+        break;
+    case 4:
+        order = 2;
+        break;
+    case 8:
+        order = 3;
+        break;
+    case 16:
+        order = 4;
+        break;
+    case 32:
+        order = 5;
+        break;
+    case 64:
+        order = 6;
+        break;
+    case 128:
+        order = 7;
+        break;
+    case 256:
+        order = 8;
+        break;
+    case 512:
+        order = 9;
+        break;
+    case 1024:
+        order = 10;
+        break;
+    case 2048:
+        order = 11;
+        break;
+    case 4096:
+        order = 12;
+        break;
+    case 8192:
+        order = 13;
+        break;
+    case 16384:
+        order = 14;
+        break;
+    default :
+        order = 0;
+        break;
+    }
+
+    return order;
+}
+
+/**
+  * @brief  This function wait sdio completed.
+  * @param  sdio  rthw_sdio
+  * @retval None
+  */
+static void rthw_sdio_wait_completed(struct rthw_sdio *sdio)
+{
+    rt_uint32_t status = 0;
+    struct rt_mmcsd_cmd *cmd = sdio->pkg->cmd;
+    struct rt_mmcsd_data *data = cmd->data;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+    rt_err_t tx_finish = -RT_ERROR;
+
+    if (rt_event_recv(&sdio->event, 0xFFFFFFFF & ~HW_SDIO_CON_DFLAG, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                        rt_tick_from_millisecond(5000), &status) != RT_EOK)
+    {
+        LOG_E("wait completed timeout");
+        cmd->err = -RT_ETIMEOUT;
+        return;
+    }
+
+    if (sdio->pkg == RT_NULL)
+    {
+        return;
+    }
+
+    cmd->resp[0] = hw_sdio[SDxARG3];
+    cmd->resp[1] = hw_sdio[SDxARG2];
+    cmd->resp[2] = hw_sdio[SDxARG1];
+    cmd->resp[3] = hw_sdio[SDxARG0];
+
+    if (!(status & HW_SDIO_CON_NRPS)) {
+        cmd->err = RT_EOK;
+        LOG_D("sta:0x%08X [%08X %08X %08X %08X]", status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
+    } else {
+        cmd->err = -RT_ERROR;
+    }
+}
+
+/**
+  * @brief  This function transfer data by dma.
+  * @param  sdio  rthw_sdio
+  * @param  pkg   sdio package
+  * @retval None
+  */
+static void rthw_sdio_transfer_by_dma(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
+{
+    struct rt_mmcsd_data *data;
+    int size;
+    void *buff;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+
+    if ((RT_NULL == pkg) || (RT_NULL == sdio))
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+
+    data = pkg->cmd->data;
+    if (RT_NULL == data)
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+
+    buff = pkg->buff;
+    if (RT_NULL == buff)
+    {
+        LOG_E("rthw_sdio_transfer_by_dma invalid args");
+        return;
+    }
+    hw_sdio = sdio->sdio_des.hw_sdio;
+    size = data->blks * data->blksize;
+
+    if (data->flags & DATA_DIR_WRITE)
+    {
+        LOG_D("DATA_DIR_WRITE %d", pkg->xfer_blks);
+        sdio->sdio_des.txconfig((rt_uint32_t *)((rt_uint8_t *)buff + (pkg->xfer_blks * data->blksize)), 512);
+    }
+    else if (data->flags & DATA_DIR_READ)
+    {
+        LOG_D("DATA_DIR_WRITE %d", pkg->xfer_blks);
+        sdio->sdio_des.rxconfig((rt_uint32_t *)((rt_uint8_t *)buff + (pkg->xfer_blks * data->blksize)), data->blksize);
+    }
+}
+
+/**
+  * @brief  This function send command.
+  * @param  sdio  rthw_sdio
+  * @param  pkg   sdio package
+  * @retval None
+  */
+static void rthw_sdio_send_command(struct rthw_sdio *sdio, struct sdio_pkg *pkg)
+{
+    struct rt_mmcsd_cmd *cmd = pkg->cmd;
+    struct rt_mmcsd_data *data = cmd->data;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+    rt_uint32_t reg_cmd = 0;
+    rt_uint32_t data_flag = 0;
+
+    /* save pkg */
+    sdio->pkg = pkg;
+
+    #define CK8E            BIT(11)             //在命令/数据包后加上8CLK
+    #define CBUSY           BIT(10)             //Busy Check
+    #define CLRSP           BIT(9)              //17Byte Long Rsp
+    #define CRSP            BIT(8)              //Need Rsp
+
+    /* config cmd reg */
+    if (cmd->cmd_code != 18) {
+        reg_cmd = cmd->cmd_code | 0x40 | CK8E;
+    } else {
+        reg_cmd = cmd->cmd_code | 0x40;
+    }
+
+    switch (resp_type(cmd))
+    {
+    case RESP_R1B:
+        reg_cmd |= CBUSY | CRSP;
+        break;
+    case RESP_R2:
+        reg_cmd |= CLRSP | CRSP;
+        break;
+    default:
+        reg_cmd |= CRSP;
+        break;
+    }
+
+    LOG_D("CMD:%d 0x%04X ARG:0x%08x RES:%s%s%s%s%s%s%s%s%s rw:%c len:%d blksize:%d",
+          cmd->cmd_code,
+          reg_cmd,
+          cmd->arg,
+          resp_type(cmd) == RESP_NONE ? "NONE"  : "",
+          resp_type(cmd) == RESP_R1  ? "R1"  : "",
+          resp_type(cmd) == RESP_R1B ? "R1B"  : "",
+          resp_type(cmd) == RESP_R2  ? "R2"  : "",
+          resp_type(cmd) == RESP_R3  ? "R3"  : "",
+          resp_type(cmd) == RESP_R4  ? "R4"  : "",
+          resp_type(cmd) == RESP_R5  ? "R5"  : "",
+          resp_type(cmd) == RESP_R6  ? "R6"  : "",
+          resp_type(cmd) == RESP_R7  ? "R7"  : "",
+          data ? (data->flags & DATA_DIR_WRITE ?  'w' : 'r') : '-',
+          data ? data->blks * data->blksize : 0,
+          data ? data->blksize : 0
+         );
+
+    /* config data reg */
+    if (data != RT_NULL)
+    {
+        rt_uint32_t dir = 0;
+        rt_uint32_t size = data->blks * data->blksize;
+        int order;
+
+        order = get_order(data->blksize);
+        dir = (data->flags & DATA_DIR_READ) ? HW_SDIO_TO_HOST : 0;
+
+        data_flag = data->flags;
+    }
+
+    /* transfer config */
+    if (data_flag & DATA_DIR_READ)
+    {
+        rthw_sdio_transfer_by_dma(sdio, pkg);
+    }
+
+    /* send cmd */
+    hw_sdio[SDxARG3] = cmd->arg;
+    hw_sdio[SDxCMD]  = reg_cmd;
+
+    /* wait cmd completed */
+    rthw_sdio_wait_completed(sdio);
+
+    /* transfer config */
+    if (data != RT_NULL)
+    {
+        do {
+            if ((data_flag & DATA_DIR_WRITE) || ((data_flag & DATA_DIR_READ) && (pkg->xfer_blks != 0))) {
+                rthw_sdio_transfer_by_dma(sdio, pkg);
+            }
+
+            rt_uint32_t status = 0;
+
+            if (rt_event_recv(&sdio->event, 0xFFFFFFFF & ~HW_SDIO_CON_DFLAG, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
+                            rt_tick_from_millisecond(5000), &status) != RT_EOK)
+            {
+                LOG_E("wait completed timeout");
+                LOG_E("SDxCON=0x%X SDxCMD=0x%X\n", hw_sdio[SDxCON], hw_sdio[SDxCMD]);
+                cmd->err = -RT_ETIMEOUT;
+            }
+
+            if (data_flag & DATA_DIR_WRITE) {
+                if (((hw_sdio[SDxCON] & HW_SDIO_CON_CRCS) >> 17) != 2) {
+                    LOG_E("Write CRC error!");
+                    cmd->err = -RT_ERROR;
+                    hw_sdio[SDxCPND] = HW_SDIO_CON_DFLAG;
+                }
+            }
+        } while(++pkg->xfer_blks != data->blks);
+    }
+
+    /* clear pkg */
+    sdio->pkg = RT_NULL;
+}
+
+/**
+  * @brief  This function send sdio request.
+  * @param  host  rt_mmcsd_host
+  * @param  req   request
+  * @retval None
+  */
+static void rthw_sdio_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
+{
+    struct sdio_pkg pkg;
+    struct rthw_sdio *sdio = host->private_data;
+    struct rt_mmcsd_data *data;
+
+    RTHW_SDIO_LOCK(sdio);
+
+    if (req->cmd != RT_NULL)
+    {
+        rt_memset(&pkg, 0, sizeof(pkg));
+        data = req->cmd->data;
+        pkg.cmd = req->cmd;
+
+        if (data != RT_NULL)
+        {
+            rt_uint32_t size = data->blks * data->blksize;
+
+            RT_ASSERT(size <= SDIO_BUFF_SIZE);
+
+            pkg.buff = data->buf;
+            if ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1))
+            {
+                pkg.buff = cache_buf;
+                if (data->flags & DATA_DIR_WRITE)
+                {
+                    rt_memcpy(cache_buf, data->buf, size);
+                }
+            }
+        }
+
+        rthw_sdio_send_command(sdio, &pkg);
+
+        if ((data != RT_NULL) && (data->flags & DATA_DIR_READ) && ((rt_uint32_t)data->buf & (SDIO_ALIGN_LEN - 1)))
+        {
+            rt_memcpy(data->buf, cache_buf, data->blksize * data->blks);
+        }
+    }
+
+    if (req->stop != RT_NULL)
+    {
+        rt_memset(&pkg, 0, sizeof(pkg));
+        pkg.cmd = req->stop;
+        rthw_sdio_send_command(sdio, &pkg);
+    }
+
+    RTHW_SDIO_UNLOCK(sdio);
+
+    mmcsd_req_complete(sdio->host);
+}
+
+/**
+  * @brief  This function config sdio.
+  * @param  host    rt_mmcsd_host
+  * @param  io_cfg  rt_mmcsd_io_cfg
+  * @retval None
+  */
+static void rthw_sdio_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
+{
+    rt_uint32_t clkcr, div, clk_src;
+    rt_uint32_t clk = io_cfg->clock;
+    struct rthw_sdio *sdio = host->private_data;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+
+    clk_src = sdio->sdio_des.clk_get(sdio->sdio_des.hw_sdio);
+    if (clk_src < 240 * 1000)
+    {
+        LOG_E("The clock rate is too low! rata:%d", clk_src);
+        return;
+    }
+
+    if (clk > host->freq_max) clk = host->freq_max;
+
+    if (clk > clk_src)
+    {
+        // LOG_W("Setting rate(%d) is greater than clock source rate(%d).", clk, clk_src);
+        // clk = clk_src;
+    }
+
+    LOG_D("clk:%d width:%s%s%s power:%s%s%s",
+          clk,
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_8 ? "8" : "",
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_4 ? "4" : "",
+          io_cfg->bus_width == MMCSD_BUS_WIDTH_1 ? "1" : "",
+          io_cfg->power_mode == MMCSD_POWER_OFF ? "OFF" : "",
+          io_cfg->power_mode == MMCSD_POWER_UP ? "UP" : "",
+          io_cfg->power_mode == MMCSD_POWER_ON ? "ON" : ""
+         );
+
+    RTHW_SDIO_LOCK(sdio);
+
+    switch (io_cfg->power_mode)
+    {
+    case MMCSD_POWER_OFF:
+        hw_sdio[SDxCON] &= ~BIT(0);
+        break;
+    case MMCSD_POWER_UP:
+        sd_baud = 199;
+        hw_sdio[SDxCON] = 0;
+        rt_thread_mdelay(1);
+
+        hw_sdio[SDxCON] |= BIT(0);                 /* SD control enable */
+        hw_sdio[SDxBAUD] = sysclk_update_baud(sd_baud);
+        hw_sdio[SDxCON] |= BIT(3);                 /* Keep clock output */
+        hw_sdio[SDxCON] |= BIT(4);
+        hw_sdio[SDxCON] |= BIT(5);                 /* Data interrupt enable */
+
+        hal_mdelay(40);
+        break;
+    case MMCSD_POWER_ON:
+        if (clk == SDIO_MAX_FREQ) {
+            hw_sdio[SDxCON] &= ~BIT(3);
+            sd_baud = 3;
+            hw_sdio[SDxBAUD] = sysclk_update_baud(sd_baud);
+        }
+        break;
+    default:
+        LOG_W("unknown power_mode %d", io_cfg->power_mode);
+        break;
+    }
+
+    RTHW_SDIO_UNLOCK(sdio);
+}
+
+/**
+  * @brief  This function update sdio interrupt.
+  * @param  host    rt_mmcsd_host
+  * @param  enable
+  * @retval None
+  */
+void rthw_sdio_irq_update(struct rt_mmcsd_host *host, rt_int32_t enable)
+{
+    struct rthw_sdio *sdio = host->private_data;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+
+    if (enable)
+    {
+        LOG_D("enable sdio irq");
+        rt_hw_irq_enable(IRQ_SD_VECTOR);
+    }
+    else
+    {
+        LOG_D("disable sdio irq");
+        rt_hw_irq_disable(IRQ_SD_VECTOR);
+    }
+}
+
+/**
+  * @brief  This function detect sdcard.
+  * @param  host    rt_mmcsd_host
+  * @retval 0x01
+  */
+static rt_int32_t rthw_sd_detect(struct rt_mmcsd_host *host)
+{
+    LOG_D("try to detect device");
+    return 0x01;
+}
+
+/**
+  * @brief  This function interrupt process function.
+  * @param  host  rt_mmcsd_host
+  * @retval None
+  */
+void rthw_sdio_irq_process(struct rt_mmcsd_host *host)
+{
+    int complete = 0;
+    struct rthw_sdio *sdio = host->private_data;
+    hal_sfr_t hw_sdio = sdio->sdio_des.hw_sdio;
+    rt_uint32_t intstatus = hw_sdio[SDxCON];
+
+    /* clear flag */
+    if (intstatus & HW_SDIO_CON_CFLAG) {
+        complete = 1;
+        hw_sdio[SDxCPND] = HW_SDIO_CON_CFLAG;
+    }
+
+    if (intstatus & HW_SDIO_CON_DFLAG) {
+        complete = 1;
+        hw_sdio[SDxCPND] = HW_SDIO_CON_DFLAG;
+    }
+
+    if (complete)
+    {
+        rt_event_send(&sdio->event, intstatus);
+    }
+}
+
+static const struct rt_mmcsd_host_ops ab32_sdio_ops =
+{
+    rthw_sdio_request,
+    rthw_sdio_iocfg,
+    rthw_sd_detect,
+    rthw_sdio_irq_update,
+};
+
+/**
+  * @brief  This function create mmcsd host.
+  * @param  sdio_des  ab32_sdio_des
+  * @retval rt_mmcsd_host
+  */
+struct rt_mmcsd_host *sdio_host_create(struct ab32_sdio_des *sdio_des)
+{
+    struct rt_mmcsd_host *host;
+    struct rthw_sdio *sdio = RT_NULL;
+
+    if ((sdio_des == RT_NULL) || (sdio_des->txconfig == RT_NULL) || (sdio_des->rxconfig == RT_NULL))
+    {
+        LOG_E("L:%d F:%s %s %s %s",
+              (sdio_des == RT_NULL ? "sdio_des is NULL" : ""),
+              (sdio_des ? (sdio_des->txconfig ? "txconfig is NULL" : "") : ""),
+              (sdio_des ? (sdio_des->rxconfig ? "rxconfig is NULL" : "") : "")
+             );
+        return RT_NULL;
+    }
+
+    sdio = rt_malloc(sizeof(struct rthw_sdio));
+    if (sdio == RT_NULL)
+    {
+        LOG_E("L:%d F:%s malloc rthw_sdio fail");
+        return RT_NULL;
+    }
+    rt_memset(sdio, 0, sizeof(struct rthw_sdio));
+
+    host = mmcsd_alloc_host();
+    if (host == RT_NULL)
+    {
+        LOG_E("L:%d F:%s mmcsd alloc host fail");
+        rt_free(sdio);
+        return RT_NULL;
+    }
+
+    rt_memcpy(&sdio->sdio_des, sdio_des, sizeof(struct ab32_sdio_des));
+    sdio->sdio_des.hw_sdio = (sdio_des->hw_sdio == RT_NULL ? SDMMC0_BASE : sdio_des->hw_sdio);
+    sdio->sdio_des.clk_get = (sdio_des->clk_get == RT_NULL ? ab32_sdio_clk_get : sdio_des->clk_get);
+
+    rt_event_init(&sdio->event, "sdio", RT_IPC_FLAG_FIFO);
+    rt_mutex_init(&sdio->mutex, "sdio", RT_IPC_FLAG_FIFO);
+
+    /* set host defautl attributes */
+    host->ops = &ab32_sdio_ops;
+    host->freq_min = 240 * 1000;
+    host->freq_max = SDIO_MAX_FREQ;
+    host->valid_ocr = 0X00FFFF80;/* The voltage range supported is 1.65v-3.6v */
+#ifndef SDIO_USING_1_BIT
+    host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
+#else
+    host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ;
+#endif
+    host->max_seg_size = SDIO_BUFF_SIZE;
+    host->max_dma_segs = 1;
+    host->max_blk_size = 512;
+    host->max_blk_count = 512;
+
+    /* link up host and sdio */
+    sdio->host = host;
+    host->private_data = sdio;
+
+    rthw_sdio_irq_update(host, 1);
+
+    /* ready to change */
+    mmcsd_change(host);
+
+    return host;
+}
+
+static rt_err_t _dma_txconfig(rt_uint32_t *src, int Size)
+{
+    hal_sfr_t sdiox = sdio_config->instance;
+
+    sdiox[SDxDMAADR] = DMA_ADR(src);
+    sdiox[SDxDMACNT] = BIT(18) | BIT(17) | BIT(16) | Size;
+    return RT_EOK;
+}
+
+static rt_err_t _dma_rxconfig(rt_uint32_t *dst, int Size)
+{
+    hal_sfr_t sdiox = sdio_config->instance;
+
+    sdiox[SDxDMAADR] = DMA_ADR(dst);
+    sdiox[SDxDMACNT] = (Size);
+    return RT_EOK;
+}
+
+void sdio_isr(int vector, void *param)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+    /* Process All SDIO Interrupt Sources */
+    rthw_sdio_irq_process(host);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+int rt_hw_sdio_init(void)
+{
+    struct ab32_sdio_des sdio_des = {0};
+    struct sd_handle hsd = {0};
+    uint8_t param = 0;
+    hsd.instance = SDMMC0_BASE;
+
+    hal_rcu_periph_clk_enable(RCU_SD0);
+    hal_sd_mspinit(&hsd);
+
+    rt_hw_interrupt_install(IRQ_SD_VECTOR, sdio_isr, &param, "sd_isr");
+
+    sdio_des.clk_get    = ab32_sdio_clk_get;
+    sdio_des.hw_sdio    = SDMMC0_BASE;
+    sdio_des.rxconfig   = _dma_rxconfig;
+    sdio_des.txconfig   = _dma_txconfig;
+
+    host = sdio_host_create(&sdio_des);
+
+    return 0;
+}
+INIT_DEVICE_EXPORT(rt_hw_sdio_init);
+
+void ab32_mmcsd_change(void)
+{
+    mmcsd_change(host);
+}
+
+#endif // 0

+ 140 - 0
bsp/bluetrum/libraries/hal_drivers/drv_sdio.h

@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-11-30     greedyhao         first version
+ */
+
+#ifndef DEV_SDIO_H__
+#define DEV_SDIO_H__
+
+#include "drv_common.h"
+#include "board.h"
+#include "drivers/mmcsd_core.h"
+#include "drivers/sdio.h"
+
+#define SDIO_BUFF_SIZE       1024
+#define SDIO_ALIGN_LEN       32
+
+#ifndef SDIO_MAX_FREQ
+#define SDIO_MAX_FREQ        (1000000)
+#endif
+
+#ifndef SDIO_BASE_ADDRESS
+#define SDIO_BASE_ADDRESS    (0x40012800U)
+#endif
+
+#ifndef SDIO_CLOCK_FREQ
+#define SDIO_CLOCK_FREQ      (48U * 1000 * 1000)
+#endif
+
+#ifndef SDIO_BUFF_SIZE
+#define SDIO_BUFF_SIZE       (4096)
+#endif
+
+#ifndef SDIO_ALIGN_LEN
+#define SDIO_ALIGN_LEN       (32)
+#endif
+
+#ifndef SDIO_MAX_FREQ
+#define SDIO_MAX_FREQ        (24 * 1000 * 1000)
+#endif
+
+
+#define HW_SDIO_CON_
+#define HW_SDIO_CON_CFLAG                       (0x01u << 12)   /*!< 0:send command or received response not finish \
+                                                                     1:send command or received response finish     */
+#define HW_SDIO_CON_DFLAG                       (0x01u << 13)   /*!< 0:send or received data not finish             \
+                                                                     1:send or received data finish                 */
+#define HW_SDIO_CON_CCRCE                       (0x01u << 14)   /*!< 0:command crc no error                         \
+                                                                     1:command crc error detected                   */
+#define HW_SDIO_CON_NRPS                        (0x01u << 15)   /*!< 0:response received 1:no response received     */
+#define HW_SDIO_CON_DCRCE                       (0x01u << 16)   /*!< 0:read data crc no error                       \
+                                                                     1:read data crc error detected                 */
+#define HW_SDIO_CON_CRCS                        (0x07u << 17)   /*!< 101:error transmission                         \
+                                                                     010:non-erroneous transmission                 \
+                                                                     111:flash error                                */
+#define HW_SDIO_CON_BUSY                        (0x01u << 20)   /*!< 0:device busy 1:device not busy                */
+
+#define HW_SDIO_ERRORS \
+    (0)
+
+#define HW_SDIO_POWER_OFF                      (0x00U)
+#define HW_SDIO_POWER_UP                       (0x02U)
+#define HW_SDIO_POWER_ON                       (0x03U)
+
+#define HW_SDIO_FLOW_ENABLE                    (0x01U << 14)
+#define HW_SDIO_BUSWIDE_1B                     (0x00U << 11)
+#define HW_SDIO_BUSWIDE_4B                     (0x01U << 11)
+#define HW_SDIO_BUSWIDE_8B                     (0x02U << 11)
+#define HW_SDIO_BYPASS_ENABLE                  (0x01U << 10)
+#define HW_SDIO_IDLE_ENABLE                    (0x01U << 9)
+#define HW_SDIO_CLK_ENABLE                     (0x01U << 8)
+
+#define HW_SDIO_SUSPEND_CMD                    (0x01U << 11)
+#define HW_SDIO_CPSM_ENABLE                    (0x01U << 10)
+#define HW_SDIO_WAIT_END                       (0x01U << 9)
+#define HW_SDIO_WAIT_INT                       (0x01U << 8)
+#define HW_SDIO_RESPONSE_NO                    (0x00U << 6)
+#define HW_SDIO_RESPONSE_SHORT                 (0x01U << 6)
+#define HW_SDIO_RESPONSE_LONG                  (0x03U << 6)
+
+#define HW_SDIO_DATA_LEN_MASK                  (0x01FFFFFFU)
+
+#define HW_SDIO_IO_ENABLE                      (0x01U << 11)
+#define HW_SDIO_RWMOD_CK                       (0x01U << 10)
+#define HW_SDIO_RWSTOP_ENABLE                  (0x01U << 9)
+#define HW_SDIO_RWSTART_ENABLE                 (0x01U << 8)
+#define HW_SDIO_DBLOCKSIZE_1                   (0x00U << 4)
+#define HW_SDIO_DBLOCKSIZE_2                   (0x01U << 4)
+#define HW_SDIO_DBLOCKSIZE_4                   (0x02U << 4)
+#define HW_SDIO_DBLOCKSIZE_8                   (0x03U << 4)
+#define HW_SDIO_DBLOCKSIZE_16                  (0x04U << 4)
+#define HW_SDIO_DBLOCKSIZE_32                  (0x05U << 4)
+#define HW_SDIO_DBLOCKSIZE_64                  (0x06U << 4)
+#define HW_SDIO_DBLOCKSIZE_128                 (0x07U << 4)
+#define HW_SDIO_DBLOCKSIZE_256                 (0x08U << 4)
+#define HW_SDIO_DBLOCKSIZE_512                 (0x09U << 4)
+#define HW_SDIO_DBLOCKSIZE_1024                (0x0AU << 4)
+#define HW_SDIO_DBLOCKSIZE_2048                (0x0BU << 4)
+#define HW_SDIO_DBLOCKSIZE_4096                (0x0CU << 4)
+#define HW_SDIO_DBLOCKSIZE_8192                (0x0DU << 4)
+#define HW_SDIO_DBLOCKSIZE_16384               (0x0EU << 4)
+#define HW_SDIO_DMA_ENABLE                     (0x01U << 3)
+#define HW_SDIO_STREAM_ENABLE                  (0x01U << 2)
+#define HW_SDIO_TO_HOST                        (0x01U << 1)
+#define HW_SDIO_DPSM_ENABLE                    (0x01U << 0)
+
+#define HW_SDIO_DATATIMEOUT                    (0xF0000000U)
+
+// struct ab32_sdio
+// {};
+
+typedef rt_err_t (*dma_txconfig)(rt_uint32_t *src, int size);
+typedef rt_err_t (*dma_rxconfig)(rt_uint32_t *dst, int size);
+typedef rt_uint32_t (*sdio_clk_get)(hal_sfr_t hw_sdio);
+
+struct ab32_sdio_des
+{
+    hal_sfr_t    hw_sdio;
+    dma_txconfig txconfig;
+    dma_rxconfig rxconfig;
+    sdio_clk_get clk_get;
+};
+
+struct ab32_sdio_config
+{
+    hal_sfr_t instance;
+    // struct dma_config dma_rx, dma_tx;
+};
+
+struct ab32_sdio_class
+{
+    const struct ab32_sdio_config *cfg;
+    struct rt_mmcsd_host host;
+};
+
+#endif

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_usart.c

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2020-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 2 - 2
bsp/bluetrum/libraries/hal_drivers/drv_usart.h

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2006-2020, Bluetrum Development Team
- *
+ * Copyright (c) 2020-2021, Bluetrum Development Team
+ * 
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:

+ 1 - 1
bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_conf.h

@@ -13,7 +13,7 @@
 #define HAL_RCU_MODULE_ENABLED
 #define HAL_WDT_MODULE_ENABLED
 // #define HAL_DAC_MODULE_ENABLED
-// #define HAL_SD_MODULE_ENABLED
+#define HAL_SD_MODULE_ENABLED
 
 /*  Includes  */
 #ifdef HAL_GPIO_MODULE_ENABLED

+ 50 - 12
bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_sd.h

@@ -8,35 +8,73 @@
 #define AB32VG1_HAL_SD_H__
 
 #include "ab32vg1_hal_def.h"
+#include "ab32vg1_ll_sdio.h"
+#include <stdbool.h>
 
-struct sd_init
+struct sd_card_info
 {
-    // uint8_t
+    uint32_t rca;           /*!< Specifies the Relative Card Address        */
+    uint32_t capacity;      /*!< Specifies the capacity of the card         */
+    uint8_t  abend;         /*!< Specifies if the card is abnormal end      */
+    uint8_t  flag_sdhc;     /*!< Specifies if the card is SDHC card         */
+    uint8_t  type;          /*!< Specifies the card type                    */
+    uint8_t  state;         /*!< Specifies the card state                   */
+    uint8_t  rw_state;      /*!< Specifies the last r/w state of the card   */
 };
+typedef struct sd_card_info* sd_card_info_t;
 
-struct sd_card_info
+struct sd_cfg
 {
-    uint32_t rca;           /*!< Specifies the Relative Card Address    */
-    uint8_t  type;          /*!< Specifies the card type                */
+    uint16_t go_ready_retry;
+    uint8_t  identification_retry;
+    uint8_t  rw_retry;
+    uint8_t  rw_init_retry;
+    uint8_t  stop_retry;
+    uint8_t  rw_need_stop;
 };
-typedef struct sd_card_info* sd_card_info_t;
 
 struct sd_handle
 {
     hal_sfr_t               instance;
-    struct sd_init          init;
+    struct sdio_init        init;
     struct sd_card_info     sdcard;
+    struct sd_cfg           cfg;
 };
 typedef struct sd_handle* sd_handle_t;
 
-#define SD0N            (0x00u)
+#define SD0N                (0x00u)
+
+// #define CARD_SDSC           (0x00u)
+// #define CARD_SDHC           (0x01u)
+// #define CARD_SECURED        (0x03u)
+
+enum
+{
+    CARD_INVAL = 0x00,
+    CARD_V1,
+    CARD_V2,
+    CARD_MMC
+};
+
+enum
+{
+    HAL_SD_RW_STATE_IDLE = 0x00,
+    HAL_SD_RW_STATE_READ,
+    HAL_SD_RW_STATE_WRITE,
+};
 
-#define CARD_V1         (0x01u)
-#define CARD_V2         (0x02u)
-#define CARD_MMC        (0x03u)
+enum
+{
+    HAL_SD_STATE_RESET = 0x00,
+    HAL_SD_STATE_NEW,
+    HAL_SD_STATE_OK,
+    HAL_SD_STATE_INVAL,
+};
 
 #define SDMMC_CHECK_PATTERM         (0x000001AAu)
 
+#define SDMMC0_BASE     ((hal_sfr_t)&SD0CON)
+
 /* Initialization functions */
 hal_error_t hal_sd_init(sd_handle_t hsd);
 void hal_sd_deinit(uint32_t sdx);
@@ -44,7 +82,7 @@ void hal_sd_mspinit(sd_handle_t hsd);
 
 hal_error_t hal_sd_control(uint32_t control, uint32_t arg);
 void hal_sd_write(uint32_t sdx, uint32_t data);
-uint32_t hal_sd_read(uint32_t sdx);
+bool hal_sd_read(sd_handle_t hsd, void *buf, uint32_t lba);
 // void hal_uart_write_it(uint32_t uartx, uint8_t data);
 // uint8_t hal_uart_read_it(uint32_t uartx);
 

+ 21 - 1
bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_ll_sdio.h

@@ -11,8 +11,28 @@
 
 struct sdio_init
 {
-    uint32_t tmp;
+    uint32_t clock_power_save;      /*!< Specifies whether SDMMC Clock output is enabled or
+                                        disabled when the bus is idle.                                      */
+    uint32_t clock_div;             /*!< Specifies the clock frequency of the SDMMC controller.
+                                      This parameter can be a value between Min_Data = 0 and Max_Data = 255 */
 };
 typedef struct sdio_init* sdio_init_t;
 
+#define SDMMC_CLOCK_POWER_SAVE_DISABLE      (0x00u)
+#define SDMMC_CLOCK_POWER_SAVE_ENABLE       (0x01u)
+
+enum
+{
+    SDxCON = 0, /* [20]:BUSY [19:17]:CRCS [16]:DCRCE [15]:NRPS [1]:Data bus width [0]:SD enable */
+    SDxCPND,
+    SDxBAUD,
+    SDxCMD,
+    SDxARG3,
+    SDxARG2,
+    SDxARG1,
+    SDxARG0,
+    SDxDMAADR,
+    SDxDMACNT,
+};
+
 #endif

+ 266 - 50
bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c

@@ -1,10 +1,7 @@
 #include "ab32vg1_hal.h"
-#include "ab32vg1_ll_sdio.h"
 
 #ifdef HAL_SD_MODULE_ENABLED
 
-#include <stdbool.h>
-
 #define HAL_LOG(...)     hal_printf(__VA_ARGS__)
 
 /*************************  LL ************************************/
@@ -27,37 +24,27 @@
 #define RSP_BUSY_TIMEOUT            2400000     //大约2s
 #define RSP_TIMEOUT                 6000        //大约5ms
 
-enum
-{
-    SDCON = 0, /* [20]:BUSY [19:17]:CRCS [16]:DCRCE [15]:NRPS [1]:Data bus width [0]:SD enable */
-    SDCPND,
-    SDBAUD,
-    SDCMD,
-    SDARG3,
-    SDARG2,
-    SDARG1,
-    SDARG0,
-    SDDMAADR,
-    SDDMACNT,
-};
-
 uint8_t sysclk_update_baud(uint8_t baud);
 
 void sdio_setbaud(hal_sfr_t sdiox, uint8_t baud)
 {
-    sdiox[SDBAUD] = sysclk_update_baud(baud);
+    sdiox[SDxBAUD] = sysclk_update_baud(baud);
 }
 
 void sdio_init(hal_sfr_t sdiox, sdio_init_t init)
 {
-    /* Set clock */
-    sdio_setbaud(sdiox, 199);
+    sdiox[SDxCON] = 0;
 
-    sdiox[SDCON] = 0;
     hal_udelay(20);
-    sdiox[SDCON] |= BIT(0);     /* SD control enable */
-    sdiox[SDCON] |= BIT(3);     /* Keep clock output */
-    sdiox[SDCON] |= BIT(5);     /* Data interrupt enable */
+    sdiox[SDxCON] |= BIT(0);                 /* SD control enable */
+    sdio_setbaud(sdiox, init->clock_div);   /* Set clock */
+    if (init->clock_power_save == SDMMC_CLOCK_POWER_SAVE_DISABLE) {
+        sdiox[SDxCON] |= BIT(3);                 /* Keep clock output */
+    } else {
+        sdiox[SDxCON] &= ~BIT(3);                 /* Keep clock output */
+    }
+    sdiox[SDxCON] |= BIT(5);                 /* Data interrupt enable */
+
     hal_mdelay(40);
 }
 
@@ -70,8 +57,8 @@ void sdio_init(hal_sfr_t sdiox, sdio_init_t init)
  */
 bool sdio_check_finish(hal_sfr_t sdiox)
 {
-    if (sdiox[SDCON] & BIT(12)) {
-        sdiox[SDCPND] = BIT(12);
+    if (sdiox[SDxCON] & BIT(12)) {
+        sdiox[SDxCPND] = BIT(12);
         return true;
     }
     return false;
@@ -86,19 +73,21 @@ bool sdio_check_finish(hal_sfr_t sdiox)
  */
 bool sdio_check_rsp(hal_sfr_t sdiox)
 {
-    return !(sdiox[SDCON] & BIT(15));
+    return !(sdiox[SDxCON] & BIT(15));
 }
 
-bool sdio_send_cmd(hal_sfr_t sdiox, uint32_t cmd, uint32_t arg)
+bool sdio_send_cmd(hal_sfr_t sdiox, uint32_t cmd, uint32_t arg, uint8_t *abend)
 {
     uint32_t time_out = (cmd & CBUSY) ? RSP_BUSY_TIMEOUT : RSP_TIMEOUT;
-    sdiox[SDCMD] = cmd;
-    sdiox[SDARG3] = arg;
+    sdiox[SDxARG3] = arg;
+    sdiox[SDxCMD] = cmd;
 
     while (sdio_check_finish(sdiox) == false) {
         if (--time_out == 0) {
             HAL_LOG("cmd time out\n");
-            // card.abend = 1;
+            if (abend != HAL_NULL) {
+                *abend = 1;
+            }
             return false;
         }
     }
@@ -108,57 +97,258 @@ bool sdio_send_cmd(hal_sfr_t sdiox, uint32_t cmd, uint32_t arg)
 
 uint8_t sdio_get_cmd_rsp(hal_sfr_t sdiox)
 {
-    return -1;
+    return sdiox[SDxCMD];
 }
 
-uint32_t sdio_get_rsp(hal_sfr_t sdiox, uint32_t rsp)
+uint32_t sdio_get_rsp(hal_sfr_t sdiox, uint32_t rsp_reg)
 {
-    return -1;
+    return sdiox[rsp_reg];
 }
 
 void sdio_read_kick(hal_sfr_t sdiox, void* buf)
-{}
+{
+    sdiox[SDxDMAADR] = DMA_ADR(buf);
+    sdiox[SDxDMACNT] = 512;
+}
 
 void sdio_write_kick(hal_sfr_t sdiox, void* buf)
-{}
+{
+    sdiox[SDxDMAADR] = DMA_ADR(buf);
+    sdiox[SDxDMACNT] = BIT(18) | BIT(17) | BIT(16) | 512;
+}
 
 bool sdio_isbusy(hal_sfr_t sdiox)
 {
     return false;
 }
 
-void sdmmc_go_idle_state(hal_sfr_t sdiox)
+bool sdmmc_cmd_go_idle_state(sd_handle_t hsd)
+{
+    return sdio_send_cmd(hsd->instance, 0 | RSP_NO, hsd->sdcard.rca, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_cmd_send_if_cond(sd_handle_t hsd)
+{
+    return sdio_send_cmd(hsd->instance, 8 | RSP_7, SDMMC_CHECK_PATTERM, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_cmd_all_send_cid(sd_handle_t hsd)
+{
+    return sdio_send_cmd(hsd->instance, 2 | RSP_2, 0, &(hsd->sdcard.abend));
+}
+
+void sdmmc_cmd_set_rel_addr(sd_handle_t hsd)
+{
+    hal_sfr_t sdiox = hsd->instance;
+
+    if (hsd->sdcard.type == CARD_MMC) {
+        hsd->sdcard.rca = 0x00010000;
+        sdio_send_cmd(sdiox, 3 | RSP_1, hsd->sdcard.rca, &(hsd->sdcard.abend));
+    } else {
+        sdio_send_cmd(sdiox, 3 | RSP_6, 0, &(hsd->sdcard.abend));
+        hsd->sdcard.rca = sdio_get_rsp(sdiox, SDxARG3) & 0xffff0000;
+    }
+}
+
+void sdmmc_cmd_send_csd(sd_handle_t hsd)
+{
+    hal_sfr_t sdiox = hsd->instance;
+
+    sdio_send_cmd(sdiox, 9 | RSP_2, hsd->sdcard.rca, &(hsd->sdcard.abend));
+    if (hsd->sdcard.type == CARD_MMC) {
+        //
+    } else {
+        if (hsd->sdcard.flag_sdhc == 1) {
+            hsd->sdcard.capacity =   (sdio_get_rsp(sdiox, SDxARG2) << 24) & 0x00ff0000;   /* rspbuf[8] */
+            hsd->sdcard.capacity |=  ((sdio_get_rsp(sdiox, SDxARG1) >> 16) & 0x0000ffff); /* rspbuf[9] rspbuf[10] */
+            hsd->sdcard.capacity +=  1;
+            hsd->sdcard.capacity <<= 10;
+        }
+    }
+    HAL_LOG("sd capacity=%d\n", hsd->sdcard.capacity);
+}
+
+void sdmmc_cmd_select_card(sd_handle_t hsd)
 {
-    // hal_sfr_t sdiox = hsd->instance;
-    sdio_send_cmd(sdiox, 0x00 | RSP_NO, 0);
+    sdio_send_cmd(hsd->instance, 7 | RSP_1B, hsd->sdcard.rca, &(hsd->sdcard.abend));
 }
 
-void sdmmc_send_if_cond(hal_sfr_t sdiox)
+bool sdmmc_cmd_read_multiblock(sd_handle_t hsd)
 {
-    // hal_sfr_t sdiox = hsd->instance;
-    sdio_send_cmd(sdiox, 0x08 | RSP_7, SDMMC_CHECK_PATTERM);
+    return sdio_send_cmd(hsd->instance, REQ_MULTREAD, hsd->sdcard.rca, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_cmd_app(sd_handle_t hsd)
+{
+    return sdio_send_cmd(hsd->instance, 55 | RSP_1, hsd->sdcard.rca, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_acmd_op_cond(sd_handle_t hsd, uint32_t voltage)
+{
+    /* SEND CMD55 APP_CMD with RCA */
+    if (sdmmc_cmd_app(hsd)) {
+        /* Send CMD41 */
+        if (sdio_send_cmd(hsd->instance, 41 | RSP_3, voltage, &(hsd->sdcard.abend))) {
+            return true;
+        }
+    }
+    return false;
 }
 
 /*************************  HAL ************************************/
 
+static bool sd_type_identification(sd_handle_t hsd)
+{
+    uint8_t retry = hsd->cfg.identification_retry;
+    while (retry-- > 0)
+    {
+        /* CMD0: GO_IDLE_STATE */
+        sdmmc_cmd_go_idle_state(hsd);
+
+        /* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
+        if (sdmmc_cmd_send_if_cond(hsd)) {
+            if (sdio_get_cmd_rsp(hsd->instance) == 0x08) {
+                hsd->sdcard.type = CARD_V2;
+                HAL_LOG("SD 2.0\n");
+                return true;
+            }
+            continue;
+        }
+        if (sdmmc_acmd_op_cond(hsd, 0x00ff8000)) {
+            hsd->sdcard.type = CARD_V1;
+            HAL_LOG("SD 1.0\n");
+            return true;
+        }
+        hal_mdelay(20);
+    }
+    return false;
+}
 
-static void sd_poweron(sd_handle_t hsd)
+static bool sd_go_ready_try(sd_handle_t hsd)
 {
-    sdmmc_go_idle_state(hsd->instance);
-    sdmmc_send_if_cond(hsd->instance);
-    if (hsd->instance[SDCMD] == 0x08) {
-        hsd->sdcard.type = CARD_V2;
-        HAL_LOG("SD 2.0\n");
+    uint32_t tmp = 0;
+    switch (hsd->sdcard.type)
+    {
+    case CARD_V1:
+        sdmmc_acmd_op_cond(hsd, 0x00ff8000);
+        break;
+    
+    case CARD_V2:
+        sdmmc_acmd_op_cond(hsd, 0x40ff8000);
+        break;
+    default:
+        break;
+    }
+
+    if (0 == (hsd->instance[SDxARG3] & BIT(31))) {
+        return false; // no ready
+    }
+
+    if ((hsd->sdcard.type == CARD_V2) && (hsd->instance[SDxARG3] & BIT(30))) {
+        HAL_LOG("SDHC\n");
+        hsd->sdcard.flag_sdhc = 1;
     }
+
+    return true;
+}
+
+static bool sd_go_ready(sd_handle_t hsd)
+{
+    if (hsd->sdcard.type == CARD_INVAL) {
+        return false;
+    }
+
+    uint8_t retry = hsd->cfg.go_ready_retry;
+    while (retry-- > 0)
+    {
+        if (sd_go_ready_try(hsd) == true) {
+            return true;
+        }
+        hal_mdelay(20);
+    }
+
+    return false;
+}
+
+static bool sd_poweron(sd_handle_t hsd)
+{
+    if (sd_type_identification(hsd) == false) {
+        HAL_LOG("card invalid\n");
+        return false;
+    }
+
+    if (sd_go_ready(hsd) == false) {
+        HAL_LOG("no ready\n");
+        return false;
+    }
+
+    return true;
+}
+
+static void sd_init_card(sd_handle_t hsd)
+{
+    /* Send CMD2 ALL_SEND_CID */
+    sdmmc_cmd_all_send_cid(hsd);
+    /* Send CMD3 SET_REL_ADDR */
+    sdmmc_cmd_set_rel_addr(hsd);
+    /* Send CMD9 SEND_CSD */
+    sdmmc_cmd_send_csd(hsd);
+    /* Select the Card */
+    sdmmc_cmd_select_card(hsd);
+
+    hsd->init.clock_div         = 3;
+    hsd->init.clock_power_save  = SDMMC_CLOCK_POWER_SAVE_ENABLE;
+
+    sdio_init(hsd->instance, &(hsd->init));
+}
+
+static bool sd_read_wait(sd_handle_t hsd)
+{
+    bool ret = false;
+    hal_sfr_t sdiox = hsd->instance;
+
+
+
+    return ret;
+}
+
+static void sd_read_start(sd_handle_t hsd, void *buf, uint32_t lba)
+{
+    if (hsd->sdcard.rw_state == HAL_SD_RW_STATE_READ) {
+
+    } else {
+        if (hsd->sdcard.rw_state == HAL_SD_RW_STATE_WRITE) {
+
+        }
+        sdio_read_kick(hsd->instance, buf);
+        sdmmc_cmd_read_multiblock(hsd);
+    }
+
+    hsd->sdcard.rw_state = HAL_SD_RW_STATE_READ;
+    // hsd->sdcard.rw_lba
+}
+
+static bool sd_read_try(sd_handle_t hsd, void *buf, uint32_t lba)
+{
+    HAL_LOG("read: %08x\n", lba);
+
+    if (hsd->sdcard.capacity < lba) {
+        lba = hsd->sdcard.capacity - 1;
+    }
+    sd_read_start(hsd, buf, lba);
+    return 0;
 }
 
 void hal_sd_initcard(sd_handle_t hsd)
 {
-    struct sdio_init init = {0};
     hal_sfr_t sdiox = hsd->instance;
 
-    sdio_init(sdiox, &init);
+    hsd->init.clock_div         = 119; /* SD clk 240KHz when system clk is 48MHz */
+    hsd->init.clock_power_save  = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+
+    sdio_init(sdiox, &(hsd->init));
     sd_poweron(hsd);
+    sd_init_card(hsd);
 }
 
 WEAK void hal_sd_mspinit(sd_handle_t hsd)
@@ -171,6 +361,11 @@ hal_error_t hal_sd_init(sd_handle_t hsd)
         return -HAL_ERROR;
     }
 
+    hsd->cfg.go_ready_retry         = 200;
+    hsd->cfg.identification_retry   = 5;
+    hsd->cfg.rw_init_retry          = 3;
+    hsd->cfg.rw_retry               = 3;
+
     hal_sd_mspinit(hsd);
     hal_sd_initcard(hsd);
 
@@ -181,4 +376,25 @@ void hal_sd_deinit(uint32_t sdx)
 {
 }
 
+bool hal_sd_read(sd_handle_t hsd, void *buf, uint32_t lba)
+{
+    uint8_t init_retry = hsd->cfg.rw_init_retry;
+
+    while (init_retry-- > 0)
+    {
+        uint8_t retry = hsd->cfg.rw_retry;
+        while (retry-- > 0)
+        {
+            if (sd_read_try(hsd, buf, lba)) {
+                return true;
+            }
+        }
+        hsd->sdcard.state = HAL_SD_STATE_INVAL; 
+        
+        hal_mdelay(20);
+    }
+
+    return false;
+}
+
 #endif

Some files were not shown because too many files changed in this diff