diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/.config b/bsp/bluetrum/ab32vg1-ab-prougen/.config
index 6dea3429e3c5da58c83de2679eaa9f23895ba78d..0503cd820e14e9d43f6f6a8618ed004114546d1f 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/.config
+++ b/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
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/.cproject b/bsp/bluetrum/ab32vg1-ab-prougen/.cproject
index e8377fab468dcdb37771b79e24fd81e9faefe676..6e4d4ca5fe6072b3d039ad82f06ccbc6d562ff9f 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/.cproject
+++ b/bsp/bluetrum/ab32vg1-ab-prougen/.cproject
@@ -1,155 +1,158 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/README.md b/bsp/bluetrum/ab32vg1-ab-prougen/README.md
index df58a01eda9a5c05c3b9019d29c3429c960fec1a..feb312a128f94449f716659aabe4ea407235d419 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/README.md
+++ b/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 的输出信息:
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c
index 005a86b41a86d44f51075f7c39399a9634b3de47..339c44f2718d8bb495c4da2a4542d802d8bde65a 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c
+++ b/bsp/bluetrum/ab32vg1-ab-prougen/applications/mnt.c
@@ -1,6 +1,59 @@
#include
-#ifdef RT_USING_DFS
+#if 1
+
+#ifdef BSP_USING_SDIO
+
+#include
+#include
+#include
+#include "drv_gpio.h"
+
+// #define DRV_DEBUG
+#define DBG_TAG "app.card"
+#include
+
+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 ab32_sdcard_mount(void)
+{
+ 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_thread_startup(tid);
+ }
+ else
+ {
+ LOG_E("create sd_mount thread err!");
+ }
+ return RT_EOK;
+}
+INIT_APP_EXPORT(ab32_sdcard_mount);
+#endif
+
+#else
+
#include
#include "dfs_romfs.h"
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c b/bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c
index 42670bf6b38fcffef72ca55275dcd0dccd5b6d2f..446f7da02624344639e5219b076a99bdb94d0533 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c
+++ b/bsp/bluetrum/ab32vg1-ab-prougen/applications/romfs.c
@@ -1,7 +1,7 @@
/* Generated by mkromfs. Edit with caution. */
#include
-#ifdef RT_USING_DFS
+#ifdef RT_USING_DFS_ROMFS
#include
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig b/bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig
index 43dc3e82294296f28cc954d6a8e8aff2ec94b138..89296912ac15e547334be7491d86ab87fd4a2038 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig
+++ b/bsp/bluetrum/ab32vg1-ab-prougen/board/Kconfig
@@ -19,6 +19,34 @@ 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"
+
+ menuconfig BSP_USING_UART0
+ bool "Enable UART0"
+ 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 "On-chip Peripheral Drivers"
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/makefile.targets b/bsp/bluetrum/ab32vg1-ab-prougen/makefile.targets
index 796588852bce39f2253a5aed5bf9e1e32eaa9e0f..76aedb496e79b147066ed115b1351c1aabac44a0 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/makefile.targets
+++ b/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)
diff --git a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h b/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h
index 3ce6012a617bc6f34cb0f733bc182139f213b547..e308ed80caebdfc6610dd9dca339e6b177f69188 100644
--- a/bsp/bluetrum/ab32vg1-ab-prougen/rtconfig.h
+++ b/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
diff --git a/bsp/bluetrum/libraries/hal_drivers/SConscript b/bsp/bluetrum/libraries/hal_drivers/SConscript
index 87c1b93152c2be7f7dc6cdb86067512705d38f5e..11a76e192a4b9bcba6a653788c4a1ae86fb15973 100644
--- a/bsp/bluetrum/libraries/hal_drivers/SConscript
+++ b/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]
diff --git a/bsp/bluetrum/libraries/hal_drivers/config/pwm_config.h b/bsp/bluetrum/libraries/hal_drivers/config/pwm_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..24d705f342b0a83c2c01339e847144cf2e4a12eb
--- /dev/null
+++ b/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
+ */
diff --git a/bsp/bluetrum/libraries/hal_drivers/drv_sdio.c b/bsp/bluetrum/libraries/hal_drivers/drv_sdio.c
new file mode 100644
index 0000000000000000000000000000000000000000..4289b82307dbd2a18b7381efdab8c2e2ae46b718
--- /dev/null
+++ b/bsp/bluetrum/libraries/hal_drivers/drv_sdio.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2006-2021, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2021-01-20 greedyhao first version
+ */
+
+#include "drv_sdio.h"
+#include "interrupt.h"
+#include
+
+#ifdef BSP_USING_SDIO
+
+// #define DRV_DEBUG
+#define LOG_TAG "drv.sdio"
+#include
+
+#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[SDARG3];
+ cmd->resp[1] = hw_sdio[SDARG2];
+ cmd->resp[2] = hw_sdio[SDARG1];
+ cmd->resp[3] = hw_sdio[SDARG0];
+
+ 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[SDARG3] = cmd->arg;
+ hw_sdio[SDCMD] = 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("SDCON=0x%X SDCMD=0x%X\n", hw_sdio[SDCON], hw_sdio[SDCMD]);
+ cmd->err = -RT_ETIMEOUT;
+ }
+
+ if (data_flag & DATA_DIR_WRITE) {
+ if (((hw_sdio[SDCON] & HW_SDIO_CON_CRCS) >> 17) != 2) {
+ LOG_E("Write CRC error!");
+ cmd->err = -RT_ERROR;
+ hw_sdio[SDCPND] = 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[SDCON] &= ~BIT(0);
+ break;
+ case MMCSD_POWER_UP:
+ sd_baud = 199;
+ hw_sdio[SDCON] = 0;
+ rt_thread_mdelay(1);
+
+ hw_sdio[SDCON] |= BIT(0); /* SD control enable */
+ hw_sdio[SDBAUD] = sysclk_update_baud(sd_baud);
+ hw_sdio[SDCON] |= BIT(3); /* Keep clock output */
+ hw_sdio[SDCON] |= BIT(4);
+ hw_sdio[SDCON] |= BIT(5); /* Data interrupt enable */
+
+ hal_mdelay(40);
+ break;
+ case MMCSD_POWER_ON:
+ if (clk == SDIO_MAX_FREQ) {
+ hw_sdio[SDCON] &= ~BIT(3);
+ sd_baud = 3;
+ hw_sdio[SDBAUD] = 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[SDCON];
+
+ /* clear flag */
+ if (intstatus & HW_SDIO_CON_CFLAG) {
+ complete = 1;
+ hw_sdio[SDCPND] = HW_SDIO_CON_CFLAG;
+ }
+
+ if (intstatus & HW_SDIO_CON_DFLAG) {
+ complete = 1;
+ hw_sdio[SDCPND] = 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[SDDMAADR] = DMA_ADR(src);
+ sdiox[SDDMACNT] = 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[SDDMAADR] = DMA_ADR(dst);
+ sdiox[SDDMACNT] = (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, ¶m, "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
diff --git a/bsp/bluetrum/libraries/hal_drivers/drv_sdio.h b/bsp/bluetrum/libraries/hal_drivers/drv_sdio.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2b5f2ba9fc090b8edc1cccc784beff8214f5ec8
--- /dev/null
+++ b/bsp/bluetrum/libraries/hal_drivers/drv_sdio.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread 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
diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_conf.h b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_conf.h
index 9c1f9b3fcb12321aa6f8c4f89825f007dd0155ff..a26714cc2895ec33fc5078d73b4a67854e899483 100644
--- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_conf.h
+++ b/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
diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_sd.h b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_sd.h
index 291d1e1e366941b02b5f470b26724276a5147efe..3c1fcbd9ad1509ff8138076e5c3e47550f54b1d4 100644
--- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_hal_sd.h
+++ b/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
-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);
diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_ll_sdio.h b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_ll_sdio.h
index 6fff778b7d29246960bf93f0d33481441b09f51f..bb2fae52566ec8794180be78cf66d8f419a0a83c 100644
--- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/include/ab32vg1_ll_sdio.h
+++ b/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
+{
+ 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,
+};
+
#endif
diff --git a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c
index 6beacf75a52f233e1275a4aee7be79f25dc6c26b..26d200dd8964f8ac08ed4d61e41cf981403a9c3a 100644
--- a/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c
+++ b/bsp/bluetrum/libraries/hal_libraries/ab32vg1_hal/source/ab32vg1_hal_sd.c
@@ -1,10 +1,8 @@
#include "ab32vg1_hal.h"
-#include "ab32vg1_ll_sdio.h"
+#undef HAL_SD_MODULE_ENABLED
#ifdef HAL_SD_MODULE_ENABLED
-#include
-
#define HAL_LOG(...) hal_printf(__VA_ARGS__)
/************************* LL ************************************/
@@ -27,20 +25,6 @@
#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)
@@ -50,14 +34,18 @@ void sdio_setbaud(hal_sfr_t sdiox, uint8_t baud)
void sdio_init(hal_sfr_t sdiox, sdio_init_t init)
{
- /* Set clock */
- sdio_setbaud(sdiox, 199);
-
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[SDCON] |= BIT(0); /* SD control enable */
+ sdio_setbaud(sdiox, init->clock_div); /* Set clock */
+ if (init->clock_power_save == SDMMC_CLOCK_POWER_SAVE_DISABLE) {
+ sdiox[SDCON] |= BIT(3); /* Keep clock output */
+ } else {
+ sdiox[SDCON] &= ~BIT(3); /* Keep clock output */
+ }
+ sdiox[SDCON] |= BIT(5); /* Data interrupt enable */
+
hal_mdelay(40);
}
@@ -89,16 +77,18 @@ bool sdio_check_rsp(hal_sfr_t sdiox)
return !(sdiox[SDCON] & 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[SDCMD] = 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 +98,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[SDCMD];
}
-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[SDDMAADR] = DMA_ADR(buf);
+ sdiox[SDDMACNT] = 512;
+}
void sdio_write_kick(hal_sfr_t sdiox, void* buf)
-{}
+{
+ sdiox[SDDMAADR] = DMA_ADR(buf);
+ sdiox[SDDMACNT] = 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, SDARG3) & 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, SDARG2) << 24) & 0x00ff0000; /* rspbuf[8] */
+ hsd->sdcard.capacity |= ((sdio_get_rsp(sdiox, SDARG1) >> 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)
+{
+ sdio_send_cmd(hsd->instance, 7 | RSP_1B, hsd->sdcard.rca, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_cmd_read_multiblock(sd_handle_t hsd)
+{
+ return sdio_send_cmd(hsd->instance, REQ_MULTREAD, hsd->sdcard.rca, &(hsd->sdcard.abend));
+}
+
+bool sdmmc_cmd_app(sd_handle_t hsd)
{
- // hal_sfr_t sdiox = hsd->instance;
- sdio_send_cmd(sdiox, 0x00 | RSP_NO, 0);
+ return sdio_send_cmd(hsd->instance, 55 | RSP_1, hsd->sdcard.rca, &(hsd->sdcard.abend));
}
-void sdmmc_send_if_cond(hal_sfr_t sdiox)
+bool sdmmc_acmd_op_cond(sd_handle_t hsd, uint32_t voltage)
{
- // hal_sfr_t sdiox = hsd->instance;
- sdio_send_cmd(sdiox, 0x08 | RSP_7, SDMMC_CHECK_PATTERM);
+ /* 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[SDARG3] & BIT(31))) {
+ return false; // no ready
}
+
+ if ((hsd->sdcard.type == CARD_V2) && (hsd->instance[SDARG3] & 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 +362,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 +377,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