[bsp] add k230
This commit is contained in:
parent
633d203fa6
commit
caac564854
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
||||||
|
#Build & install directories
|
||||||
|
build/
|
||||||
|
packages/
|
||||||
|
install/
|
||||||
|
|
||||||
|
rtthread.*
|
||||||
|
|
||||||
|
__pycache__
|
||||||
|
.config.old
|
|
@ -0,0 +1,46 @@
|
||||||
|
mainmenu "RT-Thread Project Configuration"
|
||||||
|
|
||||||
|
config BSP_DIR
|
||||||
|
string
|
||||||
|
option env="BSP_ROOT"
|
||||||
|
default "."
|
||||||
|
|
||||||
|
config RTT_DIR
|
||||||
|
string
|
||||||
|
option env="RTT_ROOT"
|
||||||
|
default "../../rt-thread"
|
||||||
|
|
||||||
|
config PKGS_DIR
|
||||||
|
string
|
||||||
|
option env="PKGS_ROOT"
|
||||||
|
default "packages"
|
||||||
|
|
||||||
|
source "$RTT_DIR/Kconfig"
|
||||||
|
source "$PKGS_DIR/Kconfig"
|
||||||
|
rsource "board/Kconfig"
|
||||||
|
|
||||||
|
config BOARD_fpgac908
|
||||||
|
bool
|
||||||
|
select ARCH_RISCV64
|
||||||
|
select RT_USING_COMPONENTS_INIT
|
||||||
|
select RT_USING_USER_MAIN
|
||||||
|
select RT_USING_CACHE
|
||||||
|
select ARCH_MM_MMU
|
||||||
|
select ARCH_RISCV_FPU_D
|
||||||
|
select ARCH_REMAP_KERNEL if RT_USING_SMART
|
||||||
|
default y
|
||||||
|
|
||||||
|
config __STACKSIZE__
|
||||||
|
int "stack size for interrupt"
|
||||||
|
default 4096
|
||||||
|
|
||||||
|
config C908_PLIC_PHY_ADDR
|
||||||
|
int "PLIC base address"
|
||||||
|
default 0xF00000000
|
||||||
|
|
||||||
|
config BSP_ROOTFS_TYPE_CROMFS
|
||||||
|
bool "Use CROMFS as ROOTFS"
|
||||||
|
select RT_USING_DFS_CROMFS
|
||||||
|
select PKG_USING_ZLIB
|
||||||
|
select PKG_USING_ZLIB_LATEST_VERSION
|
||||||
|
default y
|
|
@ -0,0 +1,38 @@
|
||||||
|
# rt-smart canaan porting
|
||||||
|
|
||||||
|
## 下载依赖的软件包
|
||||||
|
|
||||||
|
在软件包无需变更的情况下只须执行一次
|
||||||
|
```
|
||||||
|
source ~/.env/env.sh
|
||||||
|
pkgs --update
|
||||||
|
```
|
||||||
|
|
||||||
|
## 将根文件系统编译进内核
|
||||||
|
|
||||||
|
为了方便测试,这里将根文件系统制作成CROMFS格式转换成C代码编译进内核。
|
||||||
|
|
||||||
|
1. 在 https://github.com/RT-Thread/userapps 页面下载riscv64预编译镜像
|
||||||
|
2. 解压后将其中的ext4.img挂载到一个目录中
|
||||||
|
```
|
||||||
|
sudo mount ext4.img dir
|
||||||
|
```
|
||||||
|
3. 删除其中一些不必要的文件以减小内核体积
|
||||||
|
```
|
||||||
|
du -ha # 查看文件大小
|
||||||
|
sudo rm -rf dir/www dir/usr/share/fonts dir/tc
|
||||||
|
|
||||||
|
```
|
||||||
|
4. 生成cromfs文件
|
||||||
|
工具位于 https://github.com/RT-Thread/userapps/tree/main/tools/cromfs
|
||||||
|
```
|
||||||
|
sudo ./cromfs-tool-x64 dir crom.img ./ # 将生成的cromfs_data.c放入applications目录
|
||||||
|
```
|
||||||
|
|
||||||
|
## 编译
|
||||||
|
|
||||||
|
```
|
||||||
|
export RTT_EXEC_PATH=/mnt/e/tools/riscv64gc/bin # 你自己的编译器路径
|
||||||
|
|
||||||
|
scons -j8
|
||||||
|
```
|
|
@ -0,0 +1,14 @@
|
||||||
|
# for module compiling
|
||||||
|
import os
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
objs = []
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for d in list:
|
||||||
|
path = os.path.join(cwd, d)
|
||||||
|
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,37 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import rtconfig
|
||||||
|
|
||||||
|
from rtconfig import RTT_ROOT
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
|
||||||
|
|
||||||
|
DefaultEnvironment(tools=[])
|
||||||
|
env = Environment(tools = ['mingw'],
|
||||||
|
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
|
||||||
|
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
|
||||||
|
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
|
||||||
|
AR = rtconfig.AR, ARFLAGS = '-rc',
|
||||||
|
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
|
||||||
|
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
|
||||||
|
env['ASCOM'] = env['ASPPCOM']
|
||||||
|
|
||||||
|
Export('RTT_ROOT')
|
||||||
|
Export('rtconfig')
|
||||||
|
|
||||||
|
# prepare building environment
|
||||||
|
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
|
||||||
|
|
||||||
|
stack_size = 4096
|
||||||
|
|
||||||
|
stack_lds = open('link_stacksize.lds', 'w')
|
||||||
|
if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
|
||||||
|
stack_lds.write('__STACKSIZE__ = %d;' % stack_size)
|
||||||
|
stack_lds.close()
|
||||||
|
|
||||||
|
# make a building
|
||||||
|
DoBuilding(TARGET, objs)
|
|
@ -0,0 +1,9 @@
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
Return('group')
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("Hello RISC-V\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <rtthread.h>
|
||||||
|
|
||||||
|
#ifdef RT_USING_DFS
|
||||||
|
#include <dfs_fs.h>
|
||||||
|
|
||||||
|
rt_weak uint8_t *cromfs_get_partition_data(uint32_t *len)
|
||||||
|
{
|
||||||
|
return RT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mnt_cromfs(void)
|
||||||
|
{
|
||||||
|
uint32_t length = 0;
|
||||||
|
uint8_t *data = cromfs_get_partition_data(&length);
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (data && length)
|
||||||
|
{
|
||||||
|
ret = dfs_mount(NULL, "/", "crom", 0, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mnt_init(void)
|
||||||
|
{
|
||||||
|
rt_err_t ret;
|
||||||
|
|
||||||
|
ret = mnt_cromfs();
|
||||||
|
if (ret != RT_EOK)
|
||||||
|
{
|
||||||
|
rt_kprintf("CromFS mount failed!\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir("/dev/shm", 0x777);
|
||||||
|
|
||||||
|
if (dfs_mount(RT_NULL, "/dev/shm", "tmp", 0, 0) != 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("Dir /dev/shm mount failed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BSP_SD_SDIO_DEV
|
||||||
|
while (mmcsd_wait_cd_changed(100) != MMCSD_HOST_PLUGED)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (dfs_mount(BSP_SD_MNT_DEVNAME, "/mnt", "elm", 0, 0) != 0)
|
||||||
|
{
|
||||||
|
rt_kprintf("Dir /mnt mount failed!\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rt_kprintf("file system initialization done!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
INIT_ENV_EXPORT(mnt_init);
|
||||||
|
#endif
|
|
@ -0,0 +1,38 @@
|
||||||
|
menu "Drivers Configuration"
|
||||||
|
|
||||||
|
menuconfig BSP_USING_SDIO
|
||||||
|
bool "Enable SDIO"
|
||||||
|
select RT_USING_SDIO
|
||||||
|
default n
|
||||||
|
|
||||||
|
if BSP_USING_SDIO
|
||||||
|
config BSP_USING_SDIO0
|
||||||
|
bool "Enable SDIO0"
|
||||||
|
default n
|
||||||
|
|
||||||
|
if BSP_USING_SDIO0
|
||||||
|
config BSP_SDIO0_EMMC
|
||||||
|
bool "Enable eMMC"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config BSP_SDIO0_1V8
|
||||||
|
bool "Enable 1.8V"
|
||||||
|
default y
|
||||||
|
endif
|
||||||
|
|
||||||
|
config BSP_USING_SDIO1
|
||||||
|
bool "Enable SDIO1"
|
||||||
|
default y
|
||||||
|
|
||||||
|
config BSP_SD_SDIO_DEV
|
||||||
|
int "SDIO device SdCard on"
|
||||||
|
range 0 1
|
||||||
|
default 1
|
||||||
|
|
||||||
|
config BSP_SD_MNT_DEVNAME
|
||||||
|
string "The name of the SD-BlkDev to be mounted"
|
||||||
|
default "sd13"
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
endmenu
|
|
@ -0,0 +1,19 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
objs = [group]
|
||||||
|
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for item in list:
|
||||||
|
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(item, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2021-01-30 lizhirui first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "tick.h"
|
||||||
|
|
||||||
|
#include "drv_uart.h"
|
||||||
|
|
||||||
|
#include <sbi.h>
|
||||||
|
|
||||||
|
#ifdef RT_USING_SMART
|
||||||
|
#include <mmu.h>
|
||||||
|
#include "page.h"
|
||||||
|
|
||||||
|
/* respect to boot loader, must be 0xFFFFFFC000200000 */
|
||||||
|
RT_STATIC_ASSERT(kmem_region, KERNEL_VADDR_START == 0xFFFFFFC000220000);
|
||||||
|
|
||||||
|
rt_region_t init_page_region = {(rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END};
|
||||||
|
|
||||||
|
extern size_t MMUTable[];
|
||||||
|
|
||||||
|
struct mem_desc platform_mem_desc[] = {
|
||||||
|
{KERNEL_VADDR_START, (rt_size_t)RT_HW_PAGE_END - 1, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]))
|
||||||
|
|
||||||
|
#endif /* RT_USING_SMART */
|
||||||
|
|
||||||
|
#ifndef ARCH_REMAP_KERNEL
|
||||||
|
#define IOREMAP_VEND USER_VADDR_START
|
||||||
|
#else
|
||||||
|
#define IOREMAP_VEND 0ul
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//初始化BSS节区
|
||||||
|
void init_bss(void)
|
||||||
|
{
|
||||||
|
unsigned int *dst;
|
||||||
|
|
||||||
|
dst = &__bss_start;
|
||||||
|
while (dst < &__bss_end)
|
||||||
|
{
|
||||||
|
*dst++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __rt_assert_handler(const char *ex_string, const char *func, rt_size_t line)
|
||||||
|
{
|
||||||
|
rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
|
||||||
|
asm volatile("ebreak":::"memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
//BSP的C入口
|
||||||
|
void primary_cpu_entry(void)
|
||||||
|
{
|
||||||
|
//关中断
|
||||||
|
rt_hw_interrupt_disable();
|
||||||
|
rt_assert_set_hook(__rt_assert_handler);
|
||||||
|
//启动RT-Thread Smart内核
|
||||||
|
entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IOREMAP_SIZE (1ul << 30)
|
||||||
|
|
||||||
|
//这个初始化程序由内核主动调用,此时调度器还未启动,因此在此不能使用依赖线程上下文的函数
|
||||||
|
void rt_hw_board_init(void)
|
||||||
|
{
|
||||||
|
#ifdef RT_USING_SMART
|
||||||
|
/* init data structure */
|
||||||
|
rt_hw_mmu_map_init(&rt_kernel_space, (void *)(IOREMAP_VEND - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, PV_OFFSET);
|
||||||
|
|
||||||
|
/* init page allocator */
|
||||||
|
rt_page_init(init_page_region);
|
||||||
|
|
||||||
|
/* setup region, and enable MMU */
|
||||||
|
rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, NUM_MEM_DESC);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RT_USING_HEAP
|
||||||
|
/* initialize memory system */
|
||||||
|
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
|
||||||
|
#endif
|
||||||
|
/* initalize interrupt */
|
||||||
|
rt_hw_interrupt_init();
|
||||||
|
|
||||||
|
/* initialize hardware interrupt */
|
||||||
|
rt_hw_uart_init();
|
||||||
|
|
||||||
|
rt_hw_tick_init();
|
||||||
|
|
||||||
|
#ifdef RT_USING_CONSOLE
|
||||||
|
/* set console device */
|
||||||
|
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||||
|
#endif /* RT_USING_CONSOLE */
|
||||||
|
|
||||||
|
#ifdef RT_USING_COMPONENTS_INIT
|
||||||
|
rt_components_board_init();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void rt_hw_cpu_reset(void)
|
||||||
|
{
|
||||||
|
sbi_shutdown();
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine);
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2021-01-30 lizhirui first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOARD_H__
|
||||||
|
#define BOARD_H__
|
||||||
|
|
||||||
|
#include <rtconfig.h>
|
||||||
|
|
||||||
|
extern unsigned int __sram_size;
|
||||||
|
extern unsigned int __sram_base;
|
||||||
|
extern unsigned int __sram_end;
|
||||||
|
#define RAM_END (rt_size_t)((void *)&__sram_end)
|
||||||
|
|
||||||
|
extern unsigned int __bss_start;
|
||||||
|
extern unsigned int __bss_end;
|
||||||
|
|
||||||
|
#define RT_HW_HEAP_BEGIN ((void *)&__bss_end)
|
||||||
|
#define RT_HW_HEAP_END ((void *)(((rt_size_t)RT_HW_HEAP_BEGIN) + 8 * 1024 * 1024))
|
||||||
|
|
||||||
|
#define RT_HW_PAGE_START ((void *)((rt_size_t)RT_HW_HEAP_END + sizeof(rt_size_t)))
|
||||||
|
#define RT_HW_PAGE_END ((void *)(RAM_END))
|
||||||
|
|
||||||
|
void rt_hw_board_init(void);
|
||||||
|
void rt_init_user_mem(struct rt_thread *thread, const char *name, unsigned long *entry);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,21 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = []
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
src += Glob('*.c')
|
||||||
|
|
||||||
|
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
objs = [group]
|
||||||
|
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for item in list:
|
||||||
|
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(item, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,19 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('Interdrv', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
objs = [group]
|
||||||
|
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for item in list:
|
||||||
|
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(item, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,19 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('Sdio', src, depend = ['BSP_USING_SDIO'], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
objs = [group]
|
||||||
|
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for item in list:
|
||||||
|
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(item, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,930 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2017-10-10 Tanek first version
|
||||||
|
* 2021-07-07 linzhenxing add sd card drivers in mmu
|
||||||
|
* 2021-07-14 linzhenxing add emmc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "drv_sdhci.h"
|
||||||
|
#include "riscv_io.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <ioremap.h>
|
||||||
|
#include <cache.h>
|
||||||
|
|
||||||
|
#ifdef RT_USING_SDIO
|
||||||
|
|
||||||
|
#define DBG_TAG "drv_sdhci"
|
||||||
|
#ifdef RT_SDIO_DEBUG
|
||||||
|
#define DBG_LVL DBG_LOG
|
||||||
|
#else
|
||||||
|
#define DBG_LVL DBG_WARNING
|
||||||
|
#endif /* RT_SDIO_DEBUG */
|
||||||
|
#include <rtdbg.h>
|
||||||
|
|
||||||
|
#if defined(BSP_USING_SDIO0) || defined(BSP_USING_SDIO1)
|
||||||
|
|
||||||
|
#define SDHCI_SDMA_ENABLE
|
||||||
|
#define CACHE_LINESIZE (64)
|
||||||
|
|
||||||
|
#define BIT(x) (1 << x)
|
||||||
|
#define DWC_MSHC_PTR_VENDOR1 0x500
|
||||||
|
#define MSHC_CTRL_R (DWC_MSHC_PTR_VENDOR1 + 0x08)
|
||||||
|
#define EMMC_CTRL_R (DWC_MSHC_PTR_VENDOR1 + 0x2c)
|
||||||
|
#define SDHCI_VENDER_AT_CTRL_REG (DWC_MSHC_PTR_VENDOR1 + 0x40)
|
||||||
|
#define SDHCI_VENDER_AT_STAT_REG (DWC_MSHC_PTR_VENDOR1 + 0x44)
|
||||||
|
#define SDHCI_TUNE_CLK_STOP_EN_MASK BIT(16)
|
||||||
|
#define SDHCI_TUNE_SWIN_TH_VAL_LSB (24)
|
||||||
|
#define SDHCI_TUNE_SWIN_TH_VAL_MASK (0xFF)
|
||||||
|
#define CARD_IS_EMMC 0
|
||||||
|
#define EMMC_RST_N 2
|
||||||
|
#define EMMC_RST_N_OE 3
|
||||||
|
|
||||||
|
#define DWC_MSHC_PTR_PHY_REGS 0x300
|
||||||
|
#define DWC_MSHC_PHY_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x0)
|
||||||
|
#define PAD_SN_LSB 20
|
||||||
|
#define PAD_SN_MASK 0xF
|
||||||
|
#define PAD_SN_DEFAULT ((0x8 & PAD_SN_MASK) << PAD_SN_LSB)
|
||||||
|
#define PAD_SP_LSB 16
|
||||||
|
#define PAD_SP_MASK 0xF
|
||||||
|
#define PAD_SP_DEFAULT ((0x9 & PAD_SP_MASK) << PAD_SP_LSB)
|
||||||
|
#define PHY_PWRGOOD BIT(1)
|
||||||
|
#define PHY_RSTN BIT(0)
|
||||||
|
|
||||||
|
#define DWC_MSHC_CMDPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x4)
|
||||||
|
#define DWC_MSHC_DATPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x6)
|
||||||
|
#define DWC_MSHC_CLKPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x8)
|
||||||
|
#define DWC_MSHC_STBPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0xA)
|
||||||
|
#define DWC_MSHC_RSTNPAD_CNFG (DWC_MSHC_PTR_PHY_REGS + 0xC)
|
||||||
|
#define TXSLEW_N_LSB 9
|
||||||
|
#define TXSLEW_N_MASK 0xF
|
||||||
|
#define TXSLEW_P_LSB 5
|
||||||
|
#define TXSLEW_P_MASK 0xF
|
||||||
|
#define WEAKPULL_EN_LSB 3
|
||||||
|
#define WEAKPULL_EN_MASK 0x3
|
||||||
|
#define RXSEL_LSB 0
|
||||||
|
#define RXSEL_MASK 0x3
|
||||||
|
|
||||||
|
#define DWC_MSHC_COMMDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x1C)
|
||||||
|
#define DWC_MSHC_SDCLKDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x1D)
|
||||||
|
#define DWC_MSHC_SDCLKDL_DC (DWC_MSHC_PTR_PHY_REGS + 0x1E)
|
||||||
|
#define DWC_MSHC_SMPLDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x20)
|
||||||
|
#define DWC_MSHC_ATDL_CNFG (DWC_MSHC_PTR_PHY_REGS + 0x21)
|
||||||
|
|
||||||
|
#define DWC_MSHC_PHY_PAD_SD_CLK \
|
||||||
|
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (0 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
|
||||||
|
#define DWC_MSHC_PHY_PAD_SD_DAT \
|
||||||
|
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (1 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
|
||||||
|
#define DWC_MSHC_PHY_PAD_SD_STB \
|
||||||
|
((1 << TXSLEW_N_LSB) | (3 << TXSLEW_P_LSB) | (2 << WEAKPULL_EN_LSB) | (2 << RXSEL_LSB))
|
||||||
|
#define DWC_MSHC_PHY_PAD_EMMC_CLK \
|
||||||
|
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (0 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
|
||||||
|
#define DWC_MSHC_PHY_PAD_EMMC_DAT \
|
||||||
|
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (1 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
|
||||||
|
#define DWC_MSHC_PHY_PAD_EMMC_STB \
|
||||||
|
((2 << TXSLEW_N_LSB) | (2 << TXSLEW_P_LSB) | (2 << WEAKPULL_EN_LSB) | (1 << RXSEL_LSB))
|
||||||
|
|
||||||
|
static struct sdhci_host* sdhci_host0;
|
||||||
|
static struct sdhci_host* sdhci_host1;
|
||||||
|
|
||||||
|
static inline void sdhci_writel(struct sdhci_host* host, uint32_t val, int reg)
|
||||||
|
{
|
||||||
|
writel(val, (void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sdhci_writew(struct sdhci_host* host, uint16_t val, int reg)
|
||||||
|
{
|
||||||
|
writew((uint16_t)val, (void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void sdhci_writeb(struct sdhci_host* host, uint8_t val, int reg)
|
||||||
|
{
|
||||||
|
writeb((uint8_t)val, (void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t sdhci_readl(struct sdhci_host* host, int reg)
|
||||||
|
{
|
||||||
|
return (uint32_t)readl((void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t sdhci_readw(struct sdhci_host* host, int reg)
|
||||||
|
{
|
||||||
|
return (uint16_t)readw((void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t sdhci_readb(struct sdhci_host* host, int reg)
|
||||||
|
{
|
||||||
|
return (uint8_t)readb((void*)host->mapbase + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emmc_reg_display(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
rt_kprintf("SD_MASA_R:%x\n", sdhci_readl(host, SDHCI_DMA_ADDRESS));
|
||||||
|
rt_kprintf("BLCOKSIZE_R:%x\n", sdhci_readw(host, SDHCI_BLOCK_SIZE));
|
||||||
|
rt_kprintf("BLOCKCOUNT_R:%x\n", sdhci_readw(host, SDHCI_BLOCK_COUNT));
|
||||||
|
rt_kprintf("ARGUMENT_R:%x\n", sdhci_readl(host, SDHCI_ARGUMENT));
|
||||||
|
rt_kprintf("XFER_MODE_R:%x\n", sdhci_readw(host, SDHCI_TRANSFER_MODE));
|
||||||
|
rt_kprintf("CMD_R:%x\n", sdhci_readw(host, SDHCI_COMMAND));
|
||||||
|
rt_kprintf("RESP0_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE));
|
||||||
|
rt_kprintf("RESP1_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 4));
|
||||||
|
rt_kprintf("RESP2_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 8));
|
||||||
|
rt_kprintf("RESP3_R:%x\n", sdhci_readl(host, SDHCI_RESPONSE + 12));
|
||||||
|
rt_kprintf("BUF_DATA_R:%x\n", sdhci_readl(host, SDHCI_BUFFER));
|
||||||
|
rt_kprintf("PSTATE_REG_R:%x\n", sdhci_readl(host, SDHCI_PRESENT_STATE));
|
||||||
|
rt_kprintf("HOST_CTL_R:%x\n", sdhci_readb(host, SDHCI_HOST_CONTROL));
|
||||||
|
rt_kprintf("PWR_CTRL_R:%x\n", sdhci_readb(host, SDHCI_POWER_CONTROL));
|
||||||
|
rt_kprintf("BGAP_CTRL_R:%x\n", sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
|
||||||
|
rt_kprintf("WUP_CTRL_R:%x\n", sdhci_readb(host, SDHCI_WAKE_UP_CONTROL));
|
||||||
|
rt_kprintf("CLK_CTRL_R:%x\n", sdhci_readw(host, SDHCI_CLOCK_CONTROL));
|
||||||
|
rt_kprintf("TOUT_CTRL_R:%x\n", sdhci_readb(host, SDHCI_TIMEOUT_CONTROL));
|
||||||
|
rt_kprintf("SW_RSR_R:%x\n", sdhci_readb(host, SDHCI_SOFTWARE_RESET));
|
||||||
|
rt_kprintf("NORMAL_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_INT_STATUS));
|
||||||
|
rt_kprintf("ERROR_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_INT_STATUS + 2));
|
||||||
|
rt_kprintf("NORMAL_INT_STAT_EN_R:%x\n", sdhci_readw(host, SDHCI_INT_ENABLE));
|
||||||
|
rt_kprintf("ERROR_INT_STAT_EN_R:%x\n", sdhci_readw(host, SDHCI_INT_ENABLE + 2));
|
||||||
|
rt_kprintf("NORNAL_INT_SIGNAL_EN_R:%x\n", sdhci_readw(host, SDHCI_SIGNAL_ENABLE));
|
||||||
|
rt_kprintf("ERROR_INT_SIGNAL_EN_R:%x\n", sdhci_readw(host, SDHCI_SIGNAL_ENABLE + 2));
|
||||||
|
rt_kprintf("AUTO_CMD_STAT_R:%x\n", sdhci_readw(host, SDHCI_AUTO_CMD_STATUS));
|
||||||
|
rt_kprintf("HOST_CTRL2_R:%x\n", sdhci_readw(host, SDHCI_HOST_CONTROL2));
|
||||||
|
rt_kprintf("CAPABILITIES1_R:%x\n", sdhci_readl(host, SDHCI_CAPABILITIES));
|
||||||
|
rt_kprintf("CAPABILITIES2_R:%x\n", sdhci_readl(host, SDHCI_CAPABILITIES_1));
|
||||||
|
rt_kprintf("FORCE_AUTO_CMD_STAT_R:%x\n", sdhci_readw(host, SDHCI_MAX_CURRENT));
|
||||||
|
rt_kprintf("FORCE_ERROR_INT_STAT_R:%x\n", sdhci_readw(host, SDHCI_SET_ACMD12_ERROR));
|
||||||
|
rt_kprintf("AMDA_ERR_STAT_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ERROR));
|
||||||
|
rt_kprintf("AMDA_SA_LOW_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ADDRESS));
|
||||||
|
rt_kprintf("AMDA_SA_HIGH_STAT_R:%x\n", sdhci_readl(host, SDHCI_ADMA_ADDRESS_HI));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void delay_1k(unsigned int uicnt)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < uicnt; i++)
|
||||||
|
for (j = 0; j < 1000; j++)
|
||||||
|
asm("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwcmshc_phy_1_8v_init(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_CMDPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_DATPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_CLK, DWC_MSHC_CLKPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_STB, DWC_MSHC_STBPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_EMMC_DAT, DWC_MSHC_RSTNPAD_CNFG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwcmshc_phy_3_3v_init(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_CMDPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_DATPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_CLK, DWC_MSHC_CLKPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_STB, DWC_MSHC_STBPAD_CNFG);
|
||||||
|
sdhci_writew(host, DWC_MSHC_PHY_PAD_SD_DAT, DWC_MSHC_RSTNPAD_CNFG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dwcmshc_phy_delay_config(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
sdhci_writeb(host, 1, DWC_MSHC_COMMDL_CNFG);
|
||||||
|
if (host->tx_delay_line > 256) {
|
||||||
|
LOG_E("host%d: tx_delay_line err\n", host->index);
|
||||||
|
} else if (host->tx_delay_line > 128) {
|
||||||
|
sdhci_writeb(host, 0x1, DWC_MSHC_SDCLKDL_CNFG);
|
||||||
|
sdhci_writeb(host, host->tx_delay_line - 128, DWC_MSHC_SDCLKDL_DC);
|
||||||
|
} else {
|
||||||
|
sdhci_writeb(host, 0x0, DWC_MSHC_SDCLKDL_CNFG);
|
||||||
|
sdhci_writeb(host, host->tx_delay_line, DWC_MSHC_SDCLKDL_DC);
|
||||||
|
}
|
||||||
|
sdhci_writeb(host, host->rx_delay_line, DWC_MSHC_SMPLDL_CNFG);
|
||||||
|
sdhci_writeb(host, 0xc, DWC_MSHC_ATDL_CNFG);
|
||||||
|
sdhci_writel(host, (sdhci_readl(host, SDHCI_VENDER_AT_CTRL_REG) | BIT(16) | BIT(17) | BIT(19) | BIT(20)), SDHCI_VENDER_AT_CTRL_REG);
|
||||||
|
sdhci_writel(host, 0x0, SDHCI_VENDER_AT_STAT_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dwcmshc_phy_init(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t timeout = 15000;
|
||||||
|
/* reset phy */
|
||||||
|
sdhci_writew(host, 0, DWC_MSHC_PHY_CNFG);
|
||||||
|
|
||||||
|
/* Disable the clock */
|
||||||
|
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
|
||||||
|
|
||||||
|
if (host->io_fixed_1v8) {
|
||||||
|
uint32_t data = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||||
|
data |= SDHCI_CTRL_VDD_180;
|
||||||
|
sdhci_writew(host, data, SDHCI_HOST_CONTROL2);
|
||||||
|
dwcmshc_phy_1_8v_init(host);
|
||||||
|
} else {
|
||||||
|
dwcmshc_phy_3_3v_init(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
dwcmshc_phy_delay_config(host);
|
||||||
|
|
||||||
|
/* Wait max 150 ms */
|
||||||
|
while (1) {
|
||||||
|
reg = sdhci_readl(host, DWC_MSHC_PHY_CNFG);
|
||||||
|
if (reg & PHY_PWRGOOD)
|
||||||
|
break;
|
||||||
|
if (!timeout) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
timeout--;
|
||||||
|
|
||||||
|
delay_1k(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = PAD_SN_DEFAULT | PAD_SP_DEFAULT;
|
||||||
|
sdhci_writel(host, reg, DWC_MSHC_PHY_CNFG);
|
||||||
|
|
||||||
|
/* de-assert the phy */
|
||||||
|
reg |= PHY_RSTN;
|
||||||
|
sdhci_writel(host, reg, DWC_MSHC_PHY_CNFG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhci_reset(struct sdhci_host* host, uint8_t mask)
|
||||||
|
{
|
||||||
|
unsigned long timeout;
|
||||||
|
|
||||||
|
/* Wait max 100 ms */
|
||||||
|
timeout = 100;
|
||||||
|
sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
|
||||||
|
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
|
||||||
|
if (timeout == 0) {
|
||||||
|
LOG_E("%s: Reset 0x%x never completed.\n",
|
||||||
|
__func__, (int)mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timeout--;
|
||||||
|
delay_1k(1);
|
||||||
|
}
|
||||||
|
if (mask == SDHCI_RESET_ALL) {
|
||||||
|
if (host->index == 0) {
|
||||||
|
uint16_t emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
|
||||||
|
if (host->is_emmc_card)
|
||||||
|
emmc_ctl |= (1 << CARD_IS_EMMC);
|
||||||
|
else
|
||||||
|
emmc_ctl &= ~(1 << CARD_IS_EMMC);
|
||||||
|
sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
|
||||||
|
}
|
||||||
|
if (host->have_phy)
|
||||||
|
dwcmshc_phy_init(host);
|
||||||
|
else
|
||||||
|
sdhci_writeb(host, host->mshc_ctrl_r, MSHC_CTRL_R);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t sdhci_get_present_status_flag(struct sdhci_host* sdhci_host)
|
||||||
|
{
|
||||||
|
return sdhci_readl(sdhci_host, SDHCI_PRESENT_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t sdhci_get_int_status_flag(struct sdhci_host* sdhci_host)
|
||||||
|
{
|
||||||
|
return sdhci_readl(sdhci_host, SDHCI_INT_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhci_clear_int_status_flag(struct sdhci_host* sdhci_host, uint32_t mask)
|
||||||
|
{
|
||||||
|
sdhci_writel(sdhci_host, mask, SDHCI_INT_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhic_error_recovery(struct sdhci_host* sdhci_host)
|
||||||
|
{
|
||||||
|
uint32_t status;
|
||||||
|
/* get host present status */
|
||||||
|
status = sdhci_get_present_status_flag(sdhci_host);
|
||||||
|
/* check command inhibit status flag */
|
||||||
|
if ((status & SDHCI_CMD_INHIBIT) != 0U) {
|
||||||
|
/* reset command line */
|
||||||
|
sdhci_reset(sdhci_host, SDHCI_RESET_CMD);
|
||||||
|
}
|
||||||
|
/* check data inhibit status flag */
|
||||||
|
if ((status & SDHCI_DATA_INHIBIT) != 0U) {
|
||||||
|
/* reset data line */
|
||||||
|
sdhci_reset(sdhci_host, SDHCI_RESET_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_receive_command_response(struct sdhci_host* sdhci_host, struct sdhci_command* command)
|
||||||
|
{
|
||||||
|
if (command->responseType == card_response_type_r2) {
|
||||||
|
/* CRC is stripped so we need to do some shifting. */
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
command->response[3 - i] = sdhci_readl(sdhci_host, SDHCI_RESPONSE + (3 - i) * 4) << 8;
|
||||||
|
if (i != 3)
|
||||||
|
command->response[3 - i] |= sdhci_readb(sdhci_host, SDHCI_RESPONSE + (3 - i) * 4 - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
command->response[0] = sdhci_readl(sdhci_host, SDHCI_RESPONSE);
|
||||||
|
}
|
||||||
|
/* check response error flag */
|
||||||
|
if ((command->responseErrorFlags != 0U) && ((command->responseType == card_response_type_r1) || (command->responseType == card_response_type_r1b) || (command->responseType == card_response_type_r6) || (command->responseType == card_response_type_r5))) {
|
||||||
|
if (((command->responseErrorFlags) & (command->response[0U])) != 0U)
|
||||||
|
return -1; // kStatus_USDHC_SendCommandFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhci_send_command(struct sdhci_host* sdhci_host, struct sdhci_command* command, rt_bool_t enDMA)
|
||||||
|
{
|
||||||
|
RT_ASSERT(RT_NULL != command);
|
||||||
|
|
||||||
|
uint32_t cmd_r, xfer_mode;
|
||||||
|
struct sdhci_data* sdhci_data = sdhci_host->sdhci_data;
|
||||||
|
|
||||||
|
cmd_r = SDHCI_MAKE_CMD(command->index, command->flags);
|
||||||
|
|
||||||
|
if (sdhci_data != RT_NULL) {
|
||||||
|
#ifdef SDHCI_SDMA_ENABLE
|
||||||
|
rt_ubase_t start_addr, dma_addr;
|
||||||
|
if (sdhci_data->rxData)
|
||||||
|
start_addr = (rt_ubase_t)((uint8_t*)sdhci_data->rxData);
|
||||||
|
else
|
||||||
|
start_addr = (rt_ubase_t)((uint8_t*)sdhci_data->txData);
|
||||||
|
rt_hw_cpu_dcache_clean((void*)start_addr, sdhci_data->blockSize * sdhci_data->blockCount);
|
||||||
|
command->flags2 |= sdhci_enable_dma_flag;
|
||||||
|
dma_addr = rt_kmem_v2p((void*)start_addr);
|
||||||
|
sdhci_writel(sdhci_host, dma_addr, SDHCI_DMA_ADDRESS);
|
||||||
|
#endif
|
||||||
|
sdhci_writew(sdhci_host, SDHCI_MAKE_BLKSZ(7, sdhci_data->blockSize), SDHCI_BLOCK_SIZE);
|
||||||
|
sdhci_writew(sdhci_host, sdhci_data->blockCount, SDHCI_BLOCK_COUNT);
|
||||||
|
}
|
||||||
|
xfer_mode = command->flags2 & 0x1ff;
|
||||||
|
sdhci_writew(sdhci_host, xfer_mode, SDHCI_TRANSFER_MODE);
|
||||||
|
sdhci_writel(sdhci_host, command->argument, SDHCI_ARGUMENT);
|
||||||
|
sdhci_writew(sdhci_host, cmd_r, SDHCI_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_wait_command_done(struct sdhci_host* sdhci_host, struct sdhci_command* command, rt_bool_t executeTuning)
|
||||||
|
{
|
||||||
|
RT_ASSERT(RT_NULL != command);
|
||||||
|
rt_uint32_t event;
|
||||||
|
/* tuning cmd do not need to wait command done */
|
||||||
|
if (executeTuning)
|
||||||
|
return 0;
|
||||||
|
/* Wait command complete or USDHC encounters error. */
|
||||||
|
rt_event_recv(&sdhci_host->event, SDHCI_INT_ERROR | SDHCI_INT_RESPONSE,
|
||||||
|
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
|
||||||
|
if (event & SDHCI_INT_ERROR) {
|
||||||
|
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, sdhci_host->error_code);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return sdhci_receive_command_response(sdhci_host, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_transfer_data_blocking(struct sdhci_host* sdhci_host, struct sdhci_data* data, rt_bool_t enDMA)
|
||||||
|
{
|
||||||
|
#ifdef SDHCI_SDMA_ENABLE
|
||||||
|
rt_err_t err;
|
||||||
|
rt_uint32_t event;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
err = rt_event_recv(&sdhci_host->event, SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END,
|
||||||
|
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 1000, &event);
|
||||||
|
if (err == -RT_ETIMEOUT) {
|
||||||
|
rt_kprintf("%s: Transfer data timeout\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (event & SDHCI_INT_ERROR) {
|
||||||
|
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, sdhci_host->error_code);
|
||||||
|
emmc_reg_display(sdhci_host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (event & SDHCI_INT_DMA_END) {
|
||||||
|
sdhci_writel(sdhci_host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS);
|
||||||
|
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_DMA_ADDRESS), SDHCI_DMA_ADDRESS);
|
||||||
|
}
|
||||||
|
if (event & SDHCI_INT_DATA_END) {
|
||||||
|
if (data && data->rxData)
|
||||||
|
rt_hw_cpu_dcache_invalidate((void*)data->rxData, data->blockSize * data->blockCount);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32_t stat, rdy, mask, timeout, block;
|
||||||
|
|
||||||
|
block = 0;
|
||||||
|
timeout = 1000000;
|
||||||
|
rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
|
||||||
|
mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
stat = sdhci_get_int_status_flag(sdhci_host);
|
||||||
|
if (stat & SDHCI_INT_ERROR) {
|
||||||
|
LOG_D("%s: Error detected in status(0x%X)!\n", __func__, stat);
|
||||||
|
emmc_reg_display(sdhci_host);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (stat & rdy) {
|
||||||
|
if (!(sdhci_readl(sdhci_host, SDHCI_PRESENT_STATE) & mask)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sdhci_clear_int_status_flag(sdhci_host, rdy);
|
||||||
|
if (data->rxData) {
|
||||||
|
for (int i = 0; i < data->blockSize / 4; i++)
|
||||||
|
data->rxData[i + block * data->blockSize] = sdhci_readl(sdhci_host, SDHCI_BUFFER);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < data->blockSize / 4; i++)
|
||||||
|
sdhci_writel(sdhci_host, data->txData[i + block * data->blockSize], SDHCI_BUFFER);
|
||||||
|
}
|
||||||
|
block++;
|
||||||
|
if (block >= data->blockCount)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (timeout == 0) {
|
||||||
|
rt_kprintf("%s: Transfer data timeout\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
timeout--;
|
||||||
|
delay_1k(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_set_transfer_config(struct sdhci_host* sdhci_host, struct sdhci_command* sdhci_command, struct sdhci_data* sdhci_data)
|
||||||
|
{
|
||||||
|
RT_ASSERT(sdhci_command);
|
||||||
|
/* Define the flag corresponding to each response type. */
|
||||||
|
switch (sdhci_command->responseType) {
|
||||||
|
case card_response_type_none:
|
||||||
|
break;
|
||||||
|
case card_response_type_r1: /* Response 1 */
|
||||||
|
case card_response_type_r5: /* Response 5 */
|
||||||
|
case card_response_type_r6: /* Response 6 */
|
||||||
|
case card_response_type_r7: /* Response 7 */
|
||||||
|
|
||||||
|
sdhci_command->flags |= (sdhci_cmd_resp_short | sdhci_enable_cmd_crc_flag | sdhci_enable_cmd_index_chk_flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case card_response_type_r1b: /* Response 1 with busy */
|
||||||
|
case card_response_type_r5b: /* Response 5 with busy */
|
||||||
|
sdhci_command->flags |= (sdhci_cmd_resp_short_busy | sdhci_enable_cmd_crc_flag | sdhci_enable_cmd_index_chk_flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case card_response_type_r2: /* Response 2 */
|
||||||
|
sdhci_command->flags |= (sdhci_cmd_resp_long | sdhci_enable_cmd_crc_flag);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case card_response_type_r3: /* Response 3 */
|
||||||
|
case card_response_type_r4: /* Response 4 */
|
||||||
|
sdhci_command->flags |= (sdhci_cmd_resp_short);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdhci_command->type == card_command_type_abort) {
|
||||||
|
sdhci_command->flags |= sdhci_enable_command_type_abort;
|
||||||
|
} else if (sdhci_command->type == card_command_type_resume) {
|
||||||
|
sdhci_command->flags |= sdhci_enable_command_type_resume;
|
||||||
|
} else if (sdhci_command->type == card_command_type_suspend) {
|
||||||
|
sdhci_command->flags |= sdhci_enable_command_type_suspend;
|
||||||
|
} else if (sdhci_command->type == card_command_type_normal) {
|
||||||
|
sdhci_command->flags |= sdhci_enable_command_type_normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdhci_data) {
|
||||||
|
sdhci_command->flags |= sdhci_enable_cmd_data_present_flag;
|
||||||
|
sdhci_command->flags2 |= sdhci_enable_block_count_flag;
|
||||||
|
|
||||||
|
if (sdhci_data->rxData) {
|
||||||
|
sdhci_command->flags2 |= sdhci_data_read_flag;
|
||||||
|
}
|
||||||
|
if (sdhci_data->blockCount > 1U) {
|
||||||
|
sdhci_command->flags2 |= (sdhci_multiple_block_flag);
|
||||||
|
/* auto command 12 */
|
||||||
|
if (sdhci_data->enableAutoCommand12) {
|
||||||
|
/* Enable Auto command 12. */
|
||||||
|
sdhci_command->flags2 |= sdhci_enable_auto_command12_flag;
|
||||||
|
}
|
||||||
|
/* auto command 23 */
|
||||||
|
if (sdhci_data->enableAutoCommand23) {
|
||||||
|
sdhci_command->flags2 |= sdhci_enable_auto_command23_flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t sdhci_transfer_blocking(struct sdhci_host* sdhci_host)
|
||||||
|
{
|
||||||
|
RT_ASSERT(sdhci_host);
|
||||||
|
struct sdhci_command* sdhci_command = sdhci_host->sdhci_command;
|
||||||
|
struct sdhci_data* sdhci_data = sdhci_host->sdhci_data;
|
||||||
|
rt_bool_t enDMA = false;
|
||||||
|
int ret = RT_EOK;
|
||||||
|
|
||||||
|
/* Wait until command/data bus out of busy status. */
|
||||||
|
while (sdhci_get_present_status_flag(sdhci_host) & sdhci_command_inhibit_flag) {
|
||||||
|
}
|
||||||
|
while (sdhci_data && (sdhci_get_present_status_flag(sdhci_host) & sdhci_data_inhibit_flag)) {
|
||||||
|
}
|
||||||
|
sdhci_writel(sdhci_host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
|
||||||
|
|
||||||
|
ret = sdhci_set_transfer_config(sdhci_host, sdhci_command, sdhci_data);
|
||||||
|
if (ret != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_SIGNAL_ENABLE) |
|
||||||
|
SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_SIGNAL_ENABLE);
|
||||||
|
rt_event_control(&sdhci_host->event, RT_IPC_CMD_RESET, 0);
|
||||||
|
sdhci_send_command(sdhci_host, sdhci_command, enDMA);
|
||||||
|
/* wait command done */
|
||||||
|
ret = sdhci_wait_command_done(sdhci_host, sdhci_command, ((sdhci_data == RT_NULL) ? false : sdhci_data->executeTuning));
|
||||||
|
/* transfer data */
|
||||||
|
if ((sdhci_data != RT_NULL) && (ret == 0)) {
|
||||||
|
ret = sdhci_transfer_data_blocking(sdhci_host, sdhci_data, enDMA);
|
||||||
|
}
|
||||||
|
sdhci_writel(sdhci_host, sdhci_readl(sdhci_host, SDHCI_SIGNAL_ENABLE) &
|
||||||
|
~(SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK), SDHCI_SIGNAL_ENABLE);
|
||||||
|
sdhci_writel(sdhci_host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
|
||||||
|
sdhci_reset(sdhci_host, SDHCI_RESET_CMD);
|
||||||
|
sdhci_reset(sdhci_host, SDHCI_RESET_DATA);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhci_init(struct sdhci_host* host)
|
||||||
|
{
|
||||||
|
sdhci_reset(host, SDHCI_RESET_ALL);
|
||||||
|
sdhci_writeb(host, SDHCI_CTRL_HISPD, SDHCI_HOST_CONTROL);
|
||||||
|
sdhci_writeb(host, 0x7, SDHCI_TIMEOUT_CONTROL);
|
||||||
|
sdhci_writeb(host, SDHCI_POWER_ON | SDHCI_POWER_330, SDHCI_POWER_CONTROL);
|
||||||
|
sdhci_writew(host, SDHCI_CLOCK_INT_EN, SDHCI_CLOCK_CONTROL);
|
||||||
|
while ((sdhci_readw(host, SDHCI_CLOCK_CONTROL) & SDHCI_CLOCK_INT_STABLE) == 0)
|
||||||
|
;
|
||||||
|
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
|
||||||
|
sdhci_writel(host, SDHCI_INT_CARD_INT, SDHCI_SIGNAL_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sdhci_irq(int vector, void* param)
|
||||||
|
{
|
||||||
|
struct sdhci_host* host = param;
|
||||||
|
uint32_t status = sdhci_get_int_status_flag(host);
|
||||||
|
|
||||||
|
if (status & (SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_RESPONSE)) {
|
||||||
|
host->error_code = (status >> 16) & 0xffff;
|
||||||
|
rt_event_send(&host->event, status & (SDHCI_INT_ERROR | SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_RESPONSE));
|
||||||
|
}
|
||||||
|
if (status & SDHCI_INT_CARD_INT)
|
||||||
|
sdio_irq_wakeup(host->host);
|
||||||
|
sdhci_clear_int_status_flag(host, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kd_mmc_request(struct rt_mmcsd_host* host, struct rt_mmcsd_req* req)
|
||||||
|
{
|
||||||
|
struct sdhci_host* mmcsd;
|
||||||
|
struct rt_mmcsd_cmd* cmd;
|
||||||
|
struct rt_mmcsd_data* data;
|
||||||
|
rt_err_t error;
|
||||||
|
struct sdhci_data sdhci_data = { 0 };
|
||||||
|
struct sdhci_command sdhci_command = { 0 };
|
||||||
|
|
||||||
|
RT_ASSERT(host != RT_NULL);
|
||||||
|
RT_ASSERT(req != RT_NULL);
|
||||||
|
|
||||||
|
mmcsd = (struct sdhci_host*)host->private_data;
|
||||||
|
RT_ASSERT(mmcsd != RT_NULL);
|
||||||
|
|
||||||
|
cmd = req->cmd;
|
||||||
|
RT_ASSERT(cmd != RT_NULL);
|
||||||
|
|
||||||
|
LOG_D("\tcmd->cmd_code: %02d, cmd->arg: %08x, cmd->flags: %08x --> ", cmd->cmd_code, cmd->arg, cmd->flags);
|
||||||
|
|
||||||
|
data = cmd->data;
|
||||||
|
|
||||||
|
sdhci_command.index = cmd->cmd_code;
|
||||||
|
sdhci_command.argument = cmd->arg;
|
||||||
|
|
||||||
|
if (cmd->cmd_code == STOP_TRANSMISSION)
|
||||||
|
sdhci_command.type = card_command_type_abort;
|
||||||
|
else
|
||||||
|
sdhci_command.type = card_command_type_normal;
|
||||||
|
|
||||||
|
switch (cmd->flags & RESP_MASK) {
|
||||||
|
case RESP_NONE:
|
||||||
|
sdhci_command.responseType = card_response_type_none;
|
||||||
|
break;
|
||||||
|
case RESP_R1:
|
||||||
|
sdhci_command.responseType = card_response_type_r1;
|
||||||
|
break;
|
||||||
|
case RESP_R1B:
|
||||||
|
sdhci_command.responseType = card_response_type_r1b;
|
||||||
|
break;
|
||||||
|
case RESP_R2:
|
||||||
|
sdhci_command.responseType = card_response_type_r2;
|
||||||
|
break;
|
||||||
|
case RESP_R3:
|
||||||
|
sdhci_command.responseType = card_response_type_r3;
|
||||||
|
break;
|
||||||
|
case RESP_R4:
|
||||||
|
sdhci_command.responseType = card_response_type_r4;
|
||||||
|
break;
|
||||||
|
case RESP_R6:
|
||||||
|
sdhci_command.responseType = card_response_type_r6;
|
||||||
|
break;
|
||||||
|
case RESP_R7:
|
||||||
|
sdhci_command.responseType = card_response_type_r7;
|
||||||
|
break;
|
||||||
|
case RESP_R5:
|
||||||
|
sdhci_command.responseType = card_response_type_r5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RT_ASSERT(RT_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
sdhci_command.flags = 0;
|
||||||
|
sdhci_command.flags2 = 0;
|
||||||
|
sdhci_command.responseErrorFlags = 0;
|
||||||
|
mmcsd->sdhci_command = &sdhci_command;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
if (req->stop != RT_NULL)
|
||||||
|
sdhci_data.enableAutoCommand12 = true;
|
||||||
|
else
|
||||||
|
sdhci_data.enableAutoCommand12 = false;
|
||||||
|
|
||||||
|
sdhci_data.enableAutoCommand23 = false;
|
||||||
|
|
||||||
|
sdhci_data.blockSize = data->blksize;
|
||||||
|
sdhci_data.blockCount = data->blks;
|
||||||
|
|
||||||
|
if (data->flags == DATA_DIR_WRITE) {
|
||||||
|
sdhci_data.txData = data->buf;
|
||||||
|
sdhci_data.rxData = RT_NULL;
|
||||||
|
} else {
|
||||||
|
sdhci_data.rxData = data->buf;
|
||||||
|
sdhci_data.txData = RT_NULL;
|
||||||
|
}
|
||||||
|
#ifdef SDHCI_SDMA_ENABLE
|
||||||
|
uint32_t sz = sdhci_data.blockSize * sdhci_data.blockCount;
|
||||||
|
uint32_t pad = 0;
|
||||||
|
if (sz & (CACHE_LINESIZE - 1))
|
||||||
|
pad = (sz + (CACHE_LINESIZE - 1)) & ~(CACHE_LINESIZE - 1);
|
||||||
|
if (sdhci_data.rxData && (((uint64_t)(sdhci_data.rxData) & (CACHE_LINESIZE - 1)) || pad)) {
|
||||||
|
sdhci_data.rxData = rt_malloc_align(pad ? pad : sz, CACHE_LINESIZE);
|
||||||
|
} else if (((uint64_t)(sdhci_data.txData) & (CACHE_LINESIZE - 1)) || pad) {
|
||||||
|
sdhci_data.txData = rt_malloc_align(pad ? pad : sz, CACHE_LINESIZE);
|
||||||
|
rt_memcpy(sdhci_data.txData, data->buf, sz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
mmcsd->sdhci_data = &sdhci_data;
|
||||||
|
} else {
|
||||||
|
mmcsd->sdhci_data = RT_NULL;
|
||||||
|
}
|
||||||
|
error = sdhci_transfer_blocking(mmcsd);
|
||||||
|
#ifdef SDHCI_SDMA_ENABLE
|
||||||
|
if (data && sdhci_data.rxData && sdhci_data.rxData != data->buf) {
|
||||||
|
rt_memcpy(data->buf, sdhci_data.rxData, sdhci_data.blockSize * sdhci_data.blockCount);
|
||||||
|
rt_free_align(sdhci_data.rxData);
|
||||||
|
} else if (data && sdhci_data.txData && sdhci_data.txData != data->buf) {
|
||||||
|
rt_free_align(sdhci_data.txData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (error == -1) {
|
||||||
|
LOG_D(" ***USDHC_TransferBlocking error: %d*** --> \n", error);
|
||||||
|
cmd->err = -RT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmd->flags & RESP_MASK) == RESP_R2) {
|
||||||
|
cmd->resp[3] = sdhci_command.response[0];
|
||||||
|
cmd->resp[2] = sdhci_command.response[1];
|
||||||
|
cmd->resp[1] = sdhci_command.response[2];
|
||||||
|
cmd->resp[0] = sdhci_command.response[3];
|
||||||
|
LOG_D(" resp 0x%08X 0x%08X 0x%08X 0x%08X\n",
|
||||||
|
cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
|
||||||
|
} else {
|
||||||
|
cmd->resp[0] = sdhci_command.response[0];
|
||||||
|
LOG_D(" resp 0x%08X\n", cmd->resp[0]);
|
||||||
|
}
|
||||||
|
mmcsd_req_complete(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kd_mmc_clock_freq_change(struct sdhci_host* host, uint32_t clock)
|
||||||
|
{
|
||||||
|
uint32_t div, val;
|
||||||
|
|
||||||
|
val = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||||
|
val &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_PROG_CLOCK_MODE);
|
||||||
|
sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
|
||||||
|
|
||||||
|
if (clock == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (host->max_clk <= clock) {
|
||||||
|
div = 1;
|
||||||
|
} else {
|
||||||
|
for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
|
||||||
|
if ((host->max_clk / div) <= clock)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div >>= 1;
|
||||||
|
val &= ~((SDHCI_DIV_MASK << SDHCI_DIVIDER_SHIFT) | SDHCI_DIV_HI_MASK);
|
||||||
|
val |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
|
||||||
|
val |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
|
||||||
|
<< SDHCI_DIVIDER_HI_SHIFT;
|
||||||
|
val |= SDHCI_CLOCK_CARD_EN | SDHCI_PROG_CLOCK_MODE;
|
||||||
|
sdhci_writew(host, val, SDHCI_CLOCK_CONTROL);
|
||||||
|
while ((sdhci_readw(host, SDHCI_CLOCK_CONTROL) & SDHCI_CLOCK_INT_STABLE) == 0)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kd_set_iocfg(struct rt_mmcsd_host* host, struct rt_mmcsd_io_cfg* io_cfg)
|
||||||
|
{
|
||||||
|
struct sdhci_host* mmcsd;
|
||||||
|
unsigned int sdhci_clk;
|
||||||
|
unsigned int bus_width;
|
||||||
|
uint8_t ctrl;
|
||||||
|
RT_ASSERT(host != RT_NULL);
|
||||||
|
RT_ASSERT(host->private_data != RT_NULL);
|
||||||
|
RT_ASSERT(io_cfg != RT_NULL);
|
||||||
|
|
||||||
|
mmcsd = (struct sdhci_host*)host->private_data;
|
||||||
|
sdhci_clk = io_cfg->clock;
|
||||||
|
bus_width = io_cfg->bus_width;
|
||||||
|
|
||||||
|
LOG_D("%s: sdhci_clk=%d, bus_width:%d\n", __func__, sdhci_clk, bus_width);
|
||||||
|
|
||||||
|
kd_mmc_clock_freq_change(mmcsd, sdhci_clk);
|
||||||
|
ctrl = sdhci_readb(mmcsd, SDHCI_HOST_CONTROL);
|
||||||
|
ctrl &= ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS);
|
||||||
|
if (bus_width == 3)
|
||||||
|
ctrl |= SDHCI_CTRL_8BITBUS;
|
||||||
|
else if (bus_width == 2)
|
||||||
|
ctrl |= SDHCI_CTRL_4BITBUS;
|
||||||
|
sdhci_writeb(mmcsd, ctrl, SDHCI_HOST_CONTROL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kd_enable_sdio_irq(struct rt_mmcsd_host* mmcsd_host, rt_int32_t en)
|
||||||
|
{
|
||||||
|
struct sdhci_host* host = (struct sdhci_host*)mmcsd_host->private_data;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
val = sdhci_readw(host, SDHCI_INT_ENABLE);
|
||||||
|
if (en)
|
||||||
|
val |= SDHCI_INT_CARD_INT;
|
||||||
|
else
|
||||||
|
val &= ~SDHCI_INT_CARD_INT;
|
||||||
|
sdhci_writew(host, val, SDHCI_INT_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rt_mmcsd_host_ops ops = {
|
||||||
|
kd_mmc_request,
|
||||||
|
kd_set_iocfg,
|
||||||
|
RT_NULL,
|
||||||
|
kd_enable_sdio_irq,
|
||||||
|
RT_NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
void kd_sdhci0_reset(int value)
|
||||||
|
{
|
||||||
|
struct sdhci_host* host = sdhci_host0;
|
||||||
|
|
||||||
|
uint16_t emmc_ctl = sdhci_readw(host, EMMC_CTRL_R);
|
||||||
|
emmc_ctl |= (1 << EMMC_RST_N_OE);
|
||||||
|
if (value)
|
||||||
|
emmc_ctl |= (1 << EMMC_RST_N);
|
||||||
|
else
|
||||||
|
emmc_ctl &= ~(1 << EMMC_RST_N);
|
||||||
|
sdhci_writeb(host, emmc_ctl, EMMC_CTRL_R);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kd_sdhci_change(int id)
|
||||||
|
{
|
||||||
|
if (id == 0)
|
||||||
|
mmcsd_change(sdhci_host0->host);
|
||||||
|
else if (id == 1)
|
||||||
|
mmcsd_change(sdhci_host1->host);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_int32_t kd_sdhci_init(void)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
void* hi_sys_virt_addr = rt_ioremap((void*)0x91585000, 0x10);
|
||||||
|
#ifdef BSP_USING_SDIO0
|
||||||
|
val = readl(hi_sys_virt_addr + 0);
|
||||||
|
val |= 1 << 6 | 1 << 4;
|
||||||
|
writel(val, hi_sys_virt_addr + 0);
|
||||||
|
sdhci_host0 = rt_malloc(sizeof(struct sdhci_host));
|
||||||
|
if (!sdhci_host0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rt_memset(sdhci_host0, 0, sizeof(struct sdhci_host));
|
||||||
|
sdhci_host0->mapbase = (void*)rt_ioremap((void*)SDEMMC0_BASE, 0x1000);
|
||||||
|
sdhci_host0->index = 0;
|
||||||
|
sdhci_host0->have_phy = 1;
|
||||||
|
sdhci_host0->mshc_ctrl_r = 0;
|
||||||
|
sdhci_host0->rx_delay_line = 0x0d;
|
||||||
|
sdhci_host0->tx_delay_line = 0xc0;
|
||||||
|
#ifdef BSP_SDIO0_EMMC
|
||||||
|
sdhci_host0->is_emmc_card = 1;
|
||||||
|
#else
|
||||||
|
sdhci_host0->is_emmc_card = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef BSP_SDIO0_1V8
|
||||||
|
sdhci_host0->io_fixed_1v8 = 1;
|
||||||
|
#else
|
||||||
|
sdhci_host0->io_fixed_1v8 = 0;
|
||||||
|
#endif
|
||||||
|
sdhci_host0->sdhci_data = RT_NULL;
|
||||||
|
sdhci_host0->sdhci_command = RT_NULL;
|
||||||
|
sdhci_host0->max_clk = 200000000;
|
||||||
|
sdhci_init(sdhci_host0);
|
||||||
|
|
||||||
|
rt_event_init(&sdhci_host0->event, "sd0_event", RT_IPC_FLAG_PRIO);
|
||||||
|
rt_hw_interrupt_install(IRQN_SD0, sdhci_irq, sdhci_host0, "sd0");
|
||||||
|
rt_hw_interrupt_umask(IRQN_SD0);
|
||||||
|
|
||||||
|
struct rt_mmcsd_host* mmcsd_host0 = mmcsd_alloc_host();
|
||||||
|
if (!mmcsd_host0) {
|
||||||
|
rt_free(sdhci_host0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mmcsd_host0->ops = &ops;
|
||||||
|
mmcsd_host0->freq_min = 400000;
|
||||||
|
mmcsd_host0->freq_max = 50000000;
|
||||||
|
#ifdef BSP_SDIO0_EMMC
|
||||||
|
strncpy(mmcsd_host0->name, "emmc", sizeof(mmcsd_host0->name) - 1);
|
||||||
|
mmcsd_host0->flags = MMCSD_BUSWIDTH_8 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
|
||||||
|
#else
|
||||||
|
strncpy(mmcsd_host0->name, "sd0", sizeof(mmcsd_host0->name) - 1);
|
||||||
|
mmcsd_host0->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
|
||||||
|
#endif
|
||||||
|
mmcsd_host0->valid_ocr = sdhci_host0->io_fixed_1v8 ? VDD_165_195 : VDD_32_33 | VDD_33_34;
|
||||||
|
#ifdef BSP_USING_CYW43XX
|
||||||
|
mmcsd_host0->valid_ocr = VDD_32_33 | VDD_33_34;
|
||||||
|
#endif
|
||||||
|
mmcsd_host0->max_seg_size = 512 * 512;
|
||||||
|
mmcsd_host0->max_dma_segs = 1;
|
||||||
|
mmcsd_host0->max_blk_size = 512;
|
||||||
|
mmcsd_host0->max_blk_count = 4096;
|
||||||
|
mmcsd_host0->private_data = sdhci_host0;
|
||||||
|
sdhci_host0->host = mmcsd_host0;
|
||||||
|
#endif
|
||||||
|
#ifdef BSP_USING_SDIO1
|
||||||
|
val = readl(hi_sys_virt_addr + 8);
|
||||||
|
val |= 1 << 2 | 1 << 0;
|
||||||
|
writel(val, hi_sys_virt_addr + 8);
|
||||||
|
sdhci_host1 = rt_malloc(sizeof(struct sdhci_host));
|
||||||
|
if (!sdhci_host1)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
rt_memset(sdhci_host1, 0, sizeof(struct sdhci_host));
|
||||||
|
sdhci_host1->mapbase = (void*)rt_ioremap((void*)SDEMMC1_BASE, 0x1000);
|
||||||
|
sdhci_host1->index = 1;
|
||||||
|
sdhci_host1->have_phy = 0;
|
||||||
|
sdhci_host1->mshc_ctrl_r = 0;
|
||||||
|
sdhci_host1->rx_delay_line = 0;
|
||||||
|
sdhci_host1->tx_delay_line = 0;
|
||||||
|
sdhci_host1->sdhci_data = RT_NULL;
|
||||||
|
sdhci_host1->sdhci_command = RT_NULL;
|
||||||
|
sdhci_host1->max_clk = 100000000;
|
||||||
|
sdhci_init(sdhci_host1);
|
||||||
|
|
||||||
|
rt_event_init(&sdhci_host1->event, "sd1_event", RT_IPC_FLAG_PRIO);
|
||||||
|
rt_hw_interrupt_install(IRQN_SD1, sdhci_irq, sdhci_host1, "sd1");
|
||||||
|
rt_hw_interrupt_umask(IRQN_SD1);
|
||||||
|
|
||||||
|
struct rt_mmcsd_host* mmcsd_host1 = mmcsd_alloc_host();
|
||||||
|
if (!mmcsd_host1) {
|
||||||
|
rt_free(sdhci_host1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
strncpy(mmcsd_host1->name, "sd1", sizeof(mmcsd_host1->name) - 1);
|
||||||
|
mmcsd_host1->ops = &ops;
|
||||||
|
mmcsd_host1->freq_min = 400000;
|
||||||
|
mmcsd_host1->freq_max = 50000000;
|
||||||
|
mmcsd_host1->valid_ocr = VDD_32_33 | VDD_33_34;
|
||||||
|
mmcsd_host1->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ;
|
||||||
|
mmcsd_host1->max_seg_size = 512 * 512;
|
||||||
|
mmcsd_host1->max_dma_segs = 1;
|
||||||
|
mmcsd_host1->max_blk_size = 512;
|
||||||
|
mmcsd_host1->max_blk_count = 4096;
|
||||||
|
mmcsd_host1->private_data = sdhci_host1;
|
||||||
|
sdhci_host1->host = mmcsd_host1;
|
||||||
|
#endif
|
||||||
|
#ifdef BSP_SD_SDIO_DEV
|
||||||
|
kd_sdhci_change(BSP_SD_SDIO_DEV);
|
||||||
|
#endif
|
||||||
|
rt_iounmap(hi_sys_virt_addr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
INIT_DEVICE_EXPORT(kd_sdhci_init);
|
||||||
|
|
||||||
|
#endif /*defined(BSP_USING_SDIO0) || defined(BSP_USING_SDIO1)*/
|
||||||
|
|
||||||
|
#endif /*defined(RT_USING_SDIO)*/
|
|
@ -0,0 +1,496 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DRV_SDHCI__
|
||||||
|
#define __DRV_SDHCI__
|
||||||
|
|
||||||
|
#define false 0
|
||||||
|
#define true 1
|
||||||
|
#define SDEMMC0_BASE 0x91580000
|
||||||
|
#define SDEMMC1_BASE 0x91581000
|
||||||
|
#define IRQN_SD0 142
|
||||||
|
#define IRQN_SD1 144
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller registers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SDHCI_DMA_ADDRESS 0x00
|
||||||
|
#define SDHCI_ARGUMENT2 SDHCI_DMA_ADDRESS
|
||||||
|
#define SDHCI_32BIT_BLK_CNT SDHCI_DMA_ADDRESS
|
||||||
|
|
||||||
|
#define SDHCI_BLOCK_SIZE 0x04
|
||||||
|
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
|
||||||
|
|
||||||
|
#define SDHCI_BLOCK_COUNT 0x06
|
||||||
|
|
||||||
|
#define SDHCI_ARGUMENT 0x08
|
||||||
|
|
||||||
|
#define SDHCI_TRANSFER_MODE 0x0C
|
||||||
|
#define SDHCI_TRNS_DMA 0x01
|
||||||
|
#define SDHCI_TRNS_BLK_CNT_EN 0x02
|
||||||
|
#define SDHCI_TRNS_AUTO_CMD12 0x04
|
||||||
|
#define SDHCI_TRNS_AUTO_CMD23 0x08
|
||||||
|
#define SDHCI_TRNS_AUTO_SEL 0x0C
|
||||||
|
#define SDHCI_TRNS_READ 0x10
|
||||||
|
#define SDHCI_TRNS_MULTI 0x20
|
||||||
|
|
||||||
|
#define SDHCI_COMMAND 0x0E
|
||||||
|
#define SDHCI_CMD_RESP_MASK 0x03
|
||||||
|
#define SDHCI_CMD_CRC 0x08
|
||||||
|
#define SDHCI_CMD_INDEX 0x10
|
||||||
|
#define SDHCI_CMD_DATA 0x20
|
||||||
|
#define SDHCI_CMD_ABORTCMD 0xC0
|
||||||
|
|
||||||
|
#define SDHCI_CMD_RESP_NONE 0x00
|
||||||
|
#define SDHCI_CMD_RESP_LONG 0x01
|
||||||
|
#define SDHCI_CMD_RESP_SHORT 0x02
|
||||||
|
#define SDHCI_CMD_RESP_SHORT_BUSY 0x03
|
||||||
|
|
||||||
|
#define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff))
|
||||||
|
#define SDHCI_GET_CMD(c) ((c >> 8) & 0x3f)
|
||||||
|
|
||||||
|
#define SDHCI_RESPONSE 0x10
|
||||||
|
|
||||||
|
#define SDHCI_BUFFER 0x20
|
||||||
|
|
||||||
|
#define SDHCI_PRESENT_STATE 0x24
|
||||||
|
#define SDHCI_CMD_INHIBIT 0x00000001
|
||||||
|
#define SDHCI_DATA_INHIBIT 0x00000002
|
||||||
|
#define SDHCI_DOING_WRITE 0x00000100
|
||||||
|
#define SDHCI_DOING_READ 0x00000200
|
||||||
|
#define SDHCI_SPACE_AVAILABLE 0x00000400
|
||||||
|
#define SDHCI_DATA_AVAILABLE 0x00000800
|
||||||
|
#define SDHCI_CARD_PRESENT 0x00010000
|
||||||
|
#define SDHCI_CARD_PRES_SHIFT 16
|
||||||
|
#define SDHCI_CD_STABLE 0x00020000
|
||||||
|
#define SDHCI_CD_LVL 0x00040000
|
||||||
|
#define SDHCI_CD_LVL_SHIFT 18
|
||||||
|
#define SDHCI_WRITE_PROTECT 0x00080000
|
||||||
|
#define SDHCI_DATA_LVL_MASK 0x00F00000
|
||||||
|
#define SDHCI_DATA_LVL_SHIFT 20
|
||||||
|
#define SDHCI_DATA_0_LVL_MASK 0x00100000
|
||||||
|
#define SDHCI_CMD_LVL 0x01000000
|
||||||
|
|
||||||
|
#define SDHCI_HOST_CONTROL 0x28
|
||||||
|
#define SDHCI_CTRL_LED 0x01
|
||||||
|
#define SDHCI_CTRL_4BITBUS 0x02
|
||||||
|
#define SDHCI_CTRL_HISPD 0x04
|
||||||
|
#define SDHCI_CTRL_DMA_MASK 0x18
|
||||||
|
#define SDHCI_CTRL_SDMA 0x00
|
||||||
|
#define SDHCI_CTRL_ADMA1 0x08
|
||||||
|
#define SDHCI_CTRL_ADMA32 0x10
|
||||||
|
#define SDHCI_CTRL_ADMA64 0x18
|
||||||
|
#define SDHCI_CTRL_ADMA3 0x18
|
||||||
|
#define SDHCI_CTRL_8BITBUS 0x20
|
||||||
|
#define SDHCI_CTRL_CDTEST_INS 0x40
|
||||||
|
#define SDHCI_CTRL_CDTEST_EN 0x80
|
||||||
|
|
||||||
|
#define SDHCI_POWER_CONTROL 0x29
|
||||||
|
#define SDHCI_POWER_ON 0x01
|
||||||
|
#define SDHCI_POWER_180 0x0A
|
||||||
|
#define SDHCI_POWER_300 0x0C
|
||||||
|
#define SDHCI_POWER_330 0x0E
|
||||||
|
|
||||||
|
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
|
||||||
|
|
||||||
|
#define SDHCI_WAKE_UP_CONTROL 0x2B
|
||||||
|
#define SDHCI_WAKE_ON_INT 0x01
|
||||||
|
#define SDHCI_WAKE_ON_INSERT 0x02
|
||||||
|
#define SDHCI_WAKE_ON_REMOVE 0x04
|
||||||
|
|
||||||
|
#define SDHCI_CLOCK_CONTROL 0x2C
|
||||||
|
#define SDHCI_DIVIDER_SHIFT 8
|
||||||
|
#define SDHCI_DIVIDER_HI_SHIFT 6
|
||||||
|
#define SDHCI_DIV_MASK 0xFF
|
||||||
|
#define SDHCI_DIV_MASK_LEN 8
|
||||||
|
#define SDHCI_DIV_HI_MASK 0x300
|
||||||
|
#define SDHCI_PROG_CLOCK_MODE 0x0020
|
||||||
|
#define SDHCI_CLOCK_CARD_EN 0x0004
|
||||||
|
#define SDHCI_CLOCK_PLL_EN 0x0008
|
||||||
|
#define SDHCI_CLOCK_INT_STABLE 0x0002
|
||||||
|
#define SDHCI_CLOCK_INT_EN 0x0001
|
||||||
|
|
||||||
|
#define SDHCI_TIMEOUT_CONTROL 0x2E
|
||||||
|
|
||||||
|
#define SDHCI_SOFTWARE_RESET 0x2F
|
||||||
|
#define SDHCI_RESET_ALL 0x01
|
||||||
|
#define SDHCI_RESET_CMD 0x02
|
||||||
|
#define SDHCI_RESET_DATA 0x04
|
||||||
|
|
||||||
|
#define SDHCI_INT_STATUS 0x30
|
||||||
|
#define SDHCI_INT_ENABLE 0x34
|
||||||
|
#define SDHCI_SIGNAL_ENABLE 0x38
|
||||||
|
#define SDHCI_INT_RESPONSE 0x00000001
|
||||||
|
#define SDHCI_INT_DATA_END 0x00000002
|
||||||
|
#define SDHCI_INT_BLK_GAP 0x00000004
|
||||||
|
#define SDHCI_INT_DMA_END 0x00000008
|
||||||
|
#define SDHCI_INT_SPACE_AVAIL 0x00000010
|
||||||
|
#define SDHCI_INT_DATA_AVAIL 0x00000020
|
||||||
|
#define SDHCI_INT_CARD_INSERT 0x00000040
|
||||||
|
#define SDHCI_INT_CARD_REMOVE 0x00000080
|
||||||
|
#define SDHCI_INT_CARD_INT 0x00000100
|
||||||
|
#define SDHCI_INT_RETUNE 0x00001000
|
||||||
|
#define SDHCI_INT_CQE 0x00004000
|
||||||
|
#define SDHCI_INT_ERROR 0x00008000
|
||||||
|
#define SDHCI_INT_TIMEOUT 0x00010000
|
||||||
|
#define SDHCI_INT_CRC 0x00020000
|
||||||
|
#define SDHCI_INT_END_BIT 0x00040000
|
||||||
|
#define SDHCI_INT_INDEX 0x00080000
|
||||||
|
#define SDHCI_INT_DATA_TIMEOUT 0x00100000
|
||||||
|
#define SDHCI_INT_DATA_CRC 0x00200000
|
||||||
|
#define SDHCI_INT_DATA_END_BIT 0x00400000
|
||||||
|
#define SDHCI_INT_BUS_POWER 0x00800000
|
||||||
|
#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
|
||||||
|
#define SDHCI_INT_ADMA_ERROR 0x02000000
|
||||||
|
|
||||||
|
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
|
||||||
|
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
|
||||||
|
|
||||||
|
#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_AUTO_CMD_ERR)
|
||||||
|
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | SDHCI_INT_BLK_GAP)
|
||||||
|
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
|
||||||
|
|
||||||
|
#define SDHCI_CQE_INT_ERR_MASK ( \
|
||||||
|
SDHCI_INT_ADMA_ERROR | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)
|
||||||
|
|
||||||
|
#define SDHCI_CQE_INT_MASK (SDHCI_CQE_INT_ERR_MASK | SDHCI_INT_CQE)
|
||||||
|
|
||||||
|
#define SDHCI_AUTO_CMD_STATUS 0x3C
|
||||||
|
#define SDHCI_AUTO_CMD_TIMEOUT 0x00000002
|
||||||
|
#define SDHCI_AUTO_CMD_CRC 0x00000004
|
||||||
|
#define SDHCI_AUTO_CMD_END_BIT 0x00000008
|
||||||
|
#define SDHCI_AUTO_CMD_INDEX 0x00000010
|
||||||
|
|
||||||
|
#define SDHCI_HOST_CONTROL2 0x3E
|
||||||
|
#define SDHCI_CTRL_UHS_MASK 0x0007
|
||||||
|
#define SDHCI_CTRL_UHS_SDR12 0x0000
|
||||||
|
#define SDHCI_CTRL_UHS_SDR25 0x0001
|
||||||
|
#define SDHCI_CTRL_UHS_SDR50 0x0002
|
||||||
|
#define SDHCI_CTRL_UHS_SDR104 0x0003
|
||||||
|
#define SDHCI_CTRL_UHS_DDR50 0x0004
|
||||||
|
#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
|
||||||
|
#define SDHCI_CTRL_VDD_180 0x0008
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_A 0x0010
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_C 0x0020
|
||||||
|
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
|
||||||
|
#define SDHCI_CTRL_EXEC_TUNING 0x0040
|
||||||
|
#define SDHCI_CTRL_TUNED_CLK 0x0080
|
||||||
|
#define SDHCI_CMD23_ENABLE 0x0800
|
||||||
|
#define SDHCI_CTRL_V4_MODE 0x1000
|
||||||
|
#define SDHCI_CTRL_64BIT_ADDR 0x2000
|
||||||
|
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
|
||||||
|
|
||||||
|
#define SDHCI_CAPABILITIES 0x40
|
||||||
|
#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0)
|
||||||
|
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
|
||||||
|
#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8)
|
||||||
|
#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8)
|
||||||
|
#define SDHCI_MAX_BLOCK_MASK 0x00030000
|
||||||
|
#define SDHCI_MAX_BLOCK_SHIFT 16
|
||||||
|
#define SDHCI_CAN_DO_8BIT 0x00040000
|
||||||
|
#define SDHCI_CAN_DO_ADMA2 0x00080000
|
||||||
|
#define SDHCI_CAN_DO_ADMA1 0x00100000
|
||||||
|
#define SDHCI_CAN_DO_HISPD 0x00200000
|
||||||
|
#define SDHCI_CAN_DO_SDMA 0x00400000
|
||||||
|
#define SDHCI_CAN_DO_SUSPEND 0x00800000
|
||||||
|
#define SDHCI_CAN_VDD_330 0x01000000
|
||||||
|
#define SDHCI_CAN_VDD_300 0x02000000
|
||||||
|
#define SDHCI_CAN_VDD_180 0x04000000
|
||||||
|
#define SDHCI_CAN_64BIT_V4 0x08000000
|
||||||
|
#define SDHCI_CAN_64BIT 0x10000000
|
||||||
|
|
||||||
|
#define SDHCI_CAPABILITIES_1 0x44
|
||||||
|
#define SDHCI_SUPPORT_SDR50 0x00000001
|
||||||
|
#define SDHCI_SUPPORT_SDR104 0x00000002
|
||||||
|
#define SDHCI_SUPPORT_DDR50 0x00000004
|
||||||
|
#define SDHCI_DRIVER_TYPE_A 0x00000010
|
||||||
|
#define SDHCI_DRIVER_TYPE_C 0x00000020
|
||||||
|
#define SDHCI_DRIVER_TYPE_D 0x00000040
|
||||||
|
#define SDHCI_RETUNING_TIMER_COUNT_MASK GENMASK(11, 8)
|
||||||
|
#define SDHCI_USE_SDR50_TUNING 0x00002000
|
||||||
|
#define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14)
|
||||||
|
#define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16)
|
||||||
|
#define SDHCI_CAN_DO_ADMA3 0x08000000
|
||||||
|
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
|
||||||
|
|
||||||
|
#define SDHCI_MAX_CURRENT 0x48
|
||||||
|
#define SDHCI_MAX_CURRENT_LIMIT GENMASK(7, 0)
|
||||||
|
#define SDHCI_MAX_CURRENT_330_MASK GENMASK(7, 0)
|
||||||
|
#define SDHCI_MAX_CURRENT_300_MASK GENMASK(15, 8)
|
||||||
|
#define SDHCI_MAX_CURRENT_180_MASK GENMASK(23, 16)
|
||||||
|
#define SDHCI_MAX_CURRENT_MULTIPLIER 4
|
||||||
|
|
||||||
|
/* 4C-4F reserved for more max current */
|
||||||
|
|
||||||
|
#define SDHCI_SET_ACMD12_ERROR 0x50
|
||||||
|
#define SDHCI_SET_INT_ERROR 0x52
|
||||||
|
|
||||||
|
#define SDHCI_ADMA_ERROR 0x54
|
||||||
|
|
||||||
|
/* 55-57 reserved */
|
||||||
|
|
||||||
|
#define SDHCI_ADMA_ADDRESS 0x58
|
||||||
|
#define SDHCI_ADMA_ADDRESS_HI 0x5C
|
||||||
|
|
||||||
|
/* 60-FB reserved */
|
||||||
|
|
||||||
|
#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64
|
||||||
|
#define SDHCI_PRESET_FOR_SDR12 0x66
|
||||||
|
#define SDHCI_PRESET_FOR_SDR25 0x68
|
||||||
|
#define SDHCI_PRESET_FOR_SDR50 0x6A
|
||||||
|
#define SDHCI_PRESET_FOR_SDR104 0x6C
|
||||||
|
#define SDHCI_PRESET_FOR_DDR50 0x6E
|
||||||
|
#define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
|
||||||
|
#define SDHCI_PRESET_DRV_MASK GENMASK(15, 14)
|
||||||
|
#define SDHCI_PRESET_CLKGEN_SEL BIT(10)
|
||||||
|
#define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0)
|
||||||
|
|
||||||
|
#define SDHCI_SLOT_INT_STATUS 0xFC
|
||||||
|
|
||||||
|
#define SDHCI_HOST_VERSION 0xFE
|
||||||
|
#define SDHCI_VENDOR_VER_MASK 0xFF00
|
||||||
|
#define SDHCI_VENDOR_VER_SHIFT 8
|
||||||
|
#define SDHCI_SPEC_VER_MASK 0x00FF
|
||||||
|
#define SDHCI_SPEC_VER_SHIFT 0
|
||||||
|
#define SDHCI_SPEC_100 0
|
||||||
|
#define SDHCI_SPEC_200 1
|
||||||
|
#define SDHCI_SPEC_300 2
|
||||||
|
#define SDHCI_SPEC_400 3
|
||||||
|
#define SDHCI_SPEC_410 4
|
||||||
|
#define SDHCI_SPEC_420 5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End of controller registers.
|
||||||
|
*/
|
||||||
|
#define SDHCI_MAX_DIV_SPEC_300 2046
|
||||||
|
/*! @brief Transfer flag mask */
|
||||||
|
enum sdhci_transfer_mode
|
||||||
|
{
|
||||||
|
sdhci_enable_dma_flag = SDHCI_TRNS_DMA, /*!< Enable DMA */
|
||||||
|
|
||||||
|
sdhci_enable_block_count_flag = SDHCI_TRNS_BLK_CNT_EN, /*!< Enable block count */
|
||||||
|
sdhci_enable_auto_command12_flag = SDHCI_TRNS_AUTO_CMD12, /*!< Enable auto CMD12 */
|
||||||
|
sdhci_data_read_flag = SDHCI_TRNS_READ, /*!< Enable data read */
|
||||||
|
sdhci_multiple_block_flag = SDHCI_TRNS_MULTI, /*!< Multiple block data read/write */
|
||||||
|
sdhci_enable_auto_command23_flag = SDHCI_TRNS_AUTO_CMD23, /*!< Enable auto CMD23 */
|
||||||
|
sdhci_enable_auto_commamd_sel_flag = SDHCI_TRNS_AUTO_SEL, /* Enable auto command sel*/
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sdhci_command_flag
|
||||||
|
{
|
||||||
|
sdhci_cmd_resp_nono = SDHCI_CMD_RESP_NONE,
|
||||||
|
sdhci_cmd_resp_long = SDHCI_CMD_RESP_LONG,
|
||||||
|
sdhci_cmd_resp_short = SDHCI_CMD_RESP_SHORT,
|
||||||
|
sdhci_cmd_resp_short_busy = SDHCI_CMD_RESP_SHORT_BUSY,
|
||||||
|
|
||||||
|
sdhci_enable_cmd_crc_flag = SDHCI_CMD_CRC,
|
||||||
|
sdhci_enable_cmd_index_chk_flag = SDHCI_CMD_INDEX,
|
||||||
|
sdhci_enable_cmd_data_present_flag = SDHCI_CMD_DATA,
|
||||||
|
|
||||||
|
sdhci_enable_command_type_normal = 0x00,
|
||||||
|
sdhci_enable_command_type_suspend = 0x40,
|
||||||
|
sdhci_enable_command_type_resume = 0x80,
|
||||||
|
sdhci_enable_command_type_abort = 0xc0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! @brief Present status flag mask */
|
||||||
|
enum sdhci_present_status_flag
|
||||||
|
{
|
||||||
|
sdhci_command_inhibit_flag = 0x1, /*!< Command inhibit */
|
||||||
|
sdhci_data_inhibit_flag = 0x2, /*!< Data inhibit */
|
||||||
|
sdhci_data_line_active_flag = 0x4, /*!< Data line active */
|
||||||
|
sdhci_write_transfer_active_flag = 0x100, /*!< Write transfer active */
|
||||||
|
sdhci_read_transfer_active_flag = 0x200, /*!< Read transfer active */
|
||||||
|
sdhci_buffer_write_enable_flag = 0x400, /*!< Buffer write enable */
|
||||||
|
sdhci_buffer_read_enable_flag = 0x800, /*!< Buffer read enable */
|
||||||
|
|
||||||
|
sdhci_card_insert_flag = 0x10000, /*!< Card inserted */
|
||||||
|
sdhci_sd_clock_stable_flag = 0x20000, /*!< SD bus clock stable */
|
||||||
|
sdhci_card_detect_pin_level_flag = 0x40000, /*!< card detect pin level */
|
||||||
|
sdhci_write_protect_switch_pin_level_flag = 0x80000, /*<write protect switch pin level>*/
|
||||||
|
|
||||||
|
sdhci_data0_line_level_flag = (1U << 20), /*!< Data0 line signal level */
|
||||||
|
sdhci_data1_line_level_flag = (1U << (20 + 1U)), /*!< Data1 line signal level */
|
||||||
|
sdhci_data2_line_level_flag = (1U << (20 + 2U)), /*!< Data2 line signal level */
|
||||||
|
sdhci_data3_line_level_flag = (1U << (20 + 3U)), /*!< Data3 line signal level */
|
||||||
|
sdhci_data4_line_level_flag = (1U << (4 + 0U)), /*!< Data4 line signal level */
|
||||||
|
sdhci_data5_line_level_flag = (1U << (4 + 1U)), /*!< Data5 line signal level */
|
||||||
|
sdhci_data6_line_level_flag = (1U << (4 + 2U)), /*!< Data6 line signal level */
|
||||||
|
sdhci_data7_line_level_flag = (1U << (4 + 3U)), /*!< Data7 line signal level */
|
||||||
|
|
||||||
|
sdhci_command_line_signal_level_flag =0x1000000,
|
||||||
|
sdhci_host_reg_voltage_stable_flag = 0x2000000,
|
||||||
|
sdhci_command_not_issued_by_error_flag = 0x8000000,
|
||||||
|
sdhci_sub_command_status_flag = 0x10000000,
|
||||||
|
sdhci_in_dormant_status_flag = 0x20000000,
|
||||||
|
sdhci_lane_synchronization_flag = 0x40000000,
|
||||||
|
sdhci_uhs_ii_interface_detection_flag = 0x80000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! @brief Interrupt status flag mask */
|
||||||
|
enum sdhci_interrupt_status_flag
|
||||||
|
{
|
||||||
|
sdhci_command_complete_flag = 0x1, /*!< Command complete */
|
||||||
|
sdhci_data_complete_flag = 0x2, /*!< Data complete */
|
||||||
|
sdhci_block_gap_event_flag = 0x4, /*!< Block gap event */
|
||||||
|
sdhci_dma_complete_flag = 0x8, /*!< DMA interrupt */
|
||||||
|
sdhci_buffer_write_ready_flag = 0x10, /*!< Buffer write ready */
|
||||||
|
sdhci_buffer_read_ready_flag = 0x20, /*!< Buffer read ready */
|
||||||
|
sdhci_card_insertion_flag = 0x40, /*!< Card inserted */
|
||||||
|
sdhci_card_removal_flag = 0x80, /*!< Card removed */
|
||||||
|
sdhci_card_interrupt_flag = 0x100, /*!< Card interrupt */
|
||||||
|
|
||||||
|
sdhci_command_timeout_flag = 0x10000, /*!< Command timeout error */
|
||||||
|
sdhci_command_crc_error_flag = 0x20000, /*!< Command CRC error */
|
||||||
|
sdhci_command_end_bit_error_flag = 0x40000, /*!< Command end bit error */
|
||||||
|
sdhci_command_index_error_flag = 0x80000, /*!< Command index error */
|
||||||
|
sdhci_data_timeout_flag = 0x100000, /*!< Data timeout error */
|
||||||
|
sdhci_data_crc_error_flag = 0x200000, /*!< Data CRC error */
|
||||||
|
sdhci_data_end_bit_error_flag = 0x400000, /*!< Data end bit error */
|
||||||
|
sdhci_auto_command_error_flag = 0x1000000, /*!< Auto CMD error */
|
||||||
|
sdhci_dma_error_flag = 0x2000000, /*!< ADMA error */
|
||||||
|
sdhci_tuning_error_flag = 0x4000000, /* tuning err*/
|
||||||
|
sdhci_response_err_flag = 0x8000000, /*resp error*/
|
||||||
|
|
||||||
|
sdhci_command_error_flag = (sdhci_command_timeout_flag | sdhci_command_crc_error_flag | sdhci_command_end_bit_error_flag |
|
||||||
|
sdhci_command_index_error_flag), /*!< Command error */
|
||||||
|
sdhci_data_error_flag = (sdhci_data_timeout_flag | sdhci_data_crc_error_flag | sdhci_data_end_bit_error_flag |
|
||||||
|
sdhci_auto_command_error_flag), /*!< Data error */
|
||||||
|
sdhci_error_flag = (sdhci_command_error_flag | sdhci_data_error_flag | sdhci_dma_error_flag), /*!< All error */
|
||||||
|
sdhci_data_flag = (sdhci_data_complete_flag | sdhci_dma_complete_flag | sdhci_buffer_write_ready_flag |
|
||||||
|
sdhci_buffer_read_ready_flag | sdhci_data_error_flag | sdhci_dma_error_flag), /*!< Data interrupts */
|
||||||
|
sdhci_command_flag = (sdhci_command_error_flag | sdhci_command_complete_flag), /*!< Command interrupts */
|
||||||
|
sdhci_card_detect_flag = (sdhci_card_insertion_flag | sdhci_card_removal_flag), /*!< Card detection interrupts */
|
||||||
|
sdhci_sdr104_tuning_flag = (sdhci_tuning_error_flag),
|
||||||
|
|
||||||
|
sdhci_all_interrupt_flags = (sdhci_block_gap_event_flag | sdhci_card_detect_flag | sdhci_command_flag |
|
||||||
|
sdhci_data_flag | sdhci_error_flag | sdhci_sdr104_tuning_flag), /*!< All flags mask */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! @brief USDHC status */
|
||||||
|
enum sdhci_status
|
||||||
|
{
|
||||||
|
sdhci_status_busy_transferring = 65, /*!< Transfer is on-going */
|
||||||
|
sdhci_status_prepare_adma_descriptor_failed = 66, /*!< Set DMA descriptor failed */
|
||||||
|
sdhci_status_send_command_failed = 67, /*!< Send command failed */
|
||||||
|
sdhci_status_transfer_data_failed = 68, /*!< Transfer data failed */
|
||||||
|
sdhci_status_dma_data_addr_no_align = 69, /*!< data address not align */
|
||||||
|
sdhci_status_retuning_request = 70, /*!< re-tuning request */
|
||||||
|
sdhci_status_tuning_error = 71, /*!< tuning error */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ADMA2 data alignment */
|
||||||
|
#define SDHCI_ADMA2_ALIGN 4
|
||||||
|
#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1)
|
||||||
|
|
||||||
|
/*! @brief The bit shift for LENGTH field in ADMA2's descriptor */
|
||||||
|
#define SDHCI_ADMA2_DESCRIPTOR_LENGTH_SHIFT (16U)
|
||||||
|
/*! @brief The bit mask for LENGTH field in ADMA2's descriptor */
|
||||||
|
#define SDHCI_ADMA2_DESCRIPTOR_LENGTH_MASK (0xFFFFU)
|
||||||
|
/*! @brief The maximum value of LENGTH field in ADMA2's descriptor */
|
||||||
|
#define SDHCI_ADMA2_DESCRIPTOR_MAX_LENGTH_PER_ENTRY (SDHCI_ADMA2_DESCRIPTOR_LENGTH_MASK - 3U)
|
||||||
|
|
||||||
|
#define SDHCI_DESC_VALID (0x1U << 0)
|
||||||
|
#define SDHCI_DESC_END (0x1U << 1)
|
||||||
|
#define SDHCI_DESC_INT (0x1U << 2)
|
||||||
|
#define SDHCI_DESC_TRAN (0x2U << 4)
|
||||||
|
struct sdhci_64bit_adma2_descriptor
|
||||||
|
{
|
||||||
|
uint32_t attribute;
|
||||||
|
uint32_t address;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! @brief The command type */
|
||||||
|
enum sdhci_card_command_type
|
||||||
|
{
|
||||||
|
card_command_type_normal = 0U, /*!< Normal command */
|
||||||
|
card_command_type_suspend = 1U, /*!< Suspend command */
|
||||||
|
card_command_type_resume = 2U, /*!< Resume command */
|
||||||
|
card_command_type_abort = 3U, /*!< Abort command */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief The command response type.
|
||||||
|
*
|
||||||
|
* Define the command response type from card to host controller.
|
||||||
|
*/
|
||||||
|
enum sdhci_card_response_type
|
||||||
|
{
|
||||||
|
card_response_type_none = 0U, /*!< Response type: none */
|
||||||
|
card_response_type_r1 = 1U, /*!< Response type: R1 */
|
||||||
|
card_response_type_r1b = 2U, /*!< Response type: R1b */
|
||||||
|
card_response_type_r2 = 3U, /*!< Response type: R2 */
|
||||||
|
card_response_type_r3 = 4U, /*!< Response type: R3 */
|
||||||
|
card_response_type_r4 = 5U, /*!< Response type: R4 */
|
||||||
|
card_response_type_r5 = 6U, /*!< Response type: R5 */
|
||||||
|
card_response_type_r5b = 7U, /*!< Response type: R5b */
|
||||||
|
card_response_type_r6 = 8U, /*!< Response type: R6 */
|
||||||
|
card_response_type_r7 = 9U, /*!< Response type: R7 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Card data descriptor
|
||||||
|
*
|
||||||
|
* Defines a structure to contain data-related attribute. 'enableIgnoreError' is used for the case that upper card
|
||||||
|
* driver
|
||||||
|
* want to ignore the error event to read/write all the data not to stop read/write immediately when error event
|
||||||
|
* happen for example bus testing procedure for MMC card.
|
||||||
|
*/
|
||||||
|
struct sdhci_data
|
||||||
|
{
|
||||||
|
rt_bool_t enableAutoCommand12; /*!< Enable auto CMD12 */
|
||||||
|
rt_bool_t enableAutoCommand23; /*!< Enable auto CMD23 */
|
||||||
|
rt_bool_t enableIgnoreError; /*!< Enable to ignore error event to read/write all the data */
|
||||||
|
rt_bool_t executeTuning; /*!< execute tuning flag */
|
||||||
|
|
||||||
|
size_t blockSize; /*!< Block size */
|
||||||
|
uint32_t blockCount; /*!< Block count */
|
||||||
|
uint32_t *rxData; /*!< Buffer to save data read */
|
||||||
|
const uint32_t *txData; /*!< Data buffer to write */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Card command descriptor
|
||||||
|
*
|
||||||
|
* Define card command-related attribute.
|
||||||
|
*/
|
||||||
|
struct sdhci_command
|
||||||
|
{
|
||||||
|
uint32_t index; /*!< Command index */
|
||||||
|
uint32_t argument; /*!< Command argument */
|
||||||
|
enum sdhci_card_command_type type; /*!< Command type */
|
||||||
|
enum sdhci_card_response_type responseType; /*!< Command response type */
|
||||||
|
uint32_t response[4U]; /*!< Response for this command */
|
||||||
|
uint32_t responseErrorFlags; /*!< response error flag, the flag which need to check
|
||||||
|
the command reponse*/
|
||||||
|
uint16_t flags; /*!< Cmd flags */
|
||||||
|
uint16_t flags2; /*xfer mode*/
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sdhci_host
|
||||||
|
{
|
||||||
|
struct rt_mmcsd_host *host;
|
||||||
|
void *mapbase;
|
||||||
|
struct sdhci_data *sdhci_data;
|
||||||
|
struct sdhci_command *sdhci_command;
|
||||||
|
void *usdhc_adma2_table;
|
||||||
|
struct rt_event event;
|
||||||
|
uint16_t error_code;
|
||||||
|
uint32_t max_clk;
|
||||||
|
uint8_t index;
|
||||||
|
uint8_t is_emmc_card;
|
||||||
|
uint8_t io_fixed_1v8;
|
||||||
|
uint8_t have_phy;
|
||||||
|
uint8_t mshc_ctrl_r;
|
||||||
|
uint32_t rx_delay_line;
|
||||||
|
uint32_t tx_delay_line;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*__DRV_SDHCI__*/
|
|
@ -0,0 +1,19 @@
|
||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = Glob('*.c')
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
group = DefineGroup('Uart', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
objs = [group]
|
||||||
|
|
||||||
|
list = os.listdir(cwd)
|
||||||
|
|
||||||
|
for item in list:
|
||||||
|
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
|
||||||
|
objs = objs + SConscript(os.path.join(item, 'SConscript'))
|
||||||
|
|
||||||
|
Return('objs')
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <rtdevice.h>
|
||||||
|
#include <lwp_user_mm.h>
|
||||||
|
#include <ioremap.h>
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
#include "drv_uart.h"
|
||||||
|
#include "riscv_io.h"
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
#define UART_DEFAULT_BAUDRATE 115200
|
||||||
|
#define UART_CLK 50000000
|
||||||
|
#define UART_ADDR 0x91403000UL
|
||||||
|
#define UART_IRQ 0x13
|
||||||
|
|
||||||
|
|
||||||
|
#define UART_RBR (0x00) /* receive buffer register */
|
||||||
|
#define UART_THR (0x00) /* transmit holding register */
|
||||||
|
#define UART_DLL (0x00) /* divisor latch low register */
|
||||||
|
#define UART_DLH (0x04) /* diviso latch high register */
|
||||||
|
#define UART_IER (0x04) /* interrupt enable register */
|
||||||
|
#define UART_IIR (0x08) /* interrupt identity register */
|
||||||
|
#define UART_FCR (0x08) /* FIFO control register */
|
||||||
|
#define UART_LCR (0x0c) /* line control register */
|
||||||
|
#define UART_MCR (0x10) /* modem control register */
|
||||||
|
#define UART_LSR (0x14) /* line status register */
|
||||||
|
#define UART_MSR (0x18) /* modem status register */
|
||||||
|
#define UART_SCH (0x1c) /* scratch register */
|
||||||
|
#define UART_USR (0x7c) /* status register */
|
||||||
|
#define UART_TFL (0x80) /* transmit FIFO level */
|
||||||
|
#define UART_RFL (0x84) /* RFL */
|
||||||
|
#define UART_HALT (0xa4) /* halt tx register */
|
||||||
|
#define UART_DLF (0xc0) /* Divisor Latch Fraction Register */
|
||||||
|
|
||||||
|
#define BIT(x) (1 << x)
|
||||||
|
|
||||||
|
/* Line Status Rigster */
|
||||||
|
#define UART_LSR_RXFIFOE (BIT(7))
|
||||||
|
#define UART_LSR_TEMT (BIT(6))
|
||||||
|
#define UART_LSR_THRE (BIT(5))
|
||||||
|
#define UART_LSR_BI (BIT(4))
|
||||||
|
#define UART_LSR_FE (BIT(3))
|
||||||
|
#define UART_LSR_PE (BIT(2))
|
||||||
|
#define UART_LSR_OE (BIT(1))
|
||||||
|
#define UART_LSR_DR (BIT(0))
|
||||||
|
#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */
|
||||||
|
|
||||||
|
/* Line Control Register */
|
||||||
|
#define UART_LCR_DLAB (BIT(7))
|
||||||
|
#define UART_LCR_SBC (BIT(6))
|
||||||
|
#define UART_LCR_PARITY_MASK (BIT(5)|BIT(4))
|
||||||
|
#define UART_LCR_EPAR (1 << 4)
|
||||||
|
#define UART_LCR_OPAR (0 << 4)
|
||||||
|
#define UART_LCR_PARITY (BIT(3))
|
||||||
|
#define UART_LCR_STOP (BIT(2))
|
||||||
|
#define UART_LCR_DLEN_MASK (BIT(1)|BIT(0))
|
||||||
|
#define UART_LCR_WLEN5 (0)
|
||||||
|
#define UART_LCR_WLEN6 (1)
|
||||||
|
#define UART_LCR_WLEN7 (2)
|
||||||
|
#define UART_LCR_WLEN8 (3)
|
||||||
|
|
||||||
|
/* Halt Register */
|
||||||
|
#define UART_HALT_LCRUP (BIT(2))
|
||||||
|
#define UART_HALT_FORCECFG (BIT(1))
|
||||||
|
#define UART_HALT_HTX (BIT(0))
|
||||||
|
|
||||||
|
/* Interrupt Enable Register */
|
||||||
|
#define UART_IER_MASK (0xff)
|
||||||
|
#define UART_IER_PTIME (BIT(7))
|
||||||
|
#define UART_IER_RS485 (BIT(4))
|
||||||
|
#define UART_IER_MSI (BIT(3))
|
||||||
|
#define UART_IER_RLSI (BIT(2))
|
||||||
|
#define UART_IER_THRI (BIT(1))
|
||||||
|
#define UART_IER_RDI (BIT(0))
|
||||||
|
|
||||||
|
/* Interrupt ID Register */
|
||||||
|
#define UART_IIR_FEFLAG_MASK (BIT(6)|BIT(7))
|
||||||
|
#define UART_IIR_IID_MASK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
|
||||||
|
#define UART_IIR_IID_MSTA (0)
|
||||||
|
#define UART_IIR_IID_NOIRQ (1)
|
||||||
|
#define UART_IIR_IID_THREMP (2)
|
||||||
|
#define UART_IIR_IID_RXDVAL (4)
|
||||||
|
#define UART_IIR_IID_LINESTA (6)
|
||||||
|
#define UART_IIR_IID_BUSBSY (7)
|
||||||
|
#define UART_IIR_IID_CHARTO (12)
|
||||||
|
|
||||||
|
struct device_uart
|
||||||
|
{
|
||||||
|
rt_ubase_t hw_base;
|
||||||
|
rt_uint32_t irqno;
|
||||||
|
};
|
||||||
|
|
||||||
|
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
|
||||||
|
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
|
||||||
|
static int drv_uart_putc(struct rt_serial_device *serial, char c);
|
||||||
|
static int drv_uart_getc(struct rt_serial_device *serial);
|
||||||
|
|
||||||
|
const struct rt_uart_ops _uart_ops =
|
||||||
|
{
|
||||||
|
rt_uart_configure,
|
||||||
|
uart_control,
|
||||||
|
drv_uart_putc,
|
||||||
|
drv_uart_getc,
|
||||||
|
//TODO: add DMA support
|
||||||
|
RT_NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rt_serial_device serial1;
|
||||||
|
struct device_uart uart1;
|
||||||
|
|
||||||
|
#define write32(addr, val) writel(val, (void*)(addr))
|
||||||
|
#define read32(addr) readl((void*)(addr))
|
||||||
|
|
||||||
|
static void _uart_init(void *uart_base)
|
||||||
|
{
|
||||||
|
uint32_t bdiv;
|
||||||
|
uint32_t dlf;
|
||||||
|
uint32_t dlh;
|
||||||
|
uint32_t dll;
|
||||||
|
|
||||||
|
bdiv = UART_CLK / UART_DEFAULT_BAUDRATE;
|
||||||
|
dlh = bdiv >> 12;
|
||||||
|
dll = (bdiv - (dlh << 12)) / 16;
|
||||||
|
dlf = bdiv - (dlh << 12) - dll * 16;
|
||||||
|
if(dlh == 0 && dll == 0)
|
||||||
|
{
|
||||||
|
dll = 1;
|
||||||
|
dlf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
write32(uart_base + UART_LCR, 0x00);
|
||||||
|
/* Disable all interrupts */
|
||||||
|
write32(uart_base + UART_IER, 0x00);
|
||||||
|
/* Enable DLAB */
|
||||||
|
write32(uart_base + UART_LCR, 0x80);
|
||||||
|
if (bdiv) {
|
||||||
|
/* Set divisor low byte */
|
||||||
|
write32(uart_base + UART_DLL, dll);
|
||||||
|
/* Set divisor high byte */
|
||||||
|
write32(uart_base + UART_DLH, dlh);
|
||||||
|
/* Set divisor fraction byte*/
|
||||||
|
write32(uart_base + UART_DLF, dlf);
|
||||||
|
}
|
||||||
|
/* 8 bits, no parity, one stop bit */
|
||||||
|
write32(uart_base + UART_LCR, 0x03);
|
||||||
|
/* Enable FIFO */
|
||||||
|
write32(uart_base + UART_FCR, 0x01);
|
||||||
|
/* No modem control DTR RTS */
|
||||||
|
write32(uart_base + UART_MCR, 0x00);
|
||||||
|
/* Clear line status */
|
||||||
|
read32(uart_base + UART_LSR);
|
||||||
|
/* Read receive buffer */
|
||||||
|
read32(uart_base + UART_RBR);
|
||||||
|
read32(uart_base + UART_USR);
|
||||||
|
read32(uart_base + UART_FCR);
|
||||||
|
/* Set scratchpad */
|
||||||
|
write32(uart_base + UART_SCH, 0x00);
|
||||||
|
//enable uart rx irq
|
||||||
|
// write32(uart_base + UART_IER, 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uart_set_isr(void *uart_base, uint8_t enable, uint32_t irq_type)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
value = read32(uart_base + UART_IER);
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
value |= irq_type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value &= ~irq_type;
|
||||||
|
}
|
||||||
|
write32(uart_base + UART_IER, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UART interface
|
||||||
|
*/
|
||||||
|
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
|
||||||
|
{
|
||||||
|
return (RT_EOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
|
||||||
|
{
|
||||||
|
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
|
||||||
|
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
rt_ubase_t ctrl_flag = 0;
|
||||||
|
rt_ubase_t ctrl_arg;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
ctrl_arg = (rt_ubase_t)arg;
|
||||||
|
|
||||||
|
if (ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING))
|
||||||
|
{
|
||||||
|
ctrl_flag |= RT_DEVICE_FLAG_INT_RX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case RT_DEVICE_CTRL_CLR_INT:
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
|
||||||
|
#else
|
||||||
|
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
uart_set_isr((void*)(uart->hw_base), 0, UART_IER_RDI);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RT_DEVICE_CTRL_SET_INT:
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
|
||||||
|
#else
|
||||||
|
if ((size_t)arg == RT_DEVICE_FLAG_INT_RX)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
uart_set_isr((void*)(uart->hw_base), 1, UART_IER_RDI);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
case RT_DEVICE_CTRL_CONFIG:
|
||||||
|
if (ctrl_flag & RT_DEVICE_FLAG_INT_RX)
|
||||||
|
{
|
||||||
|
uart_set_isr((void*)(uart->hw_base), 1, UART_IER_RDI);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case RT_FIOMMAP2:
|
||||||
|
{
|
||||||
|
struct dfs_mmap2_args *mmap2 = (struct dfs_mmap2_args *)arg;
|
||||||
|
if (mmap2)
|
||||||
|
{
|
||||||
|
if (mmap2->length > 0x400)
|
||||||
|
{
|
||||||
|
return -RT_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
mmap2->ret = lwp_map_user_phy(lwp_self(), RT_NULL, (void*)(uart->hw_base), mmap2->length, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (RT_EOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv_uart_putc(struct rt_serial_device *serial, char c)
|
||||||
|
{
|
||||||
|
volatile uint32_t *sed_buf;
|
||||||
|
volatile uint32_t *sta;
|
||||||
|
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
|
||||||
|
|
||||||
|
sed_buf = (uint32_t *)(uart->hw_base + UART_THR);
|
||||||
|
sta = (uint32_t *)(uart->hw_base + UART_USR);
|
||||||
|
|
||||||
|
/* FIFO status, contain valid data */
|
||||||
|
// while (!(*sta & 0x02));
|
||||||
|
while (!(read32(uart->hw_base + UART_LSR) & 0x20));
|
||||||
|
|
||||||
|
*sed_buf = c;
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drv_uart_getc(struct rt_serial_device *serial)
|
||||||
|
{
|
||||||
|
struct device_uart *uart = (struct device_uart*)serial->parent.user_data;
|
||||||
|
volatile uint32_t *lsr = (uint32_t *)(uart->hw_base + UART_LSR);
|
||||||
|
volatile uint32_t *rbr = (uint32_t *)(uart->hw_base + UART_RBR);
|
||||||
|
|
||||||
|
if (!(*lsr & UART_LSR_DR))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int)*rbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rt_hw_uart_isr(int irq, void *param)
|
||||||
|
{
|
||||||
|
struct rt_serial_device *serial = (struct rt_serial_device*)param;
|
||||||
|
struct device_uart *uart;
|
||||||
|
size_t uart_base;
|
||||||
|
uint32_t iir, lsr;
|
||||||
|
|
||||||
|
uart = (struct device_uart*)serial->parent.user_data;
|
||||||
|
uart_base = uart->hw_base;
|
||||||
|
|
||||||
|
iir = readb((void*)(uart_base + UART_IIR)) & UART_IIR_IID_MASK;
|
||||||
|
lsr = readb((void*)(uart_base + UART_LSR));
|
||||||
|
// rt_kprintf("uart isr iir:%x lsr:%x\r\n", iir, lsr);
|
||||||
|
|
||||||
|
if (iir == UART_IIR_IID_BUSBSY)
|
||||||
|
{
|
||||||
|
(void)readb((void*)(uart_base + UART_USR));
|
||||||
|
}
|
||||||
|
else if (lsr & (UART_LSR_DR | UART_LSR_BI))
|
||||||
|
{
|
||||||
|
#ifdef RT_USING_SERIAL_V2
|
||||||
|
struct rt_serial_rx_fifo *rx_fifo;
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
|
||||||
|
RT_ASSERT(rx_fifo != RT_NULL);
|
||||||
|
|
||||||
|
do {
|
||||||
|
data = readb((void*)(uart_base + UART_RBR));
|
||||||
|
rt_ringbuffer_putchar(&(rx_fifo->rb), data);
|
||||||
|
lsr = readb((void*)(uart_base + UART_LSR));
|
||||||
|
} while(lsr & UART_LSR_DR);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
|
||||||
|
}
|
||||||
|
else if (iir & UART_IIR_IID_CHARTO)
|
||||||
|
/* has charto irq but no dr lsr? just read and ignore */
|
||||||
|
{
|
||||||
|
readb((void*)(uart_base + UART_RBR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UART Initiation
|
||||||
|
*/
|
||||||
|
int rt_hw_uart_init(void)
|
||||||
|
{
|
||||||
|
struct rt_serial_device *serial;
|
||||||
|
struct device_uart *uart;
|
||||||
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||||
|
|
||||||
|
{
|
||||||
|
serial = &serial1;
|
||||||
|
uart = &uart1;
|
||||||
|
|
||||||
|
serial->ops = &_uart_ops;
|
||||||
|
serial->config = config;
|
||||||
|
serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
|
||||||
|
|
||||||
|
uart->hw_base = (rt_base_t)rt_ioremap((void *)UART_ADDR, 0x1000);
|
||||||
|
uart->irqno = UART_IRQ;
|
||||||
|
|
||||||
|
_uart_init((void*)(uart->hw_base));
|
||||||
|
|
||||||
|
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart1");
|
||||||
|
rt_hw_interrupt_umask(uart->irqno);
|
||||||
|
|
||||||
|
rt_hw_serial_register(serial,
|
||||||
|
RT_CONSOLE_DEVICE_NAME,
|
||||||
|
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
|
||||||
|
uart);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020, Xim
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DRV_UART_H__
|
||||||
|
#define __DRV_UART_H__
|
||||||
|
|
||||||
|
void rt_hw_uart_start_rx_thread();
|
||||||
|
int rt_hw_uart_init(void);
|
||||||
|
void drv_uart_puts(char *str); // for syscall
|
||||||
|
|
||||||
|
#endif /* __DRV_UART_H__ */
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2020/12/12 bernard The first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
INCLUDE "link_stacksize.lds"
|
||||||
|
|
||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Memory layout:
|
||||||
|
* 2M ==> +128K: Bootloader(sbi)
|
||||||
|
* 2M+128K ==> +sizeof(rtthread.bin): Kernel
|
||||||
|
* ~ ==> 32M: Heap
|
||||||
|
* 32M - 66M: Page
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
SRAM(wx) : ORIGIN = 0xFFFFFFC000220000, LENGTH = 64M - 128K
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = ORIGIN(SRAM) ;
|
||||||
|
|
||||||
|
/* __STACKSIZE__ = 4096; */
|
||||||
|
__sram_base = ORIGIN(SRAM);
|
||||||
|
__sram_size = LENGTH(SRAM);
|
||||||
|
__sram_end = __sram_base + __sram_size;
|
||||||
|
__text_start = .;
|
||||||
|
.start :
|
||||||
|
{
|
||||||
|
*(.start);
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text) /* remaining code */
|
||||||
|
*(.text.*) /* remaining code */
|
||||||
|
*(.rodata) /* read-only data (constants) */
|
||||||
|
*(.rodata*)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t)
|
||||||
|
*(.gnu.linkonce.t*)
|
||||||
|
|
||||||
|
/* section information for finsh shell */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__fsymtab_start = .;
|
||||||
|
KEEP(*(FSymTab))
|
||||||
|
__fsymtab_end = .;
|
||||||
|
. = ALIGN(8);
|
||||||
|
__vsymtab_start = .;
|
||||||
|
KEEP(*(VSymTab))
|
||||||
|
__vsymtab_end = .;
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
/* section information for initial. */
|
||||||
|
. = ALIGN(8);
|
||||||
|
__rt_init_start = .;
|
||||||
|
KEEP(*(SORT(.rti_fn*)))
|
||||||
|
__rt_init_end = .;
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
__rt_utest_tc_tab_start = .;
|
||||||
|
KEEP(*(UtestTcTab))
|
||||||
|
__rt_utest_tc_tab_end = .;
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
_etext = .;
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
.eh_frame_hdr :
|
||||||
|
{
|
||||||
|
*(.eh_frame_hdr)
|
||||||
|
*(.eh_frame_entry)
|
||||||
|
} > SRAM
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > SRAM
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
__text_end = .;
|
||||||
|
__text_size = __text_end - __text_start;
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
|
||||||
|
*(.data1)
|
||||||
|
*(.data1.*)
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||||
|
|
||||||
|
*(.sdata)
|
||||||
|
*(.sdata.*)
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
/* stack for dual core */
|
||||||
|
.stack :
|
||||||
|
{
|
||||||
|
. = ALIGN(64);
|
||||||
|
__stack_start__ = .;
|
||||||
|
|
||||||
|
. += __STACKSIZE__;
|
||||||
|
__stack_cpu0 = .;
|
||||||
|
|
||||||
|
. += __STACKSIZE__;
|
||||||
|
__stack_cpu1 = .;
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.osdebug :
|
||||||
|
{
|
||||||
|
_osdebug_start = .;
|
||||||
|
. += 87K;
|
||||||
|
_osdebug_end = .;
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
. = ALIGN(8);
|
||||||
|
|
||||||
|
.sbss :
|
||||||
|
{
|
||||||
|
__bss_start = .;
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss.*)
|
||||||
|
*(.dynsbss)
|
||||||
|
*(.scommon)
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.dynbss)
|
||||||
|
*(COMMON)
|
||||||
|
__bss_end = .;
|
||||||
|
} > SRAM
|
||||||
|
|
||||||
|
_end = .;
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
* Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
* of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
__STACKSIZE__ = 8192;
|
|
@ -0,0 +1,77 @@
|
||||||
|
#/bin/sh
|
||||||
|
|
||||||
|
#add_firmHead xxx.bin "-n"
|
||||||
|
#output fn_$1 fa_$1 fs_$1
|
||||||
|
add_firmHead()
|
||||||
|
{
|
||||||
|
local filename="$1"
|
||||||
|
local firmware_gen="tools/firmware_gen.py"
|
||||||
|
|
||||||
|
if [ $# -ge 2 ]; then
|
||||||
|
firmArgs="$2" #add k230 firmware head
|
||||||
|
cp ${filename} ${filename}.t; python3 ${firmware_gen} -i ${filename}.t -o f${firmArgs##-}${filename} ${firmArgs};
|
||||||
|
else
|
||||||
|
#add k230 firmware head
|
||||||
|
firmArgs="-n"; cp ${filename} ${filename}.t; python3 ${firmware_gen} -i ${filename}.t -o f${firmArgs##-}_${filename} ${firmArgs};
|
||||||
|
fi
|
||||||
|
rm -rf ${filename}.t
|
||||||
|
}
|
||||||
|
|
||||||
|
k230_gzip()
|
||||||
|
{
|
||||||
|
local filename="$1"
|
||||||
|
local k230_gzip_tool="tools/k230_priv_gzip "
|
||||||
|
|
||||||
|
${k230_gzip_tool} -n8 -f -k ${filename} || ${k230_gzip_tool} -n9 -f -k ${filename} || \
|
||||||
|
${k230_gzip_tool} -n7 -f -k ${filename} || ${k230_gzip_tool} -n6 -f -k ${filename} || \
|
||||||
|
${k230_gzip_tool} -n5 -f -k ${filename} || ${k230_gzip_tool} -n4 -f -k ${filename}
|
||||||
|
|
||||||
|
sed -i -e "1s/\x08/\x09/" ${filename}.gz
|
||||||
|
}
|
||||||
|
|
||||||
|
bin_gzip_ubootHead_firmHead()
|
||||||
|
{
|
||||||
|
local mkimage="tools/mkimage"
|
||||||
|
local file_full_path="$1"
|
||||||
|
local filename=$(basename ${file_full_path})
|
||||||
|
local mkimgArgs="$2"
|
||||||
|
local firmArgs="$3"
|
||||||
|
|
||||||
|
[ "$(dirname ${file_full_path})" == "$(pwd)" ] || cp ${file_full_path} .
|
||||||
|
|
||||||
|
k230_gzip ${filename}
|
||||||
|
|
||||||
|
#add uboot head
|
||||||
|
${mkimage} -A riscv -C gzip ${mkimgArgs} -d ${filename}.gz ug_${filename}
|
||||||
|
|
||||||
|
add_firmHead ug_${filename}
|
||||||
|
rm -rf ${filename} ${filename}.gz ug_${filename}
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_rtt_bin()
|
||||||
|
{
|
||||||
|
local filename="fw_payload.bin"
|
||||||
|
local CONFIG_MEM_RTT_SYS_BASE="0x200000"
|
||||||
|
|
||||||
|
bin_gzip_ubootHead_firmHead "opensbi/build/platform/kendryte/fpgac908/firmware/${filename}" \
|
||||||
|
"-O opensbi -T multi -a ${CONFIG_MEM_RTT_SYS_BASE} -e ${CONFIG_MEM_RTT_SYS_BASE} -n rtt"
|
||||||
|
|
||||||
|
mv fn_ug_${filename} rtt_system.bin
|
||||||
|
}
|
||||||
|
|
||||||
|
build_sbi()
|
||||||
|
{
|
||||||
|
cc=~/.tools/gnu_gcc/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/bin/riscv64-unknown-linux-musl-
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
cc=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd opensbi && make FW_PAYLOAD_PATH=../rtthread.bin FW_FDT_PATH=hw.dtb PLATFORM=kendryte/fpgac908 CROSS_COMPILE=$cc
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
}
|
||||||
|
|
||||||
|
build_sbi $1
|
||||||
|
|
||||||
|
gen_rtt_bin
|
|
@ -0,0 +1,491 @@
|
||||||
|
#ifndef RT_CONFIG_H__
|
||||||
|
#define RT_CONFIG_H__
|
||||||
|
|
||||||
|
/* RT-Thread Kernel */
|
||||||
|
|
||||||
|
#define RT_NAME_MAX 8
|
||||||
|
#define RT_USING_SMART
|
||||||
|
#define RT_CPUS_NR 1
|
||||||
|
#define RT_ALIGN_SIZE 8
|
||||||
|
#define RT_THREAD_PRIORITY_32
|
||||||
|
#define RT_THREAD_PRIORITY_MAX 32
|
||||||
|
#define RT_TICK_PER_SECOND 1000
|
||||||
|
#define RT_USING_HOOK
|
||||||
|
#define RT_HOOK_USING_FUNC_PTR
|
||||||
|
#define RT_USING_HOOKLIST
|
||||||
|
#define RT_USING_IDLE_HOOK
|
||||||
|
#define RT_IDLE_HOOK_LIST_SIZE 4
|
||||||
|
#define IDLE_THREAD_STACK_SIZE 8192
|
||||||
|
#define RT_USING_TIMER_SOFT
|
||||||
|
#define RT_TIMER_THREAD_PRIO 4
|
||||||
|
#define RT_TIMER_THREAD_STACK_SIZE 8192
|
||||||
|
#define RT_USING_CPU_USAGE_TRACER
|
||||||
|
|
||||||
|
/* kservice optimization */
|
||||||
|
|
||||||
|
/* end of kservice optimization */
|
||||||
|
|
||||||
|
/* klibc optimization */
|
||||||
|
|
||||||
|
#define RT_KLIBC_USING_PRINTF_LONGLONG
|
||||||
|
/* end of klibc optimization */
|
||||||
|
#define RT_USING_DEBUG
|
||||||
|
#define RT_DEBUGING_ASSERT
|
||||||
|
#define RT_DEBUGING_COLOR
|
||||||
|
#define RT_DEBUGING_CONTEXT
|
||||||
|
#define RT_USING_OVERFLOW_CHECK
|
||||||
|
|
||||||
|
/* Inter-Thread communication */
|
||||||
|
|
||||||
|
#define RT_USING_SEMAPHORE
|
||||||
|
#define RT_USING_MUTEX
|
||||||
|
#define RT_USING_EVENT
|
||||||
|
#define RT_USING_MAILBOX
|
||||||
|
#define RT_USING_MESSAGEQUEUE
|
||||||
|
/* end of Inter-Thread communication */
|
||||||
|
|
||||||
|
/* Memory Management */
|
||||||
|
|
||||||
|
#define RT_PAGE_MAX_ORDER 11
|
||||||
|
#define RT_USING_MEMPOOL
|
||||||
|
#define RT_USING_SLAB
|
||||||
|
#define RT_USING_SLAB_AS_HEAP
|
||||||
|
#define RT_USING_HEAP
|
||||||
|
/* end of Memory Management */
|
||||||
|
#define RT_USING_DEVICE
|
||||||
|
#define RT_USING_DEVICE_OPS
|
||||||
|
#define RT_USING_SCHED_THREAD_CTX
|
||||||
|
#define RT_USING_CONSOLE
|
||||||
|
#define RT_CONSOLEBUF_SIZE 256
|
||||||
|
#define RT_CONSOLE_DEVICE_NAME "uart"
|
||||||
|
#define RT_VER_NUM 0x50200
|
||||||
|
#define RT_USING_STDC_ATOMIC
|
||||||
|
#define RT_BACKTRACE_LEVEL_MAX_NR 32
|
||||||
|
/* end of RT-Thread Kernel */
|
||||||
|
#define ARCH_CPU_64BIT
|
||||||
|
#define RT_USING_CACHE
|
||||||
|
#define ARCH_MM_MMU
|
||||||
|
#define KERNEL_VADDR_START 0xFFFFFFC000220000
|
||||||
|
#define ARCH_RISCV
|
||||||
|
#define ARCH_RISCV_FPU
|
||||||
|
#define ARCH_RISCV_FPU_D
|
||||||
|
#define ARCH_RISCV64
|
||||||
|
#define ARCH_USING_NEW_CTX_SWITCH
|
||||||
|
#define ARCH_REMAP_KERNEL
|
||||||
|
|
||||||
|
/* RT-Thread Components */
|
||||||
|
|
||||||
|
#define RT_USING_COMPONENTS_INIT
|
||||||
|
#define RT_USING_USER_MAIN
|
||||||
|
#define RT_MAIN_THREAD_STACK_SIZE 8192
|
||||||
|
#define RT_MAIN_THREAD_PRIORITY 10
|
||||||
|
#define RT_USING_MSH
|
||||||
|
#define RT_USING_FINSH
|
||||||
|
#define FINSH_USING_MSH
|
||||||
|
#define FINSH_THREAD_NAME "tshell"
|
||||||
|
#define FINSH_THREAD_PRIORITY 20
|
||||||
|
#define FINSH_THREAD_STACK_SIZE 8192
|
||||||
|
#define FINSH_USING_HISTORY
|
||||||
|
#define FINSH_HISTORY_LINES 5
|
||||||
|
#define FINSH_USING_SYMTAB
|
||||||
|
#define FINSH_CMD_SIZE 80
|
||||||
|
#define MSH_USING_BUILT_IN_COMMANDS
|
||||||
|
#define FINSH_USING_DESCRIPTION
|
||||||
|
#define FINSH_ARG_MAX 10
|
||||||
|
#define FINSH_USING_OPTION_COMPLETION
|
||||||
|
|
||||||
|
/* DFS: device virtual file system */
|
||||||
|
|
||||||
|
#define RT_USING_DFS
|
||||||
|
#define DFS_USING_POSIX
|
||||||
|
#define DFS_USING_WORKDIR
|
||||||
|
#define DFS_FD_MAX 16
|
||||||
|
#define RT_USING_DFS_V2
|
||||||
|
#define RT_USING_DFS_ELMFAT
|
||||||
|
|
||||||
|
/* elm-chan's FatFs, Generic FAT Filesystem Module */
|
||||||
|
|
||||||
|
#define RT_DFS_ELM_CODE_PAGE 437
|
||||||
|
#define RT_DFS_ELM_WORD_ACCESS
|
||||||
|
#define RT_DFS_ELM_USE_LFN_3
|
||||||
|
#define RT_DFS_ELM_USE_LFN 3
|
||||||
|
#define RT_DFS_ELM_LFN_UNICODE_0
|
||||||
|
#define RT_DFS_ELM_LFN_UNICODE 0
|
||||||
|
#define RT_DFS_ELM_MAX_LFN 255
|
||||||
|
#define RT_DFS_ELM_DRIVES 2
|
||||||
|
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
|
||||||
|
#define RT_DFS_ELM_REENTRANT
|
||||||
|
#define RT_DFS_ELM_MUTEX_TIMEOUT 3000
|
||||||
|
/* end of elm-chan's FatFs, Generic FAT Filesystem Module */
|
||||||
|
#define RT_USING_DFS_DEVFS
|
||||||
|
#define RT_USING_DFS_PTYFS
|
||||||
|
#define RT_USING_DFS_CROMFS
|
||||||
|
#define RT_USING_DFS_TMPFS
|
||||||
|
#define RT_USING_PAGECACHE
|
||||||
|
|
||||||
|
/* page cache config */
|
||||||
|
|
||||||
|
#define RT_PAGECACHE_COUNT 4096
|
||||||
|
#define RT_PAGECACHE_ASPACE_COUNT 1024
|
||||||
|
#define RT_PAGECACHE_PRELOAD 4
|
||||||
|
#define RT_PAGECACHE_HASH_NR 1024
|
||||||
|
#define RT_PAGECACHE_GC_WORK_LEVEL 90
|
||||||
|
#define RT_PAGECACHE_GC_STOP_LEVEL 70
|
||||||
|
/* end of page cache config */
|
||||||
|
/* end of DFS: device virtual file system */
|
||||||
|
|
||||||
|
/* Device Drivers */
|
||||||
|
|
||||||
|
#define RT_USING_DEVICE_IPC
|
||||||
|
#define RT_UNAMED_PIPE_NUMBER 64
|
||||||
|
#define RT_USING_SYSTEM_WORKQUEUE
|
||||||
|
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 8192
|
||||||
|
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
|
||||||
|
#define RT_USING_SERIAL
|
||||||
|
#define RT_USING_SERIAL_V1
|
||||||
|
#define RT_SERIAL_USING_DMA
|
||||||
|
#define RT_SERIAL_RB_BUFSZ 64
|
||||||
|
#define RT_USING_CPUTIME
|
||||||
|
#define RT_USING_CPUTIME_RISCV
|
||||||
|
#define CPUTIME_TIMER_FREQ 25000000
|
||||||
|
#define RT_USING_NULL
|
||||||
|
#define RT_USING_ZERO
|
||||||
|
#define RT_USING_RANDOM
|
||||||
|
#define RT_USING_RTC
|
||||||
|
#define RT_USING_SDIO
|
||||||
|
#define RT_SDIO_STACK_SIZE 8192
|
||||||
|
#define RT_SDIO_THREAD_PRIORITY 15
|
||||||
|
#define RT_MMCSD_STACK_SIZE 8192
|
||||||
|
#define RT_MMCSD_THREAD_PREORITY 22
|
||||||
|
#define RT_MMCSD_MAX_PARTITION 16
|
||||||
|
#define RT_USING_PIN
|
||||||
|
#define RT_USING_KTIME
|
||||||
|
/* end of Device Drivers */
|
||||||
|
|
||||||
|
/* C/C++ and POSIX layer */
|
||||||
|
|
||||||
|
/* ISO-ANSI C layer */
|
||||||
|
|
||||||
|
/* Timezone and Daylight Saving Time */
|
||||||
|
|
||||||
|
#define RT_LIBC_USING_LIGHT_TZ_DST
|
||||||
|
#define RT_LIBC_TZ_DEFAULT_HOUR 8
|
||||||
|
#define RT_LIBC_TZ_DEFAULT_MIN 0
|
||||||
|
#define RT_LIBC_TZ_DEFAULT_SEC 0
|
||||||
|
/* end of Timezone and Daylight Saving Time */
|
||||||
|
/* end of ISO-ANSI C layer */
|
||||||
|
|
||||||
|
/* POSIX (Portable Operating System Interface) layer */
|
||||||
|
|
||||||
|
#define RT_USING_POSIX_FS
|
||||||
|
#define RT_USING_POSIX_DEVIO
|
||||||
|
#define RT_USING_POSIX_STDIO
|
||||||
|
#define RT_USING_POSIX_POLL
|
||||||
|
#define RT_USING_POSIX_SELECT
|
||||||
|
#define RT_USING_POSIX_EPOLL
|
||||||
|
#define RT_USING_POSIX_SIGNALFD
|
||||||
|
#define RT_SIGNALFD_MAX_NUM 10
|
||||||
|
#define RT_USING_POSIX_SOCKET
|
||||||
|
#define RT_USING_POSIX_TERMIOS
|
||||||
|
#define RT_USING_POSIX_DELAY
|
||||||
|
#define RT_USING_POSIX_CLOCK
|
||||||
|
#define RT_USING_POSIX_TIMER
|
||||||
|
|
||||||
|
/* Interprocess Communication (IPC) */
|
||||||
|
|
||||||
|
|
||||||
|
/* Socket is in the 'Network' category */
|
||||||
|
|
||||||
|
/* end of Interprocess Communication (IPC) */
|
||||||
|
/* end of POSIX (Portable Operating System Interface) layer */
|
||||||
|
/* end of C/C++ and POSIX layer */
|
||||||
|
|
||||||
|
/* Network */
|
||||||
|
|
||||||
|
#define RT_USING_SAL
|
||||||
|
#define SAL_INTERNET_CHECK
|
||||||
|
|
||||||
|
/* Docking with protocol stacks */
|
||||||
|
|
||||||
|
#define SAL_USING_LWIP
|
||||||
|
/* end of Docking with protocol stacks */
|
||||||
|
#define SAL_USING_POSIX
|
||||||
|
#define RT_USING_NETDEV
|
||||||
|
#define NETDEV_USING_IFCONFIG
|
||||||
|
#define NETDEV_USING_PING
|
||||||
|
#define NETDEV_USING_NETSTAT
|
||||||
|
#define NETDEV_USING_AUTO_DEFAULT
|
||||||
|
#define NETDEV_IPV4 1
|
||||||
|
#define NETDEV_IPV6 0
|
||||||
|
#define RT_USING_LWIP
|
||||||
|
#define RT_USING_LWIP212
|
||||||
|
#define RT_USING_LWIP_VER_NUM 0x20102
|
||||||
|
#define RT_LWIP_MEM_ALIGNMENT 8
|
||||||
|
#define RT_LWIP_IGMP
|
||||||
|
#define RT_LWIP_ICMP
|
||||||
|
#define RT_LWIP_DNS
|
||||||
|
#define RT_LWIP_DHCP
|
||||||
|
#define IP_SOF_BROADCAST 1
|
||||||
|
#define IP_SOF_BROADCAST_RECV 1
|
||||||
|
|
||||||
|
/* Static IPv4 Address */
|
||||||
|
|
||||||
|
#define RT_LWIP_IPADDR "192.168.1.30"
|
||||||
|
#define RT_LWIP_GWADDR "192.168.1.1"
|
||||||
|
#define RT_LWIP_MSKADDR "255.255.255.0"
|
||||||
|
/* end of Static IPv4 Address */
|
||||||
|
#define RT_LWIP_UDP
|
||||||
|
#define RT_LWIP_TCP
|
||||||
|
#define RT_LWIP_RAW
|
||||||
|
#define RT_MEMP_NUM_NETCONN 8
|
||||||
|
#define RT_LWIP_PBUF_NUM 16
|
||||||
|
#define RT_LWIP_RAW_PCB_NUM 4
|
||||||
|
#define RT_LWIP_UDP_PCB_NUM 4
|
||||||
|
#define RT_LWIP_TCP_PCB_NUM 4
|
||||||
|
#define RT_LWIP_TCP_SEG_NUM 40
|
||||||
|
#define RT_LWIP_TCP_SND_BUF 8196
|
||||||
|
#define RT_LWIP_TCP_WND 8196
|
||||||
|
#define RT_LWIP_TCPTHREAD_PRIORITY 10
|
||||||
|
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
|
||||||
|
#define RT_LWIP_TCPTHREAD_STACKSIZE 8192
|
||||||
|
#define RT_LWIP_ETHTHREAD_PRIORITY 12
|
||||||
|
#define RT_LWIP_ETHTHREAD_STACKSIZE 8192
|
||||||
|
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
|
||||||
|
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||||
|
#define RT_LWIP_NETIF_NAMESIZE 6
|
||||||
|
#define SO_REUSE 1
|
||||||
|
#define LWIP_SO_RCVTIMEO 1
|
||||||
|
#define LWIP_SO_SNDTIMEO 1
|
||||||
|
#define LWIP_SO_RCVBUF 1
|
||||||
|
#define LWIP_SO_LINGER 0
|
||||||
|
#define LWIP_NETIF_LOOPBACK 0
|
||||||
|
#define RT_LWIP_USING_PING
|
||||||
|
/* end of Network */
|
||||||
|
|
||||||
|
/* Memory protection */
|
||||||
|
|
||||||
|
/* end of Memory protection */
|
||||||
|
|
||||||
|
/* Utilities */
|
||||||
|
|
||||||
|
#define RT_USING_RESOURCE_ID
|
||||||
|
#define RT_USING_ADT
|
||||||
|
#define RT_USING_ADT_AVL
|
||||||
|
#define RT_USING_ADT_BITMAP
|
||||||
|
#define RT_USING_ADT_HASHMAP
|
||||||
|
#define RT_USING_ADT_REF
|
||||||
|
/* end of Utilities */
|
||||||
|
#define RT_USING_LWP
|
||||||
|
#define LWP_DEBUG
|
||||||
|
#define LWP_DEBUG_INIT
|
||||||
|
#define RT_LWP_MAX_NR 30
|
||||||
|
#define LWP_TASK_STACK_SIZE 16384
|
||||||
|
#define RT_CH_MSG_MAX_NR 1024
|
||||||
|
#define LWP_TID_MAX_NR 64
|
||||||
|
#define RT_LWP_SHM_MAX_NR 64
|
||||||
|
#define RT_USING_LDSO
|
||||||
|
#define LWP_USING_TERMINAL
|
||||||
|
#define LWP_PTY_MAX_PARIS_LIMIT 64
|
||||||
|
|
||||||
|
/* Memory management */
|
||||||
|
|
||||||
|
/* end of Memory management */
|
||||||
|
|
||||||
|
/* Using USB legacy version */
|
||||||
|
|
||||||
|
/* end of Using USB legacy version */
|
||||||
|
/* end of RT-Thread Components */
|
||||||
|
|
||||||
|
/* RT-Thread Utestcases */
|
||||||
|
|
||||||
|
/* end of RT-Thread Utestcases */
|
||||||
|
|
||||||
|
/* RT-Thread online packages */
|
||||||
|
|
||||||
|
/* IoT - internet of things */
|
||||||
|
|
||||||
|
|
||||||
|
/* Wi-Fi */
|
||||||
|
|
||||||
|
/* Marvell WiFi */
|
||||||
|
|
||||||
|
/* end of Marvell WiFi */
|
||||||
|
|
||||||
|
/* Wiced WiFi */
|
||||||
|
|
||||||
|
/* end of Wiced WiFi */
|
||||||
|
|
||||||
|
/* CYW43012 WiFi */
|
||||||
|
|
||||||
|
/* end of CYW43012 WiFi */
|
||||||
|
|
||||||
|
/* BL808 WiFi */
|
||||||
|
|
||||||
|
/* end of BL808 WiFi */
|
||||||
|
|
||||||
|
/* CYW43439 WiFi */
|
||||||
|
|
||||||
|
/* end of CYW43439 WiFi */
|
||||||
|
/* end of Wi-Fi */
|
||||||
|
|
||||||
|
/* IoT Cloud */
|
||||||
|
|
||||||
|
/* end of IoT Cloud */
|
||||||
|
/* end of IoT - internet of things */
|
||||||
|
|
||||||
|
/* security packages */
|
||||||
|
|
||||||
|
/* end of security packages */
|
||||||
|
|
||||||
|
/* language packages */
|
||||||
|
|
||||||
|
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
|
||||||
|
|
||||||
|
/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
|
||||||
|
|
||||||
|
/* XML: Extensible Markup Language */
|
||||||
|
|
||||||
|
/* end of XML: Extensible Markup Language */
|
||||||
|
/* end of language packages */
|
||||||
|
|
||||||
|
/* multimedia packages */
|
||||||
|
|
||||||
|
/* LVGL: powerful and easy-to-use embedded GUI library */
|
||||||
|
|
||||||
|
/* end of LVGL: powerful and easy-to-use embedded GUI library */
|
||||||
|
|
||||||
|
/* u8g2: a monochrome graphic library */
|
||||||
|
|
||||||
|
/* end of u8g2: a monochrome graphic library */
|
||||||
|
/* end of multimedia packages */
|
||||||
|
|
||||||
|
/* tools packages */
|
||||||
|
|
||||||
|
/* end of tools packages */
|
||||||
|
|
||||||
|
/* system packages */
|
||||||
|
|
||||||
|
/* enhanced kernel services */
|
||||||
|
|
||||||
|
/* end of enhanced kernel services */
|
||||||
|
|
||||||
|
/* acceleration: Assembly language or algorithmic acceleration packages */
|
||||||
|
|
||||||
|
/* end of acceleration: Assembly language or algorithmic acceleration packages */
|
||||||
|
|
||||||
|
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||||
|
|
||||||
|
/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||||
|
|
||||||
|
/* Micrium: Micrium software products porting for RT-Thread */
|
||||||
|
|
||||||
|
/* end of Micrium: Micrium software products porting for RT-Thread */
|
||||||
|
/* end of system packages */
|
||||||
|
|
||||||
|
/* peripheral libraries and drivers */
|
||||||
|
|
||||||
|
/* HAL & SDK Drivers */
|
||||||
|
|
||||||
|
/* STM32 HAL & SDK Drivers */
|
||||||
|
|
||||||
|
/* end of STM32 HAL & SDK Drivers */
|
||||||
|
|
||||||
|
/* Infineon HAL Packages */
|
||||||
|
|
||||||
|
/* end of Infineon HAL Packages */
|
||||||
|
|
||||||
|
/* Kendryte SDK */
|
||||||
|
|
||||||
|
/* end of Kendryte SDK */
|
||||||
|
/* end of HAL & SDK Drivers */
|
||||||
|
|
||||||
|
/* sensors drivers */
|
||||||
|
|
||||||
|
/* end of sensors drivers */
|
||||||
|
|
||||||
|
/* touch drivers */
|
||||||
|
|
||||||
|
/* end of touch drivers */
|
||||||
|
/* end of peripheral libraries and drivers */
|
||||||
|
|
||||||
|
/* AI packages */
|
||||||
|
|
||||||
|
/* end of AI packages */
|
||||||
|
|
||||||
|
/* Signal Processing and Control Algorithm Packages */
|
||||||
|
|
||||||
|
/* end of Signal Processing and Control Algorithm Packages */
|
||||||
|
|
||||||
|
/* miscellaneous packages */
|
||||||
|
|
||||||
|
/* project laboratory */
|
||||||
|
|
||||||
|
/* end of project laboratory */
|
||||||
|
|
||||||
|
/* samples: kernel and components samples */
|
||||||
|
|
||||||
|
/* end of samples: kernel and components samples */
|
||||||
|
|
||||||
|
/* entertainment: terminal games and other interesting software packages */
|
||||||
|
|
||||||
|
/* end of entertainment: terminal games and other interesting software packages */
|
||||||
|
#define PKG_USING_ZLIB
|
||||||
|
#define PKG_USING_ZLIB_LATEST_VERSION
|
||||||
|
/* end of miscellaneous packages */
|
||||||
|
|
||||||
|
/* Arduino libraries */
|
||||||
|
|
||||||
|
|
||||||
|
/* Projects and Demos */
|
||||||
|
|
||||||
|
/* end of Projects and Demos */
|
||||||
|
|
||||||
|
/* Sensors */
|
||||||
|
|
||||||
|
/* end of Sensors */
|
||||||
|
|
||||||
|
/* Display */
|
||||||
|
|
||||||
|
/* end of Display */
|
||||||
|
|
||||||
|
/* Timing */
|
||||||
|
|
||||||
|
/* end of Timing */
|
||||||
|
|
||||||
|
/* Data Processing */
|
||||||
|
|
||||||
|
/* end of Data Processing */
|
||||||
|
|
||||||
|
/* Data Storage */
|
||||||
|
|
||||||
|
/* Communication */
|
||||||
|
|
||||||
|
/* end of Communication */
|
||||||
|
|
||||||
|
/* Device Control */
|
||||||
|
|
||||||
|
/* end of Device Control */
|
||||||
|
|
||||||
|
/* Other */
|
||||||
|
|
||||||
|
/* end of Other */
|
||||||
|
|
||||||
|
/* Signal IO */
|
||||||
|
|
||||||
|
/* end of Signal IO */
|
||||||
|
|
||||||
|
/* Uncategorized */
|
||||||
|
|
||||||
|
/* end of Arduino libraries */
|
||||||
|
/* end of RT-Thread online packages */
|
||||||
|
|
||||||
|
/* Drivers Configuration */
|
||||||
|
|
||||||
|
/* end of Drivers Configuration */
|
||||||
|
#define BOARD_fpgac908
|
||||||
|
#define __STACKSIZE__ 8192
|
||||||
|
#define C908_PLIC_PHY_ADDR 0xF00000000
|
||||||
|
#define BSP_ROOTFS_TYPE_CROMFS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,54 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
# toolchains options
|
||||||
|
ARCH ='risc-v'
|
||||||
|
VENDOR ='t-head'
|
||||||
|
CPU ='c908'
|
||||||
|
CROSS_TOOL ='gcc'
|
||||||
|
|
||||||
|
RTT_ROOT = os.getenv('RTT_ROOT', r'../..')
|
||||||
|
|
||||||
|
if os.getenv('RTT_CC'):
|
||||||
|
CROSS_TOOL = os.getenv('RTT_CC')
|
||||||
|
|
||||||
|
if CROSS_TOOL == 'gcc':
|
||||||
|
PLATFORM = 'gcc'
|
||||||
|
EXEC_PATH = r'/opt/Xuantie-900-gcc-elf-newlib-x86_64-V2.8.1/bin'
|
||||||
|
else:
|
||||||
|
print('Please make sure your toolchains is GNU GCC!')
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
EXEC_PATH = os.getenv('RTT_EXEC_PATH', EXEC_PATH)
|
||||||
|
|
||||||
|
BUILD = 'debug'
|
||||||
|
|
||||||
|
if PLATFORM == 'gcc':
|
||||||
|
# toolchains
|
||||||
|
#PREFIX = 'riscv64-unknown-elf-'
|
||||||
|
PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-linux-musl-'
|
||||||
|
CC = PREFIX + 'gcc'
|
||||||
|
CXX = PREFIX + 'g++'
|
||||||
|
AS = PREFIX + 'gcc'
|
||||||
|
AR = PREFIX + 'ar'
|
||||||
|
LINK = PREFIX + 'gcc'
|
||||||
|
TARGET_EXT = 'elf'
|
||||||
|
SIZE = PREFIX + 'size'
|
||||||
|
OBJDUMP = PREFIX + 'objdump'
|
||||||
|
OBJCPY = PREFIX + 'objcopy'
|
||||||
|
|
||||||
|
DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64'
|
||||||
|
CFLAGS = DEVICE + ' -Wno-cpp -fvar-tracking -ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -D_POSIX_SOURCE '
|
||||||
|
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__'
|
||||||
|
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static'
|
||||||
|
CPATH = ''
|
||||||
|
LPATH = ''
|
||||||
|
|
||||||
|
if BUILD == 'debug':
|
||||||
|
CFLAGS += ' -O2 -g -gdwarf-2'
|
||||||
|
AFLAGS += ' -g -gdwarf-2'
|
||||||
|
else:
|
||||||
|
CFLAGS += ' -O2 -g -gdwarf-2'
|
||||||
|
|
||||||
|
CXXFLAGS = CFLAGS
|
||||||
|
|
||||||
|
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
|
Loading…
Reference in New Issue