mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-06-18 03:22:17 +08:00
[bsp][bluetrum] add sdio support
This commit is contained in:
@@ -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 one or more lines are too long
@@ -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,6 +1,59 @@
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#if 1
|
||||
|
||||
#ifdef BSP_USING_SDIO
|
||||
|
||||
#include <dfs_elm.h>
|
||||
#include <dfs_fs.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 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 <dfs_fs.h>
|
||||
#include "dfs_romfs.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Generated by mkromfs. Edit with caution. */
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_DFS
|
||||
#ifdef RT_USING_DFS_ROMFS
|
||||
#include <dfs_romfs.h>
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -176,6 +176,8 @@
|
||||
|
||||
#define BSP_USING_UART0
|
||||
|
||||
/* On-chip Peripheral Drivers */
|
||||
|
||||
/* Board extended module Drivers */
|
||||
|
||||
#define BOARD_BLUETRUM_EVB
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -8,35 +8,73 @@
|
||||
#define AB32VG1_HAL_SD_H__
|
||||
|
||||
#include "ab32vg1_hal_def.h"
|
||||
|
||||
struct sd_init
|
||||
{
|
||||
// uint8_t
|
||||
};
|
||||
#include "ab32vg1_ll_sdio.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sd_card_info
|
||||
{
|
||||
uint32_t rca; /*!< Specifies the Relative Card Address */
|
||||
uint8_t type; /*!< Specifies the card type */
|
||||
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_cfg
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
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_V1 (0x01u)
|
||||
#define CARD_V2 (0x02u)
|
||||
#define CARD_MMC (0x03u)
|
||||
// #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,
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include "ab32vg1_hal.h"
|
||||
#include "ab32vg1_ll_sdio.h"
|
||||
|
||||
#undef HAL_SD_MODULE_ENABLED
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
// hal_sfr_t sdiox = hsd->instance;
|
||||
sdio_send_cmd(sdiox, 0x00 | RSP_NO, 0);
|
||||
return sdio_send_cmd(hsd->instance, 0 | RSP_NO, hsd->sdcard.rca, &(hsd->sdcard.abend));
|
||||
}
|
||||
|
||||
void sdmmc_send_if_cond(hal_sfr_t sdiox)
|
||||
bool sdmmc_cmd_send_if_cond(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, 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)
|
||||
{
|
||||
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 void sd_poweron(sd_handle_t hsd)
|
||||
static bool sd_type_identification(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");
|
||||
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 bool sd_go_ready_try(sd_handle_t hsd)
|
||||
{
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user